1 // SPDX-License-Identifier: GPL-2.0
3 * Support for Intel Camera Imaging ISP subsystem.
4 * Copyright (c) 2015, Intel Corporation.
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 #include <linux/slab.h>
19 #include <linux/vmalloc.h>
23 #include "atomisp_internal.h"
26 #include "sh_css_hrt.h" /* only for file 2 MIPI */
27 #include "ia_css_buffer.h"
28 #include "ia_css_binary.h"
29 #include "sh_css_internal.h"
30 #include "sh_css_mipi.h"
31 #include "sh_css_sp.h" /* sh_css_sp_group */
32 #include "ia_css_isys.h"
33 #include "ia_css_frame.h"
34 #include "sh_css_defs.h"
35 #include "sh_css_firmware.h"
36 #include "sh_css_params.h"
37 #include "sh_css_params_internal.h"
38 #include "sh_css_param_shading.h"
39 #include "ia_css_refcount.h"
40 #include "ia_css_rmgr.h"
41 #include "ia_css_debug.h"
42 #include "ia_css_debug_pipe.h"
43 #include "ia_css_device_access.h"
44 #include "device_access.h"
45 #include "sh_css_legacy.h"
46 #include "ia_css_pipeline.h"
47 #include "ia_css_stream.h"
48 #include "sh_css_stream_format.h"
49 #include "ia_css_pipe.h"
50 #include "ia_css_util.h"
51 #include "ia_css_pipe_util.h"
52 #include "ia_css_pipe_binarydesc.h"
53 #include "ia_css_pipe_stagedesc.h"
56 #include "assert_support.h"
57 #include "math_support.h"
58 #include "sw_event_global.h" /* Event IDs.*/
60 #include "ia_css_ifmtr.h"
62 #include "input_system.h"
63 #include "mmu_device.h" /* mmu_set_page_table_base_index(), ... */
64 #include "ia_css_mmu_private.h" /* sh_css_mmu_set_page_table_base_index() */
65 #include "gdc_device.h" /* HRT_GDC_N */
66 #include "dma.h" /* dma_set_max_burst_size() */
67 #include "irq.h" /* virq */
68 #include "sp.h" /* cnd_sp_irq_enable() */
69 #include "isp.h" /* cnd_isp_irq_enable, ISP_VEC_NELEMS */
70 #include "gp_device.h" /* gp_device_reg_store() */
71 #define __INLINE_GPIO__
73 #include "timed_ctrl.h"
74 #include "ia_css_inputfifo.h"
75 #define WITH_PC_MONITORING 0
77 #define SH_CSS_VIDEO_BUFFER_ALIGNMENT 0
80 #include "ia_css_spctrl.h"
81 #include "ia_css_version_data.h"
82 #include "sh_css_struct.h"
83 #include "ia_css_bufq.h"
84 #include "ia_css_timer.h" /* clock_value_t */
86 #include "isp/modes/interface/input_buf.isp.h"
88 /* Name of the sp program: should not be built-in */
89 #define SP_PROG_NAME "sp"
90 /* Size of Refcount List */
91 #define REFCOUNT_SIZE 1000
94 * for JPEG, we don't know the length of the image upfront,
95 * but since we support sensor up to 16MP, we take this as
98 #define JPEG_BYTES (16 * 1024 * 1024)
100 #define STATS_ENABLED(stage) (stage && stage->binary && stage->binary->info && \
101 (stage->binary->info->sp.enable.s3a || stage->binary->info->sp.enable.dis))
103 struct sh_css my_css;
105 int __printf(1, 0) (*sh_css_printf)(const char *fmt, va_list args) = NULL;
108 * modes of work: stream_create and stream_destroy will update the save/restore
109 * data only when in working mode, not suspend/resume
111 enum ia_sh_css_modes {
112 sh_css_mode_none = 0,
119 * struct sh_css_stream_seed - a stream seed, to save and restore the
122 * @orig_stream: pointer to restore the original handle
123 * @stream: handle, used as ID too.
124 * @stream_config: stream config struct
125 * @num_pipes: number of pipes
126 * @pipes: pipe handles
127 * @orig_pipes: pointer to restore original handle
128 * @pipe_config: pipe config structs
130 * the stream seed contains all the data required to "grow" the seed again
131 * after it was closed.
133 struct sh_css_stream_seed {
134 struct ia_css_stream **orig_stream;
135 struct ia_css_stream *stream;
136 struct ia_css_stream_config stream_config;
138 struct ia_css_pipe *pipes[IA_CSS_PIPE_ID_NUM];
139 struct ia_css_pipe **orig_pipes[IA_CSS_PIPE_ID_NUM];
140 struct ia_css_pipe_config pipe_config[IA_CSS_PIPE_ID_NUM];
143 #define MAX_ACTIVE_STREAMS 5
145 * A global struct for save/restore to hold all the data that should
146 * sustain power-down: MMU base, IRQ type, env for routines, binary loaded FW
147 * and the stream seeds.
150 enum ia_sh_css_modes mode;
151 u32 mmu_base; /* the last mmu_base */
152 enum ia_css_irq_type irq_type;
153 struct sh_css_stream_seed stream_seeds[MAX_ACTIVE_STREAMS];
154 struct ia_css_fw *loaded_fw; /* fw struct previously loaded */
155 struct ia_css_env driver_env; /* driver-supplied env copy */
158 static bool my_css_save_initialized; /* if my_css_save was initialized */
159 static struct sh_css_save my_css_save;
162 * pqiao NOTICE: this is for css internal buffer recycling when stopping
164 * this array is temporary and will be replaced by resource manager
167 /* Taking the biggest Size for number of Elements */
168 #define MAX_HMM_BUFFER_NUM \
169 (SH_CSS_MAX_NUM_QUEUES * (IA_CSS_NUM_ELEMS_SP2HOST_BUFFER_QUEUE + 2))
171 struct sh_css_hmm_buffer_record {
173 enum ia_css_buffer_type type;
174 struct ia_css_rmgr_vbuf_handle *h_vbuf;
175 hrt_address kernel_ptr;
178 static struct sh_css_hmm_buffer_record hmm_buffer_record[MAX_HMM_BUFFER_NUM];
180 #define GPIO_FLASH_PIN_MASK BIT(HIVE_GPIO_STROBE_TRIGGER_PIN)
182 static bool fw_explicitly_loaded;
189 allocate_delay_frames(struct ia_css_pipe *pipe);
192 sh_css_pipe_start(struct ia_css_stream *stream);
195 * @brief Check if all "ia_css_pipe" instances in the target
196 * "ia_css_stream" instance have stopped.
198 * @param[in] stream Point to the target "ia_css_stream" instance.
201 * - true, if all "ia_css_pipe" instances in the target "ia_css_stream"
202 * instance have ben stopped.
203 * - false, otherwise.
208 ia_css_pipe_check_format(struct ia_css_pipe *pipe,
209 enum ia_css_frame_format format);
213 ia_css_pipe_load_extension(struct ia_css_pipe *pipe,
214 struct ia_css_fw_info *firmware);
217 ia_css_pipe_unload_extension(struct ia_css_pipe *pipe,
218 struct ia_css_fw_info *firmware);
220 ia_css_reset_defaults(struct sh_css *css);
223 sh_css_init_host_sp_control_vars(void);
226 set_num_primary_stages(unsigned int *num, enum ia_css_pipe_version version);
229 need_capture_pp(const struct ia_css_pipe *pipe);
232 need_yuv_scaler_stage(const struct ia_css_pipe *pipe);
234 static int ia_css_pipe_create_cas_scaler_desc_single_output(
235 struct ia_css_frame_info *cas_scaler_in_info,
236 struct ia_css_frame_info *cas_scaler_out_info,
237 struct ia_css_frame_info *cas_scaler_vf_info,
238 struct ia_css_cas_binary_descr *descr);
240 static void ia_css_pipe_destroy_cas_scaler_desc(struct ia_css_cas_binary_descr
244 need_downscaling(const struct ia_css_resolution in_res,
245 const struct ia_css_resolution out_res);
247 static bool need_capt_ldc(const struct ia_css_pipe *pipe);
250 sh_css_pipe_load_binaries(struct ia_css_pipe *pipe);
253 int sh_css_pipe_get_viewfinder_frame_info(
254 struct ia_css_pipe *pipe,
255 struct ia_css_frame_info *info,
259 sh_css_pipe_get_output_frame_info(struct ia_css_pipe *pipe,
260 struct ia_css_frame_info *info,
264 capture_start(struct ia_css_pipe *pipe);
267 video_start(struct ia_css_pipe *pipe);
270 preview_start(struct ia_css_pipe *pipe);
273 yuvpp_start(struct ia_css_pipe *pipe);
275 static bool copy_on_sp(struct ia_css_pipe *pipe);
278 init_vf_frameinfo_defaults(struct ia_css_pipe *pipe,
279 struct ia_css_frame *vf_frame, unsigned int idx);
282 init_in_frameinfo_memory_defaults(struct ia_css_pipe *pipe,
283 struct ia_css_frame *frame, enum ia_css_frame_format format);
286 init_out_frameinfo_defaults(struct ia_css_pipe *pipe,
287 struct ia_css_frame *out_frame, unsigned int idx);
290 sh_css_pipeline_add_acc_stage(struct ia_css_pipeline *pipeline,
294 alloc_continuous_frames(struct ia_css_pipe *pipe, bool init_time);
297 pipe_global_init(void);
300 pipe_generate_pipe_num(const struct ia_css_pipe *pipe,
301 unsigned int *pipe_number);
304 pipe_release_pipe_num(unsigned int pipe_num);
307 create_host_pipeline_structure(struct ia_css_stream *stream);
310 create_host_pipeline(struct ia_css_stream *stream);
313 create_host_preview_pipeline(struct ia_css_pipe *pipe);
316 create_host_video_pipeline(struct ia_css_pipe *pipe);
319 create_host_copy_pipeline(struct ia_css_pipe *pipe,
320 unsigned int max_input_width,
321 struct ia_css_frame *out_frame);
324 create_host_isyscopy_capture_pipeline(struct ia_css_pipe *pipe);
327 create_host_capture_pipeline(struct ia_css_pipe *pipe);
330 create_host_yuvpp_pipeline(struct ia_css_pipe *pipe);
333 create_host_acc_pipeline(struct ia_css_pipe *pipe);
336 sh_css_get_sw_interrupt_value(unsigned int irq);
338 static struct ia_css_binary *ia_css_pipe_get_shading_correction_binary(
339 const struct ia_css_pipe *pipe);
341 static struct ia_css_binary *
342 ia_css_pipe_get_s3a_binary(const struct ia_css_pipe *pipe);
344 static struct ia_css_binary *
345 ia_css_pipe_get_sdis_binary(const struct ia_css_pipe *pipe);
348 sh_css_hmm_buffer_record_init(void);
351 sh_css_hmm_buffer_record_uninit(void);
354 sh_css_hmm_buffer_record_reset(struct sh_css_hmm_buffer_record *buffer_record);
356 static struct sh_css_hmm_buffer_record
357 *sh_css_hmm_buffer_record_acquire(struct ia_css_rmgr_vbuf_handle *h_vbuf,
358 enum ia_css_buffer_type type,
359 hrt_address kernel_ptr);
361 static struct sh_css_hmm_buffer_record
362 *sh_css_hmm_buffer_record_validate(ia_css_ptr ddr_buffer_addr,
363 enum ia_css_buffer_type type);
366 ia_css_get_acc_configs(
367 struct ia_css_pipe *pipe,
368 struct ia_css_isp_config *config);
372 static unsigned int get_crop_lines_for_bayer_order(const struct
373 ia_css_stream_config *config);
374 static unsigned int get_crop_columns_for_bayer_order(const struct
375 ia_css_stream_config *config);
376 static void get_pipe_extra_pixel(struct ia_css_pipe *pipe,
377 unsigned int *extra_row, unsigned int *extra_column);
382 sh_css_pipe_free_shading_table(struct ia_css_pipe *pipe)
385 IA_CSS_ERROR("NULL input parameter");
389 if (pipe->shading_table)
390 ia_css_shading_table_free(pipe->shading_table);
391 pipe->shading_table = NULL;
394 static enum ia_css_frame_format yuv420_copy_formats[] = {
395 IA_CSS_FRAME_FORMAT_NV12,
396 IA_CSS_FRAME_FORMAT_NV21,
397 IA_CSS_FRAME_FORMAT_YV12,
398 IA_CSS_FRAME_FORMAT_YUV420,
399 IA_CSS_FRAME_FORMAT_YUV420_16,
400 IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8,
401 IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8
404 static enum ia_css_frame_format yuv422_copy_formats[] = {
405 IA_CSS_FRAME_FORMAT_NV12,
406 IA_CSS_FRAME_FORMAT_NV16,
407 IA_CSS_FRAME_FORMAT_NV21,
408 IA_CSS_FRAME_FORMAT_NV61,
409 IA_CSS_FRAME_FORMAT_YV12,
410 IA_CSS_FRAME_FORMAT_YV16,
411 IA_CSS_FRAME_FORMAT_YUV420,
412 IA_CSS_FRAME_FORMAT_YUV420_16,
413 IA_CSS_FRAME_FORMAT_YUV422,
414 IA_CSS_FRAME_FORMAT_YUV422_16,
415 IA_CSS_FRAME_FORMAT_UYVY,
416 IA_CSS_FRAME_FORMAT_YUYV
420 * Verify whether the selected output format is can be produced
421 * by the copy binary given the stream format.
424 verify_copy_out_frame_format(struct ia_css_pipe *pipe)
426 enum ia_css_frame_format out_fmt = pipe->output_info[0].format;
427 unsigned int i, found = 0;
430 assert(pipe->stream);
432 switch (pipe->stream->config.input_config.format) {
433 case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY:
434 case ATOMISP_INPUT_FORMAT_YUV420_8:
435 for (i = 0; i < ARRAY_SIZE(yuv420_copy_formats) && !found; i++)
436 found = (out_fmt == yuv420_copy_formats[i]);
438 case ATOMISP_INPUT_FORMAT_YUV420_10:
439 case ATOMISP_INPUT_FORMAT_YUV420_16:
440 found = (out_fmt == IA_CSS_FRAME_FORMAT_YUV420_16);
442 case ATOMISP_INPUT_FORMAT_YUV422_8:
443 for (i = 0; i < ARRAY_SIZE(yuv422_copy_formats) && !found; i++)
444 found = (out_fmt == yuv422_copy_formats[i]);
446 case ATOMISP_INPUT_FORMAT_YUV422_10:
447 case ATOMISP_INPUT_FORMAT_YUV422_16:
448 found = (out_fmt == IA_CSS_FRAME_FORMAT_YUV422_16 ||
449 out_fmt == IA_CSS_FRAME_FORMAT_YUV420_16);
451 case ATOMISP_INPUT_FORMAT_RGB_444:
452 case ATOMISP_INPUT_FORMAT_RGB_555:
453 case ATOMISP_INPUT_FORMAT_RGB_565:
454 found = (out_fmt == IA_CSS_FRAME_FORMAT_RGBA888 ||
455 out_fmt == IA_CSS_FRAME_FORMAT_RGB565);
457 case ATOMISP_INPUT_FORMAT_RGB_666:
458 case ATOMISP_INPUT_FORMAT_RGB_888:
459 found = (out_fmt == IA_CSS_FRAME_FORMAT_RGBA888 ||
460 out_fmt == IA_CSS_FRAME_FORMAT_YUV420);
462 case ATOMISP_INPUT_FORMAT_RAW_6:
463 case ATOMISP_INPUT_FORMAT_RAW_7:
464 case ATOMISP_INPUT_FORMAT_RAW_8:
465 case ATOMISP_INPUT_FORMAT_RAW_10:
466 case ATOMISP_INPUT_FORMAT_RAW_12:
467 case ATOMISP_INPUT_FORMAT_RAW_14:
468 case ATOMISP_INPUT_FORMAT_RAW_16:
469 found = (out_fmt == IA_CSS_FRAME_FORMAT_RAW) ||
470 (out_fmt == IA_CSS_FRAME_FORMAT_RAW_PACKED);
472 case ATOMISP_INPUT_FORMAT_BINARY_8:
473 found = (out_fmt == IA_CSS_FRAME_FORMAT_BINARY_8);
484 ia_css_stream_input_format_bits_per_pixel(struct ia_css_stream *stream)
489 bpp = ia_css_util_input_format_bpp(stream->config.input_config.format,
490 stream->config.pixels_per_clock == 2);
495 /* TODO: move define to proper file in tools */
496 #define GP_ISEL_TPG_MODE 0x90058
498 #if !defined(ISP2401)
500 sh_css_config_input_network(struct ia_css_stream *stream)
502 unsigned int fmt_type;
503 struct ia_css_pipe *pipe = stream->last_pipe;
504 struct ia_css_binary *binary = NULL;
510 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
511 "sh_css_config_input_network() enter:\n");
513 if (pipe->pipeline.stages)
514 binary = pipe->pipeline.stages->binary;
516 err = ia_css_isys_convert_stream_format_to_mipi_format(
517 stream->config.input_config.format,
518 stream->csi_rx_config.comp,
522 sh_css_sp_program_input_circuit(fmt_type,
523 stream->config.channel_id,
524 stream->config.mode);
526 if ((binary && (binary->online || stream->config.continuous)) ||
527 pipe->config.mode == IA_CSS_PIPE_MODE_COPY) {
528 err = ia_css_ifmtr_configure(&stream->config,
534 if (stream->config.mode == IA_CSS_INPUT_MODE_TPG ||
535 stream->config.mode == IA_CSS_INPUT_MODE_PRBS) {
536 unsigned int hblank_cycles = 100,
541 width = (stream->config.input_config.input_res.width) / (1 +
542 (stream->config.pixels_per_clock == 2));
543 height = stream->config.input_config.input_res.height;
544 vblank_cycles = vblank_lines * (width + hblank_cycles);
545 sh_css_sp_configure_sync_gen(width, height, hblank_cycles,
547 if (pipe->stream->config.mode == IA_CSS_INPUT_MODE_TPG)
548 ia_css_device_store_uint32(GP_ISEL_TPG_MODE, 0);
550 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
551 "sh_css_config_input_network() leave:\n");
554 #elif defined(ISP2401)
555 static unsigned int csi2_protocol_calculate_max_subpixels_per_line(
556 enum atomisp_input_format format,
557 unsigned int pixels_per_line)
562 case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY:
564 * The frame format layout is shown below.
566 * Line 0: UYY0 UYY0 ... UYY0
567 * Line 1: VYY0 VYY0 ... VYY0
568 * Line 2: UYY0 UYY0 ... UYY0
569 * Line 3: VYY0 VYY0 ... VYY0
571 * Line (n-2): UYY0 UYY0 ... UYY0
572 * Line (n-1): VYY0 VYY0 ... VYY0
574 * In this frame format, the even-line is
575 * as wide as the odd-line.
576 * The 0 is introduced by the input system
579 rval = pixels_per_line * 2;
581 case ATOMISP_INPUT_FORMAT_YUV420_8:
582 case ATOMISP_INPUT_FORMAT_YUV420_10:
583 case ATOMISP_INPUT_FORMAT_YUV420_16:
585 * The frame format layout is shown below.
587 * Line 0: YYYY YYYY ... YYYY
588 * Line 1: UYVY UYVY ... UYVY UYVY
589 * Line 2: YYYY YYYY ... YYYY
590 * Line 3: UYVY UYVY ... UYVY UYVY
592 * Line (n-2): YYYY YYYY ... YYYY
593 * Line (n-1): UYVY UYVY ... UYVY UYVY
595 * In this frame format, the odd-line is twice
596 * wider than the even-line.
598 rval = pixels_per_line * 2;
600 case ATOMISP_INPUT_FORMAT_YUV422_8:
601 case ATOMISP_INPUT_FORMAT_YUV422_10:
602 case ATOMISP_INPUT_FORMAT_YUV422_16:
604 * The frame format layout is shown below.
606 * Line 0: UYVY UYVY ... UYVY
607 * Line 1: UYVY UYVY ... UYVY
608 * Line 2: UYVY UYVY ... UYVY
609 * Line 3: UYVY UYVY ... UYVY
611 * Line (n-2): UYVY UYVY ... UYVY
612 * Line (n-1): UYVY UYVY ... UYVY
614 * In this frame format, the even-line is
615 * as wide as the odd-line.
617 rval = pixels_per_line * 2;
619 case ATOMISP_INPUT_FORMAT_RGB_444:
620 case ATOMISP_INPUT_FORMAT_RGB_555:
621 case ATOMISP_INPUT_FORMAT_RGB_565:
622 case ATOMISP_INPUT_FORMAT_RGB_666:
623 case ATOMISP_INPUT_FORMAT_RGB_888:
625 * The frame format layout is shown below.
627 * Line 0: ABGR ABGR ... ABGR
628 * Line 1: ABGR ABGR ... ABGR
629 * Line 2: ABGR ABGR ... ABGR
630 * Line 3: ABGR ABGR ... ABGR
632 * Line (n-2): ABGR ABGR ... ABGR
633 * Line (n-1): ABGR ABGR ... ABGR
635 * In this frame format, the even-line is
636 * as wide as the odd-line.
638 rval = pixels_per_line * 4;
640 case ATOMISP_INPUT_FORMAT_RAW_6:
641 case ATOMISP_INPUT_FORMAT_RAW_7:
642 case ATOMISP_INPUT_FORMAT_RAW_8:
643 case ATOMISP_INPUT_FORMAT_RAW_10:
644 case ATOMISP_INPUT_FORMAT_RAW_12:
645 case ATOMISP_INPUT_FORMAT_RAW_14:
646 case ATOMISP_INPUT_FORMAT_RAW_16:
647 case ATOMISP_INPUT_FORMAT_BINARY_8:
648 case ATOMISP_INPUT_FORMAT_USER_DEF1:
649 case ATOMISP_INPUT_FORMAT_USER_DEF2:
650 case ATOMISP_INPUT_FORMAT_USER_DEF3:
651 case ATOMISP_INPUT_FORMAT_USER_DEF4:
652 case ATOMISP_INPUT_FORMAT_USER_DEF5:
653 case ATOMISP_INPUT_FORMAT_USER_DEF6:
654 case ATOMISP_INPUT_FORMAT_USER_DEF7:
655 case ATOMISP_INPUT_FORMAT_USER_DEF8:
657 * The frame format layout is shown below.
659 * Line 0: Pixel ... Pixel
660 * Line 1: Pixel ... Pixel
661 * Line 2: Pixel ... Pixel
662 * Line 3: Pixel ... Pixel
664 * Line (n-2): Pixel ... Pixel
665 * Line (n-1): Pixel ... Pixel
667 * In this frame format, the even-line is
668 * as wide as the odd-line.
670 rval = pixels_per_line;
680 static bool sh_css_translate_stream_cfg_to_input_system_input_port_id(
681 struct ia_css_stream_config *stream_cfg,
682 ia_css_isys_descr_t *isys_stream_descr)
687 switch (stream_cfg->mode) {
688 case IA_CSS_INPUT_MODE_TPG:
690 if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID0)
691 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT0_ID;
692 else if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID1)
693 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT1_ID;
694 else if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID2)
695 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT2_ID;
698 case IA_CSS_INPUT_MODE_PRBS:
700 if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID0)
701 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT0_ID;
702 else if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID1)
703 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT1_ID;
704 else if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID2)
705 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT2_ID;
708 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR:
710 if (stream_cfg->source.port.port == MIPI_PORT0_ID)
711 isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT0_ID;
712 else if (stream_cfg->source.port.port == MIPI_PORT1_ID)
713 isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT1_ID;
714 else if (stream_cfg->source.port.port == MIPI_PORT2_ID)
715 isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT2_ID;
726 static bool sh_css_translate_stream_cfg_to_input_system_input_port_type(
727 struct ia_css_stream_config *stream_cfg,
728 ia_css_isys_descr_t *isys_stream_descr)
733 switch (stream_cfg->mode) {
734 case IA_CSS_INPUT_MODE_TPG:
736 isys_stream_descr->mode = INPUT_SYSTEM_SOURCE_TYPE_TPG;
739 case IA_CSS_INPUT_MODE_PRBS:
741 isys_stream_descr->mode = INPUT_SYSTEM_SOURCE_TYPE_PRBS;
744 case IA_CSS_INPUT_MODE_SENSOR:
745 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR:
747 isys_stream_descr->mode = INPUT_SYSTEM_SOURCE_TYPE_SENSOR;
758 static bool sh_css_translate_stream_cfg_to_input_system_input_port_attr(
759 struct ia_css_stream_config *stream_cfg,
760 ia_css_isys_descr_t *isys_stream_descr,
766 switch (stream_cfg->mode) {
767 case IA_CSS_INPUT_MODE_TPG:
768 if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_RAMP)
769 isys_stream_descr->tpg_port_attr.mode = PIXELGEN_TPG_MODE_RAMP;
770 else if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_CHECKERBOARD)
771 isys_stream_descr->tpg_port_attr.mode = PIXELGEN_TPG_MODE_CHBO;
772 else if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_MONO)
773 isys_stream_descr->tpg_port_attr.mode = PIXELGEN_TPG_MODE_MONO;
779 * - Make "color_cfg" as part of "ia_css_tpg_config".
781 isys_stream_descr->tpg_port_attr.color_cfg.R1 = 51;
782 isys_stream_descr->tpg_port_attr.color_cfg.G1 = 102;
783 isys_stream_descr->tpg_port_attr.color_cfg.B1 = 255;
784 isys_stream_descr->tpg_port_attr.color_cfg.R2 = 0;
785 isys_stream_descr->tpg_port_attr.color_cfg.G2 = 100;
786 isys_stream_descr->tpg_port_attr.color_cfg.B2 = 160;
788 isys_stream_descr->tpg_port_attr.mask_cfg.h_mask =
789 stream_cfg->source.tpg.x_mask;
790 isys_stream_descr->tpg_port_attr.mask_cfg.v_mask =
791 stream_cfg->source.tpg.y_mask;
792 isys_stream_descr->tpg_port_attr.mask_cfg.hv_mask =
793 stream_cfg->source.tpg.xy_mask;
795 isys_stream_descr->tpg_port_attr.delta_cfg.h_delta =
796 stream_cfg->source.tpg.x_delta;
797 isys_stream_descr->tpg_port_attr.delta_cfg.v_delta =
798 stream_cfg->source.tpg.y_delta;
802 * - Make "sync_gen_cfg" as part of "ia_css_tpg_config".
804 isys_stream_descr->tpg_port_attr.sync_gen_cfg.hblank_cycles = 100;
805 isys_stream_descr->tpg_port_attr.sync_gen_cfg.vblank_cycles = 100;
806 isys_stream_descr->tpg_port_attr.sync_gen_cfg.pixels_per_clock =
807 stream_cfg->pixels_per_clock;
808 isys_stream_descr->tpg_port_attr.sync_gen_cfg.nr_of_frames = (uint32_t)~(0x0);
809 isys_stream_descr->tpg_port_attr.sync_gen_cfg.pixels_per_line =
810 stream_cfg->isys_config[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX].input_res.width;
811 isys_stream_descr->tpg_port_attr.sync_gen_cfg.lines_per_frame =
812 stream_cfg->isys_config[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX].input_res.height;
815 case IA_CSS_INPUT_MODE_PRBS:
817 isys_stream_descr->prbs_port_attr.seed0 = stream_cfg->source.prbs.seed;
818 isys_stream_descr->prbs_port_attr.seed1 = stream_cfg->source.prbs.seed1;
822 * - Make "sync_gen_cfg" as part of "ia_css_prbs_config".
824 isys_stream_descr->prbs_port_attr.sync_gen_cfg.hblank_cycles = 100;
825 isys_stream_descr->prbs_port_attr.sync_gen_cfg.vblank_cycles = 100;
826 isys_stream_descr->prbs_port_attr.sync_gen_cfg.pixels_per_clock =
827 stream_cfg->pixels_per_clock;
828 isys_stream_descr->prbs_port_attr.sync_gen_cfg.nr_of_frames = (uint32_t)~(0x0);
829 isys_stream_descr->prbs_port_attr.sync_gen_cfg.pixels_per_line =
830 stream_cfg->isys_config[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX].input_res.width;
831 isys_stream_descr->prbs_port_attr.sync_gen_cfg.lines_per_frame =
832 stream_cfg->isys_config[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX].input_res.height;
835 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR: {
837 unsigned int fmt_type;
839 err = ia_css_isys_convert_stream_format_to_mipi_format(
840 stream_cfg->isys_config[isys_stream_idx].format,
846 isys_stream_descr->csi_port_attr.active_lanes =
847 stream_cfg->source.port.num_lanes;
848 isys_stream_descr->csi_port_attr.fmt_type = fmt_type;
849 isys_stream_descr->csi_port_attr.ch_id = stream_cfg->channel_id;
851 isys_stream_descr->online = stream_cfg->online;
853 err |= ia_css_isys_convert_compressed_format(
854 &stream_cfg->source.port.compression,
860 isys_stream_descr->metadata.enable = false;
861 if (stream_cfg->metadata_config.resolution.height > 0) {
862 err = ia_css_isys_convert_stream_format_to_mipi_format(
863 stream_cfg->metadata_config.data_type,
868 isys_stream_descr->metadata.fmt_type = fmt_type;
869 isys_stream_descr->metadata.bits_per_pixel =
870 ia_css_util_input_format_bpp(stream_cfg->metadata_config.data_type, true);
871 isys_stream_descr->metadata.pixels_per_line =
872 stream_cfg->metadata_config.resolution.width;
873 isys_stream_descr->metadata.lines_per_frame =
874 stream_cfg->metadata_config.resolution.height;
877 * For new input system, number of str2mmio requests must be even.
878 * So we round up number of metadata lines to be even.
880 if (isys_stream_descr->metadata.lines_per_frame > 0)
881 isys_stream_descr->metadata.lines_per_frame +=
882 (isys_stream_descr->metadata.lines_per_frame & 1);
884 isys_stream_descr->metadata.align_req_in_bytes =
885 ia_css_csi2_calculate_input_system_alignment(
886 stream_cfg->metadata_config.data_type);
887 isys_stream_descr->metadata.enable = true;
900 static bool sh_css_translate_stream_cfg_to_input_system_input_port_resolution(
901 struct ia_css_stream_config *stream_cfg,
902 ia_css_isys_descr_t *isys_stream_descr,
905 unsigned int bits_per_subpixel;
906 unsigned int max_subpixels_per_line;
907 unsigned int lines_per_frame;
908 unsigned int align_req_in_bytes;
909 enum atomisp_input_format fmt_type;
911 fmt_type = stream_cfg->isys_config[isys_stream_idx].format;
912 if ((stream_cfg->mode == IA_CSS_INPUT_MODE_SENSOR ||
913 stream_cfg->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) &&
914 stream_cfg->source.port.compression.type != IA_CSS_CSI2_COMPRESSION_TYPE_NONE) {
915 if (stream_cfg->source.port.compression.uncompressed_bits_per_pixel ==
916 UNCOMPRESSED_BITS_PER_PIXEL_10)
917 fmt_type = ATOMISP_INPUT_FORMAT_RAW_10;
918 else if (stream_cfg->source.port.compression.uncompressed_bits_per_pixel ==
919 UNCOMPRESSED_BITS_PER_PIXEL_12)
920 fmt_type = ATOMISP_INPUT_FORMAT_RAW_12;
926 sh_css_stream_format_2_bits_per_subpixel(fmt_type);
927 if (bits_per_subpixel == 0)
930 max_subpixels_per_line =
931 csi2_protocol_calculate_max_subpixels_per_line(fmt_type,
932 stream_cfg->isys_config[isys_stream_idx].input_res.width);
933 if (max_subpixels_per_line == 0)
936 lines_per_frame = stream_cfg->isys_config[isys_stream_idx].input_res.height;
937 if (lines_per_frame == 0)
940 align_req_in_bytes = ia_css_csi2_calculate_input_system_alignment(fmt_type);
942 /* HW needs subpixel info for their settings */
943 isys_stream_descr->input_port_resolution.bits_per_pixel = bits_per_subpixel;
944 isys_stream_descr->input_port_resolution.pixels_per_line =
945 max_subpixels_per_line;
946 isys_stream_descr->input_port_resolution.lines_per_frame = lines_per_frame;
947 isys_stream_descr->input_port_resolution.align_req_in_bytes =
953 static bool sh_css_translate_stream_cfg_to_isys_stream_descr(
954 struct ia_css_stream_config *stream_cfg,
956 ia_css_isys_descr_t *isys_stream_descr,
961 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
962 "sh_css_translate_stream_cfg_to_isys_stream_descr() enter:\n");
963 rc = sh_css_translate_stream_cfg_to_input_system_input_port_id(stream_cfg,
965 rc &= sh_css_translate_stream_cfg_to_input_system_input_port_type(stream_cfg,
967 rc &= sh_css_translate_stream_cfg_to_input_system_input_port_attr(stream_cfg,
968 isys_stream_descr, isys_stream_idx);
969 rc &= sh_css_translate_stream_cfg_to_input_system_input_port_resolution(
970 stream_cfg, isys_stream_descr, isys_stream_idx);
972 isys_stream_descr->raw_packed = stream_cfg->pack_raw_pixels;
973 isys_stream_descr->linked_isys_stream_id = (int8_t)
974 stream_cfg->isys_config[isys_stream_idx].linked_isys_stream_id;
977 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
978 "sh_css_translate_stream_cfg_to_isys_stream_descr() leave:\n");
983 static bool sh_css_translate_binary_info_to_input_system_output_port_attr(
984 struct ia_css_binary *binary,
985 ia_css_isys_descr_t *isys_stream_descr)
990 isys_stream_descr->output_port_attr.left_padding = binary->left_padding;
991 isys_stream_descr->output_port_attr.max_isp_input_width =
992 binary->info->sp.input.max_width;
998 sh_css_config_input_network(struct ia_css_stream *stream)
1001 ia_css_isys_descr_t isys_stream_descr;
1002 unsigned int sp_thread_id;
1003 struct sh_css_sp_pipeline_terminal *sp_pipeline_input_terminal;
1004 struct ia_css_pipe *pipe = NULL;
1005 struct ia_css_binary *binary = NULL;
1008 bool early_polling = false;
1011 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
1012 "sh_css_config_input_network() enter 0x%p:\n", stream);
1014 if (stream->config.continuous) {
1015 if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE)
1016 pipe = stream->last_pipe;
1017 else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_YUVPP)
1018 pipe = stream->last_pipe;
1019 else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW)
1020 pipe = stream->last_pipe->pipe_settings.preview.copy_pipe;
1021 else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO)
1022 pipe = stream->last_pipe->pipe_settings.video.copy_pipe;
1024 pipe = stream->last_pipe;
1030 if (pipe->pipeline.stages)
1031 if (pipe->pipeline.stages->binary)
1032 binary = pipe->pipeline.stages->binary;
1036 * this was being done in ifmtr in 2400.
1037 * online and cont bypass the init_in_frameinfo_memory_defaults
1038 * so need to do it here
1040 ia_css_get_crop_offsets(pipe, &binary->in_frame_info);
1043 /* get the SP thread id */
1044 rc = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &sp_thread_id);
1047 /* get the target input terminal */
1048 sp_pipeline_input_terminal = &sh_css_sp_group.pipe_io[sp_thread_id].input;
1050 for (i = 0; i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++) {
1051 /* initialization */
1052 memset((void *)(&isys_stream_descr), 0, sizeof(ia_css_isys_descr_t));
1053 sp_pipeline_input_terminal->context.virtual_input_system_stream[i].valid = 0;
1054 sp_pipeline_input_terminal->ctrl.virtual_input_system_stream_cfg[i].valid = 0;
1056 if (!stream->config.isys_config[i].valid)
1059 /* translate the stream configuration to the Input System (2401) configuration */
1060 rc = sh_css_translate_stream_cfg_to_isys_stream_descr(
1063 &(isys_stream_descr), i);
1065 if (stream->config.online) {
1066 rc &= sh_css_translate_binary_info_to_input_system_output_port_attr(
1068 &(isys_stream_descr));
1074 isys_stream_id = ia_css_isys_generate_stream_id(sp_thread_id, i);
1076 /* create the virtual Input System (2401) */
1077 rc = ia_css_isys_stream_create(
1078 &(isys_stream_descr),
1079 &sp_pipeline_input_terminal->context.virtual_input_system_stream[i],
1084 /* calculate the configuration of the virtual Input System (2401) */
1085 rc = ia_css_isys_stream_calculate_cfg(
1086 &sp_pipeline_input_terminal->context.virtual_input_system_stream[i],
1087 &(isys_stream_descr),
1088 &sp_pipeline_input_terminal->ctrl.virtual_input_system_stream_cfg[i]);
1090 ia_css_isys_stream_destroy(
1091 &sp_pipeline_input_terminal->context.virtual_input_system_stream[i]);
1096 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
1097 "sh_css_config_input_network() leave:\n");
1102 static inline struct ia_css_pipe *stream_get_last_pipe(
1103 struct ia_css_stream *stream)
1105 struct ia_css_pipe *last_pipe = NULL;
1108 last_pipe = stream->last_pipe;
1113 static inline struct ia_css_pipe *stream_get_copy_pipe(
1114 struct ia_css_stream *stream)
1116 struct ia_css_pipe *copy_pipe = NULL;
1117 struct ia_css_pipe *last_pipe = NULL;
1118 enum ia_css_pipe_id pipe_id;
1120 last_pipe = stream_get_last_pipe(stream);
1124 (stream->config.continuous)) {
1125 pipe_id = last_pipe->mode;
1127 case IA_CSS_PIPE_ID_PREVIEW:
1128 copy_pipe = last_pipe->pipe_settings.preview.copy_pipe;
1130 case IA_CSS_PIPE_ID_VIDEO:
1131 copy_pipe = last_pipe->pipe_settings.video.copy_pipe;
1142 static inline struct ia_css_pipe *stream_get_target_pipe(
1143 struct ia_css_stream *stream)
1145 struct ia_css_pipe *target_pipe;
1147 /* get the pipe that consumes the stream */
1148 if (stream->config.continuous)
1149 target_pipe = stream_get_copy_pipe(stream);
1151 target_pipe = stream_get_last_pipe(stream);
1156 static int stream_csi_rx_helper(
1157 struct ia_css_stream *stream,
1158 int (*func)(enum mipi_port_id, uint32_t))
1160 int retval = -EINVAL;
1161 u32 sp_thread_id, stream_id;
1163 struct ia_css_pipe *target_pipe = NULL;
1165 if ((!stream) || (stream->config.mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR))
1168 target_pipe = stream_get_target_pipe(stream);
1173 rc = ia_css_pipeline_get_sp_thread_id(
1174 ia_css_pipe_get_pipe_num(target_pipe),
1180 /* (un)register all valid "virtual isys streams" within the ia_css_stream */
1183 if (stream->config.isys_config[stream_id].valid) {
1184 u32 isys_stream_id = ia_css_isys_generate_stream_id(sp_thread_id, stream_id);
1186 retval = func(stream->config.source.port.port, isys_stream_id);
1189 } while ((retval == 0) &&
1190 (stream_id < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH));
1196 static inline int stream_register_with_csi_rx(
1197 struct ia_css_stream *stream)
1199 return stream_csi_rx_helper(stream, ia_css_isys_csi_rx_register_stream);
1202 static inline int stream_unregister_with_csi_rx(
1203 struct ia_css_stream *stream)
1205 return stream_csi_rx_helper(stream, ia_css_isys_csi_rx_unregister_stream);
1211 start_binary(struct ia_css_pipe *pipe,
1212 struct ia_css_binary *binary)
1215 /* Acceleration uses firmware, the binary thus can be NULL */
1218 sh_css_metrics_start_binary(&binary->metrics);
1221 #if !defined(ISP2401)
1222 if (pipe->stream->reconfigure_css_rx) {
1223 ia_css_isys_rx_configure(&pipe->stream->csi_rx_config,
1224 pipe->stream->config.mode);
1225 pipe->stream->reconfigure_css_rx = false;
1230 /* start the copy function on the SP */
1232 start_copy_on_sp(struct ia_css_pipe *pipe,
1233 struct ia_css_frame *out_frame)
1237 if ((!pipe) || (!pipe->stream))
1240 #if !defined(ISP2401)
1241 if (pipe->stream->reconfigure_css_rx)
1242 ia_css_isys_rx_disable();
1245 if (pipe->stream->config.input_config.format != ATOMISP_INPUT_FORMAT_BINARY_8)
1247 sh_css_sp_start_binary_copy(ia_css_pipe_get_pipe_num(pipe), out_frame, pipe->stream->config.pixels_per_clock == 2);
1249 #if !defined(ISP2401)
1250 if (pipe->stream->reconfigure_css_rx) {
1251 ia_css_isys_rx_configure(&pipe->stream->csi_rx_config,
1252 pipe->stream->config.mode);
1253 pipe->stream->reconfigure_css_rx = false;
1260 void sh_css_binary_args_reset(struct sh_css_binary_args *args)
1264 for (i = 0; i < NUM_VIDEO_TNR_FRAMES; i++)
1265 args->tnr_frames[i] = NULL;
1266 for (i = 0; i < MAX_NUM_VIDEO_DELAY_FRAMES; i++)
1267 args->delay_frames[i] = NULL;
1268 args->in_frame = NULL;
1269 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
1270 args->out_frame[i] = NULL;
1271 args->out_vf_frame = NULL;
1272 args->copy_vf = false;
1273 args->copy_output = true;
1274 args->vf_downscale_log2 = 0;
1277 static void start_pipe(
1278 struct ia_css_pipe *me,
1279 enum sh_css_pipe_config_override copy_ovrd,
1280 enum ia_css_input_mode input_mode)
1282 IA_CSS_ENTER_PRIVATE("me = %p, copy_ovrd = %d, input_mode = %d",
1283 me, copy_ovrd, input_mode);
1285 assert(me); /* all callers are in this file and call with non null argument */
1287 sh_css_sp_init_pipeline(&me->pipeline,
1289 (uint8_t)ia_css_pipe_get_pipe_num(me),
1290 me->config.default_capture_config.enable_xnr != 0,
1291 me->stream->config.pixels_per_clock == 2,
1292 me->stream->config.continuous,
1294 me->required_bds_factor,
1297 &me->stream->config.metadata_config,
1298 &me->stream->info.metadata_info
1299 , (input_mode == IA_CSS_INPUT_MODE_MEMORY) ?
1300 (enum mipi_port_id)0 :
1301 me->stream->config.source.port.port);
1303 if (me->config.mode != IA_CSS_PIPE_MODE_COPY) {
1304 struct ia_css_pipeline_stage *stage;
1306 stage = me->pipeline.stages;
1308 me->pipeline.current_stage = stage;
1309 start_binary(me, stage->binary);
1312 IA_CSS_LEAVE_PRIVATE("void");
1316 sh_css_invalidate_shading_tables(struct ia_css_stream *stream)
1322 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1323 "sh_css_invalidate_shading_tables() enter:\n");
1325 for (i = 0; i < stream->num_pipes; i++) {
1326 assert(stream->pipes[i]);
1327 sh_css_pipe_free_shading_table(stream->pipes[i]);
1330 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1331 "sh_css_invalidate_shading_tables() leave: return_void\n");
1335 enable_interrupts(enum ia_css_irq_type irq_type)
1338 enum mipi_port_id port;
1340 bool enable_pulse = irq_type != IA_CSS_IRQ_TYPE_EDGE;
1342 IA_CSS_ENTER_PRIVATE("");
1343 /* Enable IRQ on the SP which signals that SP goes to idle
1344 * (aka ready state) */
1345 cnd_sp_irq_enable(SP0_ID, true);
1346 /* Set the IRQ device 0 to either level or pulse */
1347 irq_enable_pulse(IRQ0_ID, enable_pulse);
1349 cnd_virq_enable_channel(virq_sp, true);
1351 /* Enable SW interrupt 0, this is used to signal ISYS events */
1352 cnd_virq_enable_channel(
1353 (enum virq_id)(IRQ_SW_CHANNEL0_ID + IRQ_SW_CHANNEL_OFFSET),
1355 /* Enable SW interrupt 1, this is used to signal PSYS events */
1356 cnd_virq_enable_channel(
1357 (enum virq_id)(IRQ_SW_CHANNEL1_ID + IRQ_SW_CHANNEL_OFFSET),
1361 for (port = 0; port < N_MIPI_PORT_ID; port++)
1362 ia_css_isys_rx_enable_all_interrupts(port);
1365 IA_CSS_LEAVE_PRIVATE("");
1368 static bool sh_css_setup_spctrl_config(const struct ia_css_fw_info *fw,
1369 const char *program,
1370 ia_css_spctrl_cfg *spctrl_cfg)
1372 if ((!fw) || (!spctrl_cfg))
1374 spctrl_cfg->sp_entry = 0;
1375 spctrl_cfg->program_name = (char *)(program);
1377 spctrl_cfg->ddr_data_offset = fw->blob.data_source;
1378 spctrl_cfg->dmem_data_addr = fw->blob.data_target;
1379 spctrl_cfg->dmem_bss_addr = fw->blob.bss_target;
1380 spctrl_cfg->data_size = fw->blob.data_size;
1381 spctrl_cfg->bss_size = fw->blob.bss_size;
1383 spctrl_cfg->spctrl_config_dmem_addr = fw->info.sp.init_dmem_data;
1384 spctrl_cfg->spctrl_state_dmem_addr = fw->info.sp.sw_state;
1386 spctrl_cfg->code_size = fw->blob.size;
1387 spctrl_cfg->code = fw->blob.code;
1388 spctrl_cfg->sp_entry = fw->info.sp.sp_entry; /* entry function ptr on SP */
1394 ia_css_unload_firmware(void)
1396 if (sh_css_num_binaries) {
1397 /* we have already loaded before so get rid of the old stuff */
1398 ia_css_binary_uninit();
1399 sh_css_unload_firmware();
1401 fw_explicitly_loaded = false;
1405 ia_css_reset_defaults(struct sh_css *css)
1407 struct sh_css default_css;
1409 /* Reset everything to zero */
1410 memset(&default_css, 0, sizeof(default_css));
1412 /* Initialize the non zero values */
1413 default_css.check_system_idle = true;
1414 default_css.num_cont_raw_frames = NUM_CONTINUOUS_FRAMES;
1417 * All should be 0: but memset does it already.
1418 * default_css.num_mipi_frames[N_CSI_PORTS] = 0;
1421 default_css.irq_type = IA_CSS_IRQ_TYPE_EDGE;
1423 /* Set the defaults to the output */
1428 ia_css_load_firmware(struct device *dev, const struct ia_css_env *env,
1429 const struct ia_css_fw *fw)
1438 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_load_firmware() enter\n");
1440 /* make sure we initialize my_css */
1441 if (my_css.flush != env->cpu_mem_env.flush) {
1442 ia_css_reset_defaults(&my_css);
1443 my_css.flush = env->cpu_mem_env.flush;
1446 ia_css_unload_firmware(); /* in case we are called twice */
1447 err = sh_css_load_firmware(dev, fw->data, fw->bytes);
1449 err = ia_css_binary_init_infos();
1451 fw_explicitly_loaded = true;
1454 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_load_firmware() leave\n");
1459 ia_css_init(struct device *dev, const struct ia_css_env *env,
1460 const struct ia_css_fw *fw,
1462 enum ia_css_irq_type irq_type)
1465 ia_css_spctrl_cfg spctrl_cfg;
1467 void (*flush_func)(struct ia_css_acc_fw *fw);
1468 hrt_data select, enable;
1471 * The C99 standard does not specify the exact object representation of structs;
1472 * the representation is compiler dependent.
1474 * The structs that are communicated between host and SP/ISP should have the
1475 * exact same object representation. The compiler that is used to compile the
1476 * firmware is hivecc.
1478 * To check if a different compiler, used to compile a host application, uses
1479 * another object representation, macros are defined specifying the size of
1480 * the structs as expected by the firmware.
1482 * A host application shall verify that a sizeof( ) of the struct is equal to
1483 * the SIZE_OF_XXX macro of the corresponding struct. If they are not
1484 * equal, functionality will break.
1487 /* Check struct sh_css_ddr_address_map */
1488 COMPILATION_ERROR_IF(sizeof(struct sh_css_ddr_address_map) != SIZE_OF_SH_CSS_DDR_ADDRESS_MAP_STRUCT);
1489 /* Check struct host_sp_queues */
1490 COMPILATION_ERROR_IF(sizeof(struct host_sp_queues) != SIZE_OF_HOST_SP_QUEUES_STRUCT);
1491 COMPILATION_ERROR_IF(sizeof(struct ia_css_circbuf_desc_s) != SIZE_OF_IA_CSS_CIRCBUF_DESC_S_STRUCT);
1492 COMPILATION_ERROR_IF(sizeof(struct ia_css_circbuf_elem_s) != SIZE_OF_IA_CSS_CIRCBUF_ELEM_S_STRUCT);
1494 /* Check struct host_sp_communication */
1495 COMPILATION_ERROR_IF(sizeof(struct host_sp_communication) != SIZE_OF_HOST_SP_COMMUNICATION_STRUCT);
1496 COMPILATION_ERROR_IF(sizeof(struct sh_css_event_irq_mask) != SIZE_OF_SH_CSS_EVENT_IRQ_MASK_STRUCT);
1498 /* Check struct sh_css_hmm_buffer */
1499 COMPILATION_ERROR_IF(sizeof(struct sh_css_hmm_buffer) != SIZE_OF_SH_CSS_HMM_BUFFER_STRUCT);
1500 COMPILATION_ERROR_IF(sizeof(struct ia_css_isp_3a_statistics) != SIZE_OF_IA_CSS_ISP_3A_STATISTICS_STRUCT);
1501 COMPILATION_ERROR_IF(sizeof(struct ia_css_isp_dvs_statistics) != SIZE_OF_IA_CSS_ISP_DVS_STATISTICS_STRUCT);
1502 COMPILATION_ERROR_IF(sizeof(struct ia_css_metadata) != SIZE_OF_IA_CSS_METADATA_STRUCT);
1504 /* Check struct ia_css_init_dmem_cfg */
1505 COMPILATION_ERROR_IF(sizeof(struct ia_css_sp_init_dmem_cfg) != SIZE_OF_IA_CSS_SP_INIT_DMEM_CFG_STRUCT);
1507 if (!fw && !fw_explicitly_loaded)
1512 sh_css_printf = env->print_env.debug_print;
1514 IA_CSS_ENTER("void");
1516 flush_func = env->cpu_mem_env.flush;
1519 ia_css_pipeline_init();
1520 ia_css_queue_map_init();
1522 ia_css_device_access_init(&env->hw_access_env);
1524 select = gpio_reg_load(GPIO0_ID, _gpio_block_reg_do_select)
1525 & (~GPIO_FLASH_PIN_MASK);
1526 enable = gpio_reg_load(GPIO0_ID, _gpio_block_reg_do_e)
1527 | GPIO_FLASH_PIN_MASK;
1528 sh_css_mmu_set_page_table_base_index(mmu_l1_base);
1530 my_css_save.mmu_base = mmu_l1_base;
1532 ia_css_reset_defaults(&my_css);
1534 my_css_save.driver_env = *env;
1535 my_css.flush = flush_func;
1537 err = ia_css_rmgr_init();
1539 IA_CSS_LEAVE_ERR(err);
1543 IA_CSS_LOG("init: %d", my_css_save_initialized);
1545 if (!my_css_save_initialized) {
1546 my_css_save_initialized = true;
1547 my_css_save.mode = sh_css_mode_working;
1548 memset(my_css_save.stream_seeds, 0,
1549 sizeof(struct sh_css_stream_seed) * MAX_ACTIVE_STREAMS);
1550 IA_CSS_LOG("init: %d mode=%d", my_css_save_initialized, my_css_save.mode);
1557 * In case this has been programmed already, update internal
1558 * data structure ...
1561 my_css.page_table_base_index = mmu_get_page_table_base_index(MMU0_ID);
1564 my_css.irq_type = irq_type;
1566 my_css_save.irq_type = irq_type;
1568 enable_interrupts(my_css.irq_type);
1570 /* configure GPIO to output mode */
1571 gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_select, select);
1572 gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_e, enable);
1573 gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_0, 0);
1575 err = ia_css_refcount_init(REFCOUNT_SIZE);
1577 IA_CSS_LEAVE_ERR(err);
1580 err = sh_css_params_init();
1582 IA_CSS_LEAVE_ERR(err);
1586 ia_css_unload_firmware(); /* in case we already had firmware loaded */
1587 err = sh_css_load_firmware(dev, fw->data, fw->bytes);
1589 IA_CSS_LEAVE_ERR(err);
1592 err = ia_css_binary_init_infos();
1594 IA_CSS_LEAVE_ERR(err);
1597 fw_explicitly_loaded = false;
1599 my_css_save.loaded_fw = (struct ia_css_fw *)fw;
1601 if (!sh_css_setup_spctrl_config(&sh_css_sp_fw, SP_PROG_NAME, &spctrl_cfg))
1604 err = ia_css_spctrl_load_fw(SP0_ID, &spctrl_cfg);
1606 IA_CSS_LEAVE_ERR(err);
1610 if (!sh_css_hrt_system_is_idle()) {
1611 IA_CSS_LEAVE_ERR(-EBUSY);
1615 * can be called here, queuing works, but:
1616 * - when sp is started later, it will wipe queued items
1617 * so for now we leave it for later and make sure
1618 * updates are not called to frequently.
1619 * sh_css_init_buffer_queues();
1622 #if defined(ISP2401)
1623 gp_device_reg_store(GP_DEVICE0_ID, _REG_GP_SWITCH_ISYS2401_ADDR, 1);
1628 dma_set_max_burst_size(DMA0_ID, HIVE_DMA_BUS_DDR_CONN,
1629 ISP2400_DMA_MAX_BURST_LENGTH);
1631 dma_set_max_burst_size(DMA0_ID, HIVE_DMA_BUS_DDR_CONN,
1632 ISP2401_DMA_MAX_BURST_LENGTH);
1634 if (ia_css_isys_init() != INPUT_SYSTEM_ERR_NO_ERROR)
1637 sh_css_params_map_and_store_default_gdc_lut();
1639 IA_CSS_LEAVE_ERR(err);
1644 ia_css_enable_isys_event_queue(bool enable)
1646 if (sh_css_sp_is_running())
1648 sh_css_sp_enable_isys_event_queue(enable);
1652 /* For Acceleration API: Flush FW (shared buffer pointer) arguments */
1654 sh_css_flush(struct ia_css_acc_fw *fw)
1656 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_flush() enter:\n");
1657 if ((fw) && (my_css.flush))
1662 * Mapping sp threads. Currently, this is done when a stream is created and
1663 * pipelines are ready to be converted to sp pipelines. Be careful if you are
1664 * doing it from stream_create since we could run out of sp threads due to
1665 * allocation on inactive pipelines.
1668 map_sp_threads(struct ia_css_stream *stream, bool map)
1670 struct ia_css_pipe *main_pipe = NULL;
1671 struct ia_css_pipe *copy_pipe = NULL;
1672 struct ia_css_pipe *capture_pipe = NULL;
1673 struct ia_css_pipe *acc_pipe = NULL;
1675 enum ia_css_pipe_id pipe_id;
1677 IA_CSS_ENTER_PRIVATE("stream = %p, map = %s",
1678 stream, map ? "true" : "false");
1681 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
1685 main_pipe = stream->last_pipe;
1686 pipe_id = main_pipe->mode;
1688 ia_css_pipeline_map(main_pipe->pipe_num, map);
1691 case IA_CSS_PIPE_ID_PREVIEW:
1692 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
1693 capture_pipe = main_pipe->pipe_settings.preview.capture_pipe;
1694 acc_pipe = main_pipe->pipe_settings.preview.acc_pipe;
1697 case IA_CSS_PIPE_ID_VIDEO:
1698 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
1699 capture_pipe = main_pipe->pipe_settings.video.capture_pipe;
1702 case IA_CSS_PIPE_ID_CAPTURE:
1703 case IA_CSS_PIPE_ID_ACC:
1709 ia_css_pipeline_map(acc_pipe->pipe_num, map);
1712 ia_css_pipeline_map(capture_pipe->pipe_num, map);
1714 /* Firmware expects copy pipe to be the last pipe mapped. (if needed) */
1716 ia_css_pipeline_map(copy_pipe->pipe_num, map);
1718 /* DH regular multi pipe - not continuous mode: map the next pipes too */
1719 if (!stream->config.continuous) {
1722 for (i = 1; i < stream->num_pipes; i++)
1723 ia_css_pipeline_map(stream->pipes[i]->pipe_num, map);
1726 IA_CSS_LEAVE_ERR_PRIVATE(err);
1731 * creates a host pipeline skeleton for all pipes in a stream. Called during
1735 create_host_pipeline_structure(struct ia_css_stream *stream)
1737 struct ia_css_pipe *copy_pipe = NULL, *capture_pipe = NULL;
1738 struct ia_css_pipe *acc_pipe = NULL;
1739 enum ia_css_pipe_id pipe_id;
1740 struct ia_css_pipe *main_pipe = NULL;
1742 unsigned int copy_pipe_delay = 0,
1743 capture_pipe_delay = 0;
1745 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
1748 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
1752 main_pipe = stream->last_pipe;
1754 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
1758 pipe_id = main_pipe->mode;
1761 case IA_CSS_PIPE_ID_PREVIEW:
1762 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
1763 copy_pipe_delay = main_pipe->dvs_frame_delay;
1764 capture_pipe = main_pipe->pipe_settings.preview.capture_pipe;
1765 capture_pipe_delay = IA_CSS_FRAME_DELAY_0;
1766 acc_pipe = main_pipe->pipe_settings.preview.acc_pipe;
1767 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode,
1768 main_pipe->pipe_num, main_pipe->dvs_frame_delay);
1771 case IA_CSS_PIPE_ID_VIDEO:
1772 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
1773 copy_pipe_delay = main_pipe->dvs_frame_delay;
1774 capture_pipe = main_pipe->pipe_settings.video.capture_pipe;
1775 capture_pipe_delay = IA_CSS_FRAME_DELAY_0;
1776 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode,
1777 main_pipe->pipe_num, main_pipe->dvs_frame_delay);
1780 case IA_CSS_PIPE_ID_CAPTURE:
1781 capture_pipe = main_pipe;
1782 capture_pipe_delay = main_pipe->dvs_frame_delay;
1785 case IA_CSS_PIPE_ID_YUVPP:
1786 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode,
1787 main_pipe->pipe_num, main_pipe->dvs_frame_delay);
1790 case IA_CSS_PIPE_ID_ACC:
1791 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode,
1792 main_pipe->pipe_num, main_pipe->dvs_frame_delay);
1799 if (!(err) && copy_pipe)
1800 err = ia_css_pipeline_create(©_pipe->pipeline,
1802 copy_pipe->pipe_num,
1805 if (!(err) && capture_pipe)
1806 err = ia_css_pipeline_create(&capture_pipe->pipeline,
1808 capture_pipe->pipe_num,
1809 capture_pipe_delay);
1811 if (!(err) && acc_pipe)
1812 err = ia_css_pipeline_create(&acc_pipe->pipeline, acc_pipe->mode,
1813 acc_pipe->pipe_num, main_pipe->dvs_frame_delay);
1815 /* DH regular multi pipe - not continuous mode: create the next pipelines too */
1816 if (!stream->config.continuous) {
1819 for (i = 1; i < stream->num_pipes && 0 == err; i++) {
1820 main_pipe = stream->pipes[i];
1821 err = ia_css_pipeline_create(&main_pipe->pipeline,
1823 main_pipe->pipe_num,
1824 main_pipe->dvs_frame_delay);
1828 IA_CSS_LEAVE_ERR_PRIVATE(err);
1833 * creates a host pipeline for all pipes in a stream. Called during
1837 create_host_pipeline(struct ia_css_stream *stream)
1839 struct ia_css_pipe *copy_pipe = NULL, *capture_pipe = NULL;
1840 struct ia_css_pipe *acc_pipe = NULL;
1841 enum ia_css_pipe_id pipe_id;
1842 struct ia_css_pipe *main_pipe = NULL;
1844 unsigned int max_input_width = 0;
1846 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
1848 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
1852 main_pipe = stream->last_pipe;
1853 pipe_id = main_pipe->mode;
1856 * No continuous frame allocation for capture pipe. It uses the
1857 * "main" pipe's frames.
1859 if ((pipe_id == IA_CSS_PIPE_ID_PREVIEW) ||
1860 (pipe_id == IA_CSS_PIPE_ID_VIDEO)) {
1863 * pipe_id == IA_CSS_PIPE_ID_PREVIEW &&
1864 * stream->config.mode != IA_CSS_INPUT_MODE_MEMORY:
1866 * The original condition pipe_id == IA_CSS_PIPE_ID_PREVIEW is
1867 * too strong. E.g. in SkyCam (with memory based input frames)
1868 * there is no continuous mode and thus no need for allocated
1869 * continuous frames.
1870 * This is not only for SkyCam but for all preview cases that
1871 * use DDR based input frames. For this reason the
1872 * stream->config.mode != IA_CSS_INPUT_MODE_MEMORY has beed
1875 if (stream->config.continuous ||
1876 (pipe_id == IA_CSS_PIPE_ID_PREVIEW &&
1877 stream->config.mode != IA_CSS_INPUT_MODE_MEMORY)) {
1878 err = alloc_continuous_frames(main_pipe, true);
1884 #if !defined(ISP2401)
1885 /* old isys: need to allocate_mipi_frames() even in IA_CSS_PIPE_MODE_COPY */
1886 if (pipe_id != IA_CSS_PIPE_ID_ACC) {
1887 err = allocate_mipi_frames(main_pipe, &stream->info);
1891 #elif defined(ISP2401)
1892 if ((pipe_id != IA_CSS_PIPE_ID_ACC) &&
1893 (main_pipe->config.mode != IA_CSS_PIPE_MODE_COPY)) {
1894 err = allocate_mipi_frames(main_pipe, &stream->info);
1901 case IA_CSS_PIPE_ID_PREVIEW:
1902 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
1903 capture_pipe = main_pipe->pipe_settings.preview.capture_pipe;
1904 acc_pipe = main_pipe->pipe_settings.preview.acc_pipe;
1906 main_pipe->pipe_settings.preview.preview_binary.info->sp.input.max_width;
1908 err = create_host_preview_pipeline(main_pipe);
1914 case IA_CSS_PIPE_ID_VIDEO:
1915 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
1916 capture_pipe = main_pipe->pipe_settings.video.capture_pipe;
1918 main_pipe->pipe_settings.video.video_binary.info->sp.input.max_width;
1920 err = create_host_video_pipeline(main_pipe);
1926 case IA_CSS_PIPE_ID_CAPTURE:
1927 capture_pipe = main_pipe;
1931 case IA_CSS_PIPE_ID_YUVPP:
1932 err = create_host_yuvpp_pipeline(main_pipe);
1938 case IA_CSS_PIPE_ID_ACC:
1939 err = create_host_acc_pipeline(main_pipe);
1951 err = create_host_copy_pipeline(copy_pipe, max_input_width,
1952 main_pipe->continuous_frames[0]);
1958 err = create_host_capture_pipeline(capture_pipe);
1964 err = create_host_acc_pipeline(acc_pipe);
1969 /* DH regular multi pipe - not continuous mode: create the next pipelines too */
1970 if (!stream->config.continuous) {
1973 for (i = 1; i < stream->num_pipes && 0 == err; i++) {
1974 switch (stream->pipes[i]->mode) {
1975 case IA_CSS_PIPE_ID_PREVIEW:
1976 err = create_host_preview_pipeline(stream->pipes[i]);
1978 case IA_CSS_PIPE_ID_VIDEO:
1979 err = create_host_video_pipeline(stream->pipes[i]);
1981 case IA_CSS_PIPE_ID_CAPTURE:
1982 err = create_host_capture_pipeline(stream->pipes[i]);
1984 case IA_CSS_PIPE_ID_YUVPP:
1985 err = create_host_yuvpp_pipeline(stream->pipes[i]);
1987 case IA_CSS_PIPE_ID_ACC:
1988 err = create_host_acc_pipeline(stream->pipes[i]);
1999 IA_CSS_LEAVE_ERR_PRIVATE(err);
2003 static const struct ia_css_pipe default_pipe = IA_CSS_DEFAULT_PIPE;
2004 static const struct ia_css_preview_settings preview = IA_CSS_DEFAULT_PREVIEW_SETTINGS;
2005 static const struct ia_css_capture_settings capture = IA_CSS_DEFAULT_CAPTURE_SETTINGS;
2006 static const struct ia_css_video_settings video = IA_CSS_DEFAULT_VIDEO_SETTINGS;
2007 static const struct ia_css_yuvpp_settings yuvpp = IA_CSS_DEFAULT_YUVPP_SETTINGS;
2010 init_pipe_defaults(enum ia_css_pipe_mode mode,
2011 struct ia_css_pipe *pipe,
2015 IA_CSS_ERROR("NULL pipe parameter");
2019 /* Initialize pipe to pre-defined defaults */
2020 memcpy(pipe, &default_pipe, sizeof(default_pipe));
2022 /* TODO: JB should not be needed, but temporary backward reference */
2024 case IA_CSS_PIPE_MODE_PREVIEW:
2025 pipe->mode = IA_CSS_PIPE_ID_PREVIEW;
2026 memcpy(&pipe->pipe_settings.preview, &preview, sizeof(preview));
2028 case IA_CSS_PIPE_MODE_CAPTURE:
2030 pipe->mode = IA_CSS_PIPE_ID_COPY;
2032 pipe->mode = IA_CSS_PIPE_ID_CAPTURE;
2034 memcpy(&pipe->pipe_settings.capture, &capture, sizeof(capture));
2036 case IA_CSS_PIPE_MODE_VIDEO:
2037 pipe->mode = IA_CSS_PIPE_ID_VIDEO;
2038 memcpy(&pipe->pipe_settings.video, &video, sizeof(video));
2040 case IA_CSS_PIPE_MODE_ACC:
2041 pipe->mode = IA_CSS_PIPE_ID_ACC;
2043 case IA_CSS_PIPE_MODE_COPY:
2044 pipe->mode = IA_CSS_PIPE_ID_CAPTURE;
2046 case IA_CSS_PIPE_MODE_YUVPP:
2047 pipe->mode = IA_CSS_PIPE_ID_YUVPP;
2048 memcpy(&pipe->pipe_settings.yuvpp, &yuvpp, sizeof(yuvpp));
2058 pipe_global_init(void)
2062 my_css.pipe_counter = 0;
2063 for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++)
2064 my_css.all_pipes[i] = NULL;
2068 pipe_generate_pipe_num(const struct ia_css_pipe *pipe,
2069 unsigned int *pipe_number)
2071 const u8 INVALID_PIPE_NUM = (uint8_t)~(0);
2072 u8 pipe_num = INVALID_PIPE_NUM;
2076 IA_CSS_ERROR("NULL pipe parameter");
2080 /* Assign a new pipe_num .... search for empty place */
2081 for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) {
2082 if (!my_css.all_pipes[i]) {
2083 /* position is reserved */
2084 my_css.all_pipes[i] = (struct ia_css_pipe *)pipe;
2089 if (pipe_num == INVALID_PIPE_NUM) {
2090 /* Max number of pipes already allocated */
2091 IA_CSS_ERROR("Max number of pipes already created");
2095 my_css.pipe_counter++;
2097 IA_CSS_LOG("pipe_num (%d)", pipe_num);
2099 *pipe_number = pipe_num;
2104 pipe_release_pipe_num(unsigned int pipe_num)
2106 my_css.all_pipes[pipe_num] = NULL;
2107 my_css.pipe_counter--;
2108 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2109 "pipe_release_pipe_num (%d)\n", pipe_num);
2113 create_pipe(enum ia_css_pipe_mode mode,
2114 struct ia_css_pipe **pipe,
2118 struct ia_css_pipe *me;
2121 IA_CSS_ERROR("NULL pipe parameter");
2125 me = kmalloc(sizeof(*me), GFP_KERNEL);
2129 err = init_pipe_defaults(mode, me, copy_pipe);
2135 err = pipe_generate_pipe_num(me, &me->pipe_num);
2145 struct ia_css_pipe *
2146 find_pipe_by_num(uint32_t pipe_num)
2150 for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) {
2151 if (my_css.all_pipes[i] &&
2152 ia_css_pipe_get_pipe_num(my_css.all_pipes[i]) == pipe_num) {
2153 return my_css.all_pipes[i];
2159 static void sh_css_pipe_free_acc_binaries(
2160 struct ia_css_pipe *pipe)
2162 struct ia_css_pipeline *pipeline;
2163 struct ia_css_pipeline_stage *stage;
2166 IA_CSS_ERROR("NULL input pointer");
2169 pipeline = &pipe->pipeline;
2171 /* loop through the stages and unload them */
2172 for (stage = pipeline->stages; stage; stage = stage->next) {
2173 struct ia_css_fw_info *firmware = (struct ia_css_fw_info *)
2176 ia_css_pipe_unload_extension(pipe, firmware);
2181 ia_css_pipe_destroy(struct ia_css_pipe *pipe)
2185 IA_CSS_ENTER("pipe = %p", pipe);
2188 IA_CSS_LEAVE_ERR(-EINVAL);
2193 IA_CSS_LOG("ia_css_stream_destroy not called!");
2194 IA_CSS_LEAVE_ERR(-EINVAL);
2198 switch (pipe->config.mode) {
2199 case IA_CSS_PIPE_MODE_PREVIEW:
2201 * need to take into account that this function is also called
2202 * on the internal copy pipe
2204 if (pipe->mode == IA_CSS_PIPE_ID_PREVIEW) {
2205 ia_css_frame_free_multiple(NUM_CONTINUOUS_FRAMES,
2206 pipe->continuous_frames);
2207 ia_css_metadata_free_multiple(NUM_CONTINUOUS_FRAMES,
2208 pipe->cont_md_buffers);
2209 if (pipe->pipe_settings.preview.copy_pipe) {
2210 err = ia_css_pipe_destroy(pipe->pipe_settings.preview.copy_pipe);
2211 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2212 "ia_css_pipe_destroy(): destroyed internal copy pipe err=%d\n",
2217 case IA_CSS_PIPE_MODE_VIDEO:
2218 if (pipe->mode == IA_CSS_PIPE_ID_VIDEO) {
2219 ia_css_frame_free_multiple(NUM_CONTINUOUS_FRAMES,
2220 pipe->continuous_frames);
2221 ia_css_metadata_free_multiple(NUM_CONTINUOUS_FRAMES,
2222 pipe->cont_md_buffers);
2223 if (pipe->pipe_settings.video.copy_pipe) {
2224 err = ia_css_pipe_destroy(pipe->pipe_settings.video.copy_pipe);
2225 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2226 "ia_css_pipe_destroy(): destroyed internal copy pipe err=%d\n",
2231 ia_css_frame_free_multiple(NUM_VIDEO_TNR_FRAMES,
2232 pipe->pipe_settings.video.tnr_frames);
2234 ia_css_frame_free_multiple(NUM_VIDEO_TNR_FRAMES,
2235 pipe->pipe_settings.video.tnr_frames);
2237 ia_css_frame_free_multiple(MAX_NUM_VIDEO_DELAY_FRAMES,
2238 pipe->pipe_settings.video.delay_frames);
2240 case IA_CSS_PIPE_MODE_CAPTURE:
2241 ia_css_frame_free_multiple(MAX_NUM_VIDEO_DELAY_FRAMES,
2242 pipe->pipe_settings.capture.delay_frames);
2244 case IA_CSS_PIPE_MODE_ACC:
2245 sh_css_pipe_free_acc_binaries(pipe);
2247 case IA_CSS_PIPE_MODE_COPY:
2249 case IA_CSS_PIPE_MODE_YUVPP:
2253 if (pipe->scaler_pp_lut != mmgr_NULL) {
2254 hmm_free(pipe->scaler_pp_lut);
2255 pipe->scaler_pp_lut = mmgr_NULL;
2258 my_css.active_pipes[ia_css_pipe_get_pipe_num(pipe)] = NULL;
2259 sh_css_pipe_free_shading_table(pipe);
2261 ia_css_pipeline_destroy(&pipe->pipeline);
2262 pipe_release_pipe_num(ia_css_pipe_get_pipe_num(pipe));
2264 /* Temporarily, not every sh_css_pipe has an acc_extension. */
2265 if (pipe->config.acc_extension)
2266 ia_css_pipe_unload_extension(pipe, pipe->config.acc_extension);
2269 IA_CSS_LEAVE("err = %d", err);
2276 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_uninit() enter: void\n");
2278 sh_css_params_free_default_gdc_lut();
2280 /* TODO: JB: implement decent check and handling of freeing mipi frames */
2281 if (!mipi_is_free())
2282 dev_warn(atomisp_dev, "mipi frames are not freed.\n");
2284 /* cleanup generic data */
2285 sh_css_params_uninit();
2286 ia_css_refcount_uninit();
2288 ia_css_rmgr_uninit();
2290 #if !defined(ISP2401)
2291 /* needed for reprogramming the inputformatter after power cycle of css */
2292 ifmtr_set_if_blocking_mode_reset = true;
2295 if (!fw_explicitly_loaded)
2296 ia_css_unload_firmware();
2298 ia_css_spctrl_unload_fw(SP0_ID);
2299 sh_css_sp_set_sp_running(false);
2300 /* check and free any remaining mipi frames */
2301 free_mipi_frames(NULL);
2303 sh_css_sp_reset_global_vars();
2305 ia_css_isys_uninit();
2307 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_uninit() leave: return_void\n");
2310 int ia_css_irq_translate(
2311 unsigned int *irq_infos)
2314 enum hrt_isp_css_irq_status status = hrt_isp_css_irq_status_more_irqs;
2315 unsigned int infos = 0;
2317 /* irq_infos can be NULL, but that would make the function useless */
2318 /* assert(irq_infos != NULL); */
2319 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2320 "ia_css_irq_translate() enter: irq_infos=%p\n", irq_infos);
2322 while (status == hrt_isp_css_irq_status_more_irqs) {
2323 status = virq_get_channel_id(&irq);
2324 if (status == hrt_isp_css_irq_status_error)
2331 * When SP goes to idle, info is available in the
2334 infos |= IA_CSS_IRQ_INFO_EVENTS_READY;
2339 infos |= IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF;
2342 infos |= IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF;
2345 infos |= IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR;
2347 #if !defined(ISP2401)
2349 infos |= IA_CSS_IRQ_INFO_IF_ERROR;
2353 infos |= IA_CSS_IRQ_INFO_DMA_ERROR;
2356 infos |= sh_css_get_sw_interrupt_value(0);
2359 infos |= sh_css_get_sw_interrupt_value(1);
2360 /* pqiao TODO: also assumption here */
2370 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2371 "ia_css_irq_translate() leave: irq_infos=%u\n",
2377 int ia_css_irq_enable(
2378 enum ia_css_irq_info info,
2381 enum virq_id irq = N_virq_id;
2383 IA_CSS_ENTER("info=%d, enable=%d", info, enable);
2386 #if !defined(ISP2401)
2387 case IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF:
2388 irq = virq_isys_sof;
2390 case IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF:
2391 irq = virq_isys_eof;
2393 case IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR:
2394 irq = virq_isys_csi;
2396 case IA_CSS_IRQ_INFO_IF_ERROR:
2397 irq = virq_ifmt0_id;
2400 case IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF:
2401 case IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF:
2402 case IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR:
2403 case IA_CSS_IRQ_INFO_IF_ERROR:
2404 /* Just ignore those unused IRQs without printing errors */
2407 case IA_CSS_IRQ_INFO_DMA_ERROR:
2410 case IA_CSS_IRQ_INFO_SW_0:
2411 irq = virq_sw_pin_0;
2413 case IA_CSS_IRQ_INFO_SW_1:
2414 irq = virq_sw_pin_1;
2417 IA_CSS_LEAVE_ERR(-EINVAL);
2421 cnd_virq_enable_channel(irq, enable);
2423 IA_CSS_LEAVE_ERR(0);
2429 sh_css_get_sw_interrupt_value(unsigned int irq)
2431 unsigned int irq_value;
2433 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2434 "sh_css_get_sw_interrupt_value() enter: irq=%d\n", irq);
2435 irq_value = sh_css_sp_get_sw_interrupt_value(irq);
2436 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2437 "sh_css_get_sw_interrupt_value() leave: irq_value=%d\n", irq_value);
2442 * configure and load the copy binary, the next binary is used to
2443 * determine whether the copy binary needs to do left padding.
2445 static int load_copy_binary(
2446 struct ia_css_pipe *pipe,
2447 struct ia_css_binary *copy_binary,
2448 struct ia_css_binary *next_binary)
2450 struct ia_css_frame_info copy_out_info, copy_in_info, copy_vf_info;
2451 unsigned int left_padding;
2453 struct ia_css_binary_descr copy_descr;
2455 /* next_binary can be NULL */
2457 assert(copy_binary);
2458 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2459 "load_copy_binary() enter:\n");
2462 copy_out_info = next_binary->in_frame_info;
2463 left_padding = next_binary->left_padding;
2465 copy_out_info = pipe->output_info[0];
2466 copy_vf_info = pipe->vf_output_info[0];
2467 ia_css_frame_info_set_format(©_vf_info, IA_CSS_FRAME_FORMAT_YUV_LINE);
2471 ia_css_pipe_get_copy_binarydesc(pipe, ©_descr,
2472 ©_in_info, ©_out_info,
2473 (next_binary) ? NULL : NULL/*TODO: ©_vf_info*/);
2474 err = ia_css_binary_find(©_descr, copy_binary);
2477 copy_binary->left_padding = left_padding;
2482 alloc_continuous_frames(struct ia_css_pipe *pipe, bool init_time)
2485 struct ia_css_frame_info ref_info;
2486 enum ia_css_pipe_id pipe_id;
2488 unsigned int i, idx;
2489 unsigned int num_frames;
2491 IA_CSS_ENTER_PRIVATE("pipe = %p, init_time = %d", pipe, init_time);
2493 if ((!pipe) || (!pipe->stream)) {
2494 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
2498 pipe_id = pipe->mode;
2499 continuous = pipe->stream->config.continuous;
2503 num_frames = pipe->stream->config.init_num_cont_raw_buf;
2504 pipe->stream->continuous_pipe = pipe;
2506 num_frames = pipe->stream->config.target_num_cont_raw_buf;
2509 num_frames = NUM_ONLINE_INIT_CONTINUOUS_FRAMES;
2512 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) {
2513 ref_info = pipe->pipe_settings.preview.preview_binary.in_frame_info;
2514 } else if (pipe_id == IA_CSS_PIPE_ID_VIDEO) {
2515 ref_info = pipe->pipe_settings.video.video_binary.in_frame_info;
2517 /* should not happen */
2518 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
2522 #if defined(ISP2401)
2523 /* For CSI2+, the continuous frame will hold the full input frame */
2524 ref_info.res.width = pipe->stream->config.input_config.input_res.width;
2525 ref_info.res.height = pipe->stream->config.input_config.input_res.height;
2527 /* Ensure padded width is aligned for 2401 */
2528 ref_info.padded_width = CEIL_MUL(ref_info.res.width, 2 * ISP_VEC_NELEMS);
2531 if (pipe->stream->config.pack_raw_pixels) {
2532 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2533 "alloc_continuous_frames() IA_CSS_FRAME_FORMAT_RAW_PACKED\n");
2534 ref_info.format = IA_CSS_FRAME_FORMAT_RAW_PACKED;
2537 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2538 "alloc_continuous_frames() IA_CSS_FRAME_FORMAT_RAW\n");
2539 ref_info.format = IA_CSS_FRAME_FORMAT_RAW;
2542 /* Write format back to binary */
2543 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) {
2544 pipe->pipe_settings.preview.preview_binary.in_frame_info.format =
2546 } else if (pipe_id == IA_CSS_PIPE_ID_VIDEO) {
2547 pipe->pipe_settings.video.video_binary.in_frame_info.format = ref_info.format;
2549 /* should not happen */
2550 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
2557 idx = pipe->stream->config.init_num_cont_raw_buf;
2559 for (i = idx; i < NUM_CONTINUOUS_FRAMES; i++) {
2560 /* free previous frame */
2561 if (pipe->continuous_frames[i]) {
2562 ia_css_frame_free(pipe->continuous_frames[i]);
2563 pipe->continuous_frames[i] = NULL;
2565 /* free previous metadata buffer */
2566 ia_css_metadata_free(pipe->cont_md_buffers[i]);
2567 pipe->cont_md_buffers[i] = NULL;
2569 /* check if new frame needed */
2570 if (i < num_frames) {
2571 /* allocate new frame */
2572 err = ia_css_frame_allocate_from_info(
2573 &pipe->continuous_frames[i],
2576 IA_CSS_LEAVE_ERR_PRIVATE(err);
2579 /* allocate metadata buffer */
2580 pipe->cont_md_buffers[i] = ia_css_metadata_allocate(
2581 &pipe->stream->info.metadata_info);
2584 IA_CSS_LEAVE_ERR_PRIVATE(0);
2589 ia_css_alloc_continuous_frame_remain(struct ia_css_stream *stream)
2593 return alloc_continuous_frames(stream->continuous_pipe, false);
2597 load_preview_binaries(struct ia_css_pipe *pipe)
2599 struct ia_css_frame_info prev_in_info,
2603 struct ia_css_binary_descr preview_descr;
2606 bool need_vf_pp = false;
2607 bool need_isp_copy_binary = false;
2609 bool sensor = false;
2613 /* preview only have 1 output pin now */
2614 struct ia_css_frame_info *pipe_out_info = &pipe->output_info[0];
2615 struct ia_css_preview_settings *mycs = &pipe->pipe_settings.preview;
2617 IA_CSS_ENTER_PRIVATE("");
2619 assert(pipe->stream);
2620 assert(pipe->mode == IA_CSS_PIPE_ID_PREVIEW);
2622 online = pipe->stream->config.online;
2624 sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
2626 continuous = pipe->stream->config.continuous;
2629 if (mycs->preview_binary.info)
2632 err = ia_css_util_check_input(&pipe->stream->config, false, false);
2635 err = ia_css_frame_check_info(pipe_out_info);
2640 * Note: the current selection of vf_pp binary and
2641 * parameterization of the preview binary contains a few pieces
2642 * of hardcoded knowledge. This needs to be cleaned up such that
2643 * the binary selection becomes more generic.
2644 * The vf_pp binary is needed if one or more of the following features
2646 * 1. YUV downscaling.
2648 * 3. An output format that is not supported by the preview binary.
2649 * In practice this means something other than yuv_line or nv12.
2650 * The decision if the vf_pp binary is needed for YUV downscaling is
2651 * made after the preview binary selection, since some preview binaries
2652 * can perform the requested YUV downscaling.
2654 need_vf_pp = pipe->config.enable_dz;
2655 need_vf_pp |= pipe_out_info->format != IA_CSS_FRAME_FORMAT_YUV_LINE &&
2656 !(pipe_out_info->format == IA_CSS_FRAME_FORMAT_NV12 ||
2657 pipe_out_info->format == IA_CSS_FRAME_FORMAT_NV12_16 ||
2658 pipe_out_info->format == IA_CSS_FRAME_FORMAT_NV12_TILEY);
2660 /* Preview step 1 */
2661 if (pipe->vf_yuv_ds_input_info.res.width)
2662 prev_vf_info = pipe->vf_yuv_ds_input_info;
2664 prev_vf_info = *pipe_out_info;
2666 * If vf_pp is needed, then preview must output yuv_line.
2667 * The exception is when vf_pp is manually disabled, that is only
2668 * used in combination with a pipeline extension that requires
2669 * yuv_line as input.
2672 ia_css_frame_info_set_format(&prev_vf_info,
2673 IA_CSS_FRAME_FORMAT_YUV_LINE);
2675 err = ia_css_pipe_get_preview_binarydesc(
2684 err = ia_css_binary_find(&preview_descr, &mycs->preview_binary);
2688 /* The vf_pp binary is needed when (further) YUV downscaling is required */
2689 need_vf_pp |= mycs->preview_binary.out_frame_info[0].res.width != pipe_out_info->res.width;
2690 need_vf_pp |= mycs->preview_binary.out_frame_info[0].res.height != pipe_out_info->res.height;
2693 * When vf_pp is needed, then the output format of the selected
2694 * preview binary must be yuv_line. If this is not the case,
2695 * then the preview binary selection is done again.
2698 (mycs->preview_binary.out_frame_info[0].format != IA_CSS_FRAME_FORMAT_YUV_LINE)) {
2699 /* Preview step 2 */
2700 if (pipe->vf_yuv_ds_input_info.res.width)
2701 prev_vf_info = pipe->vf_yuv_ds_input_info;
2703 prev_vf_info = *pipe_out_info;
2705 ia_css_frame_info_set_format(&prev_vf_info,
2706 IA_CSS_FRAME_FORMAT_YUV_LINE);
2708 err = ia_css_pipe_get_preview_binarydesc(
2717 err = ia_css_binary_find(&preview_descr,
2718 &mycs->preview_binary);
2724 struct ia_css_binary_descr vf_pp_descr;
2726 /* Viewfinder post-processing */
2727 ia_css_pipe_get_vfpp_binarydesc(pipe, &vf_pp_descr,
2728 &mycs->preview_binary.out_frame_info[0],
2730 err = ia_css_binary_find(&vf_pp_descr,
2731 &mycs->vf_pp_binary);
2738 * When the input system is 2401, only the Direct Sensor Mode
2739 * Offline Preview uses the ISP copy binary.
2741 need_isp_copy_binary = !online && sensor;
2744 * About pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY:
2745 * This is typical the case with SkyCam (which has no input system) but it also applies to all cases
2746 * where the driver chooses for memory based input frames. In these cases, a copy binary (which typical
2747 * copies sensor data to DDR) does not have much use.
2750 need_isp_copy_binary = !online && !continuous;
2752 need_isp_copy_binary = !online && !continuous && !(pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY);
2756 if (need_isp_copy_binary) {
2757 err = load_copy_binary(pipe,
2759 &mycs->preview_binary);
2764 if (pipe->shading_table) {
2765 ia_css_shading_table_free(pipe->shading_table);
2766 pipe->shading_table = NULL;
2773 ia_css_binary_unload(struct ia_css_binary *binary)
2775 ia_css_binary_destroy_isp_parameters(binary);
2779 unload_preview_binaries(struct ia_css_pipe *pipe)
2781 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
2783 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) {
2784 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
2787 ia_css_binary_unload(&pipe->pipe_settings.preview.copy_binary);
2788 ia_css_binary_unload(&pipe->pipe_settings.preview.preview_binary);
2789 ia_css_binary_unload(&pipe->pipe_settings.preview.vf_pp_binary);
2791 IA_CSS_LEAVE_ERR_PRIVATE(0);
2795 static const struct ia_css_fw_info *last_output_firmware(
2796 const struct ia_css_fw_info *fw)
2798 const struct ia_css_fw_info *last_fw = NULL;
2799 /* fw can be NULL */
2800 IA_CSS_ENTER_LEAVE_PRIVATE("");
2802 for (; fw; fw = fw->next) {
2803 const struct ia_css_fw_info *info = fw;
2805 if (info->info.isp.sp.enable.output)
2811 static int add_firmwares(
2812 struct ia_css_pipeline *me,
2813 struct ia_css_binary *binary,
2814 const struct ia_css_fw_info *fw,
2815 const struct ia_css_fw_info *last_fw,
2816 unsigned int binary_mode,
2817 struct ia_css_frame *in_frame,
2818 struct ia_css_frame *out_frame,
2819 struct ia_css_frame *vf_frame,
2820 struct ia_css_pipeline_stage **my_stage,
2821 struct ia_css_pipeline_stage **vf_stage)
2824 struct ia_css_pipeline_stage *extra_stage = NULL;
2825 struct ia_css_pipeline_stage_desc stage_desc;
2827 /* all args can be NULL ??? */
2828 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2829 "add_firmwares() enter:\n");
2831 for (; fw; fw = fw->next) {
2832 struct ia_css_frame *out[IA_CSS_BINARY_MAX_OUTPUT_PORTS] = {NULL};
2833 struct ia_css_frame *in = NULL;
2834 struct ia_css_frame *vf = NULL;
2836 if ((fw == last_fw) && (fw->info.isp.sp.enable.out_frame != 0))
2839 if (fw->info.isp.sp.enable.in_frame != 0)
2842 if (fw->info.isp.sp.enable.out_frame != 0)
2845 ia_css_pipe_get_firmwares_stage_desc(&stage_desc, binary,
2846 out, in, vf, fw, binary_mode);
2847 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
2851 if (fw->info.isp.sp.enable.output != 0)
2852 in_frame = extra_stage->args.out_frame[0];
2853 if (my_stage && !*my_stage && extra_stage)
2854 *my_stage = extra_stage;
2855 if (vf_stage && !*vf_stage && extra_stage &&
2856 fw->info.isp.sp.enable.vf_veceven)
2857 *vf_stage = extra_stage;
2862 static int add_vf_pp_stage(
2863 struct ia_css_pipe *pipe,
2864 struct ia_css_frame *in_frame,
2865 struct ia_css_frame *out_frame,
2866 struct ia_css_binary *vf_pp_binary,
2867 struct ia_css_pipeline_stage **vf_pp_stage)
2869 struct ia_css_pipeline *me = NULL;
2870 const struct ia_css_fw_info *last_fw = NULL;
2872 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
2873 struct ia_css_pipeline_stage_desc stage_desc;
2875 /* out_frame can be NULL ??? */
2886 ia_css_pipe_util_create_output_frames(out_frames);
2887 me = &pipe->pipeline;
2889 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2890 "add_vf_pp_stage() enter:\n");
2892 *vf_pp_stage = NULL;
2894 last_fw = last_output_firmware(pipe->vf_stage);
2895 if (!pipe->extra_config.disable_vf_pp) {
2897 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
2898 ia_css_pipe_get_generic_stage_desc(&stage_desc, vf_pp_binary,
2899 out_frames, in_frame, NULL);
2901 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
2902 ia_css_pipe_get_generic_stage_desc(&stage_desc, vf_pp_binary,
2903 out_frames, in_frame, NULL);
2905 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc, vf_pp_stage);
2908 in_frame = (*vf_pp_stage)->args.out_frame[0];
2910 err = add_firmwares(me, vf_pp_binary, pipe->vf_stage, last_fw,
2911 IA_CSS_BINARY_MODE_VF_PP,
2912 in_frame, out_frame, NULL,
2917 static int add_yuv_scaler_stage(
2918 struct ia_css_pipe *pipe,
2919 struct ia_css_pipeline *me,
2920 struct ia_css_frame *in_frame,
2921 struct ia_css_frame *out_frame,
2922 struct ia_css_frame *internal_out_frame,
2923 struct ia_css_binary *yuv_scaler_binary,
2924 struct ia_css_pipeline_stage **pre_vf_pp_stage)
2926 const struct ia_css_fw_info *last_fw;
2928 struct ia_css_frame *vf_frame = NULL;
2929 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
2930 struct ia_css_pipeline_stage_desc stage_desc;
2932 /* out_frame can be NULL ??? */
2936 assert(yuv_scaler_binary);
2937 assert(pre_vf_pp_stage);
2938 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2939 "add_yuv_scaler_stage() enter:\n");
2941 *pre_vf_pp_stage = NULL;
2942 ia_css_pipe_util_create_output_frames(out_frames);
2944 last_fw = last_output_firmware(pipe->output_stage);
2947 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
2948 ia_css_pipe_get_generic_stage_desc(&stage_desc,
2949 yuv_scaler_binary, out_frames, in_frame, vf_frame);
2951 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
2952 ia_css_pipe_util_set_output_frames(out_frames, 1, internal_out_frame);
2953 ia_css_pipe_get_generic_stage_desc(&stage_desc,
2954 yuv_scaler_binary, out_frames, in_frame, vf_frame);
2956 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
2960 in_frame = (*pre_vf_pp_stage)->args.out_frame[0];
2962 err = add_firmwares(me, yuv_scaler_binary, pipe->output_stage, last_fw,
2963 IA_CSS_BINARY_MODE_CAPTURE_PP,
2964 in_frame, out_frame, vf_frame,
2965 NULL, pre_vf_pp_stage);
2966 /* If a firmware produce vf_pp output, we set that as vf_pp input */
2967 (*pre_vf_pp_stage)->args.vf_downscale_log2 =
2968 yuv_scaler_binary->vf_downscale_log2;
2970 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2971 "add_yuv_scaler_stage() leave:\n");
2975 static int add_capture_pp_stage(
2976 struct ia_css_pipe *pipe,
2977 struct ia_css_pipeline *me,
2978 struct ia_css_frame *in_frame,
2979 struct ia_css_frame *out_frame,
2980 struct ia_css_binary *capture_pp_binary,
2981 struct ia_css_pipeline_stage **capture_pp_stage)
2983 const struct ia_css_fw_info *last_fw = NULL;
2985 struct ia_css_frame *vf_frame = NULL;
2986 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
2987 struct ia_css_pipeline_stage_desc stage_desc;
2989 /* out_frame can be NULL ??? */
2993 assert(capture_pp_binary);
2994 assert(capture_pp_stage);
2995 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2996 "add_capture_pp_stage() enter:\n");
2998 *capture_pp_stage = NULL;
2999 ia_css_pipe_util_create_output_frames(out_frames);
3001 last_fw = last_output_firmware(pipe->output_stage);
3002 err = ia_css_frame_allocate_from_info(&vf_frame,
3003 &capture_pp_binary->vf_frame_info);
3007 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3008 ia_css_pipe_get_generic_stage_desc(&stage_desc,
3009 capture_pp_binary, out_frames, NULL, vf_frame);
3011 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
3012 ia_css_pipe_get_generic_stage_desc(&stage_desc,
3013 capture_pp_binary, out_frames, NULL, vf_frame);
3015 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
3019 err = add_firmwares(me, capture_pp_binary, pipe->output_stage, last_fw,
3020 IA_CSS_BINARY_MODE_CAPTURE_PP,
3021 in_frame, out_frame, vf_frame,
3022 NULL, capture_pp_stage);
3023 /* If a firmware produce vf_pp output, we set that as vf_pp input */
3024 if (*capture_pp_stage) {
3025 (*capture_pp_stage)->args.vf_downscale_log2 =
3026 capture_pp_binary->vf_downscale_log2;
3031 static void sh_css_setup_queues(void)
3033 const struct ia_css_fw_info *fw;
3034 unsigned int HIVE_ADDR_host_sp_queues_initialized;
3036 sh_css_hmm_buffer_record_init();
3038 sh_css_event_init_irq_mask();
3041 HIVE_ADDR_host_sp_queues_initialized =
3042 fw->info.sp.host_sp_queues_initialized;
3046 /* set "host_sp_queues_initialized" to "true" */
3047 sp_dmem_store_uint32(SP0_ID,
3048 (unsigned int)sp_address_of(host_sp_queues_initialized),
3050 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_setup_queues() leave:\n");
3054 init_vf_frameinfo_defaults(struct ia_css_pipe *pipe,
3055 struct ia_css_frame *vf_frame, unsigned int idx)
3058 unsigned int thread_id;
3059 enum sh_css_queue_id queue_id;
3063 sh_css_pipe_get_viewfinder_frame_info(pipe, &vf_frame->info, idx);
3064 vf_frame->contiguous = false;
3065 vf_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
3066 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
3067 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx, thread_id, &queue_id);
3068 vf_frame->dynamic_queue_id = queue_id;
3069 vf_frame->buf_type = IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx;
3071 err = ia_css_frame_init_planes(vf_frame);
3077 get_crop_lines_for_bayer_order(const struct ia_css_stream_config *config)
3080 if ((config->input_config.bayer_order == IA_CSS_BAYER_ORDER_BGGR) ||
3081 (config->input_config.bayer_order == IA_CSS_BAYER_ORDER_GBRG))
3088 get_crop_columns_for_bayer_order(const struct ia_css_stream_config *config)
3091 if ((config->input_config.bayer_order == IA_CSS_BAYER_ORDER_RGGB) ||
3092 (config->input_config.bayer_order == IA_CSS_BAYER_ORDER_GBRG))
3099 * This function is to get the sum of all extra pixels in addition to the effective
3100 * input, it includes dvs envelop and filter run-in
3102 static void get_pipe_extra_pixel(struct ia_css_pipe *pipe,
3103 unsigned int *extra_row, unsigned int *extra_column)
3105 enum ia_css_pipe_id pipe_id = pipe->mode;
3106 unsigned int left_cropping = 0, top_cropping = 0;
3108 struct ia_css_resolution dvs_env = pipe->config.dvs_envelope;
3111 * The dvs envelope info may not be correctly sent down via pipe config
3112 * The check is made and the correct value is populated in the binary info
3113 * Use this value when computing crop, else excess lines may get trimmed
3116 case IA_CSS_PIPE_ID_PREVIEW:
3117 if (pipe->pipe_settings.preview.preview_binary.info) {
3119 pipe->pipe_settings.preview.preview_binary.info->sp.pipeline.left_cropping;
3121 pipe->pipe_settings.preview.preview_binary.info->sp.pipeline.top_cropping;
3123 dvs_env = pipe->pipe_settings.preview.preview_binary.dvs_envelope;
3125 case IA_CSS_PIPE_ID_VIDEO:
3126 if (pipe->pipe_settings.video.video_binary.info) {
3128 pipe->pipe_settings.video.video_binary.info->sp.pipeline.left_cropping;
3130 pipe->pipe_settings.video.video_binary.info->sp.pipeline.top_cropping;
3132 dvs_env = pipe->pipe_settings.video.video_binary.dvs_envelope;
3134 case IA_CSS_PIPE_ID_CAPTURE:
3135 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
3136 if (pipe->pipe_settings.capture.primary_binary[i].info) {
3138 pipe->pipe_settings.capture.primary_binary[i].info->sp.pipeline.left_cropping;
3140 pipe->pipe_settings.capture.primary_binary[i].info->sp.pipeline.top_cropping;
3143 pipe->pipe_settings.capture.primary_binary[i].dvs_envelope.width;
3145 pipe->pipe_settings.capture.primary_binary[i].dvs_envelope.height;
3152 *extra_row = top_cropping + dvs_env.height;
3153 *extra_column = left_cropping + dvs_env.width;
3157 ia_css_get_crop_offsets(
3158 struct ia_css_pipe *pipe,
3159 struct ia_css_frame_info *in_frame)
3161 unsigned int row = 0;
3162 unsigned int column = 0;
3163 struct ia_css_resolution *input_res;
3164 struct ia_css_resolution *effective_res;
3165 unsigned int extra_row = 0, extra_col = 0;
3166 unsigned int min_reqd_height, min_reqd_width;
3169 assert(pipe->stream);
3172 IA_CSS_ENTER_PRIVATE("pipe = %p effective_wd = %u effective_ht = %u",
3173 pipe, pipe->config.input_effective_res.width,
3174 pipe->config.input_effective_res.height);
3176 input_res = &pipe->stream->config.input_config.input_res;
3178 effective_res = &pipe->stream->config.input_config.effective_res;
3180 effective_res = &pipe->config.input_effective_res;
3183 get_pipe_extra_pixel(pipe, &extra_row, &extra_col);
3185 in_frame->raw_bayer_order = pipe->stream->config.input_config.bayer_order;
3187 min_reqd_height = effective_res->height + extra_row;
3188 min_reqd_width = effective_res->width + extra_col;
3190 if (input_res->height > min_reqd_height) {
3191 row = (input_res->height - min_reqd_height) / 2;
3194 if (input_res->width > min_reqd_width) {
3195 column = (input_res->width - min_reqd_width) / 2;
3201 * 1. Require the special support for RAW10 packed mode.
3202 * 2. Require the special support for the online use cases.
3206 * ISP expects GRBG bayer order, we skip one line and/or one row
3207 * to correct in case the input bayer order is different.
3209 column += get_crop_columns_for_bayer_order(&pipe->stream->config);
3210 row += get_crop_lines_for_bayer_order(&pipe->stream->config);
3212 in_frame->crop_info.start_column = column;
3213 in_frame->crop_info.start_line = row;
3215 IA_CSS_LEAVE_PRIVATE("void start_col: %u start_row: %u", column, row);
3222 init_in_frameinfo_memory_defaults(struct ia_css_pipe *pipe,
3223 struct ia_css_frame *frame, enum ia_css_frame_format format)
3225 struct ia_css_frame *in_frame;
3227 unsigned int thread_id;
3228 enum sh_css_queue_id queue_id;
3233 in_frame->info.format = format;
3236 if (format == IA_CSS_FRAME_FORMAT_RAW)
3237 in_frame->info.format = (pipe->stream->config.pack_raw_pixels) ?
3238 IA_CSS_FRAME_FORMAT_RAW_PACKED : IA_CSS_FRAME_FORMAT_RAW;
3241 in_frame->info.res.width = pipe->stream->config.input_config.input_res.width;
3242 in_frame->info.res.height = pipe->stream->config.input_config.input_res.height;
3243 in_frame->info.raw_bit_depth =
3244 ia_css_pipe_util_pipe_input_format_bpp(pipe);
3245 ia_css_frame_info_set_width(&in_frame->info, pipe->stream->config.input_config.input_res.width, 0);
3246 in_frame->contiguous = false;
3247 in_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
3248 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
3249 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_INPUT_FRAME, thread_id, &queue_id);
3250 in_frame->dynamic_queue_id = queue_id;
3251 in_frame->buf_type = IA_CSS_BUFFER_TYPE_INPUT_FRAME;
3253 ia_css_get_crop_offsets(pipe, &in_frame->info);
3255 err = ia_css_frame_init_planes(in_frame);
3257 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3258 "init_in_frameinfo_memory_defaults() bayer_order = %d:\n", in_frame->info.raw_bayer_order);
3264 init_out_frameinfo_defaults(struct ia_css_pipe *pipe,
3265 struct ia_css_frame *out_frame, unsigned int idx)
3268 unsigned int thread_id;
3269 enum sh_css_queue_id queue_id;
3273 sh_css_pipe_get_output_frame_info(pipe, &out_frame->info, idx);
3274 out_frame->contiguous = false;
3275 out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
3276 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
3277 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx, thread_id, &queue_id);
3278 out_frame->dynamic_queue_id = queue_id;
3279 out_frame->buf_type = IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx;
3280 err = ia_css_frame_init_planes(out_frame);
3285 /* Create stages for video pipe */
3286 static int create_host_video_pipeline(struct ia_css_pipe *pipe)
3288 struct ia_css_pipeline_stage_desc stage_desc;
3289 struct ia_css_binary *copy_binary, *video_binary,
3290 *yuv_scaler_binary, *vf_pp_binary;
3291 struct ia_css_pipeline_stage *copy_stage = NULL;
3292 struct ia_css_pipeline_stage *video_stage = NULL;
3293 struct ia_css_pipeline_stage *yuv_scaler_stage = NULL;
3294 struct ia_css_pipeline_stage *vf_pp_stage = NULL;
3295 struct ia_css_pipeline *me;
3296 struct ia_css_frame *in_frame = NULL;
3297 struct ia_css_frame *out_frame;
3298 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3299 struct ia_css_frame *vf_frame = NULL;
3301 bool need_copy = false;
3302 bool need_vf_pp = false;
3303 bool need_yuv_pp = false;
3304 bool need_in_frameinfo_memory = false;
3306 unsigned int i, num_yuv_scaler;
3307 bool *is_output_stage = NULL;
3309 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3310 if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) {
3311 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
3314 ia_css_pipe_util_create_output_frames(out_frames);
3315 out_frame = &pipe->out_frame_struct;
3317 /* pipeline already created as part of create_host_pipeline_structure */
3318 me = &pipe->pipeline;
3319 ia_css_pipeline_clean(me);
3321 me->dvs_frame_delay = pipe->dvs_frame_delay;
3325 * When the input system is 2401, always enable 'in_frameinfo_memory'
3326 * except for the following: online or continuous
3328 need_in_frameinfo_memory = !(pipe->stream->config.online ||
3329 pipe->stream->config.continuous);
3331 /* Construct in_frame info (only in case we have dynamic input */
3332 need_in_frameinfo_memory = pipe->stream->config.mode ==
3333 IA_CSS_INPUT_MODE_MEMORY;
3336 /* Construct in_frame info (only in case we have dynamic input */
3337 if (need_in_frameinfo_memory) {
3338 in_frame = &pipe->in_frame_struct;
3339 err = init_in_frameinfo_memory_defaults(pipe, in_frame,
3340 IA_CSS_FRAME_FORMAT_RAW);
3345 out_frame->data = 0;
3346 err = init_out_frameinfo_defaults(pipe, out_frame, 0);
3350 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
3351 vf_frame = &pipe->vf_frame_struct;
3353 err = init_vf_frameinfo_defaults(pipe, vf_frame, 0);
3358 copy_binary = &pipe->pipe_settings.video.copy_binary;
3359 video_binary = &pipe->pipe_settings.video.video_binary;
3360 vf_pp_binary = &pipe->pipe_settings.video.vf_pp_binary;
3362 yuv_scaler_binary = pipe->pipe_settings.video.yuv_scaler_binary;
3363 num_yuv_scaler = pipe->pipe_settings.video.num_yuv_scaler;
3364 is_output_stage = pipe->pipe_settings.video.is_output_stage;
3366 need_copy = (copy_binary && copy_binary->info);
3367 need_vf_pp = (vf_pp_binary && vf_pp_binary->info);
3368 need_yuv_pp = (yuv_scaler_binary && yuv_scaler_binary->info);
3371 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3372 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
3373 out_frames, NULL, NULL);
3374 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
3378 in_frame = me->stages->args.out_frame[0];
3379 } else if (pipe->stream->config.continuous) {
3382 * When continuous is enabled, configure in_frame with the
3383 * last pipe, which is the copy pipe.
3385 in_frame = pipe->stream->last_pipe->continuous_frames[0];
3387 in_frame = pipe->continuous_frames[0];
3391 ia_css_pipe_util_set_output_frames(out_frames, 0,
3392 need_yuv_pp ? NULL : out_frame);
3395 * when the video binary supports a second output pin,
3396 * it can directly produce the vf_frame.
3399 ia_css_pipe_get_generic_stage_desc(&stage_desc, video_binary,
3400 out_frames, in_frame, NULL);
3402 ia_css_pipe_get_generic_stage_desc(&stage_desc, video_binary,
3403 out_frames, in_frame, vf_frame);
3405 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
3410 /* If we use copy iso video, the input must be yuv iso raw */
3412 video_stage->args.copy_vf =
3413 video_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY;
3414 video_stage->args.copy_output = video_stage->args.copy_vf;
3417 /* when the video binary supports only 1 output pin, vf_pp is needed to
3418 produce the vf_frame.*/
3419 if (need_vf_pp && video_stage) {
3420 in_frame = video_stage->args.out_vf_frame;
3421 err = add_vf_pp_stage(pipe, in_frame, vf_frame, vf_pp_binary,
3429 for (frm = 0; frm < NUM_VIDEO_TNR_FRAMES; frm++) {
3430 video_stage->args.tnr_frames[frm] =
3431 pipe->pipe_settings.video.tnr_frames[frm];
3433 for (frm = 0; frm < MAX_NUM_VIDEO_DELAY_FRAMES; frm++) {
3434 video_stage->args.delay_frames[frm] =
3435 pipe->pipe_settings.video.delay_frames[frm];
3439 /* Append Extension on Video out, if enabled */
3440 if (!need_vf_pp && video_stage && pipe->config.acc_extension &&
3441 (pipe->config.acc_extension->info.isp.type == IA_CSS_ACC_OUTPUT)) {
3442 struct ia_css_frame *out = NULL;
3443 struct ia_css_frame *in = NULL;
3445 if ((pipe->config.acc_extension->info.isp.sp.enable.output) &&
3446 (pipe->config.acc_extension->info.isp.sp.enable.in_frame) &&
3447 (pipe->config.acc_extension->info.isp.sp.enable.out_frame)) {
3448 /* In/Out Frame mapping to support output frame extension.*/
3449 out = video_stage->args.out_frame[0];
3450 err = ia_css_frame_allocate_from_info(&in, &pipe->output_info[0]);
3453 video_stage->args.out_frame[0] = in;
3456 err = add_firmwares(me, video_binary, pipe->output_stage,
3457 last_output_firmware(pipe->output_stage),
3458 IA_CSS_BINARY_MODE_VIDEO,
3459 in, out, NULL, &video_stage, NULL);
3464 if (need_yuv_pp && video_stage) {
3465 struct ia_css_frame *tmp_in_frame = video_stage->args.out_frame[0];
3466 struct ia_css_frame *tmp_out_frame = NULL;
3468 for (i = 0; i < num_yuv_scaler; i++) {
3469 tmp_out_frame = is_output_stage[i] ? out_frame : NULL;
3471 err = add_yuv_scaler_stage(pipe, me, tmp_in_frame,
3472 tmp_out_frame, NULL,
3473 &yuv_scaler_binary[i],
3477 IA_CSS_LEAVE_ERR_PRIVATE(err);
3480 /* we use output port 1 as internal output port */
3481 if (yuv_scaler_stage)
3482 tmp_in_frame = yuv_scaler_stage->args.out_frame[1];
3486 pipe->pipeline.acquire_isp_each_stage = false;
3487 ia_css_pipeline_finalize_stages(&pipe->pipeline,
3488 pipe->stream->config.continuous);
3491 IA_CSS_LEAVE_ERR_PRIVATE(err);
3496 create_host_acc_pipeline(struct ia_css_pipe *pipe)
3499 const struct ia_css_fw_info *fw;
3502 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3503 if ((!pipe) || (!pipe->stream)) {
3504 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
3508 pipe->pipeline.num_execs = pipe->config.acc_num_execs;
3509 /* Reset pipe_qos_config to default disable all QOS extension stages */
3510 if (pipe->config.acc_extension)
3511 pipe->pipeline.pipe_qos_config = 0;
3513 fw = pipe->vf_stage;
3514 for (i = 0; fw; fw = fw->next) {
3515 err = sh_css_pipeline_add_acc_stage(&pipe->pipeline, fw);
3520 for (i = 0; i < pipe->config.num_acc_stages; i++) {
3521 struct ia_css_fw_info *fw = pipe->config.acc_stages[i];
3523 err = sh_css_pipeline_add_acc_stage(&pipe->pipeline, fw);
3528 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
3531 IA_CSS_LEAVE_ERR_PRIVATE(err);
3535 /* Create stages for preview */
3537 create_host_preview_pipeline(struct ia_css_pipe *pipe)
3539 struct ia_css_pipeline_stage *copy_stage = NULL;
3540 struct ia_css_pipeline_stage *preview_stage = NULL;
3541 struct ia_css_pipeline_stage *vf_pp_stage = NULL;
3542 struct ia_css_pipeline_stage_desc stage_desc;
3543 struct ia_css_pipeline *me = NULL;
3544 struct ia_css_binary *copy_binary, *preview_binary, *vf_pp_binary = NULL;
3545 struct ia_css_frame *in_frame = NULL;
3547 struct ia_css_frame *out_frame;
3548 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3549 bool need_in_frameinfo_memory = false;
3551 bool sensor = false;
3552 bool buffered_sensor = false;
3553 bool online = false;
3554 bool continuous = false;
3557 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3558 if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) {
3559 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
3563 ia_css_pipe_util_create_output_frames(out_frames);
3564 /* pipeline already created as part of create_host_pipeline_structure */
3565 me = &pipe->pipeline;
3566 ia_css_pipeline_clean(me);
3570 * When the input system is 2401, always enable 'in_frameinfo_memory'
3571 * except for the following:
3572 * - Direct Sensor Mode Online Preview
3573 * - Buffered Sensor Mode Online Preview
3574 * - Direct Sensor Mode Continuous Preview
3575 * - Buffered Sensor Mode Continuous Preview
3577 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR);
3578 buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR);
3579 online = pipe->stream->config.online;
3580 continuous = pipe->stream->config.continuous;
3581 need_in_frameinfo_memory =
3582 !((sensor && (online || continuous)) || (buffered_sensor && (online || continuous)));
3584 /* Construct in_frame info (only in case we have dynamic input */
3585 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
3587 if (need_in_frameinfo_memory) {
3588 err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame,
3589 IA_CSS_FRAME_FORMAT_RAW);
3593 in_frame = &me->in_frame;
3598 err = init_out_frameinfo_defaults(pipe, &me->out_frame[0], 0);
3601 out_frame = &me->out_frame[0];
3603 copy_binary = &pipe->pipe_settings.preview.copy_binary;
3604 preview_binary = &pipe->pipe_settings.preview.preview_binary;
3605 if (pipe->pipe_settings.preview.vf_pp_binary.info)
3606 vf_pp_binary = &pipe->pipe_settings.preview.vf_pp_binary;
3608 if (pipe->pipe_settings.preview.copy_binary.info) {
3609 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3610 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
3611 out_frames, NULL, NULL);
3612 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
3616 in_frame = me->stages->args.out_frame[0];
3617 } else if (pipe->stream->config.continuous) {
3620 * When continuous is enabled, configure in_frame with the
3621 * last pipe, which is the copy pipe.
3623 if (continuous || !online)
3624 in_frame = pipe->stream->last_pipe->continuous_frames[0];
3627 in_frame = pipe->continuous_frames[0];
3632 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3633 ia_css_pipe_get_generic_stage_desc(&stage_desc, preview_binary,
3634 out_frames, in_frame, NULL);
3636 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
3637 ia_css_pipe_get_generic_stage_desc(&stage_desc, preview_binary,
3638 out_frames, in_frame, NULL);
3640 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
3644 /* If we use copy iso preview, the input must be yuv iso raw */
3645 preview_stage->args.copy_vf =
3646 preview_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY;
3647 preview_stage->args.copy_output = !preview_stage->args.copy_vf;
3648 if (preview_stage->args.copy_vf && !preview_stage->args.out_vf_frame) {
3649 /* in case of copy, use the vf frame as output frame */
3650 preview_stage->args.out_vf_frame =
3651 preview_stage->args.out_frame[0];
3654 if (preview_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY)
3655 in_frame = preview_stage->args.out_vf_frame;
3657 in_frame = preview_stage->args.out_frame[0];
3658 err = add_vf_pp_stage(pipe, in_frame, out_frame, vf_pp_binary,
3664 pipe->pipeline.acquire_isp_each_stage = false;
3665 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
3668 IA_CSS_LEAVE_ERR_PRIVATE(err);
3672 static void send_raw_frames(struct ia_css_pipe *pipe)
3674 if (pipe->stream->config.continuous) {
3677 sh_css_update_host2sp_cont_num_raw_frames
3678 (pipe->stream->config.init_num_cont_raw_buf, true);
3679 sh_css_update_host2sp_cont_num_raw_frames
3680 (pipe->stream->config.target_num_cont_raw_buf, false);
3682 /* Hand-over all the SP-internal buffers */
3683 for (i = 0; i < pipe->stream->config.init_num_cont_raw_buf; i++) {
3684 sh_css_update_host2sp_offline_frame(i,
3685 pipe->continuous_frames[i], pipe->cont_md_buffers[i]);
3693 preview_start(struct ia_css_pipe *pipe)
3696 struct ia_css_pipe *copy_pipe, *capture_pipe;
3697 struct ia_css_pipe *acc_pipe;
3698 enum sh_css_pipe_config_override copy_ovrd;
3699 enum ia_css_input_mode preview_pipe_input_mode;
3700 unsigned int thread_id;
3702 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3703 if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) {
3704 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
3708 preview_pipe_input_mode = pipe->stream->config.mode;
3710 copy_pipe = pipe->pipe_settings.preview.copy_pipe;
3711 capture_pipe = pipe->pipe_settings.preview.capture_pipe;
3712 acc_pipe = pipe->pipe_settings.preview.acc_pipe;
3714 sh_css_metrics_start_frame();
3716 /* multi stream video needs mipi buffers */
3717 err = send_mipi_frames(pipe);
3719 IA_CSS_LEAVE_ERR_PRIVATE(err);
3722 send_raw_frames(pipe);
3724 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
3725 copy_ovrd = 1 << thread_id;
3727 if (pipe->stream->cont_capt) {
3728 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe),
3730 copy_ovrd |= 1 << thread_id;
3733 /* Construct and load the copy pipe */
3734 if (pipe->stream->config.continuous) {
3735 sh_css_sp_init_pipeline(©_pipe->pipeline,
3736 IA_CSS_PIPE_ID_COPY,
3737 (uint8_t)ia_css_pipe_get_pipe_num(copy_pipe),
3739 pipe->stream->config.pixels_per_clock == 2, false,
3740 false, pipe->required_bds_factor,
3742 pipe->stream->config.mode,
3743 &pipe->stream->config.metadata_config,
3744 &pipe->stream->info.metadata_info,
3745 pipe->stream->config.source.port.port);
3748 * make the preview pipe start with mem mode input, copy handles
3751 preview_pipe_input_mode = IA_CSS_INPUT_MODE_MEMORY;
3754 /* Construct and load the capture pipe */
3755 if (pipe->stream->cont_capt) {
3756 sh_css_sp_init_pipeline(&capture_pipe->pipeline,
3757 IA_CSS_PIPE_ID_CAPTURE,
3758 (uint8_t)ia_css_pipe_get_pipe_num(capture_pipe),
3759 capture_pipe->config.default_capture_config.enable_xnr != 0,
3760 capture_pipe->stream->config.pixels_per_clock == 2,
3761 true, /* continuous */
3762 false, /* offline */
3763 capture_pipe->required_bds_factor,
3765 IA_CSS_INPUT_MODE_MEMORY,
3766 &pipe->stream->config.metadata_config,
3767 &pipe->stream->info.metadata_info,
3768 (enum mipi_port_id)0);
3772 sh_css_sp_init_pipeline(&acc_pipe->pipeline,
3774 (uint8_t)ia_css_pipe_get_pipe_num(acc_pipe),
3776 pipe->stream->config.pixels_per_clock == 2,
3777 false, /* continuous */
3778 false, /* offline */
3779 pipe->required_bds_factor,
3781 IA_CSS_INPUT_MODE_MEMORY,
3784 (enum mipi_port_id)0);
3787 start_pipe(pipe, copy_ovrd, preview_pipe_input_mode);
3789 IA_CSS_LEAVE_ERR_PRIVATE(err);
3794 ia_css_pipe_enqueue_buffer(struct ia_css_pipe *pipe,
3795 const struct ia_css_buffer *buffer)
3798 unsigned int thread_id;
3799 enum sh_css_queue_id queue_id;
3800 struct ia_css_pipeline *pipeline;
3801 struct ia_css_pipeline_stage *stage;
3802 struct ia_css_rmgr_vbuf_handle p_vbuf;
3803 struct ia_css_rmgr_vbuf_handle *h_vbuf;
3804 struct sh_css_hmm_buffer ddr_buffer;
3805 enum ia_css_buffer_type buf_type;
3806 enum ia_css_pipe_id pipe_id;
3809 IA_CSS_ENTER("pipe=%p, buffer=%p", pipe, buffer);
3811 if ((!pipe) || (!buffer)) {
3812 IA_CSS_LEAVE_ERR(-EINVAL);
3816 buf_type = buffer->type;
3818 pipe_id = pipe->mode;
3820 IA_CSS_LOG("pipe_id=%d, buf_type=%d", pipe_id, buf_type);
3822 assert(pipe_id < IA_CSS_PIPE_ID_NUM);
3823 assert(buf_type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE);
3824 if (buf_type == IA_CSS_BUFFER_TYPE_INVALID ||
3825 buf_type >= IA_CSS_NUM_DYNAMIC_BUFFER_TYPE ||
3826 pipe_id >= IA_CSS_PIPE_ID_NUM) {
3827 IA_CSS_LEAVE_ERR(-EINVAL);
3831 ret_err = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
3833 IA_CSS_LEAVE_ERR(-EINVAL);
3837 ret_err = ia_css_query_internal_queue_id(buf_type, thread_id, &queue_id);
3839 IA_CSS_LEAVE_ERR(-EINVAL);
3843 if ((queue_id <= SH_CSS_INVALID_QUEUE_ID) || (queue_id >= SH_CSS_MAX_NUM_QUEUES)) {
3844 IA_CSS_LEAVE_ERR(-EINVAL);
3848 if (!sh_css_sp_is_running()) {
3849 IA_CSS_LOG("SP is not running!");
3850 IA_CSS_LEAVE_ERR(-EBUSY);
3851 /* SP is not running. The queues are not valid */
3855 pipeline = &pipe->pipeline;
3858 pipe_id == IA_CSS_PIPE_ID_COPY ||
3859 pipe_id == IA_CSS_PIPE_ID_ACC);
3861 assert(sizeof(NULL) <= sizeof(ddr_buffer.kernel_ptr));
3862 ddr_buffer.kernel_ptr = HOST_ADDRESS(NULL);
3863 ddr_buffer.cookie_ptr = buffer->driver_cookie;
3864 ddr_buffer.timing_data = buffer->timing_data;
3866 if (buf_type == IA_CSS_BUFFER_TYPE_3A_STATISTICS) {
3867 if (!buffer->data.stats_3a) {
3868 IA_CSS_LEAVE_ERR(-EINVAL);
3871 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.stats_3a);
3872 ddr_buffer.payload.s3a = *buffer->data.stats_3a;
3873 } else if (buf_type == IA_CSS_BUFFER_TYPE_DIS_STATISTICS) {
3874 if (!buffer->data.stats_dvs) {
3875 IA_CSS_LEAVE_ERR(-EINVAL);
3878 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.stats_dvs);
3879 ddr_buffer.payload.dis = *buffer->data.stats_dvs;
3880 } else if (buf_type == IA_CSS_BUFFER_TYPE_METADATA) {
3881 if (!buffer->data.metadata) {
3882 IA_CSS_LEAVE_ERR(-EINVAL);
3885 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.metadata);
3886 ddr_buffer.payload.metadata = *buffer->data.metadata;
3887 } else if (buf_type == IA_CSS_BUFFER_TYPE_INPUT_FRAME ||
3888 buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME ||
3889 buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME ||
3890 buf_type == IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME ||
3891 buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME) {
3892 if (!buffer->data.frame) {
3893 IA_CSS_LEAVE_ERR(-EINVAL);
3896 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.frame);
3897 ddr_buffer.payload.frame.frame_data = buffer->data.frame->data;
3898 ddr_buffer.payload.frame.flashed = 0;
3900 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
3901 "ia_css_pipe_enqueue_buffer() buf_type=%d, data(DDR address)=0x%x\n",
3902 buf_type, buffer->data.frame->data);
3906 /* start of test for using rmgr for acq/rel memory */
3909 p_vbuf.size = sizeof(struct sh_css_hmm_buffer);
3911 /* TODO: change next to correct pool for optimization */
3912 ia_css_rmgr_acq_vbuf(hmm_buffer_pool, &h_vbuf);
3914 if ((!h_vbuf) || (h_vbuf->vptr == 0x0)) {
3915 IA_CSS_LEAVE_ERR(-EINVAL);
3919 hmm_store(h_vbuf->vptr,
3920 (void *)(&ddr_buffer),
3921 sizeof(struct sh_css_hmm_buffer));
3922 if (buf_type == IA_CSS_BUFFER_TYPE_3A_STATISTICS ||
3923 buf_type == IA_CSS_BUFFER_TYPE_DIS_STATISTICS ||
3924 buf_type == IA_CSS_BUFFER_TYPE_LACE_STATISTICS) {
3926 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &h_vbuf);
3927 IA_CSS_LOG("pipeline is empty!");
3928 IA_CSS_LEAVE_ERR(-EINVAL);
3932 for (stage = pipeline->stages; stage; stage = stage->next) {
3934 * The SP will read the params after it got
3937 if (STATS_ENABLED(stage)) {
3938 /* there is a stage that needs it */
3939 return_err = ia_css_bufq_enqueue_buffer(thread_id,
3941 (uint32_t)h_vbuf->vptr);
3944 } else if (buf_type == IA_CSS_BUFFER_TYPE_INPUT_FRAME ||
3945 buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME ||
3946 buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME ||
3947 buf_type == IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME ||
3948 buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME ||
3949 buf_type == IA_CSS_BUFFER_TYPE_METADATA) {
3950 return_err = ia_css_bufq_enqueue_buffer(thread_id,
3952 (uint32_t)h_vbuf->vptr);
3954 buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) {
3955 IA_CSS_LOG("pfp: enqueued OF %d to q %d thread %d",
3956 ddr_buffer.payload.frame.frame_data,
3957 queue_id, thread_id);
3962 if (sh_css_hmm_buffer_record_acquire(
3964 HOST_ADDRESS(ddr_buffer.kernel_ptr))) {
3965 IA_CSS_LOG("send vbuf=%p", h_vbuf);
3967 return_err = -EINVAL;
3968 IA_CSS_ERROR("hmm_buffer_record[]: no available slots\n");
3973 * Tell the SP which queues are not empty,
3974 * by sending the software event.
3977 if (!sh_css_sp_is_running()) {
3978 /* SP is not running. The queues are not valid */
3979 IA_CSS_LOG("SP is not running!");
3980 IA_CSS_LEAVE_ERR(-EBUSY);
3983 return_err = ia_css_bufq_enqueue_psys_event(
3984 IA_CSS_PSYS_SW_EVENT_BUFFER_ENQUEUED,
3989 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &h_vbuf);
3990 IA_CSS_ERROR("buffer not enqueued");
3993 IA_CSS_LEAVE("return value = %d", return_err);
3999 * TODO: Free up the hmm memory space.
4002 ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe,
4003 struct ia_css_buffer *buffer)
4006 enum sh_css_queue_id queue_id;
4007 ia_css_ptr ddr_buffer_addr = (ia_css_ptr)0;
4008 struct sh_css_hmm_buffer ddr_buffer;
4009 enum ia_css_buffer_type buf_type;
4010 enum ia_css_pipe_id pipe_id;
4011 unsigned int thread_id;
4012 hrt_address kernel_ptr = 0;
4015 IA_CSS_ENTER("pipe=%p, buffer=%p", pipe, buffer);
4017 if ((!pipe) || (!buffer)) {
4018 IA_CSS_LEAVE_ERR(-EINVAL);
4022 pipe_id = pipe->mode;
4024 buf_type = buffer->type;
4026 IA_CSS_LOG("pipe_id=%d, buf_type=%d", pipe_id, buf_type);
4028 ddr_buffer.kernel_ptr = 0;
4030 ret_err = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
4032 IA_CSS_LEAVE_ERR(-EINVAL);
4036 ret_err = ia_css_query_internal_queue_id(buf_type, thread_id, &queue_id);
4038 IA_CSS_LEAVE_ERR(-EINVAL);
4042 if ((queue_id <= SH_CSS_INVALID_QUEUE_ID) || (queue_id >= SH_CSS_MAX_NUM_QUEUES)) {
4043 IA_CSS_LEAVE_ERR(-EINVAL);
4047 if (!sh_css_sp_is_running()) {
4048 IA_CSS_LOG("SP is not running!");
4049 IA_CSS_LEAVE_ERR(-EBUSY);
4050 /* SP is not running. The queues are not valid */
4054 return_err = ia_css_bufq_dequeue_buffer(queue_id,
4055 (uint32_t *)&ddr_buffer_addr);
4058 struct ia_css_frame *frame;
4059 struct sh_css_hmm_buffer_record *hmm_buffer_record = NULL;
4061 IA_CSS_LOG("receive vbuf=%x", (int)ddr_buffer_addr);
4063 /* Validate the ddr_buffer_addr and buf_type */
4064 hmm_buffer_record = sh_css_hmm_buffer_record_validate(
4065 ddr_buffer_addr, buf_type);
4066 if (hmm_buffer_record) {
4068 * valid hmm_buffer_record found. Save the kernel_ptr
4069 * for validation after performing hmm_load. The
4070 * vbuf handle and buffer_record can be released.
4072 kernel_ptr = hmm_buffer_record->kernel_ptr;
4073 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &hmm_buffer_record->h_vbuf);
4074 sh_css_hmm_buffer_record_reset(hmm_buffer_record);
4076 IA_CSS_ERROR("hmm_buffer_record not found (0x%x) buf_type(%d)",
4077 ddr_buffer_addr, buf_type);
4078 IA_CSS_LEAVE_ERR(-EINVAL);
4082 hmm_load(ddr_buffer_addr,
4084 sizeof(struct sh_css_hmm_buffer));
4087 * if the kernel_ptr is 0 or an invalid, return an error.
4088 * do not access the buffer via the kernal_ptr.
4090 if ((ddr_buffer.kernel_ptr == 0) ||
4091 (kernel_ptr != HOST_ADDRESS(ddr_buffer.kernel_ptr))) {
4092 IA_CSS_ERROR("kernel_ptr invalid");
4093 IA_CSS_ERROR("expected: (0x%llx)", (u64)kernel_ptr);
4094 IA_CSS_ERROR("actual: (0x%llx)", (u64)HOST_ADDRESS(ddr_buffer.kernel_ptr));
4095 IA_CSS_ERROR("buf_type: %d\n", buf_type);
4096 IA_CSS_LEAVE_ERR(-EINVAL);
4100 if (ddr_buffer.kernel_ptr != 0) {
4102 * buffer->exp_id : all instances to be removed later
4103 * once the driver change is completed. See patch #5758
4107 buffer->driver_cookie = ddr_buffer.cookie_ptr;
4108 buffer->timing_data = ddr_buffer.timing_data;
4110 if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME ||
4111 buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME) {
4112 buffer->isys_eof_clock_tick.ticks = ddr_buffer.isys_eof_clock_tick;
4116 case IA_CSS_BUFFER_TYPE_INPUT_FRAME:
4117 case IA_CSS_BUFFER_TYPE_OUTPUT_FRAME:
4118 case IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME:
4119 if (pipe && pipe->stop_requested) {
4120 #if !defined(ISP2401)
4122 * free mipi frames only for old input
4123 * system for 2401 it is done in
4124 * ia_css_stream_destroy call
4126 return_err = free_mipi_frames(pipe);
4128 IA_CSS_LOG("free_mipi_frames() failed");
4129 IA_CSS_LEAVE_ERR(return_err);
4133 pipe->stop_requested = false;
4136 case IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME:
4137 case IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME:
4138 frame = (struct ia_css_frame *)HOST_ADDRESS(ddr_buffer.kernel_ptr);
4139 buffer->data.frame = frame;
4140 buffer->exp_id = ddr_buffer.payload.frame.exp_id;
4141 frame->exp_id = ddr_buffer.payload.frame.exp_id;
4142 frame->isp_config_id = ddr_buffer.payload.frame.isp_parameters_id;
4143 if (ddr_buffer.payload.frame.flashed == 1)
4144 frame->flash_state =
4145 IA_CSS_FRAME_FLASH_STATE_PARTIAL;
4146 if (ddr_buffer.payload.frame.flashed == 2)
4147 frame->flash_state =
4148 IA_CSS_FRAME_FLASH_STATE_FULL;
4149 frame->valid = pipe->num_invalid_frames == 0;
4151 pipe->num_invalid_frames--;
4153 if (frame->info.format == IA_CSS_FRAME_FORMAT_BINARY_8) {
4155 frame->planes.binary.size = frame->data_bytes;
4157 frame->planes.binary.size =
4158 sh_css_sp_get_binary_copy_size();
4161 if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) {
4162 IA_CSS_LOG("pfp: dequeued OF %d with config id %d thread %d",
4163 frame->data, frame->isp_config_id, thread_id);
4166 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
4167 "ia_css_pipe_dequeue_buffer() buf_type=%d, data(DDR address)=0x%x\n",
4168 buf_type, buffer->data.frame->data);
4171 case IA_CSS_BUFFER_TYPE_3A_STATISTICS:
4172 buffer->data.stats_3a =
4173 (struct ia_css_isp_3a_statistics *)HOST_ADDRESS(ddr_buffer.kernel_ptr);
4174 buffer->exp_id = ddr_buffer.payload.s3a.exp_id;
4175 buffer->data.stats_3a->exp_id = ddr_buffer.payload.s3a.exp_id;
4176 buffer->data.stats_3a->isp_config_id = ddr_buffer.payload.s3a.isp_config_id;
4178 case IA_CSS_BUFFER_TYPE_DIS_STATISTICS:
4179 buffer->data.stats_dvs =
4180 (struct ia_css_isp_dvs_statistics *)
4181 HOST_ADDRESS(ddr_buffer.kernel_ptr);
4182 buffer->exp_id = ddr_buffer.payload.dis.exp_id;
4183 buffer->data.stats_dvs->exp_id = ddr_buffer.payload.dis.exp_id;
4185 case IA_CSS_BUFFER_TYPE_LACE_STATISTICS:
4187 case IA_CSS_BUFFER_TYPE_METADATA:
4188 buffer->data.metadata =
4189 (struct ia_css_metadata *)HOST_ADDRESS(ddr_buffer.kernel_ptr);
4190 buffer->exp_id = ddr_buffer.payload.metadata.exp_id;
4191 buffer->data.metadata->exp_id = ddr_buffer.payload.metadata.exp_id;
4194 return_err = -EINVAL;
4201 * Tell the SP which queues are not full,
4202 * by sending the software event.
4205 if (!sh_css_sp_is_running()) {
4206 IA_CSS_LOG("SP is not running!");
4207 IA_CSS_LEAVE_ERR(-EBUSY);
4208 /* SP is not running. The queues are not valid */
4211 ia_css_bufq_enqueue_psys_event(
4212 IA_CSS_PSYS_SW_EVENT_BUFFER_DEQUEUED,
4217 IA_CSS_LEAVE("buffer=%p", buffer);
4223 * Cannot Move this to event module as it is of ia_css_event_type which is declared in ia_css.h
4224 * TODO: modify and move it if possible.
4226 * !!!IMPORTANT!!! KEEP THE FOLLOWING IN SYNC:
4227 * 1) "enum ia_css_event_type" (ia_css_event_public.h)
4228 * 2) "enum sh_css_sp_event_type" (sh_css_internal.h)
4229 * 3) "enum ia_css_event_type event_id_2_event_mask" (event_handler.sp.c)
4230 * 4) "enum ia_css_event_type convert_event_sp_to_host_domain" (sh_css.c)
4232 static enum ia_css_event_type convert_event_sp_to_host_domain[] = {
4233 IA_CSS_EVENT_TYPE_OUTPUT_FRAME_DONE, /* Output frame ready. */
4234 IA_CSS_EVENT_TYPE_SECOND_OUTPUT_FRAME_DONE, /* Second output frame ready. */
4235 IA_CSS_EVENT_TYPE_VF_OUTPUT_FRAME_DONE, /* Viewfinder Output frame ready. */
4236 IA_CSS_EVENT_TYPE_SECOND_VF_OUTPUT_FRAME_DONE, /* Second viewfinder Output frame ready. */
4237 IA_CSS_EVENT_TYPE_3A_STATISTICS_DONE, /* Indication that 3A statistics are available. */
4238 IA_CSS_EVENT_TYPE_DIS_STATISTICS_DONE, /* Indication that DIS statistics are available. */
4239 IA_CSS_EVENT_TYPE_PIPELINE_DONE, /* Pipeline Done event, sent after last pipeline stage. */
4240 IA_CSS_EVENT_TYPE_FRAME_TAGGED, /* Frame tagged. */
4241 IA_CSS_EVENT_TYPE_INPUT_FRAME_DONE, /* Input frame ready. */
4242 IA_CSS_EVENT_TYPE_METADATA_DONE, /* Metadata ready. */
4243 IA_CSS_EVENT_TYPE_LACE_STATISTICS_DONE, /* Indication that LACE statistics are available. */
4244 IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE, /* Extension stage executed. */
4245 IA_CSS_EVENT_TYPE_TIMER, /* Timing measurement data. */
4246 IA_CSS_EVENT_TYPE_PORT_EOF, /* End Of Frame event, sent when in buffered sensor mode. */
4247 IA_CSS_EVENT_TYPE_FW_WARNING, /* Performance warning encountered by FW */
4248 IA_CSS_EVENT_TYPE_FW_ASSERT, /* Assertion hit by FW */
4249 0, /* error if sp passes SH_CSS_SP_EVENT_NR_OF_TYPES as a valid event. */
4253 ia_css_dequeue_psys_event(struct ia_css_event *event)
4255 enum ia_css_pipe_id pipe_id = 0;
4256 u8 payload[4] = {0, 0, 0, 0};
4261 * a) use generic decoding function , same as the one used by sp.
4262 * b) group decode and dequeue into eventQueue module
4264 * We skip the IA_CSS_ENTER logging call
4265 * to avoid flooding the logs when the host application
4271 /* SP is not running. The queues are not valid */
4272 if (!sh_css_sp_is_running())
4275 /* dequeue the event (if any) from the psys event queue */
4276 ret_err = ia_css_bufq_dequeue_psys_event(payload);
4280 IA_CSS_LOG("event dequeued from psys event queue");
4282 /* Tell the SP that we dequeued an event from the event queue. */
4283 ia_css_bufq_enqueue_psys_event(
4284 IA_CSS_PSYS_SW_EVENT_EVENT_DEQUEUED, 0, 0, 0);
4287 * Events are decoded into 4 bytes of payload, the first byte
4288 * contains the sp event type. This is converted to a host enum.
4289 * TODO: can this enum conversion be eliminated
4291 event->type = convert_event_sp_to_host_domain[payload[0]];
4292 /* Some sane default values since not all events use all fields. */
4294 event->port = MIPI_PORT0_ID;
4296 event->fw_warning = IA_CSS_FW_WARNING_NONE;
4297 event->fw_handle = 0;
4298 event->timer_data = 0;
4299 event->timer_code = 0;
4300 event->timer_subcode = 0;
4302 if (event->type == IA_CSS_EVENT_TYPE_TIMER) {
4304 * timer event ??? get the 2nd event and decode the data
4305 * into the event struct
4308 /* 1st event: LSB 16-bit timer data and code */
4309 event->timer_data = ((payload[1] & 0xFF) | ((payload[3] & 0xFF) << 8));
4310 event->timer_code = payload[2];
4311 payload[0] = payload[1] = payload[2] = payload[3] = 0;
4312 ret_err = ia_css_bufq_dequeue_psys_event(payload);
4314 /* no 2nd event ??? an error */
4316 * Putting IA_CSS_ERROR is resulting in failures in
4317 * Merrifield smoke testing
4319 IA_CSS_WARNING("Timer: Error de-queuing the 2nd TIMER event!!!\n");
4322 ia_css_bufq_enqueue_psys_event(
4323 IA_CSS_PSYS_SW_EVENT_EVENT_DEQUEUED, 0, 0, 0);
4324 event->type = convert_event_sp_to_host_domain[payload[0]];
4326 if (event->type == IA_CSS_EVENT_TYPE_TIMER) {
4327 /* 2nd event data: MSB 16-bit timer and subcode */
4328 tmp_data = ((payload[1] & 0xFF) | ((payload[3] & 0xFF) << 8));
4329 event->timer_data |= (tmp_data << 16);
4330 event->timer_subcode = payload[2];
4333 * It's a non timer event. So clear first half of the
4335 * If the second part of the TIMER event is not
4336 * received, we discard the first half of the timer
4337 * data and process the non timer event without
4338 * affecting the flow. So the non timer event falls
4341 event->timer_data = 0;
4342 event->timer_code = 0;
4343 event->timer_subcode = 0;
4344 IA_CSS_ERROR("Missing 2nd timer event. Timer event discarded");
4347 if (event->type == IA_CSS_EVENT_TYPE_PORT_EOF) {
4348 event->port = (enum mipi_port_id)payload[1];
4349 event->exp_id = payload[3];
4350 } else if (event->type == IA_CSS_EVENT_TYPE_FW_WARNING) {
4351 event->fw_warning = (enum ia_css_fw_warning)payload[1];
4352 /* exp_id is only available in these warning types */
4353 if (event->fw_warning == IA_CSS_FW_WARNING_EXP_ID_LOCKED ||
4354 event->fw_warning == IA_CSS_FW_WARNING_TAG_EXP_ID_FAILED)
4355 event->exp_id = payload[3];
4356 } else if (event->type == IA_CSS_EVENT_TYPE_FW_ASSERT) {
4357 event->fw_assert_module_id = payload[1]; /* module */
4358 event->fw_assert_line_no = (payload[2] << 8) + payload[3];
4359 /* payload[2] is line_no>>8, payload[3] is line_no&0xff */
4360 } else if (event->type != IA_CSS_EVENT_TYPE_TIMER) {
4362 * pipe related events.
4363 * payload[1] contains the pipe_num,
4364 * payload[2] contains the pipe_id. These are different.
4366 event->pipe = find_pipe_by_num(payload[1]);
4367 pipe_id = (enum ia_css_pipe_id)payload[2];
4368 /* Check to see if pipe still exists */
4372 if (event->type == IA_CSS_EVENT_TYPE_FRAME_TAGGED) {
4373 /* find the capture pipe that goes with this */
4376 n = event->pipe->stream->num_pipes;
4377 for (i = 0; i < n; i++) {
4378 struct ia_css_pipe *p =
4379 event->pipe->stream->pipes[i];
4380 if (p->config.mode == IA_CSS_PIPE_MODE_CAPTURE) {
4385 event->exp_id = payload[3];
4387 if (event->type == IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE) {
4388 /* payload[3] contains the acc fw handle. */
4389 u32 stage_num = (uint32_t)payload[3];
4391 ret_err = ia_css_pipeline_get_fw_from_stage(
4392 &event->pipe->pipeline,
4396 IA_CSS_ERROR("Invalid stage num received for ACC event. stage_num:%u",
4404 IA_CSS_LEAVE("event_id=%d, pipe_id=%d", event->type, pipe_id);
4406 IA_CSS_LEAVE("event_id=%d", event->type);
4412 ia_css_dequeue_isys_event(struct ia_css_event *event)
4414 u8 payload[4] = {0, 0, 0, 0};
4418 * We skip the IA_CSS_ENTER logging call
4419 * to avoid flooding the logs when the host application
4425 /* SP is not running. The queues are not valid */
4426 if (!sh_css_sp_is_running())
4429 err = ia_css_bufq_dequeue_isys_event(payload);
4433 IA_CSS_LOG("event dequeued from isys event queue");
4435 /* Update SP state to indicate that element was dequeued. */
4436 ia_css_bufq_enqueue_isys_event(IA_CSS_ISYS_SW_EVENT_EVENT_DEQUEUED);
4438 /* Fill return struct with appropriate info */
4439 event->type = IA_CSS_EVENT_TYPE_PORT_EOF;
4440 /* EOF events are associated with a CSI port, not with a pipe */
4442 event->port = payload[1];
4443 event->exp_id = payload[3];
4445 IA_CSS_LEAVE_ERR(err);
4450 acc_start(struct ia_css_pipe *pipe)
4453 assert(pipe->stream);
4455 start_pipe(pipe, SH_CSS_PIPE_CONFIG_OVRD_NO_OVRD,
4456 pipe->stream->config.mode);
4460 sh_css_pipe_start(struct ia_css_stream *stream)
4464 struct ia_css_pipe *pipe;
4465 enum ia_css_pipe_id pipe_id;
4466 unsigned int thread_id;
4468 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
4471 IA_CSS_LEAVE_ERR(-EINVAL);
4474 pipe = stream->last_pipe;
4476 IA_CSS_LEAVE_ERR(-EINVAL);
4480 pipe_id = pipe->mode;
4482 if (stream->started) {
4483 IA_CSS_WARNING("Cannot start stream that is already started");
4484 IA_CSS_LEAVE_ERR(err);
4488 pipe->stop_requested = false;
4491 case IA_CSS_PIPE_ID_PREVIEW:
4492 err = preview_start(pipe);
4494 case IA_CSS_PIPE_ID_VIDEO:
4495 err = video_start(pipe);
4497 case IA_CSS_PIPE_ID_CAPTURE:
4498 err = capture_start(pipe);
4500 case IA_CSS_PIPE_ID_YUVPP:
4501 err = yuvpp_start(pipe);
4503 case IA_CSS_PIPE_ID_ACC:
4509 /* DH regular multi pipe - not continuous mode: start the next pipes too */
4510 if (!stream->config.continuous) {
4513 for (i = 1; i < stream->num_pipes && 0 == err ; i++) {
4514 switch (stream->pipes[i]->mode) {
4515 case IA_CSS_PIPE_ID_PREVIEW:
4516 stream->pipes[i]->stop_requested = false;
4517 err = preview_start(stream->pipes[i]);
4519 case IA_CSS_PIPE_ID_VIDEO:
4520 stream->pipes[i]->stop_requested = false;
4521 err = video_start(stream->pipes[i]);
4523 case IA_CSS_PIPE_ID_CAPTURE:
4524 stream->pipes[i]->stop_requested = false;
4525 err = capture_start(stream->pipes[i]);
4527 case IA_CSS_PIPE_ID_YUVPP:
4528 stream->pipes[i]->stop_requested = false;
4529 err = yuvpp_start(stream->pipes[i]);
4531 case IA_CSS_PIPE_ID_ACC:
4532 stream->pipes[i]->stop_requested = false;
4533 acc_start(stream->pipes[i]);
4541 IA_CSS_LEAVE_ERR_PRIVATE(err);
4546 * Force ISP parameter calculation after a mode change
4547 * Acceleration API examples pass NULL for stream but they
4548 * don't use ISP parameters anyway. So this should be okay.
4549 * The SP binary (jpeg) copy does not use any parameters.
4551 if (!copy_on_sp(pipe)) {
4552 sh_css_invalidate_params(stream);
4553 err = sh_css_param_update_isp_params(pipe,
4554 stream->isp_params_configs, true, NULL);
4556 IA_CSS_LEAVE_ERR_PRIVATE(err);
4561 ia_css_debug_pipe_graph_dump_epilogue();
4563 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
4565 if (!sh_css_sp_is_running()) {
4566 IA_CSS_LEAVE_ERR_PRIVATE(-EBUSY);
4567 /* SP is not running. The queues are not valid */
4570 ia_css_bufq_enqueue_psys_event(IA_CSS_PSYS_SW_EVENT_START_STREAM,
4571 (uint8_t)thread_id, 0, 0);
4573 /* DH regular multi pipe - not continuous mode: enqueue event to the next pipes too */
4574 if (!stream->config.continuous) {
4577 for (i = 1; i < stream->num_pipes; i++) {
4578 ia_css_pipeline_get_sp_thread_id(
4579 ia_css_pipe_get_pipe_num(stream->pipes[i]),
4581 ia_css_bufq_enqueue_psys_event(
4582 IA_CSS_PSYS_SW_EVENT_START_STREAM,
4583 (uint8_t)thread_id, 0, 0);
4587 /* in case of continuous capture mode, we also start capture thread and copy thread*/
4588 if (pipe->stream->config.continuous) {
4589 struct ia_css_pipe *copy_pipe = NULL;
4591 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
4592 copy_pipe = pipe->pipe_settings.preview.copy_pipe;
4593 else if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
4594 copy_pipe = pipe->pipe_settings.video.copy_pipe;
4597 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
4600 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(copy_pipe),
4602 /* by the time we reach here q is initialized and handle is available.*/
4603 ia_css_bufq_enqueue_psys_event(
4604 IA_CSS_PSYS_SW_EVENT_START_STREAM,
4605 (uint8_t)thread_id, 0, 0);
4607 if (pipe->stream->cont_capt) {
4608 struct ia_css_pipe *capture_pipe = NULL;
4610 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
4611 capture_pipe = pipe->pipe_settings.preview.capture_pipe;
4612 else if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
4613 capture_pipe = pipe->pipe_settings.video.capture_pipe;
4615 if (!capture_pipe) {
4616 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
4619 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe),
4621 /* by the time we reach here q is initialized and handle is available.*/
4622 ia_css_bufq_enqueue_psys_event(
4623 IA_CSS_PSYS_SW_EVENT_START_STREAM,
4624 (uint8_t)thread_id, 0, 0);
4627 /* in case of PREVIEW mode, check whether QOS acc_pipe is available, then start the qos pipe */
4628 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) {
4629 struct ia_css_pipe *acc_pipe = NULL;
4631 acc_pipe = pipe->pipe_settings.preview.acc_pipe;
4634 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(acc_pipe),
4636 /* by the time we reach here q is initialized and handle is available.*/
4637 ia_css_bufq_enqueue_psys_event(
4638 IA_CSS_PSYS_SW_EVENT_START_STREAM,
4639 (uint8_t)thread_id, 0, 0);
4643 stream->started = true;
4645 IA_CSS_LEAVE_ERR_PRIVATE(err);
4651 sh_css_enable_cont_capt(bool enable, bool stop_copy_preview)
4653 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
4654 "sh_css_enable_cont_capt() enter: enable=%d\n", enable);
4655 //my_css.cont_capt = enable;
4656 my_css.stop_copy_preview = stop_copy_preview;
4660 sh_css_continuous_is_enabled(uint8_t pipe_num)
4662 struct ia_css_pipe *pipe;
4665 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
4666 "sh_css_continuous_is_enabled() enter: pipe_num=%d\n", pipe_num);
4668 pipe = find_pipe_by_num(pipe_num);
4669 continuous = pipe && pipe->stream->config.continuous;
4670 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
4671 "sh_css_continuous_is_enabled() leave: enable=%d\n",
4678 ia_css_stream_get_max_buffer_depth(struct ia_css_stream *stream,
4683 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_max_buffer_depth() enter: void\n");
4685 *buffer_depth = NUM_CONTINUOUS_FRAMES;
4690 ia_css_stream_set_buffer_depth(struct ia_css_stream *stream, int buffer_depth)
4692 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_set_buffer_depth() enter: num_frames=%d\n", buffer_depth);
4694 if (buffer_depth > NUM_CONTINUOUS_FRAMES || buffer_depth < 1)
4696 /* ok, value allowed */
4697 stream->config.target_num_cont_raw_buf = buffer_depth;
4698 /* TODO: check what to regarding initialization */
4704 ia_css_stream_get_buffer_depth(struct ia_css_stream *stream,
4709 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_buffer_depth() enter: void\n");
4711 *buffer_depth = stream->config.target_num_cont_raw_buf;
4715 #if !defined(ISP2401)
4717 sh_css_get_mipi_sizes_for_check(const unsigned int port, const unsigned int idx)
4719 OP___assert(port < N_CSI_PORTS);
4720 OP___assert(idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT);
4721 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
4722 "sh_css_get_mipi_sizes_for_check(port %d, idx %d): %d\n",
4723 port, idx, my_css.mipi_sizes_for_check[port][idx]);
4724 return my_css.mipi_sizes_for_check[port][idx];
4728 static int sh_css_pipe_configure_output(
4729 struct ia_css_pipe *pipe,
4731 unsigned int height,
4732 unsigned int padded_width,
4733 enum ia_css_frame_format format,
4738 IA_CSS_ENTER_PRIVATE("pipe = %p, width = %d, height = %d, padded width = %d, format = %d, idx = %d",
4739 pipe, width, height, padded_width, format, idx);
4741 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
4745 err = ia_css_util_check_res(width, height);
4747 IA_CSS_LEAVE_ERR_PRIVATE(err);
4750 if (pipe->output_info[idx].res.width != width ||
4751 pipe->output_info[idx].res.height != height ||
4752 pipe->output_info[idx].format != format) {
4753 ia_css_frame_info_init(
4754 &pipe->output_info[idx],
4760 IA_CSS_LEAVE_ERR_PRIVATE(0);
4765 sh_css_pipe_get_shading_info(struct ia_css_pipe *pipe,
4766 struct ia_css_shading_info *shading_info,
4767 struct ia_css_pipe_config *pipe_config)
4770 struct ia_css_binary *binary = NULL;
4772 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
4773 "sh_css_pipe_get_shading_info() enter:\n");
4775 binary = ia_css_pipe_get_shading_correction_binary(pipe);
4778 err = ia_css_binary_get_shading_info(binary,
4779 IA_CSS_SHADING_CORRECTION_TYPE_1,
4780 pipe->required_bds_factor,
4781 (const struct ia_css_stream_config *)&pipe->stream->config,
4782 shading_info, pipe_config);
4785 * Other function calls can be added here when other shading
4786 * correction types will be added in the future.
4790 * When the pipe does not have a binary which has the shading
4791 * correction, this function does not need to fill the shading
4792 * information. It is not a error case, and then
4793 * this function should return 0.
4795 memset(shading_info, 0, sizeof(*shading_info));
4801 sh_css_pipe_get_grid_info(struct ia_css_pipe *pipe,
4802 struct ia_css_grid_info *info)
4805 struct ia_css_binary *binary = NULL;
4810 IA_CSS_ENTER_PRIVATE("");
4812 binary = ia_css_pipe_get_s3a_binary(pipe);
4815 err = ia_css_binary_3a_grid_info(binary, info, pipe);
4819 memset(&info->s3a_grid, 0, sizeof(info->s3a_grid));
4822 binary = ia_css_pipe_get_sdis_binary(pipe);
4825 ia_css_binary_dvs_grid_info(binary, info, pipe);
4826 ia_css_binary_dvs_stat_grid_info(binary, info, pipe);
4828 memset(&info->dvs_grid, 0, sizeof(info->dvs_grid));
4829 memset(&info->dvs_grid.dvs_stat_grid_info, 0,
4830 sizeof(info->dvs_grid.dvs_stat_grid_info));
4834 /* copy pipe does not have ISP binary*/
4835 info->isp_in_width = binary->internal_frame_info.res.width;
4836 info->isp_in_height = binary->internal_frame_info.res.height;
4839 info->vamem_type = IA_CSS_VAMEM_TYPE_2;
4842 IA_CSS_LEAVE_ERR_PRIVATE(err);
4848 * @brief Check if a format is supported by the pipe.
4852 ia_css_pipe_check_format(struct ia_css_pipe *pipe,
4853 enum ia_css_frame_format format)
4855 const enum ia_css_frame_format *supported_formats;
4856 int number_of_formats;
4860 IA_CSS_ENTER_PRIVATE("");
4862 if (NULL == pipe || NULL == pipe->pipe_settings.video.video_binary.info) {
4863 IA_CSS_ERROR("Pipe or binary info is not set");
4864 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
4868 supported_formats = pipe->pipe_settings.video.video_binary.info->output_formats;
4869 number_of_formats = sizeof(pipe->pipe_settings.video.video_binary.info->output_formats) / sizeof(enum ia_css_frame_format);
4871 for (i = 0; i < number_of_formats && !found; i++) {
4872 if (supported_formats[i] == format) {
4878 IA_CSS_ERROR("Requested format is not supported by binary");
4879 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
4882 IA_CSS_LEAVE_ERR_PRIVATE(0);
4886 static int load_video_binaries(struct ia_css_pipe *pipe)
4888 struct ia_css_frame_info video_in_info, tnr_info,
4889 *video_vf_info, video_bds_out_info, *pipe_out_info, *pipe_vf_out_info;
4892 bool continuous = pipe->stream->config.continuous;
4894 unsigned int num_output_pins;
4895 struct ia_css_frame_info video_bin_out_info;
4896 bool need_scaler = false;
4897 bool vf_res_different_than_output = false;
4898 bool need_vf_pp = false;
4900 struct ia_css_video_settings *mycs = &pipe->pipe_settings.video;
4902 IA_CSS_ENTER_PRIVATE("");
4904 assert(pipe->mode == IA_CSS_PIPE_ID_VIDEO);
4906 * we only test the video_binary because offline video doesn't need a
4907 * vf_pp binary and online does not (always use) the copy_binary.
4908 * All are always reset at the same time anyway.
4910 if (mycs->video_binary.info)
4913 online = pipe->stream->config.online;
4914 pipe_out_info = &pipe->output_info[0];
4915 pipe_vf_out_info = &pipe->vf_output_info[0];
4917 assert(pipe_out_info);
4920 * There is no explicit input format requirement for raw or yuv
4921 * What matters is that there is a binary that supports the stream format.
4922 * This is checked in the binary_find(), so no need to check it here
4924 err = ia_css_util_check_input(&pipe->stream->config, false, false);
4927 /* cannot have online video and input_mode memory */
4928 if (online && pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY)
4930 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
4931 err = ia_css_util_check_vf_out_info(pipe_out_info,
4936 err = ia_css_frame_check_info(pipe_out_info);
4941 if (pipe->out_yuv_ds_input_info.res.width)
4942 video_bin_out_info = pipe->out_yuv_ds_input_info;
4944 video_bin_out_info = *pipe_out_info;
4947 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
4948 video_vf_info = pipe_vf_out_info;
4949 vf_res_different_than_output = (video_vf_info->res.width !=
4950 video_bin_out_info.res.width) ||
4951 (video_vf_info->res.height != video_bin_out_info.res.height);
4953 video_vf_info = NULL;
4956 need_scaler = need_downscaling(video_bin_out_info.res, pipe_out_info->res);
4958 /* we build up the pipeline starting at the end */
4959 /* YUV post-processing if needed */
4961 struct ia_css_cas_binary_descr cas_scaler_descr = { };
4963 /* NV12 is the common format that is supported by both */
4964 /* yuv_scaler and the video_xx_isp2_min binaries. */
4965 video_bin_out_info.format = IA_CSS_FRAME_FORMAT_NV12;
4967 err = ia_css_pipe_create_cas_scaler_desc_single_output(
4968 &video_bin_out_info,
4974 mycs->num_yuv_scaler = cas_scaler_descr.num_stage;
4975 mycs->yuv_scaler_binary = kcalloc(cas_scaler_descr.num_stage,
4976 sizeof(struct ia_css_binary),
4978 if (!mycs->yuv_scaler_binary) {
4982 mycs->is_output_stage = kcalloc(cas_scaler_descr.num_stage,
4983 sizeof(bool), GFP_KERNEL);
4984 if (!mycs->is_output_stage) {
4988 for (i = 0; i < cas_scaler_descr.num_stage; i++) {
4989 struct ia_css_binary_descr yuv_scaler_descr;
4991 mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i];
4992 ia_css_pipe_get_yuvscaler_binarydesc(pipe,
4993 &yuv_scaler_descr, &cas_scaler_descr.in_info[i],
4994 &cas_scaler_descr.out_info[i],
4995 &cas_scaler_descr.internal_out_info[i],
4996 &cas_scaler_descr.vf_info[i]);
4997 err = ia_css_binary_find(&yuv_scaler_descr,
4998 &mycs->yuv_scaler_binary[i]);
5000 kfree(mycs->is_output_stage);
5001 mycs->is_output_stage = NULL;
5005 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
5009 struct ia_css_binary_descr video_descr;
5010 enum ia_css_frame_format vf_info_format;
5012 err = ia_css_pipe_get_video_binarydesc(pipe,
5013 &video_descr, &video_in_info, &video_bds_out_info, &video_bin_out_info,
5015 pipe->stream->config.left_padding);
5020 * In the case where video_vf_info is not NULL, this allows
5021 * us to find a potential video library with desired vf format.
5022 * If success, no vf_pp binary is needed.
5023 * If failed, we will look up video binary with YUV_LINE vf format
5025 err = ia_css_binary_find(&video_descr,
5026 &mycs->video_binary);
5029 /* This will do another video binary lookup later for YUV_LINE format*/
5034 } else if (video_vf_info) {
5036 * The first video binary lookup is successful, but we
5037 * may still need vf_pp binary based on additional check
5039 num_output_pins = mycs->video_binary.info->num_output_pins;
5040 vf_ds_log2 = mycs->video_binary.vf_downscale_log2;
5043 * If the binary has dual output pins, we need vf_pp
5044 * if the resolution is different.
5046 need_vf_pp |= ((num_output_pins == 2) && vf_res_different_than_output);
5049 * If the binary has single output pin, we need vf_pp
5050 * if additional scaling is needed for vf
5052 need_vf_pp |= ((num_output_pins == 1) &&
5053 ((video_vf_info->res.width << vf_ds_log2 != pipe_out_info->res.width) ||
5054 (video_vf_info->res.height << vf_ds_log2 != pipe_out_info->res.height)));
5058 /* save the current vf_info format for restoration later */
5059 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5060 "load_video_binaries() need_vf_pp; find video binary with YUV_LINE again\n");
5062 vf_info_format = video_vf_info->format;
5064 if (!pipe->config.enable_vfpp_bci)
5065 ia_css_frame_info_set_format(video_vf_info,
5066 IA_CSS_FRAME_FORMAT_YUV_LINE);
5068 ia_css_binary_destroy_isp_parameters(&mycs->video_binary);
5070 err = ia_css_binary_find(&video_descr,
5071 &mycs->video_binary);
5073 /* restore original vf_info format */
5074 ia_css_frame_info_set_format(video_vf_info,
5082 * If a video binary does not use a ref_frame, we set the frame delay
5083 * to 0. This is the case for the 1-stage low-power video binary.
5085 if (!mycs->video_binary.info->sp.enable.ref_frame)
5086 pipe->dvs_frame_delay = 0;
5089 * The delay latency determines the number of invalid frames after
5090 * a stream is started.
5092 pipe->num_invalid_frames = pipe->dvs_frame_delay;
5093 pipe->info.num_invalid_frames = pipe->num_invalid_frames;
5096 * Viewfinder frames also decrement num_invalid_frames. If the pipe
5097 * outputs a viewfinder output, then we need double the number of
5101 pipe->num_invalid_frames *= 2;
5103 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5104 "load_video_binaries() num_invalid_frames=%d dvs_frame_delay=%d\n",
5105 pipe->num_invalid_frames, pipe->dvs_frame_delay);
5107 /* pqiao TODO: temp hack for PO, should be removed after offline YUVPP is enabled */
5108 #if !defined(ISP2401)
5110 if (!online && !continuous) {
5112 * TODO: what exactly needs doing, prepend the copy binary to
5113 * video base this only on !online?
5115 err = load_copy_binary(pipe,
5117 &mycs->video_binary);
5125 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] && need_vf_pp) {
5126 struct ia_css_binary_descr vf_pp_descr;
5128 if (mycs->video_binary.vf_frame_info.format
5129 == IA_CSS_FRAME_FORMAT_YUV_LINE) {
5130 ia_css_pipe_get_vfpp_binarydesc(pipe, &vf_pp_descr,
5131 &mycs->video_binary.vf_frame_info,
5135 * output from main binary is not yuv line. currently
5136 * this is possible only when bci is enabled on vfpp
5139 assert(pipe->config.enable_vfpp_bci);
5140 ia_css_pipe_get_yuvscaler_binarydesc(pipe, &vf_pp_descr,
5141 &mycs->video_binary.vf_frame_info,
5142 pipe_vf_out_info, NULL, NULL);
5145 err = ia_css_binary_find(&vf_pp_descr,
5146 &mycs->vf_pp_binary);
5151 err = allocate_delay_frames(pipe);
5156 if (mycs->video_binary.info->sp.enable.block_output) {
5157 tnr_info = mycs->video_binary.out_frame_info[0];
5159 /* Make tnr reference buffers output block height align */
5160 tnr_info.res.height = CEIL_MUL(tnr_info.res.height,
5161 mycs->video_binary.info->sp.block.output_block_height);
5163 tnr_info = mycs->video_binary.internal_frame_info;
5165 tnr_info.format = IA_CSS_FRAME_FORMAT_YUV_LINE;
5166 tnr_info.raw_bit_depth = SH_CSS_TNR_BIT_DEPTH;
5168 for (i = 0; i < NUM_VIDEO_TNR_FRAMES; i++) {
5169 if (mycs->tnr_frames[i]) {
5170 ia_css_frame_free(mycs->tnr_frames[i]);
5171 mycs->tnr_frames[i] = NULL;
5173 err = ia_css_frame_allocate_from_info(
5174 &mycs->tnr_frames[i],
5179 IA_CSS_LEAVE_PRIVATE("");
5184 unload_video_binaries(struct ia_css_pipe *pipe)
5188 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
5190 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) {
5191 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
5194 ia_css_binary_unload(&pipe->pipe_settings.video.copy_binary);
5195 ia_css_binary_unload(&pipe->pipe_settings.video.video_binary);
5196 ia_css_binary_unload(&pipe->pipe_settings.video.vf_pp_binary);
5198 for (i = 0; i < pipe->pipe_settings.video.num_yuv_scaler; i++)
5199 ia_css_binary_unload(&pipe->pipe_settings.video.yuv_scaler_binary[i]);
5201 kfree(pipe->pipe_settings.video.is_output_stage);
5202 pipe->pipe_settings.video.is_output_stage = NULL;
5203 kfree(pipe->pipe_settings.video.yuv_scaler_binary);
5204 pipe->pipe_settings.video.yuv_scaler_binary = NULL;
5206 IA_CSS_LEAVE_ERR_PRIVATE(0);
5210 static int video_start(struct ia_css_pipe *pipe)
5213 struct ia_css_pipe *copy_pipe, *capture_pipe;
5214 enum sh_css_pipe_config_override copy_ovrd;
5215 enum ia_css_input_mode video_pipe_input_mode;
5216 unsigned int thread_id;
5218 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
5219 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) {
5220 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
5224 video_pipe_input_mode = pipe->stream->config.mode;
5226 copy_pipe = pipe->pipe_settings.video.copy_pipe;
5227 capture_pipe = pipe->pipe_settings.video.capture_pipe;
5229 sh_css_metrics_start_frame();
5231 /* multi stream video needs mipi buffers */
5233 err = send_mipi_frames(pipe);
5237 send_raw_frames(pipe);
5239 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
5240 copy_ovrd = 1 << thread_id;
5242 if (pipe->stream->cont_capt) {
5243 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe),
5245 copy_ovrd |= 1 << thread_id;
5248 /* Construct and load the copy pipe */
5249 if (pipe->stream->config.continuous) {
5250 sh_css_sp_init_pipeline(©_pipe->pipeline,
5251 IA_CSS_PIPE_ID_COPY,
5252 (uint8_t)ia_css_pipe_get_pipe_num(copy_pipe),
5254 pipe->stream->config.pixels_per_clock == 2, false,
5255 false, pipe->required_bds_factor,
5257 pipe->stream->config.mode,
5258 &pipe->stream->config.metadata_config,
5259 &pipe->stream->info.metadata_info,
5260 pipe->stream->config.source.port.port);
5263 * make the video pipe start with mem mode input, copy handles
5266 video_pipe_input_mode = IA_CSS_INPUT_MODE_MEMORY;
5269 /* Construct and load the capture pipe */
5270 if (pipe->stream->cont_capt) {
5271 sh_css_sp_init_pipeline(&capture_pipe->pipeline,
5272 IA_CSS_PIPE_ID_CAPTURE,
5273 (uint8_t)ia_css_pipe_get_pipe_num(capture_pipe),
5274 capture_pipe->config.default_capture_config.enable_xnr != 0,
5275 capture_pipe->stream->config.pixels_per_clock == 2,
5276 true, /* continuous */
5277 false, /* offline */
5278 capture_pipe->required_bds_factor,
5280 IA_CSS_INPUT_MODE_MEMORY,
5281 &pipe->stream->config.metadata_config,
5282 &pipe->stream->info.metadata_info,
5283 (enum mipi_port_id)0);
5286 start_pipe(pipe, copy_ovrd, video_pipe_input_mode);
5288 IA_CSS_LEAVE_ERR_PRIVATE(err);
5293 int sh_css_pipe_get_viewfinder_frame_info(
5294 struct ia_css_pipe *pipe,
5295 struct ia_css_frame_info *info,
5301 /* We could print the pointer as input arg, and the values as output */
5302 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
5303 "sh_css_pipe_get_viewfinder_frame_info() enter: void\n");
5305 if (pipe->mode == IA_CSS_PIPE_ID_CAPTURE &&
5306 (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW ||
5307 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER))
5309 /* offline video does not generate viewfinder output */
5310 *info = pipe->vf_output_info[idx];
5312 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
5313 "sh_css_pipe_get_viewfinder_frame_info() leave: \
5314 info.res.width=%d, info.res.height=%d, \
5315 info.padded_width=%d, info.format=%d, \
5316 info.raw_bit_depth=%d, info.raw_bayer_order=%d\n",
5317 info->res.width, info->res.height,
5318 info->padded_width, info->format,
5319 info->raw_bit_depth, info->raw_bayer_order);
5325 sh_css_pipe_configure_viewfinder(struct ia_css_pipe *pipe, unsigned int width,
5326 unsigned int height, unsigned int min_width,
5327 enum ia_css_frame_format format,
5332 IA_CSS_ENTER_PRIVATE("pipe = %p, width = %d, height = %d, min_width = %d, format = %d, idx = %d\n",
5333 pipe, width, height, min_width, format, idx);
5336 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
5340 err = ia_css_util_check_res(width, height);
5342 IA_CSS_LEAVE_ERR_PRIVATE(err);
5345 if (pipe->vf_output_info[idx].res.width != width ||
5346 pipe->vf_output_info[idx].res.height != height ||
5347 pipe->vf_output_info[idx].format != format)
5348 ia_css_frame_info_init(&pipe->vf_output_info[idx], width, height,
5351 IA_CSS_LEAVE_ERR_PRIVATE(0);
5355 static int load_copy_binaries(struct ia_css_pipe *pipe)
5360 IA_CSS_ENTER_PRIVATE("");
5362 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
5363 pipe->mode == IA_CSS_PIPE_ID_COPY);
5364 if (pipe->pipe_settings.capture.copy_binary.info)
5367 err = ia_css_frame_check_info(&pipe->output_info[0]);
5371 err = verify_copy_out_frame_format(pipe);
5375 err = load_copy_binary(pipe,
5376 &pipe->pipe_settings.capture.copy_binary,
5380 IA_CSS_LEAVE_ERR_PRIVATE(err);
5384 static bool need_capture_pp(
5385 const struct ia_css_pipe *pipe)
5387 const struct ia_css_frame_info *out_info = &pipe->output_info[0];
5389 IA_CSS_ENTER_LEAVE_PRIVATE("");
5391 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE);
5393 /* determine whether we need to use the capture_pp binary.
5394 * This is needed for:
5396 * 2. Digital Zoom or
5397 * 3. YUV downscaling
5399 if (pipe->out_yuv_ds_input_info.res.width &&
5400 ((pipe->out_yuv_ds_input_info.res.width != out_info->res.width) ||
5401 (pipe->out_yuv_ds_input_info.res.height != out_info->res.height)))
5404 if (pipe->config.default_capture_config.enable_xnr != 0)
5407 if ((pipe->stream->isp_params_configs->dz_config.dx < HRT_GDC_N) ||
5408 (pipe->stream->isp_params_configs->dz_config.dy < HRT_GDC_N) ||
5409 pipe->config.enable_dz)
5415 static bool need_capt_ldc(
5416 const struct ia_css_pipe *pipe)
5418 IA_CSS_ENTER_LEAVE_PRIVATE("");
5420 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE);
5421 return (pipe->extra_config.enable_dvs_6axis) ? true : false;
5424 static int set_num_primary_stages(unsigned int *num,
5425 enum ia_css_pipe_version version)
5433 case IA_CSS_PIPE_VERSION_2_6_1:
5434 *num = NUM_PRIMARY_HQ_STAGES;
5436 case IA_CSS_PIPE_VERSION_2_2:
5437 case IA_CSS_PIPE_VERSION_1:
5438 *num = NUM_PRIMARY_STAGES;
5448 static int load_primary_binaries(
5449 struct ia_css_pipe *pipe)
5451 bool online = false;
5452 bool need_pp = false;
5453 bool need_isp_copy_binary = false;
5454 bool need_ldc = false;
5456 bool sensor = false;
5458 bool memory, continuous;
5460 struct ia_css_frame_info prim_in_info,
5462 capt_pp_out_info, vf_info,
5463 *vf_pp_in_info, *pipe_out_info,
5464 *pipe_vf_out_info, *capt_pp_in_info,
5467 struct ia_css_capture_settings *mycs;
5469 bool need_extra_yuv_scaler = false;
5470 struct ia_css_binary_descr prim_descr[MAX_NUM_PRIMARY_STAGES];
5472 IA_CSS_ENTER_PRIVATE("");
5474 assert(pipe->stream);
5475 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
5476 pipe->mode == IA_CSS_PIPE_ID_COPY);
5478 online = pipe->stream->config.online;
5480 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR);
5482 memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
5483 continuous = pipe->stream->config.continuous;
5486 mycs = &pipe->pipe_settings.capture;
5487 pipe_out_info = &pipe->output_info[0];
5488 pipe_vf_out_info = &pipe->vf_output_info[0];
5490 if (mycs->primary_binary[0].info)
5493 err = set_num_primary_stages(&mycs->num_primary_stage,
5494 pipe->config.isp_pipe_version);
5496 IA_CSS_LEAVE_ERR_PRIVATE(err);
5500 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
5501 err = ia_css_util_check_vf_out_info(pipe_out_info, pipe_vf_out_info);
5503 IA_CSS_LEAVE_ERR_PRIVATE(err);
5507 err = ia_css_frame_check_info(pipe_out_info);
5509 IA_CSS_LEAVE_ERR_PRIVATE(err);
5513 need_pp = need_capture_pp(pipe);
5516 * we use the vf output info to get the primary/capture_pp binary
5517 * configured for vf_veceven. It will select the closest downscaling
5520 vf_info = *pipe_vf_out_info;
5523 * WARNING: The #if def flag has been added below as a
5524 * temporary solution to solve the problem of enabling the
5525 * view finder in a single binary in a capture flow. The
5526 * vf-pp stage has been removed for Skycam in the solution
5527 * provided. The vf-pp stage should be re-introduced when
5528 * required. This should not be considered as a clean solution.
5529 * Proper investigation should be done to come up with the clean
5532 ia_css_frame_info_set_format(&vf_info, IA_CSS_FRAME_FORMAT_YUV_LINE);
5535 * TODO: All this yuv_scaler and capturepp calculation logic
5536 * can be shared later. Capture_pp is also a yuv_scale binary
5537 * with extra XNR funcionality. Therefore, it can be made as the
5538 * first step of the cascade.
5540 capt_pp_out_info = pipe->out_yuv_ds_input_info;
5541 capt_pp_out_info.format = IA_CSS_FRAME_FORMAT_YUV420;
5542 capt_pp_out_info.res.width /= MAX_PREFERRED_YUV_DS_PER_STEP;
5543 capt_pp_out_info.res.height /= MAX_PREFERRED_YUV_DS_PER_STEP;
5544 ia_css_frame_info_set_width(&capt_pp_out_info, capt_pp_out_info.res.width, 0);
5546 need_extra_yuv_scaler = need_downscaling(capt_pp_out_info.res,
5547 pipe_out_info->res);
5549 if (need_extra_yuv_scaler) {
5550 struct ia_css_cas_binary_descr cas_scaler_descr = { };
5552 err = ia_css_pipe_create_cas_scaler_desc_single_output(
5558 IA_CSS_LEAVE_ERR_PRIVATE(err);
5561 mycs->num_yuv_scaler = cas_scaler_descr.num_stage;
5562 mycs->yuv_scaler_binary = kcalloc(cas_scaler_descr.num_stage,
5563 sizeof(struct ia_css_binary),
5565 if (!mycs->yuv_scaler_binary) {
5567 IA_CSS_LEAVE_ERR_PRIVATE(err);
5570 mycs->is_output_stage = kcalloc(cas_scaler_descr.num_stage,
5571 sizeof(bool), GFP_KERNEL);
5572 if (!mycs->is_output_stage) {
5574 IA_CSS_LEAVE_ERR_PRIVATE(err);
5577 for (i = 0; i < cas_scaler_descr.num_stage; i++) {
5578 struct ia_css_binary_descr yuv_scaler_descr;
5580 mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i];
5581 ia_css_pipe_get_yuvscaler_binarydesc(pipe,
5582 &yuv_scaler_descr, &cas_scaler_descr.in_info[i],
5583 &cas_scaler_descr.out_info[i],
5584 &cas_scaler_descr.internal_out_info[i],
5585 &cas_scaler_descr.vf_info[i]);
5586 err = ia_css_binary_find(&yuv_scaler_descr,
5587 &mycs->yuv_scaler_binary[i]);
5589 IA_CSS_LEAVE_ERR_PRIVATE(err);
5593 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
5596 capt_pp_out_info = pipe->output_info[0];
5599 /* TODO Do we disable ldc for skycam */
5600 need_ldc = need_capt_ldc(pipe);
5602 /* we build up the pipeline starting at the end */
5603 /* Capture post-processing */
5605 struct ia_css_binary_descr capture_pp_descr;
5607 capt_pp_in_info = need_ldc ? &capt_ldc_out_info : &prim_out_info;
5609 ia_css_pipe_get_capturepp_binarydesc(pipe,
5615 err = ia_css_binary_find(&capture_pp_descr,
5616 &mycs->capture_pp_binary);
5618 IA_CSS_LEAVE_ERR_PRIVATE(err);
5623 struct ia_css_binary_descr capt_ldc_descr;
5625 ia_css_pipe_get_ldc_binarydesc(pipe,
5628 &capt_ldc_out_info);
5630 err = ia_css_binary_find(&capt_ldc_descr,
5631 &mycs->capture_ldc_binary);
5633 IA_CSS_LEAVE_ERR_PRIVATE(err);
5638 prim_out_info = *pipe_out_info;
5642 for (i = 0; i < mycs->num_primary_stage; i++) {
5643 struct ia_css_frame_info *local_vf_info = NULL;
5645 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] &&
5646 (i == mycs->num_primary_stage - 1))
5647 local_vf_info = &vf_info;
5648 ia_css_pipe_get_primary_binarydesc(pipe, &prim_descr[i],
5649 &prim_in_info, &prim_out_info,
5651 err = ia_css_binary_find(&prim_descr[i], &mycs->primary_binary[i]);
5653 IA_CSS_LEAVE_ERR_PRIVATE(err);
5658 /* Viewfinder post-processing */
5660 vf_pp_in_info = &mycs->capture_pp_binary.vf_frame_info;
5662 vf_pp_in_info = &mycs->primary_binary[mycs->num_primary_stage - 1].vf_frame_info;
5665 * WARNING: The #if def flag has been added below as a
5666 * temporary solution to solve the problem of enabling the
5667 * view finder in a single binary in a capture flow. The
5668 * vf-pp stage has been removed for Skycam in the solution
5669 * provided. The vf-pp stage should be re-introduced when
5670 * required. Thisshould not be considered as a clean solution.
5671 * Proper * investigation should be done to come up with the clean
5674 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
5675 struct ia_css_binary_descr vf_pp_descr;
5677 ia_css_pipe_get_vfpp_binarydesc(pipe,
5678 &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info);
5679 err = ia_css_binary_find(&vf_pp_descr, &mycs->vf_pp_binary);
5681 IA_CSS_LEAVE_ERR_PRIVATE(err);
5685 err = allocate_delay_frames(pipe);
5692 * When the input system is 2401, only the Direct Sensor Mode
5693 * Offline Capture uses the ISP copy binary.
5695 need_isp_copy_binary = !online && sensor;
5697 need_isp_copy_binary = !online && !continuous && !memory;
5701 if (need_isp_copy_binary) {
5702 err = load_copy_binary(pipe,
5704 &mycs->primary_binary[0]);
5706 IA_CSS_LEAVE_ERR_PRIVATE(err);
5715 allocate_delay_frames(struct ia_css_pipe *pipe)
5717 unsigned int num_delay_frames = 0, i = 0;
5718 unsigned int dvs_frame_delay = 0;
5719 struct ia_css_frame_info ref_info;
5721 enum ia_css_pipe_id mode = IA_CSS_PIPE_ID_VIDEO;
5722 struct ia_css_frame **delay_frames = NULL;
5724 IA_CSS_ENTER_PRIVATE("");
5727 IA_CSS_ERROR("Invalid args - pipe %p", pipe);
5732 dvs_frame_delay = pipe->dvs_frame_delay;
5734 if (dvs_frame_delay > 0)
5735 num_delay_frames = dvs_frame_delay + 1;
5738 case IA_CSS_PIPE_ID_CAPTURE: {
5739 struct ia_css_capture_settings *mycs_capture = &pipe->pipe_settings.capture;
5744 case IA_CSS_PIPE_ID_VIDEO: {
5745 struct ia_css_video_settings *mycs_video = &pipe->pipe_settings.video;
5747 ref_info = mycs_video->video_binary.internal_frame_info;
5750 * The ref frame expects
5752 * 2. UV plane with line interleaving, like below
5753 * UUUUUU(width/2 times) VVVVVVVV..(width/2 times)
5755 * This format is not YUV420(which has Y, U and V planes).
5756 * Its closer to NV12, except that the UV plane has UV
5757 * interleaving, like UVUVUVUVUVUVUVUVU...
5759 * TODO: make this ref_frame format as a separate frame format
5761 ref_info.format = IA_CSS_FRAME_FORMAT_NV12;
5762 delay_frames = mycs_video->delay_frames;
5765 case IA_CSS_PIPE_ID_PREVIEW: {
5766 struct ia_css_preview_settings *mycs_preview = &pipe->pipe_settings.preview;
5768 ref_info = mycs_preview->preview_binary.internal_frame_info;
5771 * The ref frame expects
5773 * 2. UV plane with line interleaving, like below
5774 * UUUUUU(width/2 times) VVVVVVVV..(width/2 times)
5776 * This format is not YUV420(which has Y, U and V planes).
5777 * Its closer to NV12, except that the UV plane has UV
5778 * interleaving, like UVUVUVUVUVUVUVUVU...
5780 * TODO: make this ref_frame format as a separate frame format
5782 ref_info.format = IA_CSS_FRAME_FORMAT_NV12;
5783 delay_frames = mycs_preview->delay_frames;
5790 ref_info.raw_bit_depth = SH_CSS_REF_BIT_DEPTH;
5792 assert(num_delay_frames <= MAX_NUM_VIDEO_DELAY_FRAMES);
5793 for (i = 0; i < num_delay_frames; i++) {
5794 err = ia_css_frame_allocate_from_info(&delay_frames[i], &ref_info);
5798 IA_CSS_LEAVE_PRIVATE("");
5802 static int load_advanced_binaries(struct ia_css_pipe *pipe)
5804 struct ia_css_frame_info pre_in_info, gdc_in_info,
5805 post_in_info, post_out_info,
5806 vf_info, *vf_pp_in_info, *pipe_out_info,
5809 bool need_isp_copy = true;
5812 IA_CSS_ENTER_PRIVATE("");
5815 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
5816 pipe->mode == IA_CSS_PIPE_ID_COPY);
5817 if (pipe->pipe_settings.capture.pre_isp_binary.info)
5819 pipe_out_info = &pipe->output_info[0];
5820 pipe_vf_out_info = &pipe->vf_output_info[0];
5822 vf_info = *pipe_vf_out_info;
5823 err = ia_css_util_check_vf_out_info(pipe_out_info, &vf_info);
5826 need_pp = need_capture_pp(pipe);
5828 ia_css_frame_info_set_format(&vf_info,
5829 IA_CSS_FRAME_FORMAT_YUV_LINE);
5831 /* we build up the pipeline starting at the end */
5832 /* Capture post-processing */
5834 struct ia_css_binary_descr capture_pp_descr;
5836 ia_css_pipe_get_capturepp_binarydesc(pipe, &capture_pp_descr,
5838 pipe_out_info, &vf_info);
5839 err = ia_css_binary_find(&capture_pp_descr,
5840 &pipe->pipe_settings.capture.capture_pp_binary);
5844 post_out_info = *pipe_out_info;
5849 struct ia_css_binary_descr post_gdc_descr;
5851 ia_css_pipe_get_post_gdc_binarydesc(pipe, &post_gdc_descr,
5853 &post_out_info, &vf_info);
5854 err = ia_css_binary_find(&post_gdc_descr,
5855 &pipe->pipe_settings.capture.post_isp_binary);
5862 struct ia_css_binary_descr gdc_descr;
5864 ia_css_pipe_get_gdc_binarydesc(pipe, &gdc_descr, &gdc_in_info,
5865 &pipe->pipe_settings.capture.post_isp_binary.in_frame_info);
5866 err = ia_css_binary_find(&gdc_descr,
5867 &pipe->pipe_settings.capture.anr_gdc_binary);
5871 pipe->pipe_settings.capture.anr_gdc_binary.left_padding =
5872 pipe->pipe_settings.capture.post_isp_binary.left_padding;
5876 struct ia_css_binary_descr pre_gdc_descr;
5878 ia_css_pipe_get_pre_gdc_binarydesc(pipe, &pre_gdc_descr, &pre_in_info,
5879 &pipe->pipe_settings.capture.anr_gdc_binary.in_frame_info);
5880 err = ia_css_binary_find(&pre_gdc_descr,
5881 &pipe->pipe_settings.capture.pre_isp_binary);
5885 pipe->pipe_settings.capture.pre_isp_binary.left_padding =
5886 pipe->pipe_settings.capture.anr_gdc_binary.left_padding;
5888 /* Viewfinder post-processing */
5891 &pipe->pipe_settings.capture.capture_pp_binary.vf_frame_info;
5894 &pipe->pipe_settings.capture.post_isp_binary.vf_frame_info;
5898 struct ia_css_binary_descr vf_pp_descr;
5900 ia_css_pipe_get_vfpp_binarydesc(pipe,
5901 &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info);
5902 err = ia_css_binary_find(&vf_pp_descr,
5903 &pipe->pipe_settings.capture.vf_pp_binary);
5910 /* For CSI2+, only the direct sensor mode/online requires ISP copy */
5911 need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
5914 load_copy_binary(pipe,
5915 &pipe->pipe_settings.capture.copy_binary,
5916 &pipe->pipe_settings.capture.pre_isp_binary);
5921 static int load_bayer_isp_binaries(struct ia_css_pipe *pipe)
5923 struct ia_css_frame_info pre_isp_in_info, *pipe_out_info;
5925 struct ia_css_binary_descr pre_de_descr;
5927 IA_CSS_ENTER_PRIVATE("");
5929 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
5930 pipe->mode == IA_CSS_PIPE_ID_COPY);
5931 pipe_out_info = &pipe->output_info[0];
5933 if (pipe->pipe_settings.capture.pre_isp_binary.info)
5936 err = ia_css_frame_check_info(pipe_out_info);
5940 ia_css_pipe_get_pre_de_binarydesc(pipe, &pre_de_descr,
5944 err = ia_css_binary_find(&pre_de_descr,
5945 &pipe->pipe_settings.capture.pre_isp_binary);
5950 static int load_low_light_binaries(struct ia_css_pipe *pipe)
5952 struct ia_css_frame_info pre_in_info, anr_in_info,
5953 post_in_info, post_out_info,
5954 vf_info, *pipe_vf_out_info, *pipe_out_info,
5957 bool need_isp_copy = true;
5960 IA_CSS_ENTER_PRIVATE("");
5962 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
5963 pipe->mode == IA_CSS_PIPE_ID_COPY);
5965 if (pipe->pipe_settings.capture.pre_isp_binary.info)
5967 pipe_vf_out_info = &pipe->vf_output_info[0];
5968 pipe_out_info = &pipe->output_info[0];
5970 vf_info = *pipe_vf_out_info;
5971 err = ia_css_util_check_vf_out_info(pipe_out_info,
5975 need_pp = need_capture_pp(pipe);
5977 ia_css_frame_info_set_format(&vf_info,
5978 IA_CSS_FRAME_FORMAT_YUV_LINE);
5980 /* we build up the pipeline starting at the end */
5981 /* Capture post-processing */
5983 struct ia_css_binary_descr capture_pp_descr;
5985 ia_css_pipe_get_capturepp_binarydesc(pipe, &capture_pp_descr,
5987 pipe_out_info, &vf_info);
5988 err = ia_css_binary_find(&capture_pp_descr,
5989 &pipe->pipe_settings.capture.capture_pp_binary);
5993 post_out_info = *pipe_out_info;
5998 struct ia_css_binary_descr post_anr_descr;
6000 ia_css_pipe_get_post_anr_binarydesc(pipe,
6001 &post_anr_descr, &post_in_info, &post_out_info, &vf_info);
6002 err = ia_css_binary_find(&post_anr_descr,
6003 &pipe->pipe_settings.capture.post_isp_binary);
6010 struct ia_css_binary_descr anr_descr;
6012 ia_css_pipe_get_anr_binarydesc(pipe, &anr_descr, &anr_in_info,
6013 &pipe->pipe_settings.capture.post_isp_binary.in_frame_info);
6014 err = ia_css_binary_find(&anr_descr,
6015 &pipe->pipe_settings.capture.anr_gdc_binary);
6019 pipe->pipe_settings.capture.anr_gdc_binary.left_padding =
6020 pipe->pipe_settings.capture.post_isp_binary.left_padding;
6024 struct ia_css_binary_descr pre_anr_descr;
6026 ia_css_pipe_get_pre_anr_binarydesc(pipe, &pre_anr_descr, &pre_in_info,
6027 &pipe->pipe_settings.capture.anr_gdc_binary.in_frame_info);
6028 err = ia_css_binary_find(&pre_anr_descr,
6029 &pipe->pipe_settings.capture.pre_isp_binary);
6033 pipe->pipe_settings.capture.pre_isp_binary.left_padding =
6034 pipe->pipe_settings.capture.anr_gdc_binary.left_padding;
6036 /* Viewfinder post-processing */
6039 &pipe->pipe_settings.capture.capture_pp_binary.vf_frame_info;
6042 &pipe->pipe_settings.capture.post_isp_binary.vf_frame_info;
6046 struct ia_css_binary_descr vf_pp_descr;
6048 ia_css_pipe_get_vfpp_binarydesc(pipe, &vf_pp_descr,
6049 vf_pp_in_info, pipe_vf_out_info);
6050 err = ia_css_binary_find(&vf_pp_descr,
6051 &pipe->pipe_settings.capture.vf_pp_binary);
6058 /* For CSI2+, only the direct sensor mode/online requires ISP copy */
6059 need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
6062 err = load_copy_binary(pipe,
6063 &pipe->pipe_settings.capture.copy_binary,
6064 &pipe->pipe_settings.capture.pre_isp_binary);
6069 static bool copy_on_sp(struct ia_css_pipe *pipe)
6074 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "copy_on_sp() enter:\n");
6078 rval &= (pipe->mode == IA_CSS_PIPE_ID_CAPTURE);
6080 rval &= (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW);
6082 rval &= ((pipe->stream->config.input_config.format ==
6083 ATOMISP_INPUT_FORMAT_BINARY_8) ||
6084 (pipe->config.mode == IA_CSS_PIPE_MODE_COPY));
6089 static int load_capture_binaries(struct ia_css_pipe *pipe)
6094 IA_CSS_ENTER_PRIVATE("");
6096 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
6097 pipe->mode == IA_CSS_PIPE_ID_COPY);
6099 if (pipe->pipe_settings.capture.primary_binary[0].info) {
6100 IA_CSS_LEAVE_ERR_PRIVATE(0);
6104 /* in primary, advanced,low light or bayer,
6105 the input format must be raw */
6107 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_ADVANCED ||
6108 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER ||
6109 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT;
6110 err = ia_css_util_check_input(&pipe->stream->config, must_be_raw, false);
6112 IA_CSS_LEAVE_ERR_PRIVATE(err);
6115 if (copy_on_sp(pipe) &&
6116 pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) {
6117 ia_css_frame_info_init(
6118 &pipe->output_info[0],
6121 IA_CSS_FRAME_FORMAT_BINARY_8,
6123 IA_CSS_LEAVE_ERR_PRIVATE(0);
6127 switch (pipe->config.default_capture_config.mode) {
6128 case IA_CSS_CAPTURE_MODE_RAW:
6129 err = load_copy_binaries(pipe);
6130 #if defined(ISP2401)
6132 pipe->pipe_settings.capture.copy_binary.online = pipe->stream->config.online;
6135 case IA_CSS_CAPTURE_MODE_BAYER:
6136 err = load_bayer_isp_binaries(pipe);
6138 case IA_CSS_CAPTURE_MODE_PRIMARY:
6139 err = load_primary_binaries(pipe);
6141 case IA_CSS_CAPTURE_MODE_ADVANCED:
6142 err = load_advanced_binaries(pipe);
6144 case IA_CSS_CAPTURE_MODE_LOW_LIGHT:
6145 err = load_low_light_binaries(pipe);
6149 IA_CSS_LEAVE_ERR_PRIVATE(err);
6153 IA_CSS_LEAVE_ERR_PRIVATE(err);
6158 unload_capture_binaries(struct ia_css_pipe *pipe)
6162 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
6164 if (!pipe || (pipe->mode != IA_CSS_PIPE_ID_CAPTURE &&
6165 pipe->mode != IA_CSS_PIPE_ID_COPY)) {
6166 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
6169 ia_css_binary_unload(&pipe->pipe_settings.capture.copy_binary);
6170 for (i = 0; i < MAX_NUM_PRIMARY_STAGES; i++)
6171 ia_css_binary_unload(&pipe->pipe_settings.capture.primary_binary[i]);
6172 ia_css_binary_unload(&pipe->pipe_settings.capture.pre_isp_binary);
6173 ia_css_binary_unload(&pipe->pipe_settings.capture.anr_gdc_binary);
6174 ia_css_binary_unload(&pipe->pipe_settings.capture.post_isp_binary);
6175 ia_css_binary_unload(&pipe->pipe_settings.capture.capture_pp_binary);
6176 ia_css_binary_unload(&pipe->pipe_settings.capture.capture_ldc_binary);
6177 ia_css_binary_unload(&pipe->pipe_settings.capture.vf_pp_binary);
6179 for (i = 0; i < pipe->pipe_settings.capture.num_yuv_scaler; i++)
6180 ia_css_binary_unload(&pipe->pipe_settings.capture.yuv_scaler_binary[i]);
6182 kfree(pipe->pipe_settings.capture.is_output_stage);
6183 pipe->pipe_settings.capture.is_output_stage = NULL;
6184 kfree(pipe->pipe_settings.capture.yuv_scaler_binary);
6185 pipe->pipe_settings.capture.yuv_scaler_binary = NULL;
6187 IA_CSS_LEAVE_ERR_PRIVATE(0);
6192 need_downscaling(const struct ia_css_resolution in_res,
6193 const struct ia_css_resolution out_res)
6195 if (in_res.width > out_res.width || in_res.height > out_res.height)
6202 need_yuv_scaler_stage(const struct ia_css_pipe *pipe)
6205 struct ia_css_resolution in_res, out_res;
6207 bool need_format_conversion = false;
6209 IA_CSS_ENTER_PRIVATE("");
6211 assert(pipe->mode == IA_CSS_PIPE_ID_YUVPP);
6213 /* TODO: make generic function */
6214 need_format_conversion =
6215 ((pipe->stream->config.input_config.format ==
6216 ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY) &&
6217 (pipe->output_info[0].format != IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8));
6219 in_res = pipe->config.input_effective_res;
6221 if (pipe->config.enable_dz)
6224 if ((pipe->output_info[0].res.width != 0) && need_format_conversion)
6227 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
6228 out_res = pipe->output_info[i].res;
6230 /* A non-zero width means it is a valid output port */
6231 if ((out_res.width != 0) && need_downscaling(in_res, out_res))
6239 * TODO: it is temporarily created from ia_css_pipe_create_cas_scaler_desc
6240 * which has some hard-coded knowledge which prevents reuse of the function.
6241 * Later, merge this with ia_css_pipe_create_cas_scaler_desc
6243 static int ia_css_pipe_create_cas_scaler_desc_single_output(
6244 struct ia_css_frame_info *cas_scaler_in_info,
6245 struct ia_css_frame_info *cas_scaler_out_info,
6246 struct ia_css_frame_info *cas_scaler_vf_info,
6247 struct ia_css_cas_binary_descr *descr)
6250 unsigned int hor_ds_factor = 0, ver_ds_factor = 0;
6252 struct ia_css_frame_info tmp_in_info;
6254 unsigned int max_scale_factor_per_stage = MAX_PREFERRED_YUV_DS_PER_STEP;
6256 assert(cas_scaler_in_info);
6257 assert(cas_scaler_out_info);
6259 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
6260 "ia_css_pipe_create_cas_scaler_desc() enter:\n");
6262 /* We assume that this function is used only for single output port case. */
6263 descr->num_output_stage = 1;
6265 hor_ds_factor = CEIL_DIV(cas_scaler_in_info->res.width,
6266 cas_scaler_out_info->res.width);
6267 ver_ds_factor = CEIL_DIV(cas_scaler_in_info->res.height,
6268 cas_scaler_out_info->res.height);
6269 /* use the same horizontal and vertical downscaling factor for simplicity */
6270 assert(hor_ds_factor == ver_ds_factor);
6273 while (i < hor_ds_factor) {
6275 i *= max_scale_factor_per_stage;
6278 descr->in_info = kmalloc(descr->num_stage *
6279 sizeof(struct ia_css_frame_info),
6281 if (!descr->in_info) {
6285 descr->internal_out_info = kmalloc(descr->num_stage *
6286 sizeof(struct ia_css_frame_info),
6288 if (!descr->internal_out_info) {
6292 descr->out_info = kmalloc(descr->num_stage *
6293 sizeof(struct ia_css_frame_info),
6295 if (!descr->out_info) {
6299 descr->vf_info = kmalloc(descr->num_stage *
6300 sizeof(struct ia_css_frame_info),
6302 if (!descr->vf_info) {
6306 descr->is_output_stage = kmalloc(descr->num_stage * sizeof(bool),
6308 if (!descr->is_output_stage) {
6313 tmp_in_info = *cas_scaler_in_info;
6314 for (i = 0; i < descr->num_stage; i++) {
6315 descr->in_info[i] = tmp_in_info;
6316 if ((tmp_in_info.res.width / max_scale_factor_per_stage) <=
6317 cas_scaler_out_info->res.width) {
6318 descr->is_output_stage[i] = true;
6319 if ((descr->num_output_stage > 1) && (i != (descr->num_stage - 1))) {
6320 descr->internal_out_info[i].res.width = cas_scaler_out_info->res.width;
6321 descr->internal_out_info[i].res.height = cas_scaler_out_info->res.height;
6322 descr->internal_out_info[i].padded_width = cas_scaler_out_info->padded_width;
6323 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
6325 assert(i == (descr->num_stage - 1));
6326 descr->internal_out_info[i].res.width = 0;
6327 descr->internal_out_info[i].res.height = 0;
6329 descr->out_info[i].res.width = cas_scaler_out_info->res.width;
6330 descr->out_info[i].res.height = cas_scaler_out_info->res.height;
6331 descr->out_info[i].padded_width = cas_scaler_out_info->padded_width;
6332 descr->out_info[i].format = cas_scaler_out_info->format;
6333 if (cas_scaler_vf_info) {
6334 descr->vf_info[i].res.width = cas_scaler_vf_info->res.width;
6335 descr->vf_info[i].res.height = cas_scaler_vf_info->res.height;
6336 descr->vf_info[i].padded_width = cas_scaler_vf_info->padded_width;
6337 ia_css_frame_info_set_format(&descr->vf_info[i], IA_CSS_FRAME_FORMAT_YUV_LINE);
6339 descr->vf_info[i].res.width = 0;
6340 descr->vf_info[i].res.height = 0;
6341 descr->vf_info[i].padded_width = 0;
6344 descr->is_output_stage[i] = false;
6345 descr->internal_out_info[i].res.width = tmp_in_info.res.width /
6346 max_scale_factor_per_stage;
6347 descr->internal_out_info[i].res.height = tmp_in_info.res.height /
6348 max_scale_factor_per_stage;
6349 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
6350 ia_css_frame_info_init(&descr->internal_out_info[i],
6351 tmp_in_info.res.width / max_scale_factor_per_stage,
6352 tmp_in_info.res.height / max_scale_factor_per_stage,
6353 IA_CSS_FRAME_FORMAT_YUV420, 0);
6354 descr->out_info[i].res.width = 0;
6355 descr->out_info[i].res.height = 0;
6356 descr->vf_info[i].res.width = 0;
6357 descr->vf_info[i].res.height = 0;
6359 tmp_in_info = descr->internal_out_info[i];
6362 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
6363 "ia_css_pipe_create_cas_scaler_desc() leave, err=%d\n",
6368 /* FIXME: merge most of this and single output version */
6370 ia_css_pipe_create_cas_scaler_desc(struct ia_css_pipe *pipe,
6371 struct ia_css_cas_binary_descr *descr)
6373 struct ia_css_frame_info in_info = IA_CSS_BINARY_DEFAULT_FRAME_INFO;
6374 struct ia_css_frame_info *out_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
6375 struct ia_css_frame_info *vf_out_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
6376 struct ia_css_frame_info tmp_in_info = IA_CSS_BINARY_DEFAULT_FRAME_INFO;
6378 unsigned int hor_scale_factor[IA_CSS_PIPE_MAX_OUTPUT_STAGE],
6379 ver_scale_factor[IA_CSS_PIPE_MAX_OUTPUT_STAGE],
6381 unsigned int num_stages = 0;
6384 unsigned int max_scale_factor_per_stage = MAX_PREFERRED_YUV_DS_PER_STEP;
6386 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
6387 "ia_css_pipe_create_cas_scaler_desc() enter:\n");
6389 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
6391 vf_out_info[i] = NULL;
6392 hor_scale_factor[i] = 0;
6393 ver_scale_factor[i] = 0;
6396 in_info.res = pipe->config.input_effective_res;
6397 in_info.padded_width = in_info.res.width;
6398 descr->num_output_stage = 0;
6399 /* Find out how much scaling we need for each output */
6400 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
6401 if (pipe->output_info[i].res.width != 0) {
6402 out_info[i] = &pipe->output_info[i];
6403 if (pipe->vf_output_info[i].res.width != 0)
6404 vf_out_info[i] = &pipe->vf_output_info[i];
6405 descr->num_output_stage += 1;
6409 hor_scale_factor[i] = CEIL_DIV(in_info.res.width, out_info[i]->res.width);
6410 ver_scale_factor[i] = CEIL_DIV(in_info.res.height, out_info[i]->res.height);
6411 /* use the same horizontal and vertical scaling factor for simplicity */
6412 assert(hor_scale_factor[i] == ver_scale_factor[i]);
6416 scale_factor *= max_scale_factor_per_stage;
6417 } while (scale_factor < hor_scale_factor[i]);
6419 in_info.res = out_info[i]->res;
6423 if (need_yuv_scaler_stage(pipe) && (num_stages == 0))
6426 descr->num_stage = num_stages;
6428 descr->in_info = kmalloc_array(descr->num_stage,
6429 sizeof(struct ia_css_frame_info),
6431 if (!descr->in_info) {
6435 descr->internal_out_info = kmalloc(descr->num_stage *
6436 sizeof(struct ia_css_frame_info),
6438 if (!descr->internal_out_info) {
6442 descr->out_info = kmalloc(descr->num_stage *
6443 sizeof(struct ia_css_frame_info),
6445 if (!descr->out_info) {
6449 descr->vf_info = kmalloc(descr->num_stage *
6450 sizeof(struct ia_css_frame_info),
6452 if (!descr->vf_info) {
6456 descr->is_output_stage = kmalloc(descr->num_stage * sizeof(bool),
6458 if (!descr->is_output_stage) {
6463 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
6466 assert((out_info[i - 1]->res.width >= out_info[i]->res.width) &&
6467 (out_info[i - 1]->res.height >= out_info[i]->res.height));
6472 tmp_in_info.res = pipe->config.input_effective_res;
6473 tmp_in_info.format = IA_CSS_FRAME_FORMAT_YUV420;
6474 for (i = 0, j = 0; i < descr->num_stage; i++) {
6476 assert(out_info[j]);
6478 descr->in_info[i] = tmp_in_info;
6479 if ((tmp_in_info.res.width / max_scale_factor_per_stage) <=
6480 out_info[j]->res.width) {
6481 descr->is_output_stage[i] = true;
6482 if ((descr->num_output_stage > 1) && (i != (descr->num_stage - 1))) {
6483 descr->internal_out_info[i].res.width = out_info[j]->res.width;
6484 descr->internal_out_info[i].res.height = out_info[j]->res.height;
6485 descr->internal_out_info[i].padded_width = out_info[j]->padded_width;
6486 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
6488 assert(i == (descr->num_stage - 1));
6489 descr->internal_out_info[i].res.width = 0;
6490 descr->internal_out_info[i].res.height = 0;
6492 descr->out_info[i].res.width = out_info[j]->res.width;
6493 descr->out_info[i].res.height = out_info[j]->res.height;
6494 descr->out_info[i].padded_width = out_info[j]->padded_width;
6495 descr->out_info[i].format = out_info[j]->format;
6496 if (vf_out_info[j]) {
6497 descr->vf_info[i].res.width = vf_out_info[j]->res.width;
6498 descr->vf_info[i].res.height = vf_out_info[j]->res.height;
6499 descr->vf_info[i].padded_width = vf_out_info[j]->padded_width;
6500 ia_css_frame_info_set_format(&descr->vf_info[i], IA_CSS_FRAME_FORMAT_YUV_LINE);
6502 descr->vf_info[i].res.width = 0;
6503 descr->vf_info[i].res.height = 0;
6504 descr->vf_info[i].padded_width = 0;
6508 descr->is_output_stage[i] = false;
6509 descr->internal_out_info[i].res.width = tmp_in_info.res.width /
6510 max_scale_factor_per_stage;
6511 descr->internal_out_info[i].res.height = tmp_in_info.res.height /
6512 max_scale_factor_per_stage;
6513 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
6514 ia_css_frame_info_init(&descr->internal_out_info[i],
6515 tmp_in_info.res.width / max_scale_factor_per_stage,
6516 tmp_in_info.res.height / max_scale_factor_per_stage,
6517 IA_CSS_FRAME_FORMAT_YUV420, 0);
6518 descr->out_info[i].res.width = 0;
6519 descr->out_info[i].res.height = 0;
6520 descr->vf_info[i].res.width = 0;
6521 descr->vf_info[i].res.height = 0;
6523 tmp_in_info = descr->internal_out_info[i];
6526 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
6527 "ia_css_pipe_create_cas_scaler_desc() leave, err=%d\n",
6532 static void ia_css_pipe_destroy_cas_scaler_desc(struct ia_css_cas_binary_descr
6535 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
6536 "ia_css_pipe_destroy_cas_scaler_desc() enter:\n");
6537 kfree(descr->in_info);
6538 descr->in_info = NULL;
6539 kfree(descr->internal_out_info);
6540 descr->internal_out_info = NULL;
6541 kfree(descr->out_info);
6542 descr->out_info = NULL;
6543 kfree(descr->vf_info);
6544 descr->vf_info = NULL;
6545 kfree(descr->is_output_stage);
6546 descr->is_output_stage = NULL;
6547 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
6548 "ia_css_pipe_destroy_cas_scaler_desc() leave\n");
6552 load_yuvpp_binaries(struct ia_css_pipe *pipe)
6555 bool need_scaler = false;
6556 struct ia_css_frame_info *vf_pp_in_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
6557 struct ia_css_yuvpp_settings *mycs;
6558 struct ia_css_binary *next_binary;
6559 struct ia_css_cas_binary_descr cas_scaler_descr = { };
6561 bool need_isp_copy_binary = false;
6563 IA_CSS_ENTER_PRIVATE("");
6565 assert(pipe->stream);
6566 assert(pipe->mode == IA_CSS_PIPE_ID_YUVPP);
6568 if (pipe->pipe_settings.yuvpp.copy_binary.info)
6571 /* Set both must_be_raw and must_be_yuv to false then yuvpp can take rgb inputs */
6572 err = ia_css_util_check_input(&pipe->stream->config, false, false);
6576 mycs = &pipe->pipe_settings.yuvpp;
6578 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
6579 if (pipe->vf_output_info[i].res.width != 0) {
6580 err = ia_css_util_check_vf_out_info(&pipe->output_info[i],
6581 &pipe->vf_output_info[i]);
6585 vf_pp_in_info[i] = NULL;
6588 need_scaler = need_yuv_scaler_stage(pipe);
6590 /* we build up the pipeline starting at the end */
6591 /* Capture post-processing */
6593 struct ia_css_binary_descr yuv_scaler_descr;
6595 err = ia_css_pipe_create_cas_scaler_desc(pipe,
6599 mycs->num_output = cas_scaler_descr.num_output_stage;
6600 mycs->num_yuv_scaler = cas_scaler_descr.num_stage;
6601 mycs->yuv_scaler_binary = kcalloc(cas_scaler_descr.num_stage,
6602 sizeof(struct ia_css_binary),
6604 if (!mycs->yuv_scaler_binary) {
6608 mycs->is_output_stage = kcalloc(cas_scaler_descr.num_stage,
6609 sizeof(bool), GFP_KERNEL);
6610 if (!mycs->is_output_stage) {
6614 for (i = 0; i < cas_scaler_descr.num_stage; i++) {
6615 mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i];
6616 ia_css_pipe_get_yuvscaler_binarydesc(pipe,
6618 &cas_scaler_descr.in_info[i],
6619 &cas_scaler_descr.out_info[i],
6620 &cas_scaler_descr.internal_out_info[i],
6621 &cas_scaler_descr.vf_info[i]);
6622 err = ia_css_binary_find(&yuv_scaler_descr,
6623 &mycs->yuv_scaler_binary[i]);
6627 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
6629 mycs->num_output = 1;
6633 next_binary = &mycs->yuv_scaler_binary[0];
6637 #if defined(ISP2401)
6640 * - Why does the "yuvpp" pipe needs "isp_copy_binary" (i.e. ISP Copy) when
6641 * its input is "ATOMISP_INPUT_FORMAT_YUV422_8"?
6643 * In most use cases, the first stage in the "yuvpp" pipe is the "yuv_scale_
6644 * binary". However, the "yuv_scale_binary" does NOT support the input-frame
6645 * format as "IA_CSS_STREAM _FORMAT_YUV422_8".
6647 * Hence, the "isp_copy_binary" is required to be present in front of the "yuv
6648 * _scale_binary". It would translate the input-frame to the frame formats that
6649 * are supported by the "yuv_scale_binary".
6651 * Please refer to "FrameWork/css/isp/pipes/capture_pp/capture_pp_1.0/capture_
6652 * pp_defs.h" for the list of input-frame formats that are supported by the
6653 * "yuv_scale_binary".
6655 need_isp_copy_binary =
6656 (pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_YUV422_8);
6657 #else /* !ISP2401 */
6658 need_isp_copy_binary = true;
6659 #endif /* ISP2401 */
6661 if (need_isp_copy_binary) {
6662 err = load_copy_binary(pipe,
6671 * - Why is "pipe->pipe_settings.capture.copy_binary.online" specified?
6673 * In some use cases, the first stage in the "yuvpp" pipe is the
6674 * "isp_copy_binary". The "isp_copy_binary" is designed to process
6675 * the input from either the system DDR or from the IPU internal VMEM.
6676 * So it provides the flag "online" to specify where its input is from,
6679 * (1) "online <= true", the input is from the IPU internal VMEM.
6680 * (2) "online <= false", the input is from the system DDR.
6682 * In other use cases, the first stage in the "yuvpp" pipe is the
6683 * "yuv_scale_binary". "The "yuv_scale_binary" is designed to process the
6684 * input ONLY from the system DDR. So it does not provide the flag "online"
6685 * to specify where its input is from.
6687 pipe->pipe_settings.capture.copy_binary.online = pipe->stream->config.online;
6690 /* Viewfinder post-processing */
6692 for (i = 0, j = 0; i < mycs->num_yuv_scaler; i++) {
6693 if (mycs->is_output_stage[i]) {
6696 &mycs->yuv_scaler_binary[i].vf_frame_info;
6700 mycs->num_vf_pp = j;
6703 &mycs->copy_binary.vf_frame_info;
6704 for (i = 1; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++)
6705 vf_pp_in_info[i] = NULL;
6707 mycs->num_vf_pp = 1;
6709 mycs->vf_pp_binary = kcalloc(mycs->num_vf_pp,
6710 sizeof(struct ia_css_binary),
6712 if (!mycs->vf_pp_binary) {
6718 struct ia_css_binary_descr vf_pp_descr;
6720 for (i = 0; i < mycs->num_vf_pp; i++) {
6721 if (pipe->vf_output_info[i].res.width != 0) {
6722 ia_css_pipe_get_vfpp_binarydesc(pipe,
6723 &vf_pp_descr, vf_pp_in_info[i], &pipe->vf_output_info[i]);
6724 err = ia_css_binary_find(&vf_pp_descr, &mycs->vf_pp_binary[i]);
6736 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
6738 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "load_yuvpp_binaries() leave, err=%d\n",
6744 unload_yuvpp_binaries(struct ia_css_pipe *pipe)
6748 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
6750 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) {
6751 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
6754 ia_css_binary_unload(&pipe->pipe_settings.yuvpp.copy_binary);
6755 for (i = 0; i < pipe->pipe_settings.yuvpp.num_yuv_scaler; i++)
6756 ia_css_binary_unload(&pipe->pipe_settings.yuvpp.yuv_scaler_binary[i]);
6758 for (i = 0; i < pipe->pipe_settings.yuvpp.num_vf_pp; i++)
6759 ia_css_binary_unload(&pipe->pipe_settings.yuvpp.vf_pp_binary[i]);
6761 kfree(pipe->pipe_settings.yuvpp.is_output_stage);
6762 pipe->pipe_settings.yuvpp.is_output_stage = NULL;
6763 kfree(pipe->pipe_settings.yuvpp.yuv_scaler_binary);
6764 pipe->pipe_settings.yuvpp.yuv_scaler_binary = NULL;
6765 kfree(pipe->pipe_settings.yuvpp.vf_pp_binary);
6766 pipe->pipe_settings.yuvpp.vf_pp_binary = NULL;
6768 IA_CSS_LEAVE_ERR_PRIVATE(0);
6772 static int yuvpp_start(struct ia_css_pipe *pipe)
6775 enum sh_css_pipe_config_override copy_ovrd;
6776 enum ia_css_input_mode yuvpp_pipe_input_mode;
6777 unsigned int thread_id;
6779 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
6780 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) {
6781 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
6785 yuvpp_pipe_input_mode = pipe->stream->config.mode;
6787 sh_css_metrics_start_frame();
6789 /* multi stream video needs mipi buffers */
6791 err = send_mipi_frames(pipe);
6793 IA_CSS_LEAVE_ERR_PRIVATE(err);
6797 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
6798 copy_ovrd = 1 << thread_id;
6800 start_pipe(pipe, copy_ovrd, yuvpp_pipe_input_mode);
6802 IA_CSS_LEAVE_ERR_PRIVATE(err);
6807 sh_css_pipe_unload_binaries(struct ia_css_pipe *pipe)
6811 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
6814 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
6817 /* PIPE_MODE_COPY has no binaries, but has output frames to outside*/
6818 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY) {
6819 IA_CSS_LEAVE_ERR_PRIVATE(0);
6823 switch (pipe->mode) {
6824 case IA_CSS_PIPE_ID_PREVIEW:
6825 err = unload_preview_binaries(pipe);
6827 case IA_CSS_PIPE_ID_VIDEO:
6828 err = unload_video_binaries(pipe);
6830 case IA_CSS_PIPE_ID_CAPTURE:
6831 err = unload_capture_binaries(pipe);
6833 case IA_CSS_PIPE_ID_YUVPP:
6834 err = unload_yuvpp_binaries(pipe);
6839 IA_CSS_LEAVE_ERR_PRIVATE(err);
6844 sh_css_pipe_load_binaries(struct ia_css_pipe *pipe)
6849 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "sh_css_pipe_load_binaries() enter:\n");
6851 /* PIPE_MODE_COPY has no binaries, but has output frames to outside*/
6852 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY)
6855 switch (pipe->mode) {
6856 case IA_CSS_PIPE_ID_PREVIEW:
6857 err = load_preview_binaries(pipe);
6859 case IA_CSS_PIPE_ID_VIDEO:
6860 err = load_video_binaries(pipe);
6862 case IA_CSS_PIPE_ID_CAPTURE:
6863 err = load_capture_binaries(pipe);
6865 case IA_CSS_PIPE_ID_YUVPP:
6866 err = load_yuvpp_binaries(pipe);
6868 case IA_CSS_PIPE_ID_ACC:
6875 if (sh_css_pipe_unload_binaries(pipe)) {
6877 * currently css does not support multiple error
6878 * returns in a single function, using -EINVAL in
6888 create_host_yuvpp_pipeline(struct ia_css_pipe *pipe)
6890 struct ia_css_pipeline *me;
6892 struct ia_css_pipeline_stage *vf_pp_stage = NULL,
6894 *yuv_scaler_stage = NULL;
6895 struct ia_css_binary *copy_binary,
6898 bool need_scaler = false;
6899 unsigned int num_stage, num_output_stage;
6902 struct ia_css_frame *in_frame = NULL;
6903 struct ia_css_frame *out_frame[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
6904 struct ia_css_frame *bin_out_frame[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
6905 struct ia_css_frame *vf_frame[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
6906 struct ia_css_pipeline_stage_desc stage_desc;
6907 bool need_in_frameinfo_memory = false;
6909 bool sensor = false;
6910 bool buffered_sensor = false;
6911 bool online = false;
6912 bool continuous = false;
6915 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
6916 if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) {
6917 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
6920 me = &pipe->pipeline;
6921 ia_css_pipeline_clean(me);
6922 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
6923 out_frame[i] = NULL;
6926 ia_css_pipe_util_create_output_frames(bin_out_frame);
6927 num_stage = pipe->pipe_settings.yuvpp.num_yuv_scaler;
6928 num_output_stage = pipe->pipe_settings.yuvpp.num_output;
6932 * When the input system is 2401, always enable 'in_frameinfo_memory'
6933 * except for the following:
6934 * - Direct Sensor Mode Online Capture
6935 * - Direct Sensor Mode Continuous Capture
6936 * - Buffered Sensor Mode Continuous Capture
6938 sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
6939 buffered_sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR;
6940 online = pipe->stream->config.online;
6941 continuous = pipe->stream->config.continuous;
6942 need_in_frameinfo_memory =
6943 !((sensor && (online || continuous)) || (buffered_sensor && continuous));
6945 /* Construct in_frame info (only in case we have dynamic input */
6946 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
6949 * the input frame can come from:
6951 * a) memory: connect yuvscaler to me->in_frame
6952 * b) sensor, via copy binary: connect yuvscaler to copy binary later
6955 if (need_in_frameinfo_memory) {
6956 /* TODO: improve for different input formats. */
6959 * "pipe->stream->config.input_config.format" represents the sensor output
6960 * frame format, e.g. YUV422 8-bit.
6962 * "in_frame_format" represents the imaging pipe's input frame format, e.g.
6965 int in_frame_format;
6967 if (pipe->stream->config.input_config.format ==
6968 ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY) {
6969 in_frame_format = IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8;
6970 } else if (pipe->stream->config.input_config.format ==
6971 ATOMISP_INPUT_FORMAT_YUV422_8) {
6973 * When the sensor output frame format is "ATOMISP_INPUT_FORMAT_YUV422_8",
6974 * the "isp_copy_var" binary is selected as the first stage in the yuvpp
6977 * For the "isp_copy_var" binary, it reads the YUV422-8 pixels from
6978 * the frame buffer (at DDR) to the frame-line buffer (at VMEM).
6980 * By now, the "isp_copy_var" binary does NOT provide a separated
6981 * frame-line buffer to store the YUV422-8 pixels. Instead, it stores
6982 * the YUV422-8 pixels in the frame-line buffer which is designed to
6983 * store the Bayer-Quad RAW pixels.
6985 * To direct the "isp_copy_var" binary reading from the RAW frame-line
6986 * buffer, its input frame format must be specified as "IA_CSS_FRAME_
6989 in_frame_format = IA_CSS_FRAME_FORMAT_RAW;
6991 in_frame_format = IA_CSS_FRAME_FORMAT_NV12;
6994 err = init_in_frameinfo_memory_defaults(pipe,
6999 IA_CSS_LEAVE_ERR_PRIVATE(err);
7003 in_frame = &me->in_frame;
7008 for (i = 0; i < num_output_stage; i++) {
7009 assert(i < IA_CSS_PIPE_MAX_OUTPUT_STAGE);
7010 if (pipe->output_info[i].res.width != 0) {
7011 err = init_out_frameinfo_defaults(pipe, &me->out_frame[i], i);
7013 IA_CSS_LEAVE_ERR_PRIVATE(err);
7016 out_frame[i] = &me->out_frame[i];
7019 /* Construct vf_frame info (only in case we have VF) */
7020 if (pipe->vf_output_info[i].res.width != 0) {
7021 err = init_vf_frameinfo_defaults(pipe, &me->vf_frame[i], i);
7023 IA_CSS_LEAVE_ERR_PRIVATE(err);
7026 vf_frame[i] = &me->vf_frame[i];
7030 copy_binary = &pipe->pipe_settings.yuvpp.copy_binary;
7031 vf_pp_binary = pipe->pipe_settings.yuvpp.vf_pp_binary;
7032 yuv_scaler_binary = pipe->pipe_settings.yuvpp.yuv_scaler_binary;
7033 need_scaler = need_yuv_scaler_stage(pipe);
7035 if (pipe->pipe_settings.yuvpp.copy_binary.info) {
7036 struct ia_css_frame *in_frame_local = NULL;
7039 /* After isp copy is enabled in_frame needs to be passed. */
7041 in_frame_local = in_frame;
7045 ia_css_pipe_util_set_output_frames(bin_out_frame,
7047 ia_css_pipe_get_generic_stage_desc(&stage_desc,
7053 ia_css_pipe_util_set_output_frames(bin_out_frame,
7055 ia_css_pipe_get_generic_stage_desc(&stage_desc,
7062 err = ia_css_pipeline_create_and_add_stage(me,
7067 IA_CSS_LEAVE_ERR_PRIVATE(err);
7072 /* if we use yuv scaler binary, vf output should be from there */
7073 copy_stage->args.copy_vf = !need_scaler;
7074 /* for yuvpp pipe, it should always be enabled */
7075 copy_stage->args.copy_output = true;
7076 /* connect output of copy binary to input of yuv scaler */
7077 in_frame = copy_stage->args.out_frame[0];
7082 struct ia_css_frame *tmp_out_frame = NULL;
7083 struct ia_css_frame *tmp_vf_frame = NULL;
7084 struct ia_css_frame *tmp_in_frame = in_frame;
7086 for (i = 0, j = 0; i < num_stage; i++) {
7087 assert(j < num_output_stage);
7088 if (pipe->pipe_settings.yuvpp.is_output_stage[i]) {
7089 tmp_out_frame = out_frame[j];
7090 tmp_vf_frame = vf_frame[j];
7092 tmp_out_frame = NULL;
7093 tmp_vf_frame = NULL;
7096 err = add_yuv_scaler_stage(pipe, me, tmp_in_frame,
7099 &yuv_scaler_binary[i],
7103 IA_CSS_LEAVE_ERR_PRIVATE(err);
7106 /* we use output port 1 as internal output port */
7107 tmp_in_frame = yuv_scaler_stage->args.out_frame[1];
7108 if (pipe->pipe_settings.yuvpp.is_output_stage[i]) {
7109 if (tmp_vf_frame && (tmp_vf_frame->info.res.width != 0)) {
7110 in_frame = yuv_scaler_stage->args.out_vf_frame;
7111 err = add_vf_pp_stage(pipe, in_frame,
7117 IA_CSS_LEAVE_ERR_PRIVATE(err);
7124 } else if (copy_stage) {
7125 if (vf_frame[0] && vf_frame[0]->info.res.width != 0) {
7126 in_frame = copy_stage->args.out_vf_frame;
7127 err = add_vf_pp_stage(pipe, in_frame, vf_frame[0],
7128 &vf_pp_binary[0], &vf_pp_stage);
7131 IA_CSS_LEAVE_ERR_PRIVATE(err);
7136 ia_css_pipeline_finalize_stages(&pipe->pipeline,
7137 pipe->stream->config.continuous);
7139 IA_CSS_LEAVE_ERR_PRIVATE(0);
7145 create_host_copy_pipeline(struct ia_css_pipe *pipe,
7146 unsigned int max_input_width,
7147 struct ia_css_frame *out_frame)
7149 struct ia_css_pipeline *me;
7151 struct ia_css_pipeline_stage_desc stage_desc;
7153 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7154 "create_host_copy_pipeline() enter:\n");
7156 /* pipeline already created as part of create_host_pipeline_structure */
7157 me = &pipe->pipeline;
7158 ia_css_pipeline_clean(me);
7160 /* Construct out_frame info */
7161 out_frame->contiguous = false;
7162 out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
7164 if (copy_on_sp(pipe) &&
7165 pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) {
7166 ia_css_frame_info_init(&out_frame->info, JPEG_BYTES, 1,
7167 IA_CSS_FRAME_FORMAT_BINARY_8, 0);
7168 } else if (out_frame->info.format == IA_CSS_FRAME_FORMAT_RAW) {
7169 out_frame->info.raw_bit_depth =
7170 ia_css_pipe_util_pipe_input_format_bpp(pipe);
7174 me->pipe_id = IA_CSS_PIPE_ID_COPY;
7175 pipe->mode = IA_CSS_PIPE_ID_COPY;
7177 ia_css_pipe_get_sp_func_stage_desc(&stage_desc, out_frame,
7178 IA_CSS_PIPELINE_RAW_COPY,
7180 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc, NULL);
7182 ia_css_pipeline_finalize_stages(&pipe->pipeline,
7183 pipe->stream->config.continuous);
7185 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7186 "create_host_copy_pipeline() leave:\n");
7192 create_host_isyscopy_capture_pipeline(struct ia_css_pipe *pipe)
7194 struct ia_css_pipeline *me = &pipe->pipeline;
7196 struct ia_css_pipeline_stage_desc stage_desc;
7197 struct ia_css_frame *out_frame = &me->out_frame[0];
7198 struct ia_css_pipeline_stage *out_stage = NULL;
7199 unsigned int thread_id;
7200 enum sh_css_queue_id queue_id;
7201 unsigned int max_input_width = MAX_VECTORS_PER_INPUT_LINE_CONT * ISP_VEC_NELEMS;
7203 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7204 "create_host_isyscopy_capture_pipeline() enter:\n");
7205 ia_css_pipeline_clean(me);
7207 /* Construct out_frame info */
7208 err = sh_css_pipe_get_output_frame_info(pipe, &out_frame->info, 0);
7211 out_frame->contiguous = false;
7212 out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
7213 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
7214 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, thread_id, &queue_id);
7215 out_frame->dynamic_queue_id = queue_id;
7216 out_frame->buf_type = IA_CSS_BUFFER_TYPE_OUTPUT_FRAME;
7219 me->pipe_id = IA_CSS_PIPE_ID_CAPTURE;
7220 pipe->mode = IA_CSS_PIPE_ID_CAPTURE;
7221 ia_css_pipe_get_sp_func_stage_desc(&stage_desc, out_frame,
7222 IA_CSS_PIPELINE_ISYS_COPY,
7224 err = ia_css_pipeline_create_and_add_stage(me,
7225 &stage_desc, &out_stage);
7229 ia_css_pipeline_finalize_stages(me, pipe->stream->config.continuous);
7231 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7232 "create_host_isyscopy_capture_pipeline() leave:\n");
7238 create_host_regular_capture_pipeline(struct ia_css_pipe *pipe)
7240 struct ia_css_pipeline *me;
7242 enum ia_css_capture_mode mode;
7243 struct ia_css_pipeline_stage *current_stage = NULL;
7244 struct ia_css_pipeline_stage *yuv_scaler_stage = NULL;
7245 struct ia_css_binary *copy_binary,
7246 *primary_binary[MAX_NUM_PRIMARY_STAGES],
7253 *capture_ldc_binary;
7254 bool need_pp = false;
7257 struct ia_css_frame *in_frame;
7258 struct ia_css_frame *out_frame;
7259 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
7260 struct ia_css_frame *vf_frame;
7261 struct ia_css_pipeline_stage_desc stage_desc;
7262 bool need_in_frameinfo_memory = false;
7264 bool sensor = false;
7265 bool buffered_sensor = false;
7266 bool online = false;
7267 bool continuous = false;
7269 unsigned int i, num_yuv_scaler, num_primary_stage;
7270 bool need_yuv_pp = false;
7271 bool *is_output_stage = NULL;
7272 bool need_ldc = false;
7274 IA_CSS_ENTER_PRIVATE("");
7276 assert(pipe->stream);
7277 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
7278 pipe->mode == IA_CSS_PIPE_ID_COPY);
7280 me = &pipe->pipeline;
7281 mode = pipe->config.default_capture_config.mode;
7282 raw = (mode == IA_CSS_CAPTURE_MODE_RAW);
7283 ia_css_pipeline_clean(me);
7284 ia_css_pipe_util_create_output_frames(out_frames);
7288 * When the input system is 2401, always enable 'in_frameinfo_memory'
7289 * except for the following:
7290 * - Direct Sensor Mode Online Capture
7291 * - Direct Sensor Mode Online Capture
7292 * - Direct Sensor Mode Continuous Capture
7293 * - Buffered Sensor Mode Continuous Capture
7295 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR);
7296 buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR);
7297 online = pipe->stream->config.online;
7298 continuous = pipe->stream->config.continuous;
7299 need_in_frameinfo_memory =
7300 !((sensor && (online || continuous)) || (buffered_sensor && (online || continuous)));
7302 /* Construct in_frame info (only in case we have dynamic input */
7303 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
7305 if (need_in_frameinfo_memory) {
7306 err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame,
7307 IA_CSS_FRAME_FORMAT_RAW);
7309 IA_CSS_LEAVE_ERR_PRIVATE(err);
7313 in_frame = &me->in_frame;
7318 err = init_out_frameinfo_defaults(pipe, &me->out_frame[0], 0);
7320 IA_CSS_LEAVE_ERR_PRIVATE(err);
7323 out_frame = &me->out_frame[0];
7325 /* Construct vf_frame info (only in case we have VF) */
7326 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
7327 if (mode == IA_CSS_CAPTURE_MODE_RAW || mode == IA_CSS_CAPTURE_MODE_BAYER) {
7328 /* These modes don't support viewfinder output */
7331 init_vf_frameinfo_defaults(pipe, &me->vf_frame[0], 0);
7332 vf_frame = &me->vf_frame[0];
7338 copy_binary = &pipe->pipe_settings.capture.copy_binary;
7339 num_primary_stage = pipe->pipe_settings.capture.num_primary_stage;
7340 if ((num_primary_stage == 0) && (mode == IA_CSS_CAPTURE_MODE_PRIMARY)) {
7341 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
7345 for (i = 0; i < num_primary_stage; i++)
7346 primary_binary[i] = &pipe->pipe_settings.capture.primary_binary[i];
7348 vf_pp_binary = &pipe->pipe_settings.capture.vf_pp_binary;
7349 pre_isp_binary = &pipe->pipe_settings.capture.pre_isp_binary;
7350 anr_gdc_binary = &pipe->pipe_settings.capture.anr_gdc_binary;
7351 post_isp_binary = &pipe->pipe_settings.capture.post_isp_binary;
7352 capture_pp_binary = &pipe->pipe_settings.capture.capture_pp_binary;
7353 yuv_scaler_binary = pipe->pipe_settings.capture.yuv_scaler_binary;
7354 num_yuv_scaler = pipe->pipe_settings.capture.num_yuv_scaler;
7355 is_output_stage = pipe->pipe_settings.capture.is_output_stage;
7356 capture_ldc_binary = &pipe->pipe_settings.capture.capture_ldc_binary;
7358 need_pp = (need_capture_pp(pipe) || pipe->output_stage) &&
7359 mode != IA_CSS_CAPTURE_MODE_RAW &&
7360 mode != IA_CSS_CAPTURE_MODE_BAYER;
7361 need_yuv_pp = (yuv_scaler_binary && yuv_scaler_binary->info);
7362 need_ldc = (capture_ldc_binary && capture_ldc_binary->info);
7364 if (pipe->pipe_settings.capture.copy_binary.info) {
7366 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
7367 #if defined(ISP2401)
7369 ia_css_pipe_get_generic_stage_desc(&stage_desc,
7375 in_frame = pipe->stream->last_pipe->continuous_frames[0];
7376 ia_css_pipe_get_generic_stage_desc(&stage_desc,
7383 ia_css_pipe_get_generic_stage_desc(&stage_desc,
7389 ia_css_pipe_util_set_output_frames(out_frames, 0,
7391 ia_css_pipe_get_generic_stage_desc(&stage_desc,
7397 err = ia_css_pipeline_create_and_add_stage(me,
7401 IA_CSS_LEAVE_ERR_PRIVATE(err);
7404 } else if (pipe->stream->config.continuous) {
7405 in_frame = pipe->stream->last_pipe->continuous_frames[0];
7408 if (mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
7409 struct ia_css_frame *local_in_frame = NULL;
7410 struct ia_css_frame *local_out_frame = NULL;
7412 for (i = 0; i < num_primary_stage; i++) {
7414 local_in_frame = in_frame;
7416 local_in_frame = NULL;
7418 if (!need_pp && (i == num_primary_stage - 1))
7420 if (!need_pp && (i == num_primary_stage - 1) && !need_ldc)
7422 local_out_frame = out_frame;
7424 local_out_frame = NULL;
7425 ia_css_pipe_util_set_output_frames(out_frames, 0, local_out_frame);
7427 * WARNING: The #if def flag has been added below as a
7428 * temporary solution to solve the problem of enabling the
7429 * view finder in a single binary in a capture flow. The
7430 * vf-pp stage has been removed from Skycam in the solution
7431 * provided. The vf-pp stage should be re-introduced when
7432 * required. This * should not be considered as a clean solution.
7433 * Proper investigation should be done to come up with the clean
7436 ia_css_pipe_get_generic_stage_desc(&stage_desc,
7441 err = ia_css_pipeline_create_and_add_stage(me,
7445 IA_CSS_LEAVE_ERR_PRIVATE(err);
7449 /* If we use copy iso primary, the input must be yuv iso raw */
7450 current_stage->args.copy_vf =
7451 primary_binary[0]->info->sp.pipeline.mode ==
7452 IA_CSS_BINARY_MODE_COPY;
7453 current_stage->args.copy_output = current_stage->args.copy_vf;
7454 } else if (mode == IA_CSS_CAPTURE_MODE_ADVANCED ||
7455 mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) {
7456 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
7457 ia_css_pipe_get_generic_stage_desc(&stage_desc, pre_isp_binary,
7458 out_frames, in_frame, NULL);
7459 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
7462 IA_CSS_LEAVE_ERR_PRIVATE(err);
7465 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
7466 ia_css_pipe_get_generic_stage_desc(&stage_desc, anr_gdc_binary,
7467 out_frames, NULL, NULL);
7468 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
7471 IA_CSS_LEAVE_ERR_PRIVATE(err);
7476 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
7477 ia_css_pipe_get_generic_stage_desc(&stage_desc,
7482 ia_css_pipe_util_set_output_frames(out_frames, 0,
7484 ia_css_pipe_get_generic_stage_desc(&stage_desc,
7490 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
7493 IA_CSS_LEAVE_ERR_PRIVATE(err);
7496 } else if (mode == IA_CSS_CAPTURE_MODE_BAYER) {
7497 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
7498 ia_css_pipe_get_generic_stage_desc(&stage_desc, pre_isp_binary,
7499 out_frames, in_frame, NULL);
7500 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc,
7503 IA_CSS_LEAVE_ERR_PRIVATE(err);
7508 if (need_pp && current_stage) {
7509 struct ia_css_frame *local_in_frame = NULL;
7511 local_in_frame = current_stage->args.out_frame[0];
7514 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
7515 ia_css_pipe_get_generic_stage_desc(&stage_desc,
7520 err = ia_css_pipeline_create_and_add_stage(me,
7523 local_in_frame = current_stage->args.out_frame[0];
7525 err = add_capture_pp_stage(pipe, me, local_in_frame,
7526 need_yuv_pp ? NULL : out_frame,
7530 IA_CSS_LEAVE_ERR_PRIVATE(err);
7535 if (need_yuv_pp && current_stage) {
7536 struct ia_css_frame *tmp_in_frame = current_stage->args.out_frame[0];
7537 struct ia_css_frame *tmp_out_frame = NULL;
7539 for (i = 0; i < num_yuv_scaler; i++) {
7540 if (is_output_stage[i])
7541 tmp_out_frame = out_frame;
7543 tmp_out_frame = NULL;
7545 err = add_yuv_scaler_stage(pipe, me, tmp_in_frame,
7546 tmp_out_frame, NULL,
7547 &yuv_scaler_binary[i],
7550 IA_CSS_LEAVE_ERR_PRIVATE(err);
7553 /* we use output port 1 as internal output port */
7554 tmp_in_frame = yuv_scaler_stage->args.out_frame[1];
7559 * WARNING: The #if def flag has been added below as a
7560 * temporary solution to solve the problem of enabling the
7561 * view finder in a single binary in a capture flow. The vf-pp
7562 * stage has been removed from Skycam in the solution provided.
7563 * The vf-pp stage should be re-introduced when required. This
7564 * should not be considered as a clean solution. Proper
7565 * investigation should be done to come up with the clean solution.
7567 if (mode != IA_CSS_CAPTURE_MODE_RAW &&
7568 mode != IA_CSS_CAPTURE_MODE_BAYER &&
7569 current_stage && vf_frame) {
7570 in_frame = current_stage->args.out_vf_frame;
7571 err = add_vf_pp_stage(pipe, in_frame, vf_frame, vf_pp_binary,
7574 IA_CSS_LEAVE_ERR_PRIVATE(err);
7578 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
7580 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7581 "create_host_regular_capture_pipeline() leave:\n");
7587 create_host_capture_pipeline(struct ia_css_pipe *pipe)
7591 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
7593 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY)
7594 err = create_host_isyscopy_capture_pipeline(pipe);
7596 err = create_host_regular_capture_pipeline(pipe);
7598 IA_CSS_LEAVE_ERR_PRIVATE(err);
7602 IA_CSS_LEAVE_ERR_PRIVATE(err);
7607 static int capture_start(struct ia_css_pipe *pipe)
7609 struct ia_css_pipeline *me;
7610 unsigned int thread_id;
7613 enum sh_css_pipe_config_override copy_ovrd;
7615 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
7617 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
7621 me = &pipe->pipeline;
7623 if ((pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW ||
7624 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER) &&
7625 (pipe->config.mode != IA_CSS_PIPE_MODE_COPY)) {
7626 if (copy_on_sp(pipe)) {
7627 err = start_copy_on_sp(pipe, &me->out_frame[0]);
7628 IA_CSS_LEAVE_ERR_PRIVATE(err);
7633 #if !defined(ISP2401)
7634 /* old isys: need to send_mipi_frames() in all pipe modes */
7635 err = send_mipi_frames(pipe);
7637 IA_CSS_LEAVE_ERR_PRIVATE(err);
7641 if (pipe->config.mode != IA_CSS_PIPE_MODE_COPY) {
7642 err = send_mipi_frames(pipe);
7644 IA_CSS_LEAVE_ERR_PRIVATE(err);
7650 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
7651 copy_ovrd = 1 << thread_id;
7653 start_pipe(pipe, copy_ovrd, pipe->stream->config.mode);
7655 #if !defined(ISP2401)
7657 * old isys: for IA_CSS_PIPE_MODE_COPY pipe, isys rx has to be configured,
7658 * which is currently done in start_binary(); but COPY pipe contains no binary,
7659 * and does not call start_binary(); so we need to configure the rx here.
7661 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY &&
7662 pipe->stream->reconfigure_css_rx) {
7663 ia_css_isys_rx_configure(&pipe->stream->csi_rx_config,
7664 pipe->stream->config.mode);
7665 pipe->stream->reconfigure_css_rx = false;
7669 IA_CSS_LEAVE_ERR_PRIVATE(err);
7674 sh_css_pipe_get_output_frame_info(struct ia_css_pipe *pipe,
7675 struct ia_css_frame_info *info,
7681 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7682 "sh_css_pipe_get_output_frame_info() enter:\n");
7684 *info = pipe->output_info[idx];
7685 if (copy_on_sp(pipe) &&
7686 pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) {
7687 ia_css_frame_info_init(
7691 IA_CSS_FRAME_FORMAT_BINARY_8,
7693 } else if (info->format == IA_CSS_FRAME_FORMAT_RAW ||
7694 info->format == IA_CSS_FRAME_FORMAT_RAW_PACKED) {
7695 info->raw_bit_depth =
7696 ia_css_pipe_util_pipe_input_format_bpp(pipe);
7699 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7700 "sh_css_pipe_get_output_frame_info() leave:\n");
7705 ia_css_stream_send_input_frame(const struct ia_css_stream *stream,
7706 const unsigned short *data,
7708 unsigned int height)
7712 ia_css_inputfifo_send_input_frame(
7713 data, width, height,
7714 stream->config.channel_id,
7715 stream->config.input_config.format,
7716 stream->config.pixels_per_clock == 2);
7720 ia_css_stream_start_input_frame(const struct ia_css_stream *stream)
7724 ia_css_inputfifo_start_frame(
7725 stream->config.channel_id,
7726 stream->config.input_config.format,
7727 stream->config.pixels_per_clock == 2);
7731 ia_css_stream_send_input_line(const struct ia_css_stream *stream,
7732 const unsigned short *data,
7734 const unsigned short *data2,
7735 unsigned int width2)
7739 ia_css_inputfifo_send_line(stream->config.channel_id,
7740 data, width, data2, width2);
7744 ia_css_stream_send_input_embedded_line(const struct ia_css_stream *stream,
7745 enum atomisp_input_format format,
7746 const unsigned short *data,
7750 if (!data || width == 0)
7752 ia_css_inputfifo_send_embedded_line(stream->config.channel_id,
7753 format, data, width);
7757 ia_css_stream_end_input_frame(const struct ia_css_stream *stream)
7761 ia_css_inputfifo_end_frame(stream->config.channel_id);
7765 append_firmware(struct ia_css_fw_info **l, struct ia_css_fw_info *firmware)
7767 IA_CSS_ENTER_PRIVATE("l = %p, firmware = %p", l, firmware);
7769 IA_CSS_ERROR("NULL fw_info");
7770 IA_CSS_LEAVE_PRIVATE("");
7776 /* when multiple acc extensions are loaded, 'next' can be not NULL */
7777 /*firmware->next = NULL;*/
7778 IA_CSS_LEAVE_PRIVATE("");
7782 remove_firmware(struct ia_css_fw_info **l, struct ia_css_fw_info *firmware)
7788 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "remove_firmware() enter:\n");
7790 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "remove_firmware() leave:\n");
7791 return; /* removing single and multiple firmware is handled in acc_unload_extension() */
7794 static int upload_isp_code(struct ia_css_fw_info *firmware)
7799 IA_CSS_ERROR("NULL input parameter");
7802 binary = firmware->info.isp.xmem_addr;
7805 unsigned int size = firmware->blob.size;
7806 const unsigned char *blob;
7807 const unsigned char *binary_name;
7810 (const unsigned char *)(IA_CSS_EXT_ISP_PROG_NAME(
7812 blob = binary_name +
7813 strlen((const char *)binary_name) +
7815 binary = sh_css_load_blob(blob, size);
7816 firmware->info.isp.xmem_addr = binary;
7825 acc_load_extension(struct ia_css_fw_info *firmware)
7828 struct ia_css_fw_info *hd = firmware;
7831 err = upload_isp_code(hd);
7839 firmware->loaded = true;
7844 acc_unload_extension(struct ia_css_fw_info *firmware)
7846 struct ia_css_fw_info *hd = firmware;
7847 struct ia_css_fw_info *hdn = NULL;
7849 if (!firmware) /* should not happen */
7851 /* unload and remove multiple firmwares */
7853 hdn = (hd->next) ? &(*hd->next) : NULL;
7854 if (hd->info.isp.xmem_addr) {
7855 hmm_free(hd->info.isp.xmem_addr);
7856 hd->info.isp.xmem_addr = mmgr_NULL;
7858 hd->isp_code = NULL;
7863 firmware->loaded = false;
7866 /* Load firmware for extension */
7868 ia_css_pipe_load_extension(struct ia_css_pipe *pipe,
7869 struct ia_css_fw_info *firmware)
7873 IA_CSS_ENTER_PRIVATE("fw = %p pipe = %p", firmware, pipe);
7875 if ((!firmware) || (!pipe)) {
7876 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
7880 if (firmware->info.isp.type == IA_CSS_ACC_OUTPUT)
7881 append_firmware(&pipe->output_stage, firmware);
7882 else if (firmware->info.isp.type == IA_CSS_ACC_VIEWFINDER)
7883 append_firmware(&pipe->vf_stage, firmware);
7884 err = acc_load_extension(firmware);
7886 IA_CSS_LEAVE_ERR_PRIVATE(err);
7890 /* Unload firmware for extension */
7892 ia_css_pipe_unload_extension(struct ia_css_pipe *pipe,
7893 struct ia_css_fw_info *firmware)
7895 IA_CSS_ENTER_PRIVATE("fw = %p pipe = %p", firmware, pipe);
7897 if ((!firmware) || (!pipe)) {
7898 IA_CSS_ERROR("NULL input parameters");
7899 IA_CSS_LEAVE_PRIVATE("");
7903 if (firmware->info.isp.type == IA_CSS_ACC_OUTPUT)
7904 remove_firmware(&pipe->output_stage, firmware);
7905 else if (firmware->info.isp.type == IA_CSS_ACC_VIEWFINDER)
7906 remove_firmware(&pipe->vf_stage, firmware);
7907 acc_unload_extension(firmware);
7909 IA_CSS_LEAVE_PRIVATE("");
7913 ia_css_pipeline_uses_params(struct ia_css_pipeline *me)
7915 struct ia_css_pipeline_stage *stage;
7919 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
7920 "ia_css_pipeline_uses_params() enter: me=%p\n", me);
7922 for (stage = me->stages; stage; stage = stage->next)
7923 if (stage->binary_info && stage->binary_info->enable.params) {
7924 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
7925 "ia_css_pipeline_uses_params() leave: return_bool=true\n");
7928 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
7929 "ia_css_pipeline_uses_params() leave: return_bool=false\n");
7934 sh_css_pipeline_add_acc_stage(struct ia_css_pipeline *pipeline,
7937 struct ia_css_fw_info *fw = (struct ia_css_fw_info *)acc_fw;
7938 /* In QoS case, load_extension already called, so skipping */
7942 err = acc_load_extension(fw);
7944 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
7945 "sh_css_pipeline_add_acc_stage() enter: pipeline=%p, acc_fw=%p\n",
7949 struct ia_css_pipeline_stage_desc stage_desc;
7951 ia_css_pipe_get_acc_stage_desc(&stage_desc, NULL, fw);
7952 err = ia_css_pipeline_create_and_add_stage(pipeline,
7957 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
7958 "sh_css_pipeline_add_acc_stage() leave: return_err=%d\n", err);
7963 * @brief Tag a specific frame in continuous capture.
7964 * Refer to "sh_css_internal.h" for details.
7966 int ia_css_stream_capture_frame(struct ia_css_stream *stream,
7967 unsigned int exp_id)
7969 struct sh_css_tag_descr tag_descr;
7970 u32 encoded_tag_descr;
7974 IA_CSS_ENTER("exp_id=%d", exp_id);
7976 /* Only continuous streams have a tagger */
7977 if (exp_id == 0 || !stream->config.continuous) {
7978 IA_CSS_LEAVE_ERR(-EINVAL);
7982 if (!sh_css_sp_is_running()) {
7983 /* SP is not running. The queues are not valid */
7984 IA_CSS_LEAVE_ERR(-EBUSY);
7988 /* Create the tag descriptor from the parameters */
7989 sh_css_create_tag_descr(0, 0, 0, exp_id, &tag_descr);
7990 /* Encode the tag descriptor into a 32-bit value */
7991 encoded_tag_descr = sh_css_encode_tag_descr(&tag_descr);
7993 * Enqueue the encoded tag to the host2sp queue.
7994 * Note: The pipe and stage IDs for tag_cmd queue are hard-coded to 0
7995 * on both host and the SP side.
7996 * It is mainly because it is enough to have only one tag_cmd queue
7998 err = ia_css_bufq_enqueue_tag_cmd(encoded_tag_descr);
8000 IA_CSS_LEAVE_ERR(err);
8005 * @brief Configure the continuous capture.
8006 * Refer to "sh_css_internal.h" for details.
8008 int ia_css_stream_capture(struct ia_css_stream *stream, int num_captures,
8009 unsigned int skip, int offset)
8011 struct sh_css_tag_descr tag_descr;
8012 unsigned int encoded_tag_descr;
8018 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8019 "ia_css_stream_capture() enter: num_captures=%d, skip=%d, offset=%d\n",
8020 num_captures, skip, offset);
8022 /* Check if the tag descriptor is valid */
8023 if (num_captures < SH_CSS_MINIMUM_TAG_ID) {
8024 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8025 "ia_css_stream_capture() leave: return_err=%d\n",
8030 /* Create the tag descriptor from the parameters */
8031 sh_css_create_tag_descr(num_captures, skip, offset, 0, &tag_descr);
8033 /* Encode the tag descriptor into a 32-bit value */
8034 encoded_tag_descr = sh_css_encode_tag_descr(&tag_descr);
8036 if (!sh_css_sp_is_running()) {
8037 /* SP is not running. The queues are not valid */
8038 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8039 "ia_css_stream_capture() leaving:queues unavailable\n");
8044 * Enqueue the encoded tag to the host2sp queue.
8045 * Note: The pipe and stage IDs for tag_cmd queue are hard-coded to 0
8046 * on both host and the SP side.
8047 * It is mainly because it is enough to have only one tag_cmd queue
8049 return_err = ia_css_bufq_enqueue_tag_cmd((uint32_t)encoded_tag_descr);
8051 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8052 "ia_css_stream_capture() leave: return_err=%d\n",
8058 void ia_css_stream_request_flash(struct ia_css_stream *stream)
8063 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8064 "ia_css_stream_request_flash() enter: void\n");
8067 sh_css_write_host2sp_command(host2sp_cmd_start_flash);
8069 if (sh_css_sp_is_running()) {
8070 if (!sh_css_write_host2sp_command(host2sp_cmd_start_flash)) {
8071 IA_CSS_ERROR("Call to 'sh-css_write_host2sp_command()' failed");
8072 ia_css_debug_dump_sp_sw_debug_info();
8073 ia_css_debug_dump_debug_info(NULL);
8076 IA_CSS_LOG("SP is not running!");
8080 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8081 "ia_css_stream_request_flash() leave: return_void\n");
8085 sh_css_init_host_sp_control_vars(void)
8087 const struct ia_css_fw_info *fw;
8088 unsigned int HIVE_ADDR_ia_css_ispctrl_sp_isp_started;
8090 unsigned int HIVE_ADDR_host_sp_queues_initialized;
8091 unsigned int HIVE_ADDR_sp_sleep_mode;
8092 unsigned int HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb;
8093 unsigned int HIVE_ADDR_sp_stop_copy_preview;
8094 unsigned int HIVE_ADDR_host_sp_com;
8095 unsigned int o = offsetof(struct host_sp_communication, host2sp_command)
8100 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8101 "sh_css_init_host_sp_control_vars() enter: void\n");
8104 HIVE_ADDR_ia_css_ispctrl_sp_isp_started = fw->info.sp.isp_started;
8106 HIVE_ADDR_host_sp_queues_initialized =
8107 fw->info.sp.host_sp_queues_initialized;
8108 HIVE_ADDR_sp_sleep_mode = fw->info.sp.sleep_mode;
8109 HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb = fw->info.sp.invalidate_tlb;
8110 HIVE_ADDR_sp_stop_copy_preview = fw->info.sp.stop_copy_preview;
8111 HIVE_ADDR_host_sp_com = fw->info.sp.host_sp_com;
8113 sp_dmem_store_uint32(SP0_ID,
8114 (unsigned int)sp_address_of(ia_css_ispctrl_sp_isp_started),
8117 sp_dmem_store_uint32(SP0_ID,
8118 (unsigned int)sp_address_of(host_sp_queues_initialized),
8120 sp_dmem_store_uint32(SP0_ID,
8121 (unsigned int)sp_address_of(sp_sleep_mode),
8123 sp_dmem_store_uint32(SP0_ID,
8124 (unsigned int)sp_address_of(ia_css_dmaproxy_sp_invalidate_tlb),
8126 sp_dmem_store_uint32(SP0_ID,
8127 (unsigned int)sp_address_of(sp_stop_copy_preview),
8128 my_css.stop_copy_preview ? (uint32_t)(1) : (uint32_t)(0));
8129 store_sp_array_uint(host_sp_com, o, host2sp_cmd_ready);
8131 for (i = 0; i < N_CSI_PORTS; i++) {
8132 sh_css_update_host2sp_num_mipi_frames
8133 (my_css.num_mipi_frames[i]);
8136 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8137 "sh_css_init_host_sp_control_vars() leave: return_void\n");
8141 * create the internal structures and fill in the configuration data
8145 ia_css_pipe_config ia_css_pipe_default_config = DEFAULT_PIPE_CONFIG;
8147 void ia_css_pipe_config_defaults(struct ia_css_pipe_config *pipe_config)
8149 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_config_defaults()\n");
8150 memcpy(pipe_config, &ia_css_pipe_default_config, sizeof(*pipe_config));
8154 ia_css_pipe_extra_config_defaults(struct ia_css_pipe_extra_config *extra_config)
8156 if (!extra_config) {
8157 IA_CSS_ERROR("NULL input parameter");
8161 extra_config->enable_raw_binning = false;
8162 extra_config->enable_yuv_ds = false;
8163 extra_config->enable_high_speed = false;
8164 extra_config->enable_dvs_6axis = false;
8165 extra_config->enable_reduced_pipe = false;
8166 extra_config->disable_vf_pp = false;
8167 extra_config->enable_fractional_ds = false;
8170 void ia_css_stream_config_defaults(struct ia_css_stream_config *stream_config)
8172 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_config_defaults()\n");
8173 assert(stream_config);
8174 memset(stream_config, 0, sizeof(*stream_config));
8175 stream_config->online = true;
8176 stream_config->left_padding = -1;
8177 stream_config->pixels_per_clock = 1;
8179 * temporary default value for backwards compatibility.
8180 * This field used to be hardcoded within CSS but this has now
8181 * been moved to the stream_config struct.
8183 stream_config->source.port.rxcount = 0x04040404;
8187 ia_css_acc_pipe_create(struct ia_css_pipe *pipe)
8192 IA_CSS_ERROR("NULL input parameter");
8196 /* There is not meaning for num_execs = 0 semantically. Run at least once. */
8197 if (pipe->config.acc_num_execs == 0)
8198 pipe->config.acc_num_execs = 1;
8200 if (pipe->config.acc_extension)
8201 err = ia_css_pipe_load_extension(pipe, pipe->config.acc_extension);
8206 int ia_css_pipe_create(const struct ia_css_pipe_config *config,
8207 struct ia_css_pipe **pipe)
8211 IA_CSS_ENTER_PRIVATE("config = %p, pipe = %p", config, pipe);
8213 if (!config || !pipe) {
8214 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
8218 err = ia_css_pipe_create_extra(config, NULL, pipe);
8221 IA_CSS_LOG("pipe created successfully = %p", *pipe);
8223 IA_CSS_LEAVE_ERR_PRIVATE(err);
8229 ia_css_pipe_create_extra(const struct ia_css_pipe_config *config,
8230 const struct ia_css_pipe_extra_config *extra_config,
8231 struct ia_css_pipe **pipe)
8234 struct ia_css_pipe *internal_pipe = NULL;
8237 IA_CSS_ENTER_PRIVATE("config = %p, extra_config = %p and pipe = %p", config, extra_config, pipe);
8239 /* do not allow to create more than the maximum limit */
8240 if (my_css.pipe_counter >= IA_CSS_PIPELINE_NUM_MAX) {
8241 IA_CSS_LEAVE_ERR_PRIVATE(-ENOSPC);
8245 if ((!pipe) || (!config)) {
8246 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
8250 ia_css_debug_dump_pipe_config(config);
8251 ia_css_debug_dump_pipe_extra_config(extra_config);
8253 err = create_pipe(config->mode, &internal_pipe, false);
8255 IA_CSS_LEAVE_ERR_PRIVATE(err);
8259 /* now we have a pipe structure to fill */
8260 internal_pipe->config = *config;
8262 internal_pipe->extra_config = *extra_config;
8264 ia_css_pipe_extra_config_defaults(&internal_pipe->extra_config);
8266 if (config->mode == IA_CSS_PIPE_MODE_ACC) {
8268 * Temporary hack to migrate acceleration to CSS 2.0.
8269 * In the future the code for all pipe types should be
8272 *pipe = internal_pipe;
8273 if (!internal_pipe->config.acc_extension &&
8274 internal_pipe->config.num_acc_stages ==
8275 0) { /* if no acc binary and no standalone stage */
8277 IA_CSS_LEAVE_ERR_PRIVATE(0);
8280 return ia_css_acc_pipe_create(internal_pipe);
8284 * Use config value when dvs_frame_delay setting equal to 2,
8285 * otherwise always 1 by default
8287 if (internal_pipe->config.dvs_frame_delay == IA_CSS_FRAME_DELAY_2)
8288 internal_pipe->dvs_frame_delay = 2;
8290 internal_pipe->dvs_frame_delay = 1;
8293 * we still keep enable_raw_binning for backward compatibility,
8294 * for any new fractional bayer downscaling, we should use
8295 * bayer_ds_out_res. if both are specified, bayer_ds_out_res will
8296 * take precedence.if none is specified, we set bayer_ds_out_res
8297 * equal to IF output resolution(IF may do cropping on sensor output)
8298 * or use default decimation factor 1.
8301 /* YUV downscaling */
8302 if ((internal_pipe->config.vf_pp_in_res.width ||
8303 internal_pipe->config.capt_pp_in_res.width)) {
8304 enum ia_css_frame_format format;
8306 if (internal_pipe->config.vf_pp_in_res.width) {
8307 format = IA_CSS_FRAME_FORMAT_YUV_LINE;
8308 ia_css_frame_info_init(
8309 &internal_pipe->vf_yuv_ds_input_info,
8310 internal_pipe->config.vf_pp_in_res.width,
8311 internal_pipe->config.vf_pp_in_res.height,
8314 if (internal_pipe->config.capt_pp_in_res.width) {
8315 format = IA_CSS_FRAME_FORMAT_YUV420;
8316 ia_css_frame_info_init(
8317 &internal_pipe->out_yuv_ds_input_info,
8318 internal_pipe->config.capt_pp_in_res.width,
8319 internal_pipe->config.capt_pp_in_res.height,
8323 if (internal_pipe->config.vf_pp_in_res.width &&
8324 internal_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) {
8325 ia_css_frame_info_init(
8326 &internal_pipe->vf_yuv_ds_input_info,
8327 internal_pipe->config.vf_pp_in_res.width,
8328 internal_pipe->config.vf_pp_in_res.height,
8329 IA_CSS_FRAME_FORMAT_YUV_LINE, 0);
8331 /* handle bayer downscaling output info */
8332 if (internal_pipe->config.bayer_ds_out_res.width) {
8333 ia_css_frame_info_init(
8334 &internal_pipe->bds_output_info,
8335 internal_pipe->config.bayer_ds_out_res.width,
8336 internal_pipe->config.bayer_ds_out_res.height,
8337 IA_CSS_FRAME_FORMAT_RAW, 0);
8340 /* handle output info, assume always needed */
8341 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
8342 if (internal_pipe->config.output_info[i].res.width) {
8343 err = sh_css_pipe_configure_output(
8345 internal_pipe->config.output_info[i].res.width,
8346 internal_pipe->config.output_info[i].res.height,
8347 internal_pipe->config.output_info[i].padded_width,
8348 internal_pipe->config.output_info[i].format,
8351 IA_CSS_LEAVE_ERR_PRIVATE(err);
8352 kvfree(internal_pipe);
8353 internal_pipe = NULL;
8358 /* handle vf output info, when configured */
8359 internal_pipe->enable_viewfinder[i] =
8360 (internal_pipe->config.vf_output_info[i].res.width != 0);
8361 if (internal_pipe->config.vf_output_info[i].res.width) {
8362 err = sh_css_pipe_configure_viewfinder(
8364 internal_pipe->config.vf_output_info[i].res.width,
8365 internal_pipe->config.vf_output_info[i].res.height,
8366 internal_pipe->config.vf_output_info[i].padded_width,
8367 internal_pipe->config.vf_output_info[i].format,
8370 IA_CSS_LEAVE_ERR_PRIVATE(err);
8371 kvfree(internal_pipe);
8372 internal_pipe = NULL;
8377 if (internal_pipe->config.acc_extension) {
8378 err = ia_css_pipe_load_extension(internal_pipe,
8379 internal_pipe->config.acc_extension);
8381 IA_CSS_LEAVE_ERR_PRIVATE(err);
8382 kvfree(internal_pipe);
8386 /* set all info to zeroes first */
8387 memset(&internal_pipe->info, 0, sizeof(internal_pipe->info));
8389 /* all went well, return the pipe */
8390 *pipe = internal_pipe;
8391 IA_CSS_LEAVE_ERR_PRIVATE(0);
8396 ia_css_pipe_get_info(const struct ia_css_pipe *pipe,
8397 struct ia_css_pipe_info *pipe_info)
8399 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8400 "ia_css_pipe_get_info()\n");
8402 ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR,
8403 "ia_css_pipe_get_info: pipe_info cannot be NULL\n");
8406 if (!pipe || !pipe->stream) {
8407 ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR,
8408 "ia_css_pipe_get_info: ia_css_stream_create needs to be called before ia_css_[stream/pipe]_get_info\n");
8411 /* we succeeded return the info */
8412 *pipe_info = pipe->info;
8413 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_get_info() leave\n");
8417 bool ia_css_pipe_has_dvs_stats(struct ia_css_pipe_info *pipe_info)
8422 for (i = 0; i < IA_CSS_DVS_STAT_NUM_OF_LEVELS; i++) {
8423 if (pipe_info->grid_info.dvs_grid.dvs_stat_grid_info.grd_cfg[i].grd_start.enable)
8432 ia_css_pipe_override_frame_format(struct ia_css_pipe *pipe,
8434 enum ia_css_frame_format new_format)
8438 IA_CSS_ENTER_PRIVATE("pipe = %p, pin_index = %d, new_formats = %d", pipe, pin_index, new_format);
8441 IA_CSS_ERROR("pipe is not set");
8443 IA_CSS_LEAVE_ERR_PRIVATE(err);
8446 if (0 != pin_index && 1 != pin_index) {
8447 IA_CSS_ERROR("pin index is not valid");
8449 IA_CSS_LEAVE_ERR_PRIVATE(err);
8452 if (new_format != IA_CSS_FRAME_FORMAT_NV12_TILEY) {
8453 IA_CSS_ERROR("new format is not valid");
8455 IA_CSS_LEAVE_ERR_PRIVATE(err);
8458 err = ia_css_pipe_check_format(pipe, new_format);
8461 pipe->output_info[0].format = new_format;
8463 pipe->vf_output_info[0].format = new_format;
8466 IA_CSS_LEAVE_ERR_PRIVATE(err);
8470 #if !defined(ISP2401)
8471 /* Configuration of INPUT_SYSTEM_VERSION_2401 is done on SP */
8473 ia_css_stream_configure_rx(struct ia_css_stream *stream)
8475 struct ia_css_input_port *config;
8479 config = &stream->config.source.port;
8480 /* AM: this code is not reliable, especially for 2400 */
8481 if (config->num_lanes == 1)
8482 stream->csi_rx_config.mode = MONO_1L_1L_0L;
8483 else if (config->num_lanes == 2)
8484 stream->csi_rx_config.mode = MONO_2L_1L_0L;
8485 else if (config->num_lanes == 3)
8486 stream->csi_rx_config.mode = MONO_3L_1L_0L;
8487 else if (config->num_lanes == 4)
8488 stream->csi_rx_config.mode = MONO_4L_1L_0L;
8489 else if (config->num_lanes != 0)
8492 if (config->port > MIPI_PORT2_ID)
8494 stream->csi_rx_config.port =
8495 ia_css_isys_port_to_mipi_port(config->port);
8496 stream->csi_rx_config.timeout = config->timeout;
8497 stream->csi_rx_config.initcount = 0;
8498 stream->csi_rx_config.synccount = 0x28282828;
8499 stream->csi_rx_config.rxcount = config->rxcount;
8500 if (config->compression.type == IA_CSS_CSI2_COMPRESSION_TYPE_NONE)
8501 stream->csi_rx_config.comp = MIPI_PREDICTOR_NONE;
8504 * not implemented yet, requires extension of the rx_cfg_t
8509 stream->csi_rx_config.is_two_ppc = (stream->config.pixels_per_clock == 2);
8510 stream->reconfigure_css_rx = true;
8515 static struct ia_css_pipe *
8516 find_pipe(struct ia_css_pipe *pipes[], unsigned int num_pipes,
8517 enum ia_css_pipe_mode mode, bool copy_pipe)
8522 for (i = 0; i < num_pipes; i++) {
8524 if (pipes[i]->config.mode != mode)
8526 if (copy_pipe && pipes[i]->mode != IA_CSS_PIPE_ID_COPY)
8534 ia_css_acc_stream_create(struct ia_css_stream *stream)
8539 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
8542 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
8546 for (i = 0; i < stream->num_pipes; i++) {
8547 struct ia_css_pipe *pipe = stream->pipes[i];
8550 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
8554 pipe->stream = stream;
8557 /* Map SP threads before doing anything. */
8558 err = map_sp_threads(stream, true);
8560 IA_CSS_LEAVE_ERR_PRIVATE(err);
8564 for (i = 0; i < stream->num_pipes; i++) {
8565 struct ia_css_pipe *pipe = stream->pipes[i];
8568 ia_css_pipe_map_queue(pipe, true);
8571 err = create_host_pipeline_structure(stream);
8573 IA_CSS_LEAVE_ERR_PRIVATE(err);
8577 stream->started = false;
8579 IA_CSS_LEAVE_ERR_PRIVATE(0);
8585 metadata_info_init(const struct ia_css_metadata_config *mdc,
8586 struct ia_css_metadata_info *md)
8588 /* Either both width and height should be set or neither */
8589 if ((mdc->resolution.height > 0) ^ (mdc->resolution.width > 0))
8592 md->resolution = mdc->resolution;
8594 * We round up the stride to a multiple of the width
8595 * of the port going to DDR, this is a HW requirements (DMA).
8597 md->stride = CEIL_MUL(mdc->resolution.width, HIVE_ISP_DDR_WORD_BYTES);
8598 md->size = mdc->resolution.height * md->stride;
8603 ia_css_stream_create(const struct ia_css_stream_config *stream_config,
8605 struct ia_css_pipe *pipes[],
8606 struct ia_css_stream **stream)
8608 struct ia_css_pipe *curr_pipe;
8609 struct ia_css_stream *curr_stream = NULL;
8611 bool sensor_binning_changed;
8614 struct ia_css_metadata_info md_info;
8615 struct ia_css_resolution effective_res;
8617 IA_CSS_ENTER("num_pipes=%d", num_pipes);
8618 ia_css_debug_dump_stream_config(stream_config, num_pipes);
8621 if (num_pipes == 0 ||
8625 IA_CSS_LEAVE_ERR(err);
8629 #if !defined(ISP2401)
8630 /* We don't support metadata for JPEG stream, since they both use str2mem */
8631 if (stream_config->input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8 &&
8632 stream_config->metadata_config.resolution.height > 0) {
8634 IA_CSS_LEAVE_ERR(err);
8640 if (stream_config->online && stream_config->pack_raw_pixels) {
8641 IA_CSS_LOG("online and pack raw is invalid on input system 2401");
8643 IA_CSS_LEAVE_ERR(err);
8648 ia_css_debug_pipe_graph_dump_stream_config(stream_config);
8650 /* check if mipi size specified */
8651 if (stream_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
8653 if (!stream_config->online)
8656 unsigned int port = (unsigned int)stream_config->source.port.port;
8658 if (port >= N_MIPI_PORT_ID) {
8660 IA_CSS_LEAVE_ERR(err);
8664 if (my_css.size_mem_words != 0) {
8665 my_css.mipi_frame_size[port] = my_css.size_mem_words;
8666 } else if (stream_config->mipi_buffer_config.size_mem_words != 0) {
8667 my_css.mipi_frame_size[port] = stream_config->mipi_buffer_config.size_mem_words;
8669 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8670 "ia_css_stream_create() exit: error, need to set mipi frame size.\n");
8671 assert(stream_config->mipi_buffer_config.size_mem_words != 0);
8673 IA_CSS_LEAVE_ERR(err);
8677 if (my_css.size_mem_words != 0) {
8678 my_css.num_mipi_frames[port] =
8679 2; /* Temp change: Default for backwards compatibility. */
8680 } else if (stream_config->mipi_buffer_config.nof_mipi_buffers != 0) {
8681 my_css.num_mipi_frames[port] =
8682 stream_config->mipi_buffer_config.nof_mipi_buffers;
8684 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8685 "ia_css_stream_create() exit: error, need to set number of mipi frames.\n");
8686 assert(stream_config->mipi_buffer_config.nof_mipi_buffers != 0);
8688 IA_CSS_LEAVE_ERR(err);
8693 /* Currently we only supported metadata up to a certain size. */
8694 err = metadata_info_init(&stream_config->metadata_config, &md_info);
8696 IA_CSS_LEAVE_ERR(err);
8700 /* allocate the stream instance */
8701 curr_stream = kzalloc(sizeof(struct ia_css_stream), GFP_KERNEL);
8704 IA_CSS_LEAVE_ERR(err);
8707 /* default all to 0 */
8708 curr_stream->info.metadata_info = md_info;
8710 /* allocate pipes */
8711 curr_stream->num_pipes = num_pipes;
8712 curr_stream->pipes = kcalloc(num_pipes, sizeof(struct ia_css_pipe *), GFP_KERNEL);
8713 if (!curr_stream->pipes) {
8714 curr_stream->num_pipes = 0;
8718 IA_CSS_LEAVE_ERR(err);
8722 spcopyonly = (num_pipes == 1) && (pipes[0]->config.mode == IA_CSS_PIPE_MODE_COPY);
8723 for (i = 0; i < num_pipes; i++)
8724 curr_stream->pipes[i] = pipes[i];
8725 curr_stream->last_pipe = curr_stream->pipes[0];
8726 /* take over stream config */
8727 curr_stream->config = *stream_config;
8729 #if defined(ISP2401)
8730 if (stream_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR &&
8731 stream_config->online)
8732 curr_stream->config.online = false;
8736 if (curr_stream->config.online) {
8737 curr_stream->config.source.port.num_lanes =
8738 stream_config->source.port.num_lanes;
8739 curr_stream->config.mode = IA_CSS_INPUT_MODE_BUFFERED_SENSOR;
8742 /* in case driver doesn't configure init number of raw buffers, configure it here */
8743 if (curr_stream->config.target_num_cont_raw_buf == 0)
8744 curr_stream->config.target_num_cont_raw_buf = NUM_CONTINUOUS_FRAMES;
8745 if (curr_stream->config.init_num_cont_raw_buf == 0)
8746 curr_stream->config.init_num_cont_raw_buf = curr_stream->config.target_num_cont_raw_buf;
8748 /* Enable locking & unlocking of buffers in RAW buffer pool */
8749 if (curr_stream->config.ia_css_enable_raw_buffer_locking)
8750 sh_css_sp_configure_enable_raw_pool_locking(
8751 curr_stream->config.lock_all);
8753 /* copy mode specific stuff */
8754 switch (curr_stream->config.mode) {
8755 case IA_CSS_INPUT_MODE_SENSOR:
8756 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR:
8757 #if !defined(ISP2401)
8758 ia_css_stream_configure_rx(curr_stream);
8761 case IA_CSS_INPUT_MODE_TPG:
8762 #if !defined(ISP2401)
8763 IA_CSS_LOG("tpg_configuration: x_mask=%d, y_mask=%d, x_delta=%d, y_delta=%d, xy_mask=%d",
8764 curr_stream->config.source.tpg.x_mask,
8765 curr_stream->config.source.tpg.y_mask,
8766 curr_stream->config.source.tpg.x_delta,
8767 curr_stream->config.source.tpg.y_delta,
8768 curr_stream->config.source.tpg.xy_mask);
8770 sh_css_sp_configure_tpg(
8771 curr_stream->config.source.tpg.x_mask,
8772 curr_stream->config.source.tpg.y_mask,
8773 curr_stream->config.source.tpg.x_delta,
8774 curr_stream->config.source.tpg.y_delta,
8775 curr_stream->config.source.tpg.xy_mask);
8778 case IA_CSS_INPUT_MODE_PRBS:
8779 #if !defined(ISP2401)
8780 IA_CSS_LOG("mode prbs");
8781 sh_css_sp_configure_prbs(curr_stream->config.source.prbs.seed);
8784 case IA_CSS_INPUT_MODE_MEMORY:
8785 IA_CSS_LOG("mode memory");
8786 curr_stream->reconfigure_css_rx = false;
8789 IA_CSS_LOG("mode sensor/default");
8792 for (i = 0; i < num_pipes; i++) {
8793 struct ia_css_resolution effective_res;
8795 curr_pipe = pipes[i];
8796 /* set current stream */
8797 curr_pipe->stream = curr_stream;
8798 /* take over effective info */
8800 effective_res = curr_pipe->config.input_effective_res;
8801 if (effective_res.height == 0 || effective_res.width == 0) {
8802 effective_res = curr_pipe->stream->config.input_config.effective_res;
8804 curr_pipe->config.input_effective_res = effective_res;
8806 IA_CSS_LOG("effective_res=%dx%d",
8807 effective_res.width,
8808 effective_res.height);
8811 err = ia_css_stream_isp_parameters_init(curr_stream);
8814 IA_CSS_LOG("isp_params_configs: %p", curr_stream->isp_params_configs);
8816 if (num_pipes == 1 && pipes[0]->config.mode == IA_CSS_PIPE_MODE_ACC) {
8817 *stream = curr_stream;
8818 err = ia_css_acc_stream_create(curr_stream);
8821 /* sensor binning */
8823 sensor_binning_changed =
8824 sh_css_params_set_binning_factor(curr_stream,
8825 curr_stream->config.sensor_binning_factor);
8827 sensor_binning_changed = false;
8830 IA_CSS_LOG("sensor_binning=%d, changed=%d",
8831 curr_stream->config.sensor_binning_factor, sensor_binning_changed);
8832 /* loop over pipes */
8833 IA_CSS_LOG("num_pipes=%d", num_pipes);
8834 curr_stream->cont_capt = false;
8835 /* Temporary hack: we give the preview pipe a reference to the capture
8836 * pipe in continuous capture mode. */
8837 if (curr_stream->config.continuous) {
8838 /* Search for the preview pipe and create the copy pipe */
8839 struct ia_css_pipe *preview_pipe;
8840 struct ia_css_pipe *video_pipe;
8841 struct ia_css_pipe *acc_pipe;
8842 struct ia_css_pipe *capture_pipe = NULL;
8843 struct ia_css_pipe *copy_pipe = NULL;
8845 if (num_pipes >= 2) {
8846 curr_stream->cont_capt = true;
8847 curr_stream->disable_cont_vf = curr_stream->config.disable_cont_viewfinder;
8848 curr_stream->stop_copy_preview = my_css.stop_copy_preview;
8851 /* Create copy pipe here, since it may not be exposed to the driver */
8852 preview_pipe = find_pipe(pipes, num_pipes,
8853 IA_CSS_PIPE_MODE_PREVIEW, false);
8854 video_pipe = find_pipe(pipes, num_pipes,
8855 IA_CSS_PIPE_MODE_VIDEO, false);
8856 acc_pipe = find_pipe(pipes, num_pipes, IA_CSS_PIPE_MODE_ACC,
8858 if (acc_pipe && num_pipes == 2 && curr_stream->cont_capt)
8859 curr_stream->cont_capt =
8860 false; /* preview + QoS case will not need cont_capt switch */
8861 if (curr_stream->cont_capt) {
8862 capture_pipe = find_pipe(pipes, num_pipes,
8863 IA_CSS_PIPE_MODE_CAPTURE,
8865 if (!capture_pipe) {
8870 /* We do not support preview and video pipe at the same time */
8871 if (preview_pipe && video_pipe) {
8876 if (preview_pipe && !preview_pipe->pipe_settings.preview.copy_pipe) {
8877 err = create_pipe(IA_CSS_PIPE_MODE_CAPTURE, ©_pipe, true);
8880 ia_css_pipe_config_defaults(©_pipe->config);
8881 preview_pipe->pipe_settings.preview.copy_pipe = copy_pipe;
8882 copy_pipe->stream = curr_stream;
8884 if (preview_pipe && curr_stream->cont_capt)
8885 preview_pipe->pipe_settings.preview.capture_pipe = capture_pipe;
8887 if (video_pipe && !video_pipe->pipe_settings.video.copy_pipe) {
8888 err = create_pipe(IA_CSS_PIPE_MODE_CAPTURE, ©_pipe, true);
8891 ia_css_pipe_config_defaults(©_pipe->config);
8892 video_pipe->pipe_settings.video.copy_pipe = copy_pipe;
8893 copy_pipe->stream = curr_stream;
8895 if (video_pipe && curr_stream->cont_capt)
8896 video_pipe->pipe_settings.video.capture_pipe = capture_pipe;
8898 if (preview_pipe && acc_pipe)
8899 preview_pipe->pipe_settings.preview.acc_pipe = acc_pipe;
8901 for (i = 0; i < num_pipes; i++) {
8902 curr_pipe = pipes[i];
8903 /* set current stream */
8904 curr_pipe->stream = curr_stream;
8906 /* take over effective info */
8908 effective_res = curr_pipe->config.input_effective_res;
8909 err = ia_css_util_check_res(
8910 effective_res.width,
8911 effective_res.height);
8915 /* sensor binning per pipe */
8916 if (sensor_binning_changed)
8917 sh_css_pipe_free_shading_table(curr_pipe);
8920 /* now pipes have been configured, info should be available */
8921 for (i = 0; i < num_pipes; i++) {
8922 struct ia_css_pipe_info *pipe_info = NULL;
8924 curr_pipe = pipes[i];
8926 err = sh_css_pipe_load_binaries(curr_pipe);
8930 /* handle each pipe */
8931 pipe_info = &curr_pipe->info;
8932 for (j = 0; j < IA_CSS_PIPE_MAX_OUTPUT_STAGE; j++) {
8933 err = sh_css_pipe_get_output_frame_info(curr_pipe,
8934 &pipe_info->output_info[j], j);
8941 err = sh_css_pipe_get_shading_info(curr_pipe,
8942 &pipe_info->shading_info,
8945 err = sh_css_pipe_get_shading_info(curr_pipe,
8946 &pipe_info->shading_info,
8947 &curr_pipe->config);
8951 err = sh_css_pipe_get_grid_info(curr_pipe,
8952 &pipe_info->grid_info);
8955 for (j = 0; j < IA_CSS_PIPE_MAX_OUTPUT_STAGE; j++) {
8956 sh_css_pipe_get_viewfinder_frame_info(curr_pipe,
8957 &pipe_info->vf_output_info[j],
8964 my_css.active_pipes[ia_css_pipe_get_pipe_num(curr_pipe)] = curr_pipe;
8967 curr_stream->started = false;
8969 /* Map SP threads before doing anything. */
8970 err = map_sp_threads(curr_stream, true);
8972 IA_CSS_LOG("map_sp_threads: return_err=%d", err);
8976 for (i = 0; i < num_pipes; i++) {
8977 curr_pipe = pipes[i];
8978 ia_css_pipe_map_queue(curr_pipe, true);
8981 /* Create host side pipeline objects without stages */
8982 err = create_host_pipeline_structure(curr_stream);
8984 IA_CSS_LOG("create_host_pipeline_structure: return_err=%d", err);
8988 /* assign curr_stream */
8989 *stream = curr_stream;
8993 /* working mode: enter into the seed list */
8994 if (my_css_save.mode == sh_css_mode_working) {
8995 for (i = 0; i < MAX_ACTIVE_STREAMS; i++) {
8996 if (!my_css_save.stream_seeds[i].stream) {
8997 IA_CSS_LOG("entered stream into loc=%d", i);
8998 my_css_save.stream_seeds[i].orig_stream = stream;
8999 my_css_save.stream_seeds[i].stream = curr_stream;
9000 my_css_save.stream_seeds[i].num_pipes = num_pipes;
9001 my_css_save.stream_seeds[i].stream_config = *stream_config;
9002 for (j = 0; j < num_pipes; j++) {
9003 my_css_save.stream_seeds[i].pipe_config[j] = pipes[j]->config;
9004 my_css_save.stream_seeds[i].pipes[j] = pipes[j];
9005 my_css_save.stream_seeds[i].orig_pipes[j] = &pipes[j];
9011 ia_css_stream_destroy(curr_stream);
9014 ia_css_stream_destroy(curr_stream);
9016 IA_CSS_LEAVE("return_err=%d mode=%d", err, my_css_save.mode);
9021 ia_css_stream_destroy(struct ia_css_stream *stream)
9026 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
9029 IA_CSS_LEAVE_ERR_PRIVATE(err);
9033 ia_css_stream_isp_parameters_uninit(stream);
9035 if ((stream->last_pipe) &&
9036 ia_css_pipeline_is_mapped(stream->last_pipe->pipe_num)) {
9037 #if defined(ISP2401)
9038 for (i = 0; i < stream->num_pipes; i++) {
9039 struct ia_css_pipe *entry = stream->pipes[i];
9040 unsigned int sp_thread_id;
9041 struct sh_css_sp_pipeline_terminal *sp_pipeline_input_terminal;
9045 /* get the SP thread id */
9046 if (!ia_css_pipeline_get_sp_thread_id(
9047 ia_css_pipe_get_pipe_num(entry), &sp_thread_id))
9049 /* get the target input terminal */
9050 sp_pipeline_input_terminal =
9051 &sh_css_sp_group.pipe_io[sp_thread_id].input;
9053 for (i = 0; i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++) {
9054 ia_css_isys_stream_h isys_stream =
9055 &sp_pipeline_input_terminal->context.virtual_input_system_stream[i];
9056 if (stream->config.isys_config[i].valid && isys_stream->valid)
9057 ia_css_isys_stream_destroy(isys_stream);
9061 if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
9062 for (i = 0; i < stream->num_pipes; i++) {
9063 struct ia_css_pipe *entry = stream->pipes[i];
9065 * free any mipi frames that are remaining:
9066 * some test stream create-destroy cycles do
9067 * not generate output frames
9068 * and the mipi buffer is not freed in the
9072 free_mipi_frames(entry);
9075 stream_unregister_with_csi_rx(stream);
9078 for (i = 0; i < stream->num_pipes; i++) {
9079 struct ia_css_pipe *curr_pipe = stream->pipes[i];
9082 ia_css_pipe_map_queue(curr_pipe, false);
9085 err = map_sp_threads(stream, false);
9087 IA_CSS_LEAVE_ERR_PRIVATE(err);
9092 /* remove references from pipes to stream */
9093 for (i = 0; i < stream->num_pipes; i++) {
9094 struct ia_css_pipe *entry = stream->pipes[i];
9098 /* clear reference to stream */
9099 entry->stream = NULL;
9100 /* check internal copy pipe */
9101 if (entry->mode == IA_CSS_PIPE_ID_PREVIEW &&
9102 entry->pipe_settings.preview.copy_pipe) {
9103 IA_CSS_LOG("clearing stream on internal preview copy pipe");
9104 entry->pipe_settings.preview.copy_pipe->stream = NULL;
9106 if (entry->mode == IA_CSS_PIPE_ID_VIDEO &&
9107 entry->pipe_settings.video.copy_pipe) {
9108 IA_CSS_LOG("clearing stream on internal video copy pipe");
9109 entry->pipe_settings.video.copy_pipe->stream = NULL;
9111 err = sh_css_pipe_unload_binaries(entry);
9114 /* free associated memory of stream struct */
9115 kfree(stream->pipes);
9116 stream->pipes = NULL;
9117 stream->num_pipes = 0;
9119 /* working mode: take out of the seed list */
9120 if (my_css_save.mode == sh_css_mode_working) {
9121 for (i = 0; i < MAX_ACTIVE_STREAMS; i++) {
9122 if (my_css_save.stream_seeds[i].stream == stream) {
9123 IA_CSS_LOG("took out stream %d", i);
9124 my_css_save.stream_seeds[i].stream = NULL;
9131 IA_CSS_LEAVE_ERR(err);
9137 ia_css_stream_get_info(const struct ia_css_stream *stream,
9138 struct ia_css_stream_info *stream_info)
9140 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_info: enter/exit\n");
9142 assert(stream_info);
9144 *stream_info = stream->info;
9149 ia_css_stream_start(struct ia_css_stream *stream)
9153 IA_CSS_ENTER("stream = %p", stream);
9154 if ((!stream) || (!stream->last_pipe)) {
9155 IA_CSS_LEAVE_ERR(-EINVAL);
9158 IA_CSS_LOG("starting %d", stream->last_pipe->mode);
9160 sh_css_sp_set_disable_continuous_viewfinder(stream->disable_cont_vf);
9162 /* Create host side pipeline. */
9163 err = create_host_pipeline(stream);
9165 IA_CSS_LEAVE_ERR(err);
9169 #if defined(ISP2401)
9170 if ((stream->config.mode == IA_CSS_INPUT_MODE_SENSOR) ||
9171 (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR))
9172 stream_register_with_csi_rx(stream);
9175 #if !defined(ISP2401)
9176 /* Initialize mipi size checks */
9177 if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
9179 unsigned int port = (unsigned int)(stream->config.source.port.port);
9181 for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT; idx++) {
9182 sh_css_sp_group.config.mipi_sizes_for_check[port][idx] =
9183 sh_css_get_mipi_sizes_for_check(port, idx);
9188 if (stream->config.mode != IA_CSS_INPUT_MODE_MEMORY) {
9189 err = sh_css_config_input_network(stream);
9194 err = sh_css_pipe_start(stream);
9195 IA_CSS_LEAVE_ERR(err);
9200 ia_css_stream_stop(struct ia_css_stream *stream)
9204 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_stop() enter/exit\n");
9206 assert(stream->last_pipe);
9207 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_stop: stopping %d\n",
9208 stream->last_pipe->mode);
9210 #if !defined(ISP2401)
9211 /* De-initialize mipi size checks */
9212 if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
9214 unsigned int port = (unsigned int)(stream->config.source.port.port);
9216 for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT; idx++)
9217 sh_css_sp_group.config.mipi_sizes_for_check[port][idx] = 0;
9221 err = ia_css_pipeline_request_stop(&stream->last_pipe->pipeline);
9226 * Ideally, unmapping should happen after pipeline_stop, but current
9227 * semantics do not allow that.
9229 /* err = map_sp_threads(stream, false); */
9235 ia_css_stream_has_stopped(struct ia_css_stream *stream)
9241 stopped = ia_css_pipeline_has_stopped(&stream->last_pipe->pipeline);
9248 * Destroy the stream and all the pipes related to it.
9249 * The stream handle is used to identify the correct entry in the css_save struct
9252 ia_css_stream_unload(struct ia_css_stream *stream)
9257 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_unload() enter,\n");
9260 for (i = 0; i < MAX_ACTIVE_STREAMS; i++)
9261 if (my_css_save.stream_seeds[i].stream == stream) {
9264 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
9265 "ia_css_stream_unload(): unloading %d (%p)\n", i,
9266 my_css_save.stream_seeds[i].stream);
9267 ia_css_stream_destroy(stream);
9268 for (j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++)
9269 ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[j]);
9270 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
9271 "ia_css_stream_unload(): after unloading %d (%p)\n", i,
9272 my_css_save.stream_seeds[i].stream);
9275 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_unload() exit,\n");
9280 ia_css_temp_pipe_to_pipe_id(const struct ia_css_pipe *pipe,
9281 enum ia_css_pipe_id *pipe_id)
9283 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_temp_pipe_to_pipe_id() enter/exit\n");
9285 *pipe_id = pipe->mode;
9287 *pipe_id = IA_CSS_PIPE_ID_COPY;
9292 enum atomisp_input_format
9293 ia_css_stream_get_format(const struct ia_css_stream *stream)
9295 return stream->config.input_config.format;
9299 ia_css_stream_get_two_pixels_per_clock(const struct ia_css_stream *stream)
9301 return (stream->config.pixels_per_clock == 2);
9304 struct ia_css_binary *
9305 ia_css_stream_get_shading_correction_binary(const struct ia_css_stream
9308 struct ia_css_pipe *pipe;
9312 pipe = stream->pipes[0];
9314 if (stream->num_pipes == 2) {
9315 assert(stream->pipes[1]);
9316 if (stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_VIDEO ||
9317 stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_PREVIEW)
9318 pipe = stream->pipes[1];
9321 return ia_css_pipe_get_shading_correction_binary(pipe);
9324 struct ia_css_binary *
9325 ia_css_stream_get_dvs_binary(const struct ia_css_stream *stream)
9328 struct ia_css_pipe *video_pipe = NULL;
9330 /* First we find the video pipe */
9331 for (i = 0; i < stream->num_pipes; i++) {
9332 struct ia_css_pipe *pipe = stream->pipes[i];
9334 if (pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) {
9340 return &video_pipe->pipe_settings.video.video_binary;
9344 struct ia_css_binary *
9345 ia_css_stream_get_3a_binary(const struct ia_css_stream *stream)
9347 struct ia_css_pipe *pipe;
9348 struct ia_css_binary *s3a_binary = NULL;
9352 pipe = stream->pipes[0];
9354 if (stream->num_pipes == 2) {
9355 assert(stream->pipes[1]);
9356 if (stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_VIDEO ||
9357 stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_PREVIEW)
9358 pipe = stream->pipes[1];
9361 s3a_binary = ia_css_pipe_get_s3a_binary(pipe);
9367 ia_css_stream_set_output_padded_width(struct ia_css_stream *stream,
9368 unsigned int output_padded_width)
9370 struct ia_css_pipe *pipe;
9374 pipe = stream->last_pipe;
9378 /* set the config also just in case (redundant info? why do we save config in pipe?) */
9379 pipe->config.output_info[IA_CSS_PIPE_OUTPUT_STAGE_0].padded_width = output_padded_width;
9380 pipe->output_info[IA_CSS_PIPE_OUTPUT_STAGE_0].padded_width = output_padded_width;
9385 static struct ia_css_binary *
9386 ia_css_pipe_get_shading_correction_binary(const struct ia_css_pipe *pipe)
9388 struct ia_css_binary *binary = NULL;
9392 switch (pipe->config.mode) {
9393 case IA_CSS_PIPE_MODE_PREVIEW:
9394 binary = (struct ia_css_binary *)&pipe->pipe_settings.preview.preview_binary;
9396 case IA_CSS_PIPE_MODE_VIDEO:
9397 binary = (struct ia_css_binary *)&pipe->pipe_settings.video.video_binary;
9399 case IA_CSS_PIPE_MODE_CAPTURE:
9400 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
9403 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
9404 if (pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.sc) {
9405 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.primary_binary[i];
9409 } else if (pipe->config.default_capture_config.mode ==
9410 IA_CSS_CAPTURE_MODE_BAYER)
9411 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
9412 else if (pipe->config.default_capture_config.mode ==
9413 IA_CSS_CAPTURE_MODE_ADVANCED ||
9414 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) {
9415 if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_1)
9416 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
9417 else if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_2_2)
9418 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.post_isp_binary;
9425 if (binary && binary->info->sp.enable.sc)
9431 static struct ia_css_binary *
9432 ia_css_pipe_get_s3a_binary(const struct ia_css_pipe *pipe)
9434 struct ia_css_binary *binary = NULL;
9438 switch (pipe->config.mode) {
9439 case IA_CSS_PIPE_MODE_PREVIEW:
9440 binary = (struct ia_css_binary *)&pipe->pipe_settings.preview.preview_binary;
9442 case IA_CSS_PIPE_MODE_VIDEO:
9443 binary = (struct ia_css_binary *)&pipe->pipe_settings.video.video_binary;
9445 case IA_CSS_PIPE_MODE_CAPTURE:
9446 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
9449 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
9450 if (pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.s3a) {
9451 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.primary_binary[i];
9455 } else if (pipe->config.default_capture_config.mode ==
9456 IA_CSS_CAPTURE_MODE_BAYER) {
9457 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
9458 } else if (pipe->config.default_capture_config.mode ==
9459 IA_CSS_CAPTURE_MODE_ADVANCED ||
9460 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) {
9461 if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_1)
9462 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
9463 else if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_2_2)
9464 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.post_isp_binary;
9473 if (binary && !binary->info->sp.enable.s3a)
9479 static struct ia_css_binary *
9480 ia_css_pipe_get_sdis_binary(const struct ia_css_pipe *pipe)
9482 struct ia_css_binary *binary = NULL;
9486 switch (pipe->config.mode) {
9487 case IA_CSS_PIPE_MODE_VIDEO:
9488 binary = (struct ia_css_binary *)&pipe->pipe_settings.video.video_binary;
9494 if (binary && !binary->info->sp.enable.dis)
9500 struct ia_css_pipeline *
9501 ia_css_pipe_get_pipeline(const struct ia_css_pipe *pipe)
9505 return (struct ia_css_pipeline *)&pipe->pipeline;
9509 ia_css_pipe_get_pipe_num(const struct ia_css_pipe *pipe)
9514 * KW was not sure this function was not returning a value
9515 * that was out of range; so added an assert, and, for the
9516 * case when asserts are not enabled, clip to the largest
9517 * value; pipe_num is unsigned so the value cannot be too small
9519 assert(pipe->pipe_num < IA_CSS_PIPELINE_NUM_MAX);
9521 if (pipe->pipe_num >= IA_CSS_PIPELINE_NUM_MAX)
9522 return (IA_CSS_PIPELINE_NUM_MAX - 1);
9524 return pipe->pipe_num;
9528 ia_css_pipe_get_isp_pipe_version(const struct ia_css_pipe *pipe)
9532 return (unsigned int)pipe->config.isp_pipe_version;
9535 #define SP_START_TIMEOUT_US 30000000
9538 ia_css_start_sp(void)
9540 unsigned long timeout;
9544 sh_css_sp_start_isp();
9546 /* waiting for the SP is completely started */
9547 timeout = SP_START_TIMEOUT_US;
9548 while ((ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_INITIALIZED) && timeout) {
9553 IA_CSS_ERROR("timeout during SP initialization");
9557 /* Workaround, in order to run two streams in parallel. See TASK 4271*/
9558 /* TODO: Fix this. */
9560 sh_css_init_host_sp_control_vars();
9562 /* buffers should be initialized only when sp is started */
9563 /* AM: At the moment it will be done only when there is no stream active. */
9565 sh_css_setup_queues();
9566 ia_css_bufq_dump_queue_info();
9568 IA_CSS_LEAVE_ERR(err);
9573 * Time to wait SP for termincate. Only condition when this can happen
9574 * is a fatal hw failure, but we must be able to detect this and emit
9575 * a proper error trace.
9577 #define SP_SHUTDOWN_TIMEOUT_US 200000
9580 ia_css_stop_sp(void)
9582 unsigned long timeout;
9585 IA_CSS_ENTER("void");
9587 if (!sh_css_sp_is_running()) {
9589 IA_CSS_LEAVE("SP already stopped : return_err=%d", err);
9591 /* Return an error - stop SP should not have been called by driver */
9595 /* For now, stop whole SP */
9596 if (!sh_css_write_host2sp_command(host2sp_cmd_terminate)) {
9597 IA_CSS_ERROR("Call to 'sh-css_write_host2sp_command()' failed");
9598 ia_css_debug_dump_sp_sw_debug_info();
9599 ia_css_debug_dump_debug_info(NULL);
9602 sh_css_sp_set_sp_running(false);
9604 timeout = SP_SHUTDOWN_TIMEOUT_US;
9605 while (!ia_css_spctrl_is_idle(SP0_ID) && timeout) {
9609 if (ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_TERMINATED)
9610 IA_CSS_WARNING("SP has not terminated (SW)");
9613 IA_CSS_WARNING("SP is not idle");
9614 ia_css_debug_dump_sp_sw_debug_info();
9616 timeout = SP_SHUTDOWN_TIMEOUT_US;
9617 while (!isp_ctrl_getbit(ISP0_ID, ISP_SC_REG, ISP_IDLE_BIT) && timeout) {
9622 IA_CSS_WARNING("ISP is not idle");
9623 ia_css_debug_dump_sp_sw_debug_info();
9626 sh_css_hmm_buffer_record_uninit();
9628 /* clear pending param sets from refcount */
9629 sh_css_param_clear_param_sets();
9631 IA_CSS_LEAVE_ERR(err);
9636 ia_css_update_continuous_frames(struct ia_css_stream *stream)
9638 struct ia_css_pipe *pipe;
9641 ia_css_debug_dtrace(
9643 "sh_css_update_continuous_frames() enter:\n");
9646 ia_css_debug_dtrace(
9648 "sh_css_update_continuous_frames() leave: invalid stream, return_void\n");
9652 pipe = stream->continuous_pipe;
9654 for (i = stream->config.init_num_cont_raw_buf;
9655 i < stream->config.target_num_cont_raw_buf; i++)
9656 sh_css_update_host2sp_offline_frame(i,
9657 pipe->continuous_frames[i], pipe->cont_md_buffers[i]);
9659 sh_css_update_host2sp_cont_num_raw_frames
9660 (stream->config.target_num_cont_raw_buf, true);
9661 ia_css_debug_dtrace(
9663 "sh_css_update_continuous_frames() leave: return_void\n");
9668 void ia_css_pipe_map_queue(struct ia_css_pipe *pipe, bool map)
9670 unsigned int thread_id;
9671 unsigned int pipe_num;
9672 bool need_input_queue;
9677 pipe_num = pipe->pipe_num;
9679 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
9681 #if defined(ISP2401)
9682 need_input_queue = true;
9684 need_input_queue = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
9687 /* map required buffer queues to resources */
9688 /* TODO: to be improved */
9689 if (pipe->mode == IA_CSS_PIPE_ID_PREVIEW) {
9690 if (need_input_queue)
9691 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
9692 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
9693 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
9694 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
9695 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
9696 if (pipe->pipe_settings.preview.preview_binary.info &&
9697 pipe->pipe_settings.preview.preview_binary.info->sp.enable.s3a)
9698 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
9699 } else if (pipe->mode == IA_CSS_PIPE_ID_CAPTURE) {
9702 if (need_input_queue)
9703 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
9704 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
9705 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME, map);
9706 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
9707 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
9708 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
9709 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
9710 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
9711 if (pipe->pipe_settings.capture.primary_binary[i].info &&
9712 pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.s3a) {
9713 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
9717 } else if (pipe->config.default_capture_config.mode ==
9718 IA_CSS_CAPTURE_MODE_ADVANCED ||
9719 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT ||
9720 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER) {
9721 if (pipe->pipe_settings.capture.pre_isp_binary.info &&
9722 pipe->pipe_settings.capture.pre_isp_binary.info->sp.enable.s3a)
9723 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
9725 } else if (pipe->mode == IA_CSS_PIPE_ID_VIDEO) {
9726 if (need_input_queue)
9727 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
9728 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
9729 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0])
9730 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME, map);
9731 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
9732 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
9733 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
9734 if (pipe->pipe_settings.video.video_binary.info &&
9735 pipe->pipe_settings.video.video_binary.info->sp.enable.s3a)
9736 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
9737 if (pipe->pipe_settings.video.video_binary.info &&
9738 (pipe->pipe_settings.video.video_binary.info->sp.enable.dis
9740 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_DIS_STATISTICS, map);
9741 } else if (pipe->mode == IA_CSS_PIPE_ID_COPY) {
9742 if (need_input_queue)
9743 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
9744 if (!pipe->stream->config.continuous)
9745 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
9746 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
9747 } else if (pipe->mode == IA_CSS_PIPE_ID_ACC) {
9748 if (need_input_queue)
9749 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
9750 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
9751 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
9752 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
9753 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
9754 } else if (pipe->mode == IA_CSS_PIPE_ID_YUVPP) {
9757 for (idx = 0; idx < IA_CSS_PIPE_MAX_OUTPUT_STAGE; idx++) {
9758 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx, map);
9759 if (pipe->enable_viewfinder[idx])
9760 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx, map);
9762 if (need_input_queue)
9763 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
9764 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
9765 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
9772 ia_css_unlock_raw_frame(struct ia_css_stream *stream, uint32_t exp_id)
9779 * Only continuous streams have a tagger to which we can send the
9782 if (!stream || !stream->config.continuous) {
9783 IA_CSS_ERROR("invalid stream pointer");
9787 if (exp_id > IA_CSS_ISYS_MAX_EXPOSURE_ID ||
9788 exp_id < IA_CSS_ISYS_MIN_EXPOSURE_ID) {
9789 IA_CSS_ERROR("invalid exposure ID: %d\n", exp_id);
9794 * Send the event. Since we verified that the exp_id is valid,
9795 * we can safely assign it to an 8-bit argument here.
9797 ret = ia_css_bufq_enqueue_psys_event(
9798 IA_CSS_PSYS_SW_EVENT_UNLOCK_RAW_BUFFER, exp_id, 0, 0);
9800 IA_CSS_LEAVE_ERR(ret);
9805 * @brief Set the state (Enable or Disable) of the Extension stage in the
9809 ia_css_pipe_set_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle,
9812 unsigned int thread_id;
9813 struct ia_css_pipeline_stage *stage;
9818 /* Parameter Check */
9819 if (!pipe || !pipe->stream) {
9820 IA_CSS_ERROR("Invalid Pipe.");
9822 } else if (!(pipe->config.acc_extension)) {
9823 IA_CSS_ERROR("Invalid Pipe(No Extension Firmware)");
9825 } else if (!sh_css_sp_is_running()) {
9826 IA_CSS_ERROR("Leaving: queue unavailable.");
9829 /* Query the threadid and stage_num for the Extension firmware*/
9830 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
9831 err = ia_css_pipeline_get_stage_from_fw(&pipe->pipeline, fw_handle, &stage);
9833 /* Set the Extension State;. TODO: Add check for stage firmware.type (QOS)*/
9834 err = ia_css_bufq_enqueue_psys_event(
9835 (uint8_t)IA_CSS_PSYS_SW_EVENT_STAGE_ENABLE_DISABLE,
9837 (uint8_t)stage->stage_num,
9841 SH_CSS_QOS_STAGE_ENABLE(&sh_css_sp_group.pipe[thread_id], stage->stage_num);
9843 SH_CSS_QOS_STAGE_DISABLE(&sh_css_sp_group.pipe[thread_id], stage->stage_num);
9847 IA_CSS_LEAVE("err:%d handle:%u enable:%d", err, fw_handle, enable);
9852 * @brief Get the state (Enable or Disable) of the Extension stage in the
9856 ia_css_pipe_get_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle,
9859 struct ia_css_pipeline_stage *stage;
9860 unsigned int thread_id;
9865 /* Parameter Check */
9866 if (!pipe || !pipe->stream) {
9867 IA_CSS_ERROR("Invalid Pipe.");
9869 } else if (!(pipe->config.acc_extension)) {
9870 IA_CSS_ERROR("Invalid Pipe (No Extension Firmware).");
9872 } else if (!sh_css_sp_is_running()) {
9873 IA_CSS_ERROR("Leaving: queue unavailable.");
9876 /* Query the threadid and stage_num corresponding to the Extension firmware*/
9877 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
9878 err = ia_css_pipeline_get_stage_from_fw(&pipe->pipeline, fw_handle, &stage);
9881 /* Get the Extension State */
9882 *enable = (SH_CSS_QOS_STAGE_IS_ENABLED(&sh_css_sp_group.pipe[thread_id],
9883 stage->stage_num)) ? true : false;
9886 IA_CSS_LEAVE("err:%d handle:%u enable:%d", err, fw_handle, *enable);
9891 sh_css_hmm_buffer_record_init(void)
9895 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++)
9896 sh_css_hmm_buffer_record_reset(&hmm_buffer_record[i]);
9900 sh_css_hmm_buffer_record_uninit(void)
9903 struct sh_css_hmm_buffer_record *buffer_record = NULL;
9905 buffer_record = &hmm_buffer_record[0];
9906 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
9907 if (buffer_record->in_use) {
9908 if (buffer_record->h_vbuf)
9909 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &buffer_record->h_vbuf);
9910 sh_css_hmm_buffer_record_reset(buffer_record);
9917 sh_css_hmm_buffer_record_reset(struct sh_css_hmm_buffer_record *buffer_record)
9919 assert(buffer_record);
9920 buffer_record->in_use = false;
9921 buffer_record->type = IA_CSS_BUFFER_TYPE_INVALID;
9922 buffer_record->h_vbuf = NULL;
9923 buffer_record->kernel_ptr = 0;
9926 static struct sh_css_hmm_buffer_record
9927 *sh_css_hmm_buffer_record_acquire(struct ia_css_rmgr_vbuf_handle *h_vbuf,
9928 enum ia_css_buffer_type type,
9929 hrt_address kernel_ptr)
9932 struct sh_css_hmm_buffer_record *buffer_record = NULL;
9933 struct sh_css_hmm_buffer_record *out_buffer_record = NULL;
9936 assert((type > IA_CSS_BUFFER_TYPE_INVALID) &&
9937 (type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE));
9938 assert(kernel_ptr != 0);
9940 buffer_record = &hmm_buffer_record[0];
9941 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
9942 if (!buffer_record->in_use) {
9943 buffer_record->in_use = true;
9944 buffer_record->type = type;
9945 buffer_record->h_vbuf = h_vbuf;
9946 buffer_record->kernel_ptr = kernel_ptr;
9947 out_buffer_record = buffer_record;
9953 return out_buffer_record;
9956 static struct sh_css_hmm_buffer_record
9957 *sh_css_hmm_buffer_record_validate(ia_css_ptr ddr_buffer_addr,
9958 enum ia_css_buffer_type type)
9961 struct sh_css_hmm_buffer_record *buffer_record = NULL;
9962 bool found_record = false;
9964 buffer_record = &hmm_buffer_record[0];
9965 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
9966 if ((buffer_record->in_use) &&
9967 (buffer_record->type == type) &&
9968 (buffer_record->h_vbuf) &&
9969 (buffer_record->h_vbuf->vptr == ddr_buffer_addr)) {
9970 found_record = true;
9977 return buffer_record;