1 /*
2  * Support for Intel Camera Imaging ISP subsystem.
3  * Copyright (c) 2015, Intel Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  */
14 
15 /*! \file */
16 #include <linux/mm.h>
17 #include <linux/slab.h>
18 #include <linux/vmalloc.h>
19 
20 #include "ia_css.h"
21 #include "sh_css_hrt.h"		/* only for file 2 MIPI */
22 #include "ia_css_buffer.h"
23 #include "ia_css_binary.h"
24 #include "sh_css_internal.h"
25 #include "sh_css_mipi.h"
26 #include "sh_css_sp.h"		/* sh_css_sp_group */
27 #if !defined(HAS_NO_INPUT_SYSTEM)
28 #include "ia_css_isys.h"
29 #endif
30 #include "ia_css_frame.h"
31 #include "sh_css_defs.h"
32 #include "sh_css_firmware.h"
33 #include "sh_css_params.h"
34 #include "sh_css_params_internal.h"
35 #include "sh_css_param_shading.h"
36 #include "ia_css_refcount.h"
37 #include "ia_css_rmgr.h"
38 #include "ia_css_debug.h"
39 #include "ia_css_debug_pipe.h"
40 #include "ia_css_device_access.h"
41 #include "device_access.h"
42 #include "sh_css_legacy.h"
43 #include "ia_css_pipeline.h"
44 #include "ia_css_stream.h"
45 #include "sh_css_stream_format.h"
46 #include "ia_css_pipe.h"
47 #include "ia_css_util.h"
48 #include "ia_css_pipe_util.h"
49 #include "ia_css_pipe_binarydesc.h"
50 #include "ia_css_pipe_stagedesc.h"
51 #ifdef USE_INPUT_SYSTEM_VERSION_2
52 #include "ia_css_isys.h"
53 #endif
54 
55 #include "memory_access.h"
56 #include "tag.h"
57 #include "assert_support.h"
58 #include "math_support.h"
59 #include "sw_event_global.h"			/* Event IDs.*/
60 #if !defined(HAS_NO_INPUT_FORMATTER)
61 #include "ia_css_ifmtr.h"
62 #endif
63 #if !defined(HAS_NO_INPUT_SYSTEM)
64 #include "input_system.h"
65 #endif
66 #include "mmu_device.h"		/* mmu_set_page_table_base_index(), ... */
67 #include "ia_css_mmu_private.h" /* sh_css_mmu_set_page_table_base_index() */
68 #include "gdc_device.h"		/* HRT_GDC_N */
69 #include "dma.h"		/* dma_set_max_burst_size() */
70 #include "irq.h"			/* virq */
71 #include "sp.h"				/* cnd_sp_irq_enable() */
72 #include "isp.h"			/* cnd_isp_irq_enable, ISP_VEC_NELEMS */
73 #include "gp_device.h"		/* gp_device_reg_store() */
74 #define __INLINE_GPIO__
75 #include "gpio.h"
76 #include "timed_ctrl.h"
77 #include "platform_support.h" /* hrt_sleep(), inline */
78 #include "ia_css_inputfifo.h"
79 #define WITH_PC_MONITORING  0
80 
81 #define SH_CSS_VIDEO_BUFFER_ALIGNMENT 0
82 
83 #if WITH_PC_MONITORING
84 #define MULTIPLE_SAMPLES 1
85 #define NOF_SAMPLES      60
86 #include "linux/kthread.h"
87 #include "linux/sched.h"
88 #include "linux/delay.h"
89 #include "sh_css_metrics.h"
90 static int thread_alive;
91 #endif /* WITH_PC_MONITORING */
92 
93 #include "ia_css_spctrl.h"
94 #include "ia_css_version_data.h"
95 #include "sh_css_struct.h"
96 #include "ia_css_bufq.h"
97 #include "ia_css_timer.h" /* clock_value_t */
98 
99 #include "isp/modes/interface/input_buf.isp.h"
100 
101 /* Name of the sp program: should not be built-in */
102 #define SP_PROG_NAME "sp"
103 /* Size of Refcount List */
104 #define REFCOUNT_SIZE 1000
105 
106 /* for JPEG, we don't know the length of the image upfront,
107  * but since we support sensor upto 16MP, we take this as
108  * upper limit.
109  */
110 #define JPEG_BYTES (16 * 1024 * 1024)
111 
112 #define STATS_ENABLED(stage) (stage && stage->binary && stage->binary->info && \
113 	(stage->binary->info->sp.enable.s3a || stage->binary->info->sp.enable.dis))
114 
115 struct sh_css my_css;
116 
117 int (*sh_css_printf)(const char *fmt, va_list args) = NULL;
118 
119 /* modes of work: stream_create and stream_destroy will update the save/restore data
120    only when in working mode, not suspend/resume
121 */
122 enum ia_sh_css_modes {
123 	sh_css_mode_none = 0,
124 	sh_css_mode_working,
125 	sh_css_mode_suspend,
126 	sh_css_mode_resume
127 };
128 
129 /* a stream seed, to save and restore the stream data.
130    the stream seed contains all the data required to "grow" the seed again after it was closed.
131 */
132 struct sh_css_stream_seed {
133 	struct ia_css_stream
134 		**orig_stream;                /* pointer to restore the original handle */
135 	struct ia_css_stream		*stream;                      /* handle, used as ID too.*/
136 	struct ia_css_stream_config	stream_config;				/* stream config struct */
137 	int				num_pipes;
138 	struct ia_css_pipe		*pipes[IA_CSS_PIPE_ID_NUM];			/* pipe handles */
139 	struct ia_css_pipe
140 		**orig_pipes[IA_CSS_PIPE_ID_NUM];	/* pointer to restore original handle */
141 	struct ia_css_pipe_config
142 		pipe_config[IA_CSS_PIPE_ID_NUM];	/* pipe config structs */
143 };
144 
145 #define MAX_ACTIVE_STREAMS	5
146 /* A global struct for save/restore to hold all the data that should sustain power-down:
147    MMU base, IRQ type, env for routines, binary loaded FW and the stream seeds.
148 */
149 struct sh_css_save {
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 */
156 };
157 
158 static bool my_css_save_initialized;	/* if my_css_save was initialized */
159 static struct sh_css_save my_css_save;
160 
161 /* pqiao NOTICE: this is for css internal buffer recycling when stopping pipeline,
162    this array is temporary and will be replaced by resource manager*/
163 /* Taking the biggest Size for number of Elements */
164 #define MAX_HMM_BUFFER_NUM	\
165 	(SH_CSS_MAX_NUM_QUEUES * (IA_CSS_NUM_ELEMS_SP2HOST_BUFFER_QUEUE + 2))
166 
167 struct sh_css_hmm_buffer_record {
168 	bool in_use;
169 	enum ia_css_buffer_type type;
170 	struct ia_css_rmgr_vbuf_handle *h_vbuf;
171 	hrt_address kernel_ptr;
172 };
173 
174 static struct sh_css_hmm_buffer_record hmm_buffer_record[MAX_HMM_BUFFER_NUM];
175 
176 #define GPIO_FLASH_PIN_MASK BIT(HIVE_GPIO_STROBE_TRIGGER_PIN)
177 
178 static bool fw_explicitly_loaded;
179 
180 /*
181  * Local prototypes
182  */
183 
184 static enum ia_css_err
185 allocate_delay_frames(struct ia_css_pipe *pipe);
186 
187 static enum ia_css_err
188 sh_css_pipe_start(struct ia_css_stream *stream);
189 
190 /* ISP 2401 */
191 /*
192  * @brief Stop all "ia_css_pipe" instances in the target
193  * "ia_css_stream" instance.
194  *
195  * @param[in] stream	Point to the target "ia_css_stream" instance.
196  *
197  * @return
198  * - IA_CSS_SUCCESS, if the "stop" requests have been successfully sent out.
199  * - CSS error code, otherwise.
200  *
201  *
202  * NOTE
203  * This API sends the "stop" requests to the "ia_css_pipe"
204  * instances in the same "ia_css_stream" instance. It will
205  * return without waiting for all "ia_css_pipe" instatnces
206  * being stopped.
207  */
208 static enum ia_css_err
209 sh_css_pipes_stop(struct ia_css_stream *stream);
210 
211 /*
212  * @brief Check if all "ia_css_pipe" instances in the target
213  * "ia_css_stream" instance have stopped.
214  *
215  * @param[in] stream	Point to the target "ia_css_stream" instance.
216  *
217  * @return
218  * - true, if all "ia_css_pipe" instances in the target "ia_css_stream"
219  *   instance have ben stopped.
220  * - false, otherwise.
221  */
222 /* ISP 2401 */
223 static bool
224 sh_css_pipes_have_stopped(struct ia_css_stream *stream);
225 
226 /* ISP 2401 */
227 static enum ia_css_err
228 ia_css_pipe_check_format(struct ia_css_pipe *pipe,
229 			 enum ia_css_frame_format format);
230 
231 /* ISP 2401 */
232 static enum ia_css_err
233 check_pipe_resolutions(const struct ia_css_pipe *pipe);
234 
235 static enum ia_css_err
236 ia_css_pipe_load_extension(struct ia_css_pipe *pipe,
237 			   struct ia_css_fw_info *firmware);
238 
239 static void
240 ia_css_pipe_unload_extension(struct ia_css_pipe *pipe,
241 			     struct ia_css_fw_info *firmware);
242 static void
243 ia_css_reset_defaults(struct sh_css *css);
244 
245 static void
246 sh_css_init_host_sp_control_vars(void);
247 
248 static enum ia_css_err set_num_primary_stages(unsigned int *num,
249 	enum ia_css_pipe_version version);
250 
251 static bool
252 need_capture_pp(const struct ia_css_pipe *pipe);
253 
254 static bool
255 need_yuv_scaler_stage(const struct ia_css_pipe *pipe);
256 
257 static enum ia_css_err ia_css_pipe_create_cas_scaler_desc_single_output(
258     struct ia_css_frame_info *cas_scaler_in_info,
259     struct ia_css_frame_info *cas_scaler_out_info,
260     struct ia_css_frame_info *cas_scaler_vf_info,
261     struct ia_css_cas_binary_descr *descr);
262 
263 static void ia_css_pipe_destroy_cas_scaler_desc(struct ia_css_cas_binary_descr
264 	*descr);
265 
266 static bool
267 need_downscaling(const struct ia_css_resolution in_res,
268 		 const struct ia_css_resolution out_res);
269 
270 static bool need_capt_ldc(const struct ia_css_pipe *pipe);
271 
272 static enum ia_css_err
273 sh_css_pipe_load_binaries(struct ia_css_pipe *pipe);
274 
275 static
276 enum ia_css_err sh_css_pipe_get_viewfinder_frame_info(
277     struct ia_css_pipe *pipe,
278     struct ia_css_frame_info *info,
279     unsigned int idx);
280 
281 static enum ia_css_err
282 sh_css_pipe_get_output_frame_info(struct ia_css_pipe *pipe,
283 				  struct ia_css_frame_info *info,
284 				  unsigned int idx);
285 
286 static enum ia_css_err
287 capture_start(struct ia_css_pipe *pipe);
288 
289 static enum ia_css_err
290 video_start(struct ia_css_pipe *pipe);
291 
292 static enum ia_css_err
293 preview_start(struct ia_css_pipe *pipe);
294 
295 static enum ia_css_err
296 yuvpp_start(struct ia_css_pipe *pipe);
297 
298 static bool copy_on_sp(struct ia_css_pipe *pipe);
299 
300 static enum ia_css_err
301 init_vf_frameinfo_defaults(struct ia_css_pipe *pipe,
302 			   struct ia_css_frame *vf_frame, unsigned int idx);
303 
304 static enum ia_css_err
305 init_in_frameinfo_memory_defaults(struct ia_css_pipe *pipe,
306 				  struct ia_css_frame *frame, enum ia_css_frame_format format);
307 
308 static enum ia_css_err
309 init_out_frameinfo_defaults(struct ia_css_pipe *pipe,
310 			    struct ia_css_frame *out_frame, unsigned int idx);
311 
312 static enum ia_css_err
313 sh_css_pipeline_add_acc_stage(struct ia_css_pipeline *pipeline,
314 			      const void *acc_fw);
315 
316 static enum ia_css_err
317 alloc_continuous_frames(
318     struct ia_css_pipe *pipe, bool init_time);
319 
320 static void
321 pipe_global_init(void);
322 
323 static enum ia_css_err
324 pipe_generate_pipe_num(const struct ia_css_pipe *pipe,
325 		       unsigned int *pipe_number);
326 
327 static void
328 pipe_release_pipe_num(unsigned int pipe_num);
329 
330 static enum ia_css_err
331 create_host_pipeline_structure(struct ia_css_stream *stream);
332 
333 static enum ia_css_err
334 create_host_pipeline(struct ia_css_stream *stream);
335 
336 static enum ia_css_err
337 create_host_preview_pipeline(struct ia_css_pipe *pipe);
338 
339 static enum ia_css_err
340 create_host_video_pipeline(struct ia_css_pipe *pipe);
341 
342 static enum ia_css_err
343 create_host_copy_pipeline(struct ia_css_pipe *pipe,
344 			  unsigned int max_input_width,
345 			  struct ia_css_frame *out_frame);
346 
347 static enum ia_css_err
348 create_host_isyscopy_capture_pipeline(struct ia_css_pipe *pipe);
349 
350 static enum ia_css_err
351 create_host_capture_pipeline(struct ia_css_pipe *pipe);
352 
353 static enum ia_css_err
354 create_host_yuvpp_pipeline(struct ia_css_pipe *pipe);
355 
356 static enum ia_css_err
357 create_host_acc_pipeline(struct ia_css_pipe *pipe);
358 
359 static unsigned int
360 sh_css_get_sw_interrupt_value(unsigned int irq);
361 
362 static struct ia_css_binary *ia_css_pipe_get_shading_correction_binary(
363     const struct ia_css_pipe *pipe);
364 
365 static struct ia_css_binary *
366 ia_css_pipe_get_s3a_binary(const struct ia_css_pipe *pipe);
367 
368 static struct ia_css_binary *
369 ia_css_pipe_get_sdis_binary(const struct ia_css_pipe *pipe);
370 
371 static void
372 sh_css_hmm_buffer_record_init(void);
373 
374 static void
375 sh_css_hmm_buffer_record_uninit(void);
376 
377 static void
378 sh_css_hmm_buffer_record_reset(struct sh_css_hmm_buffer_record *buffer_record);
379 
380 static struct sh_css_hmm_buffer_record
381 *sh_css_hmm_buffer_record_acquire(struct ia_css_rmgr_vbuf_handle *h_vbuf,
382 				  enum ia_css_buffer_type type,
383 				  hrt_address kernel_ptr);
384 
385 static struct sh_css_hmm_buffer_record
386 *sh_css_hmm_buffer_record_validate(hrt_vaddress ddr_buffer_addr,
387 				   enum ia_css_buffer_type type);
388 
389 void
390 ia_css_get_acc_configs(
391     struct ia_css_pipe *pipe,
392     struct ia_css_isp_config *config);
393 
394 #if CONFIG_ON_FRAME_ENQUEUE()
395 static enum ia_css_err set_config_on_frame_enqueue(struct ia_css_frame_info
396 	*info, struct frame_data_wrapper *frame);
397 #endif
398 
399 #ifdef USE_INPUT_SYSTEM_VERSION_2401
400 static unsigned int get_crop_lines_for_bayer_order(const struct
401 	ia_css_stream_config *config);
402 static unsigned int get_crop_columns_for_bayer_order(const struct
403 	ia_css_stream_config *config);
404 static void get_pipe_extra_pixel(struct ia_css_pipe *pipe,
405 				 unsigned int *extra_row, unsigned int *extra_column);
406 static enum ia_css_err
407 aspect_ratio_crop_init(struct ia_css_stream *curr_stream,
408 		       struct ia_css_pipe *pipes[],
409 		       bool *do_crop_status);
410 
411 static bool
412 aspect_ratio_crop_check(bool enabled, struct ia_css_pipe *curr_pipe);
413 
414 static enum ia_css_err
415 aspect_ratio_crop(struct ia_css_pipe *curr_pipe,
416 		  struct ia_css_resolution *effective_res);
417 #endif
418 
419 static void
420 sh_css_pipe_free_shading_table(struct ia_css_pipe *pipe)
421 {
422 	assert(pipe);
423 	if (!pipe) {
424 		IA_CSS_ERROR("NULL input parameter");
425 		return;
426 	}
427 
428 	if (pipe->shading_table)
429 		ia_css_shading_table_free(pipe->shading_table);
430 	pipe->shading_table = NULL;
431 }
432 
433 static enum ia_css_frame_format yuv420_copy_formats[] = {
434 	IA_CSS_FRAME_FORMAT_NV12,
435 	IA_CSS_FRAME_FORMAT_NV21,
436 	IA_CSS_FRAME_FORMAT_YV12,
437 	IA_CSS_FRAME_FORMAT_YUV420,
438 	IA_CSS_FRAME_FORMAT_YUV420_16,
439 	IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8,
440 	IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8
441 };
442 
443 static enum ia_css_frame_format yuv422_copy_formats[] = {
444 	IA_CSS_FRAME_FORMAT_NV12,
445 	IA_CSS_FRAME_FORMAT_NV16,
446 	IA_CSS_FRAME_FORMAT_NV21,
447 	IA_CSS_FRAME_FORMAT_NV61,
448 	IA_CSS_FRAME_FORMAT_YV12,
449 	IA_CSS_FRAME_FORMAT_YV16,
450 	IA_CSS_FRAME_FORMAT_YUV420,
451 	IA_CSS_FRAME_FORMAT_YUV420_16,
452 	IA_CSS_FRAME_FORMAT_YUV422,
453 	IA_CSS_FRAME_FORMAT_YUV422_16,
454 	IA_CSS_FRAME_FORMAT_UYVY,
455 	IA_CSS_FRAME_FORMAT_YUYV
456 };
457 
458 /* Verify whether the selected output format is can be produced
459  * by the copy binary given the stream format.
460  * */
461 static enum ia_css_err
462 verify_copy_out_frame_format(struct ia_css_pipe *pipe) {
463 	enum ia_css_frame_format out_fmt = pipe->output_info[0].format;
464 	unsigned int i, found = 0;
465 
466 	assert(pipe);
467 	assert(pipe->stream);
468 
469 	switch (pipe->stream->config.input_config.format)
470 	{
471 	case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY:
472 	case ATOMISP_INPUT_FORMAT_YUV420_8:
473 		for (i = 0; i < ARRAY_SIZE(yuv420_copy_formats) && !found; i++)
474 			found = (out_fmt == yuv420_copy_formats[i]);
475 		break;
476 	case ATOMISP_INPUT_FORMAT_YUV420_10:
477 	case ATOMISP_INPUT_FORMAT_YUV420_16:
478 		found = (out_fmt == IA_CSS_FRAME_FORMAT_YUV420_16);
479 		break;
480 	case ATOMISP_INPUT_FORMAT_YUV422_8:
481 		for (i = 0; i < ARRAY_SIZE(yuv422_copy_formats) && !found; i++)
482 			found = (out_fmt == yuv422_copy_formats[i]);
483 		break;
484 	case ATOMISP_INPUT_FORMAT_YUV422_10:
485 	case ATOMISP_INPUT_FORMAT_YUV422_16:
486 		found = (out_fmt == IA_CSS_FRAME_FORMAT_YUV422_16 ||
487 			 out_fmt == IA_CSS_FRAME_FORMAT_YUV420_16);
488 		break;
489 	case ATOMISP_INPUT_FORMAT_RGB_444:
490 	case ATOMISP_INPUT_FORMAT_RGB_555:
491 	case ATOMISP_INPUT_FORMAT_RGB_565:
492 		found = (out_fmt == IA_CSS_FRAME_FORMAT_RGBA888 ||
493 			 out_fmt == IA_CSS_FRAME_FORMAT_RGB565);
494 		break;
495 	case ATOMISP_INPUT_FORMAT_RGB_666:
496 	case ATOMISP_INPUT_FORMAT_RGB_888:
497 		found = (out_fmt == IA_CSS_FRAME_FORMAT_RGBA888 ||
498 			 out_fmt == IA_CSS_FRAME_FORMAT_YUV420);
499 		break;
500 	case ATOMISP_INPUT_FORMAT_RAW_6:
501 	case ATOMISP_INPUT_FORMAT_RAW_7:
502 	case ATOMISP_INPUT_FORMAT_RAW_8:
503 	case ATOMISP_INPUT_FORMAT_RAW_10:
504 	case ATOMISP_INPUT_FORMAT_RAW_12:
505 	case ATOMISP_INPUT_FORMAT_RAW_14:
506 	case ATOMISP_INPUT_FORMAT_RAW_16:
507 		found = (out_fmt == IA_CSS_FRAME_FORMAT_RAW) ||
508 		(out_fmt == IA_CSS_FRAME_FORMAT_RAW_PACKED);
509 		break;
510 	case ATOMISP_INPUT_FORMAT_BINARY_8:
511 		found = (out_fmt == IA_CSS_FRAME_FORMAT_BINARY_8);
512 		break;
513 	default:
514 		break;
515 	}
516 	if (!found)
517 		return IA_CSS_ERR_INVALID_ARGUMENTS;
518 	return IA_CSS_SUCCESS;
519 }
520 
521 unsigned int
522 ia_css_stream_input_format_bits_per_pixel(struct ia_css_stream *stream)
523 {
524 	int bpp = 0;
525 
526 	if (stream)
527 		bpp = ia_css_util_input_format_bpp(stream->config.input_config.format,
528 						   stream->config.pixels_per_clock == 2);
529 
530 	return bpp;
531 }
532 
533 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
534 static enum ia_css_err
535 sh_css_config_input_network(struct ia_css_stream *stream) {
536 	unsigned int fmt_type;
537 	struct ia_css_pipe *pipe = stream->last_pipe;
538 	struct ia_css_binary *binary = NULL;
539 	enum ia_css_err err = IA_CSS_SUCCESS;
540 
541 	assert(stream);
542 	assert(pipe);
543 
544 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
545 			    "sh_css_config_input_network() enter:\n");
546 
547 	if (pipe->pipeline.stages)
548 		binary = pipe->pipeline.stages->binary;
549 
550 	err = ia_css_isys_convert_stream_format_to_mipi_format(
551 	    stream->config.input_config.format,
552 	    stream->csi_rx_config.comp,
553 	    &fmt_type);
554 	if (err != IA_CSS_SUCCESS)
555 		return err;
556 	sh_css_sp_program_input_circuit(fmt_type,
557 					stream->config.channel_id,
558 					stream->config.mode);
559 
560 	if ((binary && (binary->online || stream->config.continuous)) ||
561 	    pipe->config.mode == IA_CSS_PIPE_MODE_COPY)
562 	{
563 		err = ia_css_ifmtr_configure(&stream->config,
564 					     binary);
565 		if (err != IA_CSS_SUCCESS)
566 			return err;
567 	}
568 
569 	if (stream->config.mode == IA_CSS_INPUT_MODE_TPG ||
570 	    stream->config.mode == IA_CSS_INPUT_MODE_PRBS)
571 	{
572 		unsigned int hblank_cycles = 100,
573 		vblank_lines = 6,
574 		width,
575 		height,
576 		vblank_cycles;
577 		width  = (stream->config.input_config.input_res.width) / (1 +
578 			(stream->config.pixels_per_clock == 2));
579 		height = stream->config.input_config.input_res.height;
580 		vblank_cycles = vblank_lines * (width + hblank_cycles);
581 		sh_css_sp_configure_sync_gen(width, height, hblank_cycles,
582 					     vblank_cycles);
583 		if (pipe->stream->config.mode == IA_CSS_INPUT_MODE_TPG) {
584 			/* TODO: move define to proper file in tools */
585 #define GP_ISEL_TPG_MODE 0x90058
586 			ia_css_device_store_uint32(GP_ISEL_TPG_MODE, 0);
587 		}
588 	}
589 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
590 			    "sh_css_config_input_network() leave:\n");
591 	return IA_CSS_SUCCESS;
592 }
593 #elif !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2401)
594 static unsigned int csi2_protocol_calculate_max_subpixels_per_line(
595     enum atomisp_input_format	format,
596     unsigned int			pixels_per_line)
597 {
598 	unsigned int rval;
599 
600 	switch (format) {
601 	case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY:
602 		/*
603 		 * The frame format layout is shown below.
604 		 *
605 		 *		Line	0:	UYY0 UYY0 ... UYY0
606 		 *		Line	1:	VYY0 VYY0 ... VYY0
607 		 *		Line	2:	UYY0 UYY0 ... UYY0
608 		 *		Line	3:	VYY0 VYY0 ... VYY0
609 		 *		...
610 		 *		Line (n-2):	UYY0 UYY0 ... UYY0
611 		 *		Line (n-1):	VYY0 VYY0 ... VYY0
612 		 *
613 		 *	In this frame format, the even-line is
614 		 *	as wide as the odd-line.
615 		 *	The 0 is introduced by the input system
616 		 *	(mipi backend).
617 		 */
618 		rval = pixels_per_line * 2;
619 		break;
620 	case ATOMISP_INPUT_FORMAT_YUV420_8:
621 	case ATOMISP_INPUT_FORMAT_YUV420_10:
622 	case ATOMISP_INPUT_FORMAT_YUV420_16:
623 		/*
624 		 * The frame format layout is shown below.
625 		 *
626 		 *		Line	0:	YYYY YYYY ... YYYY
627 		 *		Line	1:	UYVY UYVY ... UYVY UYVY
628 		 *		Line	2:	YYYY YYYY ... YYYY
629 		 *		Line	3:	UYVY UYVY ... UYVY UYVY
630 		 *		...
631 		 *		Line (n-2):	YYYY YYYY ... YYYY
632 		 *		Line (n-1):	UYVY UYVY ... UYVY UYVY
633 		 *
634 		 * In this frame format, the odd-line is twice
635 		 * wider than the even-line.
636 		 */
637 		rval = pixels_per_line * 2;
638 		break;
639 	case ATOMISP_INPUT_FORMAT_YUV422_8:
640 	case ATOMISP_INPUT_FORMAT_YUV422_10:
641 	case ATOMISP_INPUT_FORMAT_YUV422_16:
642 		/*
643 		 * The frame format layout is shown below.
644 		 *
645 		 *		Line	0:	UYVY UYVY ... UYVY
646 		 *		Line	1:	UYVY UYVY ... UYVY
647 		 *		Line	2:	UYVY UYVY ... UYVY
648 		 *		Line	3:	UYVY UYVY ... UYVY
649 		 *		...
650 		 *		Line (n-2):	UYVY UYVY ... UYVY
651 		 *		Line (n-1):	UYVY UYVY ... UYVY
652 		 *
653 		 * In this frame format, the even-line is
654 		 * as wide as the odd-line.
655 		 */
656 		rval = pixels_per_line * 2;
657 		break;
658 	case ATOMISP_INPUT_FORMAT_RGB_444:
659 	case ATOMISP_INPUT_FORMAT_RGB_555:
660 	case ATOMISP_INPUT_FORMAT_RGB_565:
661 	case ATOMISP_INPUT_FORMAT_RGB_666:
662 	case ATOMISP_INPUT_FORMAT_RGB_888:
663 		/*
664 		 * The frame format layout is shown below.
665 		 *
666 		 *		Line	0:	ABGR ABGR ... ABGR
667 		 *		Line	1:	ABGR ABGR ... ABGR
668 		 *		Line	2:	ABGR ABGR ... ABGR
669 		 *		Line	3:	ABGR ABGR ... ABGR
670 		 *		...
671 		 *		Line (n-2):	ABGR ABGR ... ABGR
672 		 *		Line (n-1):	ABGR ABGR ... ABGR
673 		 *
674 		 * In this frame format, the even-line is
675 		 * as wide as the odd-line.
676 		 */
677 		rval = pixels_per_line * 4;
678 		break;
679 	case ATOMISP_INPUT_FORMAT_RAW_6:
680 	case ATOMISP_INPUT_FORMAT_RAW_7:
681 	case ATOMISP_INPUT_FORMAT_RAW_8:
682 	case ATOMISP_INPUT_FORMAT_RAW_10:
683 	case ATOMISP_INPUT_FORMAT_RAW_12:
684 	case ATOMISP_INPUT_FORMAT_RAW_14:
685 	case ATOMISP_INPUT_FORMAT_RAW_16:
686 	case ATOMISP_INPUT_FORMAT_BINARY_8:
687 	case ATOMISP_INPUT_FORMAT_USER_DEF1:
688 	case ATOMISP_INPUT_FORMAT_USER_DEF2:
689 	case ATOMISP_INPUT_FORMAT_USER_DEF3:
690 	case ATOMISP_INPUT_FORMAT_USER_DEF4:
691 	case ATOMISP_INPUT_FORMAT_USER_DEF5:
692 	case ATOMISP_INPUT_FORMAT_USER_DEF6:
693 	case ATOMISP_INPUT_FORMAT_USER_DEF7:
694 	case ATOMISP_INPUT_FORMAT_USER_DEF8:
695 		/*
696 		 * The frame format layout is shown below.
697 		 *
698 		 *		Line	0:	Pixel Pixel ... Pixel
699 		 *		Line	1:	Pixel Pixel ... Pixel
700 		 *		Line	2:	Pixel Pixel ... Pixel
701 		 *		Line	3:	Pixel Pixel ... Pixel
702 		 *		...
703 		 *		Line (n-2):	Pixel Pixel ... Pixel
704 		 *		Line (n-1):	Pixel Pixel ... Pixel
705 		 *
706 		 * In this frame format, the even-line is
707 		 * as wide as the odd-line.
708 		 */
709 		rval = pixels_per_line;
710 		break;
711 	default:
712 		rval = 0;
713 		break;
714 	}
715 
716 	return rval;
717 }
718 
719 static bool sh_css_translate_stream_cfg_to_input_system_input_port_id(
720     struct ia_css_stream_config *stream_cfg,
721     ia_css_isys_descr_t	*isys_stream_descr)
722 {
723 	bool rc;
724 
725 	rc = true;
726 	switch (stream_cfg->mode) {
727 	case IA_CSS_INPUT_MODE_TPG:
728 
729 		if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID0) {
730 			isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT0_ID;
731 		} else if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID1) {
732 			isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT1_ID;
733 		} else if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID2) {
734 			isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT2_ID;
735 		}
736 
737 		break;
738 	case IA_CSS_INPUT_MODE_PRBS:
739 
740 		if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID0) {
741 			isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT0_ID;
742 		} else if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID1) {
743 			isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT1_ID;
744 		} else if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID2) {
745 			isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT2_ID;
746 		}
747 
748 		break;
749 	case IA_CSS_INPUT_MODE_BUFFERED_SENSOR:
750 
751 		if (stream_cfg->source.port.port == MIPI_PORT0_ID) {
752 			isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT0_ID;
753 		} else if (stream_cfg->source.port.port == MIPI_PORT1_ID) {
754 			isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT1_ID;
755 		} else if (stream_cfg->source.port.port == MIPI_PORT2_ID) {
756 			isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT2_ID;
757 		}
758 
759 		break;
760 	default:
761 		rc = false;
762 		break;
763 	}
764 
765 	return rc;
766 }
767 
768 static bool sh_css_translate_stream_cfg_to_input_system_input_port_type(
769     struct ia_css_stream_config *stream_cfg,
770     ia_css_isys_descr_t	*isys_stream_descr)
771 {
772 	bool rc;
773 
774 	rc = true;
775 	switch (stream_cfg->mode) {
776 	case IA_CSS_INPUT_MODE_TPG:
777 
778 		isys_stream_descr->mode = INPUT_SYSTEM_SOURCE_TYPE_TPG;
779 
780 		break;
781 	case IA_CSS_INPUT_MODE_PRBS:
782 
783 		isys_stream_descr->mode = INPUT_SYSTEM_SOURCE_TYPE_PRBS;
784 
785 		break;
786 	case IA_CSS_INPUT_MODE_SENSOR:
787 	case IA_CSS_INPUT_MODE_BUFFERED_SENSOR:
788 
789 		isys_stream_descr->mode = INPUT_SYSTEM_SOURCE_TYPE_SENSOR;
790 		break;
791 
792 	default:
793 		rc = false;
794 		break;
795 	}
796 
797 	return rc;
798 }
799 
800 static bool sh_css_translate_stream_cfg_to_input_system_input_port_attr(
801     struct ia_css_stream_config *stream_cfg,
802     ia_css_isys_descr_t	*isys_stream_descr,
803     int isys_stream_idx)
804 {
805 	bool rc;
806 
807 	rc = true;
808 	switch (stream_cfg->mode) {
809 	case IA_CSS_INPUT_MODE_TPG:
810 		if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_RAMP) {
811 			isys_stream_descr->tpg_port_attr.mode = PIXELGEN_TPG_MODE_RAMP;
812 		} else if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_CHECKERBOARD) {
813 			isys_stream_descr->tpg_port_attr.mode = PIXELGEN_TPG_MODE_CHBO;
814 		} else if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_MONO) {
815 			isys_stream_descr->tpg_port_attr.mode = PIXELGEN_TPG_MODE_MONO;
816 		} else {
817 			rc = false;
818 		}
819 
820 		/*
821 		 * TODO
822 		 * - Make "color_cfg" as part of "ia_css_tpg_config".
823 		 */
824 		isys_stream_descr->tpg_port_attr.color_cfg.R1 = 51;
825 		isys_stream_descr->tpg_port_attr.color_cfg.G1 = 102;
826 		isys_stream_descr->tpg_port_attr.color_cfg.B1 = 255;
827 		isys_stream_descr->tpg_port_attr.color_cfg.R2 = 0;
828 		isys_stream_descr->tpg_port_attr.color_cfg.G2 = 100;
829 		isys_stream_descr->tpg_port_attr.color_cfg.B2 = 160;
830 
831 		isys_stream_descr->tpg_port_attr.mask_cfg.h_mask =
832 		    stream_cfg->source.tpg.x_mask;
833 		isys_stream_descr->tpg_port_attr.mask_cfg.v_mask =
834 		    stream_cfg->source.tpg.y_mask;
835 		isys_stream_descr->tpg_port_attr.mask_cfg.hv_mask =
836 		    stream_cfg->source.tpg.xy_mask;
837 
838 		isys_stream_descr->tpg_port_attr.delta_cfg.h_delta =
839 		    stream_cfg->source.tpg.x_delta;
840 		isys_stream_descr->tpg_port_attr.delta_cfg.v_delta =
841 		    stream_cfg->source.tpg.y_delta;
842 
843 		/*
844 		 * TODO
845 		 * - Make "sync_gen_cfg" as part of "ia_css_tpg_config".
846 		 */
847 		isys_stream_descr->tpg_port_attr.sync_gen_cfg.hblank_cycles = 100;
848 		isys_stream_descr->tpg_port_attr.sync_gen_cfg.vblank_cycles = 100;
849 		isys_stream_descr->tpg_port_attr.sync_gen_cfg.pixels_per_clock =
850 		    stream_cfg->pixels_per_clock;
851 		isys_stream_descr->tpg_port_attr.sync_gen_cfg.nr_of_frames = (uint32_t)~(0x0);
852 		isys_stream_descr->tpg_port_attr.sync_gen_cfg.pixels_per_line =
853 		    stream_cfg->isys_config[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX].input_res.width;
854 		isys_stream_descr->tpg_port_attr.sync_gen_cfg.lines_per_frame =
855 		    stream_cfg->isys_config[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX].input_res.height;
856 
857 		break;
858 	case IA_CSS_INPUT_MODE_PRBS:
859 
860 		isys_stream_descr->prbs_port_attr.seed0 = stream_cfg->source.prbs.seed;
861 		isys_stream_descr->prbs_port_attr.seed1 = stream_cfg->source.prbs.seed1;
862 
863 		/*
864 		 * TODO
865 		 * - Make "sync_gen_cfg" as part of "ia_css_prbs_config".
866 		 */
867 		isys_stream_descr->prbs_port_attr.sync_gen_cfg.hblank_cycles = 100;
868 		isys_stream_descr->prbs_port_attr.sync_gen_cfg.vblank_cycles = 100;
869 		isys_stream_descr->prbs_port_attr.sync_gen_cfg.pixels_per_clock =
870 		    stream_cfg->pixels_per_clock;
871 		isys_stream_descr->prbs_port_attr.sync_gen_cfg.nr_of_frames = (uint32_t)~(0x0);
872 		isys_stream_descr->prbs_port_attr.sync_gen_cfg.pixels_per_line =
873 		    stream_cfg->isys_config[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX].input_res.width;
874 		isys_stream_descr->prbs_port_attr.sync_gen_cfg.lines_per_frame =
875 		    stream_cfg->isys_config[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX].input_res.height;
876 
877 		break;
878 	case IA_CSS_INPUT_MODE_BUFFERED_SENSOR: {
879 		enum ia_css_err err;
880 		unsigned int fmt_type;
881 
882 		err = ia_css_isys_convert_stream_format_to_mipi_format(
883 			  stream_cfg->isys_config[isys_stream_idx].format,
884 			  MIPI_PREDICTOR_NONE,
885 			  &fmt_type);
886 		if (err != IA_CSS_SUCCESS)
887 			rc = false;
888 
889 		isys_stream_descr->csi_port_attr.active_lanes =
890 		    stream_cfg->source.port.num_lanes;
891 		isys_stream_descr->csi_port_attr.fmt_type = fmt_type;
892 		isys_stream_descr->csi_port_attr.ch_id = stream_cfg->channel_id;
893 #ifdef USE_INPUT_SYSTEM_VERSION_2401
894 		isys_stream_descr->online = stream_cfg->online;
895 #endif
896 		err |= ia_css_isys_convert_compressed_format(
897 			   &stream_cfg->source.port.compression,
898 			   isys_stream_descr);
899 		if (err != IA_CSS_SUCCESS)
900 			rc = false;
901 
902 		/* metadata */
903 		isys_stream_descr->metadata.enable = false;
904 		if (stream_cfg->metadata_config.resolution.height > 0) {
905 			err = ia_css_isys_convert_stream_format_to_mipi_format(
906 				  stream_cfg->metadata_config.data_type,
907 				  MIPI_PREDICTOR_NONE,
908 				  &fmt_type);
909 			if (err != IA_CSS_SUCCESS)
910 				rc = false;
911 			isys_stream_descr->metadata.fmt_type = fmt_type;
912 			isys_stream_descr->metadata.bits_per_pixel =
913 			    ia_css_util_input_format_bpp(stream_cfg->metadata_config.data_type, true);
914 			isys_stream_descr->metadata.pixels_per_line =
915 			    stream_cfg->metadata_config.resolution.width;
916 			isys_stream_descr->metadata.lines_per_frame =
917 			    stream_cfg->metadata_config.resolution.height;
918 #ifdef USE_INPUT_SYSTEM_VERSION_2401
919 			/* For new input system, number of str2mmio requests must be even.
920 			 * So we round up number of metadata lines to be even. */
921 			if (isys_stream_descr->metadata.lines_per_frame > 0)
922 				isys_stream_descr->metadata.lines_per_frame +=
923 				    (isys_stream_descr->metadata.lines_per_frame & 1);
924 #endif
925 			isys_stream_descr->metadata.align_req_in_bytes =
926 			    ia_css_csi2_calculate_input_system_alignment(
927 				stream_cfg->metadata_config.data_type);
928 			isys_stream_descr->metadata.enable = true;
929 		}
930 
931 		break;
932 	}
933 	default:
934 		rc = false;
935 		break;
936 	}
937 
938 	return rc;
939 }
940 
941 static bool sh_css_translate_stream_cfg_to_input_system_input_port_resolution(
942     struct ia_css_stream_config *stream_cfg,
943     ia_css_isys_descr_t	*isys_stream_descr,
944     int isys_stream_idx)
945 {
946 	unsigned int bits_per_subpixel;
947 	unsigned int max_subpixels_per_line;
948 	unsigned int lines_per_frame;
949 	unsigned int align_req_in_bytes;
950 	enum atomisp_input_format fmt_type;
951 
952 	fmt_type = stream_cfg->isys_config[isys_stream_idx].format;
953 	if ((stream_cfg->mode == IA_CSS_INPUT_MODE_SENSOR ||
954 	     stream_cfg->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) &&
955 	    stream_cfg->source.port.compression.type != IA_CSS_CSI2_COMPRESSION_TYPE_NONE) {
956 		if (stream_cfg->source.port.compression.uncompressed_bits_per_pixel ==
957 		    UNCOMPRESSED_BITS_PER_PIXEL_10) {
958 			fmt_type = ATOMISP_INPUT_FORMAT_RAW_10;
959 		} else if (stream_cfg->source.port.compression.uncompressed_bits_per_pixel ==
960 			   UNCOMPRESSED_BITS_PER_PIXEL_12) {
961 			fmt_type = ATOMISP_INPUT_FORMAT_RAW_12;
962 		} else
963 			return false;
964 	}
965 
966 	bits_per_subpixel =
967 	    sh_css_stream_format_2_bits_per_subpixel(fmt_type);
968 	if (bits_per_subpixel == 0)
969 		return false;
970 
971 	max_subpixels_per_line =
972 	    csi2_protocol_calculate_max_subpixels_per_line(fmt_type,
973 		    stream_cfg->isys_config[isys_stream_idx].input_res.width);
974 	if (max_subpixels_per_line == 0)
975 		return false;
976 
977 	lines_per_frame = stream_cfg->isys_config[isys_stream_idx].input_res.height;
978 	if (lines_per_frame == 0)
979 		return false;
980 
981 	align_req_in_bytes = ia_css_csi2_calculate_input_system_alignment(fmt_type);
982 
983 	/* HW needs subpixel info for their settings */
984 	isys_stream_descr->input_port_resolution.bits_per_pixel = bits_per_subpixel;
985 	isys_stream_descr->input_port_resolution.pixels_per_line =
986 	    max_subpixels_per_line;
987 	isys_stream_descr->input_port_resolution.lines_per_frame = lines_per_frame;
988 	isys_stream_descr->input_port_resolution.align_req_in_bytes =
989 	    align_req_in_bytes;
990 
991 	return true;
992 }
993 
994 static bool sh_css_translate_stream_cfg_to_isys_stream_descr(
995     struct ia_css_stream_config *stream_cfg,
996     bool early_polling,
997     ia_css_isys_descr_t	*isys_stream_descr,
998     int isys_stream_idx)
999 {
1000 	bool rc;
1001 
1002 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
1003 			    "sh_css_translate_stream_cfg_to_isys_stream_descr() enter:\n");
1004 	rc  = sh_css_translate_stream_cfg_to_input_system_input_port_id(stream_cfg,
1005 		isys_stream_descr);
1006 	rc &= sh_css_translate_stream_cfg_to_input_system_input_port_type(stream_cfg,
1007 		isys_stream_descr);
1008 	rc &= sh_css_translate_stream_cfg_to_input_system_input_port_attr(stream_cfg,
1009 		isys_stream_descr, isys_stream_idx);
1010 	rc &= sh_css_translate_stream_cfg_to_input_system_input_port_resolution(
1011 		  stream_cfg, isys_stream_descr, isys_stream_idx);
1012 
1013 	isys_stream_descr->raw_packed = stream_cfg->pack_raw_pixels;
1014 	isys_stream_descr->linked_isys_stream_id = (int8_t)
1015 		stream_cfg->isys_config[isys_stream_idx].linked_isys_stream_id;
1016 	/*
1017 	 * Early polling is required for timestamp accuracy in certain case.
1018 	 * The ISYS HW polling is started on
1019 	 * ia_css_isys_stream_capture_indication() instead of
1020 	 * ia_css_pipeline_sp_wait_for_isys_stream_N() as isp processing of
1021 	 * capture takes longer than getting an ISYS frame
1022 	 *
1023 	 * Only 2401 relevant ??
1024 	 */
1025 	isys_stream_descr->polling_mode
1026 	    = early_polling ? INPUT_SYSTEM_POLL_ON_CAPTURE_REQUEST
1027 	      : INPUT_SYSTEM_POLL_ON_WAIT_FOR_FRAME;
1028 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
1029 			    "sh_css_translate_stream_cfg_to_isys_stream_descr() leave:\n");
1030 
1031 	return rc;
1032 }
1033 
1034 static bool sh_css_translate_binary_info_to_input_system_output_port_attr(
1035     struct ia_css_binary *binary,
1036     ia_css_isys_descr_t     *isys_stream_descr)
1037 {
1038 	if (!binary)
1039 		return false;
1040 
1041 	isys_stream_descr->output_port_attr.left_padding = binary->left_padding;
1042 	isys_stream_descr->output_port_attr.max_isp_input_width =
1043 	    binary->info->sp.input.max_width;
1044 
1045 	return true;
1046 }
1047 
1048 static enum ia_css_err
1049 sh_css_config_input_network(struct ia_css_stream *stream) {
1050 	bool					rc;
1051 	ia_css_isys_descr_t			isys_stream_descr;
1052 	unsigned int				sp_thread_id;
1053 	struct sh_css_sp_pipeline_terminal	*sp_pipeline_input_terminal;
1054 	struct ia_css_pipe *pipe = NULL;
1055 	struct ia_css_binary *binary = NULL;
1056 	int i;
1057 	u32 isys_stream_id;
1058 	bool early_polling = false;
1059 
1060 	assert(stream);
1061 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
1062 			    "sh_css_config_input_network() enter 0x%p:\n", stream);
1063 
1064 	if (stream->config.continuous == true)
1065 	{
1066 		if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE) {
1067 			pipe = stream->last_pipe;
1068 		} else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_YUVPP) {
1069 			pipe = stream->last_pipe;
1070 		} else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) {
1071 			pipe = stream->last_pipe->pipe_settings.preview.copy_pipe;
1072 		} else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) {
1073 			pipe = stream->last_pipe->pipe_settings.video.copy_pipe;
1074 		}
1075 	} else
1076 	{
1077 		pipe = stream->last_pipe;
1078 		if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE) {
1079 			/*
1080 			 * We need to poll the ISYS HW in capture_indication itself
1081 			 * for "non-continuous" capture usecase for getting accurate
1082 			 * isys frame capture timestamps.
1083 			 * This is because the capturepipe propcessing takes longer
1084 			 * to execute than the input system frame capture.
1085 			 * 2401 specific
1086 			 */
1087 			early_polling = true;
1088 		}
1089 	}
1090 
1091 	assert(pipe);
1092 	if (!pipe)
1093 		return IA_CSS_ERR_INTERNAL_ERROR;
1094 
1095 	if (pipe->pipeline.stages)
1096 		if (pipe->pipeline.stages->binary)
1097 			binary = pipe->pipeline.stages->binary;
1098 
1099 	if (binary)
1100 	{
1101 		/* this was being done in ifmtr in 2400.
1102 		 * online and cont bypass the init_in_frameinfo_memory_defaults
1103 		 * so need to do it here
1104 		 */
1105 		ia_css_get_crop_offsets(pipe, &binary->in_frame_info);
1106 	}
1107 
1108 	/* get the SP thread id */
1109 	rc = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &sp_thread_id);
1110 	if (!rc)
1111 		return IA_CSS_ERR_INTERNAL_ERROR;
1112 	/* get the target input terminal */
1113 	sp_pipeline_input_terminal = &sh_css_sp_group.pipe_io[sp_thread_id].input;
1114 
1115 	for (i = 0; i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++)
1116 	{
1117 		/* initialization */
1118 		memset((void *)(&isys_stream_descr), 0, sizeof(ia_css_isys_descr_t));
1119 		sp_pipeline_input_terminal->context.virtual_input_system_stream[i].valid = 0;
1120 		sp_pipeline_input_terminal->ctrl.virtual_input_system_stream_cfg[i].valid = 0;
1121 
1122 		if (!stream->config.isys_config[i].valid)
1123 			continue;
1124 
1125 		/* translate the stream configuration to the Input System (2401) configuration */
1126 		rc = sh_css_translate_stream_cfg_to_isys_stream_descr(
1127 			 &stream->config,
1128 			 early_polling,
1129 			 &(isys_stream_descr), i);
1130 
1131 		if (stream->config.online) {
1132 			rc &= sh_css_translate_binary_info_to_input_system_output_port_attr(
1133 				  binary,
1134 				  &(isys_stream_descr));
1135 		}
1136 
1137 		if (!rc)
1138 			return IA_CSS_ERR_INTERNAL_ERROR;
1139 
1140 		isys_stream_id = ia_css_isys_generate_stream_id(sp_thread_id, i);
1141 
1142 		/* create the virtual Input System (2401) */
1143 		rc =  ia_css_isys_stream_create(
1144 			  &(isys_stream_descr),
1145 			  &sp_pipeline_input_terminal->context.virtual_input_system_stream[i],
1146 			  isys_stream_id);
1147 		if (!rc)
1148 			return IA_CSS_ERR_INTERNAL_ERROR;
1149 
1150 		/* calculate the configuration of the virtual Input System (2401) */
1151 		rc = ia_css_isys_stream_calculate_cfg(
1152 			 &sp_pipeline_input_terminal->context.virtual_input_system_stream[i],
1153 			 &(isys_stream_descr),
1154 			 &sp_pipeline_input_terminal->ctrl.virtual_input_system_stream_cfg[i]);
1155 		if (!rc) {
1156 			ia_css_isys_stream_destroy(
1157 			    &sp_pipeline_input_terminal->context.virtual_input_system_stream[i]);
1158 			return IA_CSS_ERR_INTERNAL_ERROR;
1159 		}
1160 	}
1161 
1162 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
1163 			    "sh_css_config_input_network() leave:\n");
1164 
1165 	return IA_CSS_SUCCESS;
1166 }
1167 
1168 static inline struct ia_css_pipe *stream_get_last_pipe(
1169     struct ia_css_stream *stream)
1170 {
1171 	struct ia_css_pipe *last_pipe = NULL;
1172 
1173 	if (stream)
1174 		last_pipe = stream->last_pipe;
1175 
1176 	return last_pipe;
1177 }
1178 
1179 static inline struct ia_css_pipe *stream_get_copy_pipe(
1180     struct ia_css_stream *stream)
1181 {
1182 	struct ia_css_pipe *copy_pipe = NULL;
1183 	struct ia_css_pipe *last_pipe = NULL;
1184 	enum ia_css_pipe_id pipe_id;
1185 
1186 	last_pipe = stream_get_last_pipe(stream);
1187 
1188 	if ((stream) &&
1189 	    (last_pipe) &&
1190 	    (stream->config.continuous)) {
1191 		pipe_id = last_pipe->mode;
1192 		switch (pipe_id) {
1193 		case IA_CSS_PIPE_ID_PREVIEW:
1194 			copy_pipe = last_pipe->pipe_settings.preview.copy_pipe;
1195 			break;
1196 		case IA_CSS_PIPE_ID_VIDEO:
1197 			copy_pipe = last_pipe->pipe_settings.video.copy_pipe;
1198 			break;
1199 		default:
1200 			copy_pipe = NULL;
1201 			break;
1202 		}
1203 	}
1204 
1205 	return copy_pipe;
1206 }
1207 
1208 static inline struct ia_css_pipe *stream_get_target_pipe(
1209     struct ia_css_stream *stream)
1210 {
1211 	struct ia_css_pipe *target_pipe;
1212 
1213 	/* get the pipe that consumes the stream */
1214 	if (stream->config.continuous) {
1215 		target_pipe = stream_get_copy_pipe(stream);
1216 	} else {
1217 		target_pipe = stream_get_last_pipe(stream);
1218 	}
1219 
1220 	return target_pipe;
1221 }
1222 
1223 static enum ia_css_err stream_csi_rx_helper(
1224     struct ia_css_stream *stream,
1225     enum ia_css_err (*func)(enum mipi_port_id, uint32_t))
1226 {
1227 	enum ia_css_err retval = IA_CSS_ERR_INTERNAL_ERROR;
1228 	u32 sp_thread_id, stream_id;
1229 	bool rc;
1230 	struct ia_css_pipe *target_pipe = NULL;
1231 
1232 	if ((!stream) || (stream->config.mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR))
1233 		goto exit;
1234 
1235 	target_pipe = stream_get_target_pipe(stream);
1236 
1237 	if (!target_pipe)
1238 		goto exit;
1239 
1240 	rc = ia_css_pipeline_get_sp_thread_id(
1241 		 ia_css_pipe_get_pipe_num(target_pipe),
1242 		 &sp_thread_id);
1243 
1244 	if (!rc)
1245 		goto exit;
1246 
1247 	/* (un)register all valid "virtual isys streams" within the ia_css_stream */
1248 	stream_id = 0;
1249 	do {
1250 		if (stream->config.isys_config[stream_id].valid) {
1251 			u32 isys_stream_id = ia_css_isys_generate_stream_id(sp_thread_id, stream_id);
1252 
1253 			retval = func(stream->config.source.port.port, isys_stream_id);
1254 		}
1255 		stream_id++;
1256 	} while ((retval == IA_CSS_SUCCESS) &&
1257 		 (stream_id < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH));
1258 
1259 exit:
1260 	return retval;
1261 }
1262 
1263 static inline enum ia_css_err stream_register_with_csi_rx(
1264     struct ia_css_stream *stream)
1265 {
1266 	return stream_csi_rx_helper(stream, ia_css_isys_csi_rx_register_stream);
1267 }
1268 
1269 static inline enum ia_css_err stream_unregister_with_csi_rx(
1270     struct ia_css_stream *stream)
1271 {
1272 	return stream_csi_rx_helper(stream, ia_css_isys_csi_rx_unregister_stream);
1273 }
1274 #endif
1275 
1276 #if WITH_PC_MONITORING
1277 static struct task_struct *my_kthread;    /* Handle for the monitoring thread */
1278 static int sh_binary_running;         /* Enable sampling in the thread */
1279 
1280 static void print_pc_histo(char *core_name, struct sh_css_pc_histogram *hist)
1281 {
1282 	unsigned int i;
1283 	unsigned int cnt_run = 0;
1284 	unsigned int cnt_stall = 0;
1285 
1286 	if (!hist)
1287 		return;
1288 
1289 	sh_css_print("%s histogram length = %d\n", core_name, hist->length);
1290 	sh_css_print("%s PC\turn\tstall\n", core_name);
1291 
1292 	for (i = 0; i < hist->length; i++) {
1293 		if ((hist->run[i] == 0) && (hist->run[i] == hist->stall[i]))
1294 			continue;
1295 		sh_css_print("%s %d\t%d\t%d\n",
1296 			     core_name, i, hist->run[i], hist->stall[i]);
1297 		cnt_run += hist->run[i];
1298 		cnt_stall += hist->stall[i];
1299 	}
1300 
1301 	sh_css_print(" Statistics for %s, cnt_run = %d, cnt_stall = %d, hist->length = %d\n",
1302 		     core_name, cnt_run, cnt_stall, hist->length);
1303 }
1304 
1305 static void print_pc_histogram(void)
1306 {
1307 	struct ia_css_binary_metrics *metrics;
1308 
1309 	for (metrics = sh_css_metrics.binary_metrics;
1310 	     metrics;
1311 	     metrics = metrics->next) {
1312 		if (metrics->mode == IA_CSS_BINARY_MODE_PREVIEW ||
1313 		    metrics->mode == IA_CSS_BINARY_MODE_VF_PP) {
1314 			sh_css_print("pc_histogram for binary %d is SKIPPED\n",
1315 				     metrics->id);
1316 			continue;
1317 		}
1318 
1319 		sh_css_print(" pc_histogram for binary %d\n", metrics->id);
1320 		print_pc_histo("  ISP", &metrics->isp_histogram);
1321 		print_pc_histo("  SP",   &metrics->sp_histogram);
1322 		sh_css_print("print_pc_histogram() done for binay->id = %d, done.\n",
1323 			     metrics->id);
1324 	}
1325 
1326 	sh_css_print("PC_MONITORING:print_pc_histogram() -- DONE\n");
1327 }
1328 
1329 static int pc_monitoring(void *data)
1330 {
1331 	int i = 0;
1332 
1333 	(void)data;
1334 	while (true) {
1335 		if (sh_binary_running) {
1336 			sh_css_metrics_sample_pcs();
1337 #if MULTIPLE_SAMPLES
1338 			for (i = 0; i < NOF_SAMPLES; i++)
1339 				sh_css_metrics_sample_pcs();
1340 #endif
1341 		}
1342 		usleep_range(10, 50);
1343 	}
1344 	return 0;
1345 }
1346 
1347 static void spying_thread_create(void)
1348 {
1349 	my_kthread = kthread_run(pc_monitoring, NULL, "sh_pc_monitor");
1350 	sh_css_metrics_enable_pc_histogram(1);
1351 }
1352 
1353 static void input_frame_info(struct ia_css_frame_info frame_info)
1354 {
1355 	sh_css_print("SH_CSS:input_frame_info() -- frame->info.res.width = %d, frame->info.res.height = %d, format = %d\n",
1356 		     frame_info.res.width, frame_info.res.height, frame_info.format);
1357 }
1358 #endif /* WITH_PC_MONITORING */
1359 
1360 static void
1361 start_binary(struct ia_css_pipe *pipe,
1362 	     struct ia_css_binary *binary)
1363 {
1364 	struct ia_css_stream *stream;
1365 
1366 	assert(pipe);
1367 	/* Acceleration uses firmware, the binary thus can be NULL */
1368 	/* assert(binary != NULL); */
1369 
1370 	(void)binary;
1371 
1372 #if !defined(HAS_NO_INPUT_SYSTEM)
1373 	stream = pipe->stream;
1374 #else
1375 	(void)pipe;
1376 	(void)stream;
1377 #endif
1378 
1379 	if (binary)
1380 		sh_css_metrics_start_binary(&binary->metrics);
1381 
1382 #if WITH_PC_MONITORING
1383 	sh_css_print("PC_MONITORING: %s() -- binary id = %d , enable_dvs_envelope = %d\n",
1384 		     __func__, binary->info->sp.id,
1385 		     binary->info->sp.enable.dvs_envelope);
1386 	input_frame_info(binary->in_frame_info);
1387 
1388 	if (binary && binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_VIDEO)
1389 		sh_binary_running = true;
1390 #endif
1391 
1392 #if !defined(HAS_NO_INPUT_SYSTEM) && !defined(USE_INPUT_SYSTEM_VERSION_2401)
1393 	if (stream->reconfigure_css_rx) {
1394 		ia_css_isys_rx_configure(&pipe->stream->csi_rx_config,
1395 					 pipe->stream->config.mode);
1396 		stream->reconfigure_css_rx = false;
1397 	}
1398 #endif
1399 }
1400 
1401 /* start the copy function on the SP */
1402 static enum ia_css_err
1403 start_copy_on_sp(struct ia_css_pipe *pipe,
1404 		 struct ia_css_frame *out_frame) {
1405 	(void)out_frame;
1406 	assert(pipe);
1407 	assert(pipe->stream);
1408 
1409 	if ((!pipe) || (!pipe->stream))
1410 		return IA_CSS_ERR_INVALID_ARGUMENTS;
1411 
1412 #if !defined(HAS_NO_INPUT_SYSTEM) && !defined(USE_INPUT_SYSTEM_VERSION_2401)
1413 	if (pipe->stream->reconfigure_css_rx)
1414 		ia_css_isys_rx_disable();
1415 #endif
1416 
1417 	if (pipe->stream->config.input_config.format != ATOMISP_INPUT_FORMAT_BINARY_8)
1418 		return IA_CSS_ERR_INTERNAL_ERROR;
1419 	sh_css_sp_start_binary_copy(ia_css_pipe_get_pipe_num(pipe), out_frame, pipe->stream->config.pixels_per_clock == 2);
1420 
1421 #if !defined(HAS_NO_INPUT_SYSTEM) && !defined(USE_INPUT_SYSTEM_VERSION_2401)
1422 	if (pipe->stream->reconfigure_css_rx)
1423 	{
1424 		ia_css_isys_rx_configure(&pipe->stream->csi_rx_config,
1425 					 pipe->stream->config.mode);
1426 		pipe->stream->reconfigure_css_rx = false;
1427 	}
1428 #endif
1429 
1430 	return IA_CSS_SUCCESS;
1431 }
1432 
1433 void sh_css_binary_args_reset(struct sh_css_binary_args *args)
1434 {
1435 	unsigned int i;
1436 
1437 	for (i = 0; i < NUM_TNR_FRAMES; i++)
1438 		args->tnr_frames[i] = NULL;
1439 	for (i = 0; i < MAX_NUM_VIDEO_DELAY_FRAMES; i++)
1440 		args->delay_frames[i] = NULL;
1441 	args->in_frame      = NULL;
1442 	for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
1443 		args->out_frame[i] = NULL;
1444 	args->out_vf_frame  = NULL;
1445 	args->copy_vf       = false;
1446 	args->copy_output   = true;
1447 	args->vf_downscale_log2 = 0;
1448 }
1449 
1450 static void start_pipe(
1451     struct ia_css_pipe *me,
1452     enum sh_css_pipe_config_override copy_ovrd,
1453     enum ia_css_input_mode input_mode)
1454 {
1455 	const struct ia_css_coordinate *coord = NULL;
1456 	const struct ia_css_isp_parameters *params = NULL;
1457 
1458 #if defined(HAS_NO_INPUT_SYSTEM)
1459 	(void)input_mode;
1460 #endif
1461 
1462 	IA_CSS_ENTER_PRIVATE("me = %p, copy_ovrd = %d, input_mode = %d",
1463 			     me, copy_ovrd, input_mode);
1464 
1465 	assert(me); /* all callers are in this file and call with non null argument */
1466 
1467 	if (atomisp_hw_is_isp2401) {
1468 		coord = &me->config.internal_frame_origin_bqs_on_sctbl;
1469 		params = me->stream->isp_params_configs;
1470 	}
1471 
1472 	sh_css_sp_init_pipeline(&me->pipeline,
1473 				me->mode,
1474 				(uint8_t)ia_css_pipe_get_pipe_num(me),
1475 				me->config.default_capture_config.enable_xnr != 0,
1476 				me->stream->config.pixels_per_clock == 2,
1477 				me->stream->config.continuous,
1478 				false,
1479 				me->required_bds_factor,
1480 				copy_ovrd,
1481 				input_mode,
1482 				&me->stream->config.metadata_config,
1483 				&me->stream->info.metadata_info
1484 #if !defined(HAS_NO_INPUT_SYSTEM)
1485 				, (input_mode == IA_CSS_INPUT_MODE_MEMORY) ?
1486 				(enum mipi_port_id)0 :
1487 				me->stream->config.source.port.port,
1488 #endif
1489 				coord,
1490 				params);
1491 
1492 	if (me->config.mode != IA_CSS_PIPE_MODE_COPY) {
1493 		struct ia_css_pipeline_stage *stage;
1494 
1495 		stage = me->pipeline.stages;
1496 		if (stage) {
1497 			me->pipeline.current_stage = stage;
1498 			start_binary(me, stage->binary);
1499 		}
1500 	}
1501 	IA_CSS_LEAVE_PRIVATE("void");
1502 }
1503 
1504 void
1505 sh_css_invalidate_shading_tables(struct ia_css_stream *stream)
1506 {
1507 	int i;
1508 
1509 	assert(stream);
1510 
1511 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1512 			    "sh_css_invalidate_shading_tables() enter:\n");
1513 
1514 	for (i = 0; i < stream->num_pipes; i++) {
1515 		assert(stream->pipes[i]);
1516 		sh_css_pipe_free_shading_table(stream->pipes[i]);
1517 	}
1518 
1519 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1520 			    "sh_css_invalidate_shading_tables() leave: return_void\n");
1521 }
1522 
1523 static void
1524 enable_interrupts(enum ia_css_irq_type irq_type)
1525 {
1526 #ifdef USE_INPUT_SYSTEM_VERSION_2
1527 	enum mipi_port_id port;
1528 #endif
1529 	bool enable_pulse = irq_type != IA_CSS_IRQ_TYPE_EDGE;
1530 
1531 	IA_CSS_ENTER_PRIVATE("");
1532 	/* Enable IRQ on the SP which signals that SP goes to idle
1533 	 * (aka ready state) */
1534 	cnd_sp_irq_enable(SP0_ID, true);
1535 	/* Set the IRQ device 0 to either level or pulse */
1536 	irq_enable_pulse(IRQ0_ID, enable_pulse);
1537 
1538 	cnd_virq_enable_channel(virq_sp, true);
1539 
1540 	/* Enable SW interrupt 0, this is used to signal ISYS events */
1541 	cnd_virq_enable_channel(
1542 	    (virq_id_t)(IRQ_SW_CHANNEL0_ID + IRQ_SW_CHANNEL_OFFSET),
1543 	    true);
1544 	/* Enable SW interrupt 1, this is used to signal PSYS events */
1545 	cnd_virq_enable_channel(
1546 	    (virq_id_t)(IRQ_SW_CHANNEL1_ID + IRQ_SW_CHANNEL_OFFSET),
1547 	    true);
1548 #if !defined(HAS_IRQ_MAP_VERSION_2)
1549 	/* IRQ_SW_CHANNEL2_ID does not exist on 240x systems */
1550 	cnd_virq_enable_channel(
1551 	    (virq_id_t)(IRQ_SW_CHANNEL2_ID + IRQ_SW_CHANNEL_OFFSET),
1552 	    true);
1553 	virq_clear_all();
1554 #endif
1555 
1556 #ifdef USE_INPUT_SYSTEM_VERSION_2
1557 	for (port = 0; port < N_MIPI_PORT_ID; port++)
1558 		ia_css_isys_rx_enable_all_interrupts(port);
1559 #endif
1560 
1561 	IA_CSS_LEAVE_PRIVATE("");
1562 }
1563 
1564 static bool sh_css_setup_spctrl_config(const struct ia_css_fw_info *fw,
1565 				       const char *program,
1566 				       ia_css_spctrl_cfg  *spctrl_cfg)
1567 {
1568 	if ((!fw) || (!spctrl_cfg))
1569 		return false;
1570 	spctrl_cfg->sp_entry = 0;
1571 	spctrl_cfg->program_name = (char *)(program);
1572 
1573 	spctrl_cfg->ddr_data_offset =  fw->blob.data_source;
1574 	spctrl_cfg->dmem_data_addr = fw->blob.data_target;
1575 	spctrl_cfg->dmem_bss_addr = fw->blob.bss_target;
1576 	spctrl_cfg->data_size = fw->blob.data_size;
1577 	spctrl_cfg->bss_size = fw->blob.bss_size;
1578 
1579 	spctrl_cfg->spctrl_config_dmem_addr = fw->info.sp.init_dmem_data;
1580 	spctrl_cfg->spctrl_state_dmem_addr = fw->info.sp.sw_state;
1581 
1582 	spctrl_cfg->code_size = fw->blob.size;
1583 	spctrl_cfg->code      = fw->blob.code;
1584 	spctrl_cfg->sp_entry  = fw->info.sp.sp_entry; /* entry function ptr on SP */
1585 
1586 	return true;
1587 }
1588 
1589 void
1590 ia_css_unload_firmware(void)
1591 {
1592 	if (sh_css_num_binaries) {
1593 		/* we have already loaded before so get rid of the old stuff */
1594 		ia_css_binary_uninit();
1595 		sh_css_unload_firmware();
1596 	}
1597 	fw_explicitly_loaded = false;
1598 }
1599 
1600 static void
1601 ia_css_reset_defaults(struct sh_css *css)
1602 {
1603 	struct sh_css default_css;
1604 
1605 	/* Reset everything to zero */
1606 	memset(&default_css, 0, sizeof(default_css));
1607 
1608 	/* Initialize the non zero values*/
1609 	default_css.check_system_idle = true;
1610 	default_css.num_cont_raw_frames = NUM_CONTINUOUS_FRAMES;
1611 
1612 	/* All should be 0: but memset does it already.
1613 	 * default_css.num_mipi_frames[N_CSI_PORTS] = 0;
1614 	 */
1615 
1616 	default_css.irq_type = IA_CSS_IRQ_TYPE_EDGE;
1617 
1618 	/*Set the defaults to the output */
1619 	*css = default_css;
1620 }
1621 
1622 bool
1623 ia_css_check_firmware_version(const struct ia_css_fw  *fw)
1624 {
1625 	bool retval = false;
1626 
1627 	if (fw) {
1628 		retval = sh_css_check_firmware_version(fw->data);
1629 	}
1630 	return retval;
1631 }
1632 
1633 enum ia_css_err
1634 ia_css_load_firmware(const struct ia_css_env *env,
1635 		     const struct ia_css_fw  *fw) {
1636 	enum ia_css_err err;
1637 
1638 	if (!env)
1639 		return IA_CSS_ERR_INVALID_ARGUMENTS;
1640 	if (!fw)
1641 		return IA_CSS_ERR_INVALID_ARGUMENTS;
1642 
1643 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_load_firmware() enter\n");
1644 
1645 	/* make sure we initialize my_css */
1646 	if (my_css.flush != env->cpu_mem_env.flush)
1647 	{
1648 		ia_css_reset_defaults(&my_css);
1649 		my_css.flush = env->cpu_mem_env.flush;
1650 	}
1651 
1652 	ia_css_unload_firmware(); /* in case we are called twice */
1653 	err = sh_css_load_firmware(fw->data, fw->bytes);
1654 	if (err == IA_CSS_SUCCESS)
1655 	{
1656 		err = ia_css_binary_init_infos();
1657 		if (err == IA_CSS_SUCCESS)
1658 			fw_explicitly_loaded = true;
1659 	}
1660 
1661 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_load_firmware() leave\n");
1662 	return err;
1663 }
1664 
1665 enum ia_css_err
1666 ia_css_init(const struct ia_css_env *env,
1667 	    const struct ia_css_fw  *fw,
1668 	    u32                 mmu_l1_base,
1669 	    enum ia_css_irq_type     irq_type) {
1670 	enum ia_css_err err;
1671 	ia_css_spctrl_cfg spctrl_cfg;
1672 
1673 	void (*flush_func)(struct ia_css_acc_fw *fw);
1674 	hrt_data select, enable;
1675 
1676 	/*
1677 	 * The C99 standard does not specify the exact object representation of structs;
1678 	 * the representation is compiler dependent.
1679 	 *
1680 	 * The structs that are communicated between host and SP/ISP should have the
1681 	 * exact same object representation. The compiler that is used to compile the
1682 	 * firmware is hivecc.
1683 	 *
1684 	 * To check if a different compiler, used to compile a host application, uses
1685 	 * another object representation, macros are defined specifying the size of
1686 	 * the structs as expected by the firmware.
1687 	 *
1688 	 * A host application shall verify that a sizeof( ) of the struct is equal to
1689 	 * the SIZE_OF_XXX macro of the corresponding struct. If they are not
1690 	 * equal, functionality will break.
1691 	 */
1692 	/* Check struct sh_css_ddr_address_map */
1693 	COMPILATION_ERROR_IF(sizeof(struct sh_css_ddr_address_map)		!= SIZE_OF_SH_CSS_DDR_ADDRESS_MAP_STRUCT);
1694 	/* Check struct host_sp_queues */
1695 	COMPILATION_ERROR_IF(sizeof(struct host_sp_queues)			!= SIZE_OF_HOST_SP_QUEUES_STRUCT);
1696 	COMPILATION_ERROR_IF(sizeof(struct ia_css_circbuf_desc_s)		!= SIZE_OF_IA_CSS_CIRCBUF_DESC_S_STRUCT);
1697 	COMPILATION_ERROR_IF(sizeof(struct ia_css_circbuf_elem_s)		!= SIZE_OF_IA_CSS_CIRCBUF_ELEM_S_STRUCT);
1698 
1699 	/* Check struct host_sp_communication */
1700 	COMPILATION_ERROR_IF(sizeof(struct host_sp_communication)		!= SIZE_OF_HOST_SP_COMMUNICATION_STRUCT);
1701 	COMPILATION_ERROR_IF(sizeof(struct sh_css_event_irq_mask)		!= SIZE_OF_SH_CSS_EVENT_IRQ_MASK_STRUCT);
1702 
1703 	/* Check struct sh_css_hmm_buffer */
1704 	COMPILATION_ERROR_IF(sizeof(struct sh_css_hmm_buffer)			!= SIZE_OF_SH_CSS_HMM_BUFFER_STRUCT);
1705 	COMPILATION_ERROR_IF(sizeof(struct ia_css_isp_3a_statistics)		!= SIZE_OF_IA_CSS_ISP_3A_STATISTICS_STRUCT);
1706 	COMPILATION_ERROR_IF(sizeof(struct ia_css_isp_dvs_statistics)		!= SIZE_OF_IA_CSS_ISP_DVS_STATISTICS_STRUCT);
1707 	COMPILATION_ERROR_IF(sizeof(struct ia_css_metadata)			!= SIZE_OF_IA_CSS_METADATA_STRUCT);
1708 
1709 	/* Check struct ia_css_init_dmem_cfg */
1710 	COMPILATION_ERROR_IF(sizeof(struct ia_css_sp_init_dmem_cfg)		!= SIZE_OF_IA_CSS_SP_INIT_DMEM_CFG_STRUCT);
1711 
1712 	if (!fw && !fw_explicitly_loaded)
1713 		return IA_CSS_ERR_INVALID_ARGUMENTS;
1714 	if (!env)
1715 		return IA_CSS_ERR_INVALID_ARGUMENTS;
1716 
1717 	sh_css_printf = env->print_env.debug_print;
1718 
1719 	IA_CSS_ENTER("void");
1720 
1721 	flush_func     = env->cpu_mem_env.flush;
1722 
1723 	pipe_global_init();
1724 	ia_css_pipeline_init();
1725 	ia_css_queue_map_init();
1726 
1727 	ia_css_device_access_init(&env->hw_access_env);
1728 
1729 	select = gpio_reg_load(GPIO0_ID, _gpio_block_reg_do_select)
1730 	& (~GPIO_FLASH_PIN_MASK);
1731 	enable = gpio_reg_load(GPIO0_ID, _gpio_block_reg_do_e)
1732 	| GPIO_FLASH_PIN_MASK;
1733 	sh_css_mmu_set_page_table_base_index(mmu_l1_base);
1734 
1735 	my_css_save.mmu_base = mmu_l1_base;
1736 
1737 	ia_css_reset_defaults(&my_css);
1738 
1739 	my_css_save.driver_env = *env;
1740 	my_css.flush     = flush_func;
1741 
1742 	err = ia_css_rmgr_init();
1743 	if (err != IA_CSS_SUCCESS)
1744 	{
1745 		IA_CSS_LEAVE_ERR(err);
1746 		return err;
1747 	}
1748 
1749 	IA_CSS_LOG("init: %d", my_css_save_initialized);
1750 
1751 	if (!my_css_save_initialized)
1752 	{
1753 		my_css_save_initialized = true;
1754 		my_css_save.mode = sh_css_mode_working;
1755 		memset(my_css_save.stream_seeds, 0,
1756 		       sizeof(struct sh_css_stream_seed) * MAX_ACTIVE_STREAMS);
1757 		IA_CSS_LOG("init: %d mode=%d", my_css_save_initialized, my_css_save.mode);
1758 	}
1759 
1760 	mipi_init();
1761 
1762 #ifndef ISP2401
1763 	/* In case this has been programmed already, update internal
1764 	   data structure ... DEPRECATED */
1765 	my_css.page_table_base_index = mmu_get_page_table_base_index(MMU0_ID);
1766 
1767 #endif
1768 	my_css.irq_type = irq_type;
1769 
1770 	my_css_save.irq_type = irq_type;
1771 
1772 	enable_interrupts(my_css.irq_type);
1773 
1774 	/* configure GPIO to output mode */
1775 	gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_select, select);
1776 	gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_e, enable);
1777 	gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_0, 0);
1778 
1779 	err = ia_css_refcount_init(REFCOUNT_SIZE);
1780 	if (err != IA_CSS_SUCCESS)
1781 	{
1782 		IA_CSS_LEAVE_ERR(err);
1783 		return err;
1784 	}
1785 	err = sh_css_params_init();
1786 	if (err != IA_CSS_SUCCESS)
1787 	{
1788 		IA_CSS_LEAVE_ERR(err);
1789 		return err;
1790 	}
1791 	if (fw)
1792 	{
1793 		ia_css_unload_firmware(); /* in case we already had firmware loaded */
1794 		err = sh_css_load_firmware(fw->data, fw->bytes);
1795 		if (err != IA_CSS_SUCCESS) {
1796 			IA_CSS_LEAVE_ERR(err);
1797 			return err;
1798 		}
1799 		err = ia_css_binary_init_infos();
1800 		if (err != IA_CSS_SUCCESS) {
1801 			IA_CSS_LEAVE_ERR(err);
1802 			return err;
1803 		}
1804 		fw_explicitly_loaded = false;
1805 #ifndef ISP2401
1806 		my_css_save.loaded_fw = (struct ia_css_fw *)fw;
1807 #endif
1808 	}
1809 	if (!sh_css_setup_spctrl_config(&sh_css_sp_fw, SP_PROG_NAME, &spctrl_cfg))
1810 		return IA_CSS_ERR_INTERNAL_ERROR;
1811 
1812 	err = ia_css_spctrl_load_fw(SP0_ID, &spctrl_cfg);
1813 	if (err != IA_CSS_SUCCESS)
1814 	{
1815 		IA_CSS_LEAVE_ERR(err);
1816 		return err;
1817 	}
1818 
1819 #if WITH_PC_MONITORING
1820 	if (!thread_alive)
1821 	{
1822 		thread_alive++;
1823 		sh_css_print("PC_MONITORING: %s() -- create thread DISABLED\n",
1824 			     __func__);
1825 		spying_thread_create();
1826 	}
1827 #endif
1828 	if (!sh_css_hrt_system_is_idle())
1829 	{
1830 		IA_CSS_LEAVE_ERR(IA_CSS_ERR_SYSTEM_NOT_IDLE);
1831 		return IA_CSS_ERR_SYSTEM_NOT_IDLE;
1832 	}
1833 	/* can be called here, queuing works, but:
1834 	   - when sp is started later, it will wipe queued items
1835 	   so for now we leave it for later and make sure
1836 	   updates are not called to frequently.
1837 	sh_css_init_buffer_queues();
1838 	*/
1839 
1840 #if defined(HAS_INPUT_SYSTEM_VERSION_2) && defined(HAS_INPUT_SYSTEM_VERSION_2401)
1841 #if	defined(USE_INPUT_SYSTEM_VERSION_2)
1842 	gp_device_reg_store(GP_DEVICE0_ID, _REG_GP_SWITCH_ISYS2401_ADDR, 0);
1843 #elif defined(USE_INPUT_SYSTEM_VERSION_2401)
1844 	gp_device_reg_store(GP_DEVICE0_ID, _REG_GP_SWITCH_ISYS2401_ADDR, 1);
1845 #endif
1846 #endif
1847 
1848 #if !defined(HAS_NO_INPUT_SYSTEM)
1849 	dma_set_max_burst_size(DMA0_ID, HIVE_DMA_BUS_DDR_CONN,
1850 			       ISP_DMA_MAX_BURST_LENGTH);
1851 
1852 	if (ia_css_isys_init() != INPUT_SYSTEM_ERR_NO_ERROR)
1853 		err = IA_CSS_ERR_INVALID_ARGUMENTS;
1854 #endif
1855 
1856 	sh_css_params_map_and_store_default_gdc_lut();
1857 
1858 	IA_CSS_LEAVE_ERR(err);
1859 	return err;
1860 }
1861 
1862 enum ia_css_err ia_css_suspend(void)
1863 {
1864 	int i;
1865 
1866 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_suspend() enter\n");
1867 	my_css_save.mode = sh_css_mode_suspend;
1868 	for (i = 0; i < MAX_ACTIVE_STREAMS; i++)
1869 		if (my_css_save.stream_seeds[i].stream) {
1870 			ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "==*> unloading seed %d (%p)\n", i,
1871 					    my_css_save.stream_seeds[i].stream);
1872 			ia_css_stream_unload(my_css_save.stream_seeds[i].stream);
1873 		}
1874 	my_css_save.mode = sh_css_mode_working;
1875 	ia_css_stop_sp();
1876 	ia_css_uninit();
1877 	for (i = 0; i < MAX_ACTIVE_STREAMS; i++)
1878 		ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "==*> after 1: seed %d (%p)\n", i,
1879 				    my_css_save.stream_seeds[i].stream);
1880 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_suspend() leave\n");
1881 	return IA_CSS_SUCCESS;
1882 }
1883 
1884 enum ia_css_err
1885 ia_css_resume(void) {
1886 	int i, j;
1887 	enum ia_css_err err;
1888 
1889 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_resume() enter: void\n");
1890 
1891 	err = ia_css_init(&my_css_save.driver_env, my_css_save.loaded_fw, my_css_save.mmu_base, my_css_save.irq_type);
1892 	if (err != IA_CSS_SUCCESS)
1893 		return err;
1894 	err = ia_css_start_sp();
1895 	if (err != IA_CSS_SUCCESS)
1896 		return err;
1897 	my_css_save.mode = sh_css_mode_resume;
1898 	for (i = 0; i < MAX_ACTIVE_STREAMS; i++)
1899 	{
1900 		ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "==*> seed stream %p\n",
1901 				    my_css_save.stream_seeds[i].stream);
1902 		if (my_css_save.stream_seeds[i].stream) {
1903 			ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "==*> loading seed %d\n", i);
1904 			err = ia_css_stream_load(my_css_save.stream_seeds[i].stream);
1905 			if (err != IA_CSS_SUCCESS) {
1906 				if (i)
1907 					for (j = 0; j < i; j++)
1908 						ia_css_stream_unload(my_css_save.stream_seeds[j].stream);
1909 				return err;
1910 			}
1911 			err = ia_css_stream_start(my_css_save.stream_seeds[i].stream);
1912 			if (err != IA_CSS_SUCCESS) {
1913 				for (j = 0; j <= i; j++) {
1914 					ia_css_stream_stop(my_css_save.stream_seeds[j].stream);
1915 					ia_css_stream_unload(my_css_save.stream_seeds[j].stream);
1916 				}
1917 				return err;
1918 			}
1919 			*my_css_save.stream_seeds[i].orig_stream = my_css_save.stream_seeds[i].stream;
1920 			for (j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++)
1921 				*my_css_save.stream_seeds[i].orig_pipes[j] =
1922 				    my_css_save.stream_seeds[i].pipes[j];
1923 		}
1924 	}
1925 	my_css_save.mode = sh_css_mode_working;
1926 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_resume() leave: return_void\n");
1927 	return IA_CSS_SUCCESS;
1928 }
1929 
1930 enum ia_css_err
1931 ia_css_enable_isys_event_queue(bool enable) {
1932 	if (sh_css_sp_is_running())
1933 		return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
1934 	sh_css_sp_enable_isys_event_queue(enable);
1935 	return IA_CSS_SUCCESS;
1936 }
1937 
1938 void *sh_css_malloc(size_t size)
1939 {
1940 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_malloc() enter: size=%zu\n",
1941 			    size);
1942 	/* FIXME: This first test can probably go away */
1943 	if (size == 0)
1944 		return NULL;
1945 	if (size > PAGE_SIZE)
1946 		return vmalloc(size);
1947 	return kmalloc(size, GFP_KERNEL);
1948 }
1949 
1950 void *sh_css_calloc(size_t N, size_t size)
1951 {
1952 	void *p;
1953 
1954 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1955 			    "sh_css_calloc() enter: N=%zu, size=%zu\n", N, size);
1956 
1957 	/* FIXME: this test can probably go away */
1958 	if (size > 0) {
1959 		p = sh_css_malloc(N * size);
1960 		if (p)
1961 			memset(p, 0, size);
1962 		return p;
1963 	}
1964 	return NULL;
1965 }
1966 
1967 void sh_css_free(void *ptr)
1968 {
1969 	if (is_vmalloc_addr(ptr))
1970 		vfree(ptr);
1971 	else
1972 		kfree(ptr);
1973 }
1974 
1975 /* For Acceleration API: Flush FW (shared buffer pointer) arguments */
1976 void
1977 sh_css_flush(struct ia_css_acc_fw *fw)
1978 {
1979 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_flush() enter:\n");
1980 	if ((fw) && (my_css.flush))
1981 		my_css.flush(fw);
1982 }
1983 
1984 /* Mapping sp threads. Currently, this is done when a stream is created and
1985  * pipelines are ready to be converted to sp pipelines. Be careful if you are
1986  * doing it from stream_create since we could run out of sp threads due to
1987  * allocation on inactive pipelines. */
1988 static enum ia_css_err
1989 map_sp_threads(struct ia_css_stream *stream, bool map) {
1990 	struct ia_css_pipe *main_pipe = NULL;
1991 	struct ia_css_pipe *copy_pipe = NULL;
1992 	struct ia_css_pipe *capture_pipe = NULL;
1993 	struct ia_css_pipe *acc_pipe = NULL;
1994 	enum ia_css_err err = IA_CSS_SUCCESS;
1995 	enum ia_css_pipe_id pipe_id;
1996 
1997 	assert(stream);
1998 	IA_CSS_ENTER_PRIVATE("stream = %p, map = %s",
1999 			     stream, map ? "true" : "false");
2000 
2001 	if (!stream)
2002 	{
2003 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
2004 		return IA_CSS_ERR_INVALID_ARGUMENTS;
2005 	}
2006 
2007 	main_pipe = stream->last_pipe;
2008 	pipe_id	= main_pipe->mode;
2009 
2010 	ia_css_pipeline_map(main_pipe->pipe_num, map);
2011 
2012 	switch (pipe_id)
2013 	{
2014 	case IA_CSS_PIPE_ID_PREVIEW:
2015 		copy_pipe    = main_pipe->pipe_settings.preview.copy_pipe;
2016 		capture_pipe = main_pipe->pipe_settings.preview.capture_pipe;
2017 		acc_pipe     = main_pipe->pipe_settings.preview.acc_pipe;
2018 		break;
2019 
2020 	case IA_CSS_PIPE_ID_VIDEO:
2021 		copy_pipe    = main_pipe->pipe_settings.video.copy_pipe;
2022 		capture_pipe = main_pipe->pipe_settings.video.capture_pipe;
2023 		break;
2024 
2025 	case IA_CSS_PIPE_ID_CAPTURE:
2026 	case IA_CSS_PIPE_ID_ACC:
2027 	default:
2028 		break;
2029 	}
2030 
2031 	if (acc_pipe)
2032 	{
2033 		ia_css_pipeline_map(acc_pipe->pipe_num, map);
2034 	}
2035 
2036 	if (capture_pipe)
2037 	{
2038 		ia_css_pipeline_map(capture_pipe->pipe_num, map);
2039 	}
2040 
2041 	/* Firmware expects copy pipe to be the last pipe mapped. (if needed) */
2042 	if (copy_pipe)
2043 	{
2044 		ia_css_pipeline_map(copy_pipe->pipe_num, map);
2045 	}
2046 	/* DH regular multi pipe - not continuous mode: map the next pipes too */
2047 	if (!stream->config.continuous)
2048 	{
2049 		int i;
2050 
2051 		for (i = 1; i < stream->num_pipes; i++)
2052 			ia_css_pipeline_map(stream->pipes[i]->pipe_num, map);
2053 	}
2054 
2055 	IA_CSS_LEAVE_ERR_PRIVATE(err);
2056 	return err;
2057 }
2058 
2059 /* creates a host pipeline skeleton for all pipes in a stream. Called during
2060  * stream_create. */
2061 static enum ia_css_err
2062 create_host_pipeline_structure(struct ia_css_stream *stream) {
2063 	struct ia_css_pipe *copy_pipe = NULL, *capture_pipe = NULL;
2064 	struct ia_css_pipe *acc_pipe = NULL;
2065 	enum ia_css_pipe_id pipe_id;
2066 	struct ia_css_pipe *main_pipe = NULL;
2067 	enum ia_css_err err = IA_CSS_SUCCESS;
2068 	unsigned int copy_pipe_delay = 0,
2069 	capture_pipe_delay = 0;
2070 
2071 	assert(stream);
2072 	IA_CSS_ENTER_PRIVATE("stream = %p", stream);
2073 
2074 	if (!stream)
2075 	{
2076 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
2077 		return IA_CSS_ERR_INVALID_ARGUMENTS;
2078 	}
2079 
2080 	main_pipe	= stream->last_pipe;
2081 	assert(main_pipe);
2082 	if (!main_pipe)
2083 	{
2084 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
2085 		return IA_CSS_ERR_INVALID_ARGUMENTS;
2086 	}
2087 
2088 	pipe_id	= main_pipe->mode;
2089 
2090 	switch (pipe_id)
2091 	{
2092 	case IA_CSS_PIPE_ID_PREVIEW:
2093 		copy_pipe    = main_pipe->pipe_settings.preview.copy_pipe;
2094 		copy_pipe_delay = main_pipe->dvs_frame_delay;
2095 		capture_pipe = main_pipe->pipe_settings.preview.capture_pipe;
2096 		capture_pipe_delay = IA_CSS_FRAME_DELAY_0;
2097 		acc_pipe     = main_pipe->pipe_settings.preview.acc_pipe;
2098 		err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode,
2099 					     main_pipe->pipe_num, main_pipe->dvs_frame_delay);
2100 		break;
2101 
2102 	case IA_CSS_PIPE_ID_VIDEO:
2103 		copy_pipe    = main_pipe->pipe_settings.video.copy_pipe;
2104 		copy_pipe_delay = main_pipe->dvs_frame_delay;
2105 		capture_pipe = main_pipe->pipe_settings.video.capture_pipe;
2106 		capture_pipe_delay = IA_CSS_FRAME_DELAY_0;
2107 		err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode,
2108 					     main_pipe->pipe_num, main_pipe->dvs_frame_delay);
2109 		break;
2110 
2111 	case IA_CSS_PIPE_ID_CAPTURE:
2112 		capture_pipe = main_pipe;
2113 		capture_pipe_delay = main_pipe->dvs_frame_delay;
2114 		break;
2115 
2116 	case IA_CSS_PIPE_ID_YUVPP:
2117 		err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode,
2118 					     main_pipe->pipe_num, main_pipe->dvs_frame_delay);
2119 		break;
2120 
2121 	case IA_CSS_PIPE_ID_ACC:
2122 		err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode,
2123 					     main_pipe->pipe_num, main_pipe->dvs_frame_delay);
2124 		break;
2125 
2126 	default:
2127 		err = IA_CSS_ERR_INVALID_ARGUMENTS;
2128 	}
2129 
2130 	if ((err == IA_CSS_SUCCESS) && copy_pipe)
2131 	{
2132 		err = ia_css_pipeline_create(&copy_pipe->pipeline,
2133 					     copy_pipe->mode,
2134 					     copy_pipe->pipe_num,
2135 					     copy_pipe_delay);
2136 	}
2137 
2138 	if ((err == IA_CSS_SUCCESS) && capture_pipe)
2139 	{
2140 		err = ia_css_pipeline_create(&capture_pipe->pipeline,
2141 					     capture_pipe->mode,
2142 					     capture_pipe->pipe_num,
2143 					     capture_pipe_delay);
2144 	}
2145 
2146 	if ((err == IA_CSS_SUCCESS) && acc_pipe)
2147 	{
2148 		err = ia_css_pipeline_create(&acc_pipe->pipeline, acc_pipe->mode,
2149 					     acc_pipe->pipe_num, main_pipe->dvs_frame_delay);
2150 	}
2151 
2152 	/* DH regular multi pipe - not continuous mode: create the next pipelines too */
2153 	if (!stream->config.continuous)
2154 	{
2155 		int i;
2156 
2157 		for (i = 1; i < stream->num_pipes && IA_CSS_SUCCESS == err; i++) {
2158 			main_pipe = stream->pipes[i];
2159 			err = ia_css_pipeline_create(&main_pipe->pipeline,
2160 						     main_pipe->mode,
2161 						     main_pipe->pipe_num,
2162 						     main_pipe->dvs_frame_delay);
2163 		}
2164 	}
2165 
2166 	IA_CSS_LEAVE_ERR_PRIVATE(err);
2167 	return err;
2168 }
2169 
2170 /* creates a host pipeline for all pipes in a stream. Called during
2171  * stream_start. */
2172 static enum ia_css_err
2173 create_host_pipeline(struct ia_css_stream *stream) {
2174 	struct ia_css_pipe *copy_pipe = NULL, *capture_pipe = NULL;
2175 	struct ia_css_pipe *acc_pipe = NULL;
2176 	enum ia_css_pipe_id pipe_id;
2177 	struct ia_css_pipe *main_pipe = NULL;
2178 	enum ia_css_err err = IA_CSS_SUCCESS;
2179 	unsigned int max_input_width = 0;
2180 
2181 	IA_CSS_ENTER_PRIVATE("stream = %p", stream);
2182 	if (!stream)
2183 	{
2184 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
2185 		return IA_CSS_ERR_INVALID_ARGUMENTS;
2186 	}
2187 
2188 	main_pipe	= stream->last_pipe;
2189 	pipe_id	= main_pipe->mode;
2190 
2191 	/* No continuous frame allocation for capture pipe. It uses the
2192 	 * "main" pipe's frames. */
2193 	if ((pipe_id == IA_CSS_PIPE_ID_PREVIEW) ||
2194 	    (pipe_id == IA_CSS_PIPE_ID_VIDEO))
2195 	{
2196 		/* About pipe_id == IA_CSS_PIPE_ID_PREVIEW && stream->config.mode != IA_CSS_INPUT_MODE_MEMORY:
2197 		 * The original condition pipe_id == IA_CSS_PIPE_ID_PREVIEW is too strong. E.g. in SkyCam (with memory
2198 		 * based input frames) there is no continuous mode and thus no need for allocated continuous frames
2199 		 * This is not only for SkyCam but for all preview cases that use DDR based input frames. For this
2200 		 * reason the stream->config.mode != IA_CSS_INPUT_MODE_MEMORY has beed added.
2201 		 */
2202 		if (stream->config.continuous ||
2203 		    (pipe_id == IA_CSS_PIPE_ID_PREVIEW &&
2204 		     stream->config.mode != IA_CSS_INPUT_MODE_MEMORY)) {
2205 			err = alloc_continuous_frames(main_pipe, true);
2206 			if (err != IA_CSS_SUCCESS)
2207 				goto ERR;
2208 		}
2209 	}
2210 
2211 #if defined(USE_INPUT_SYSTEM_VERSION_2)
2212 	/* old isys: need to allocate_mipi_frames() even in IA_CSS_PIPE_MODE_COPY */
2213 	if (pipe_id != IA_CSS_PIPE_ID_ACC)
2214 	{
2215 		err = allocate_mipi_frames(main_pipe, &stream->info);
2216 		if (err != IA_CSS_SUCCESS)
2217 			goto ERR;
2218 	}
2219 #elif defined(USE_INPUT_SYSTEM_VERSION_2401)
2220 	if ((pipe_id != IA_CSS_PIPE_ID_ACC) &&
2221 	    (main_pipe->config.mode != IA_CSS_PIPE_MODE_COPY))
2222 	{
2223 		err = allocate_mipi_frames(main_pipe, &stream->info);
2224 		if (err != IA_CSS_SUCCESS)
2225 			goto ERR;
2226 	}
2227 #endif
2228 
2229 	switch (pipe_id)
2230 	{
2231 	case IA_CSS_PIPE_ID_PREVIEW:
2232 		copy_pipe    = main_pipe->pipe_settings.preview.copy_pipe;
2233 		capture_pipe = main_pipe->pipe_settings.preview.capture_pipe;
2234 		acc_pipe     = main_pipe->pipe_settings.preview.acc_pipe;
2235 		max_input_width =
2236 		    main_pipe->pipe_settings.preview.preview_binary.info->sp.input.max_width;
2237 
2238 		err = create_host_preview_pipeline(main_pipe);
2239 		if (err != IA_CSS_SUCCESS)
2240 			goto ERR;
2241 
2242 		break;
2243 
2244 	case IA_CSS_PIPE_ID_VIDEO:
2245 		copy_pipe    = main_pipe->pipe_settings.video.copy_pipe;
2246 		capture_pipe = main_pipe->pipe_settings.video.capture_pipe;
2247 		max_input_width =
2248 		    main_pipe->pipe_settings.video.video_binary.info->sp.input.max_width;
2249 
2250 		err = create_host_video_pipeline(main_pipe);
2251 		if (err != IA_CSS_SUCCESS)
2252 			goto ERR;
2253 
2254 		break;
2255 
2256 	case IA_CSS_PIPE_ID_CAPTURE:
2257 		capture_pipe = main_pipe;
2258 
2259 		break;
2260 
2261 	case IA_CSS_PIPE_ID_YUVPP:
2262 		err = create_host_yuvpp_pipeline(main_pipe);
2263 		if (err != IA_CSS_SUCCESS)
2264 			goto ERR;
2265 
2266 		break;
2267 
2268 	case IA_CSS_PIPE_ID_ACC:
2269 		err = create_host_acc_pipeline(main_pipe);
2270 		if (err != IA_CSS_SUCCESS)
2271 			goto ERR;
2272 
2273 		break;
2274 	default:
2275 		err = IA_CSS_ERR_INVALID_ARGUMENTS;
2276 	}
2277 	if (err != IA_CSS_SUCCESS)
2278 		goto ERR;
2279 
2280 	if (copy_pipe)
2281 	{
2282 		err = create_host_copy_pipeline(copy_pipe, max_input_width,
2283 						main_pipe->continuous_frames[0]);
2284 		if (err != IA_CSS_SUCCESS)
2285 			goto ERR;
2286 	}
2287 
2288 	if (capture_pipe)
2289 	{
2290 		err = create_host_capture_pipeline(capture_pipe);
2291 		if (err != IA_CSS_SUCCESS)
2292 			goto ERR;
2293 	}
2294 
2295 	if (acc_pipe)
2296 	{
2297 		err = create_host_acc_pipeline(acc_pipe);
2298 		if (err != IA_CSS_SUCCESS)
2299 			goto ERR;
2300 	}
2301 
2302 	/* DH regular multi pipe - not continuous mode: create the next pipelines too */
2303 	if (!stream->config.continuous)
2304 	{
2305 		int i;
2306 
2307 		for (i = 1; i < stream->num_pipes && IA_CSS_SUCCESS == err; i++) {
2308 			switch (stream->pipes[i]->mode) {
2309 			case IA_CSS_PIPE_ID_PREVIEW:
2310 				err = create_host_preview_pipeline(stream->pipes[i]);
2311 				break;
2312 			case IA_CSS_PIPE_ID_VIDEO:
2313 				err = create_host_video_pipeline(stream->pipes[i]);
2314 				break;
2315 			case IA_CSS_PIPE_ID_CAPTURE:
2316 				err = create_host_capture_pipeline(stream->pipes[i]);
2317 				break;
2318 			case IA_CSS_PIPE_ID_YUVPP:
2319 				err = create_host_yuvpp_pipeline(stream->pipes[i]);
2320 				break;
2321 			case IA_CSS_PIPE_ID_ACC:
2322 				err = create_host_acc_pipeline(stream->pipes[i]);
2323 				break;
2324 			default:
2325 				err = IA_CSS_ERR_INVALID_ARGUMENTS;
2326 			}
2327 			if (err != IA_CSS_SUCCESS)
2328 				goto ERR;
2329 		}
2330 	}
2331 
2332 ERR:
2333 	IA_CSS_LEAVE_ERR_PRIVATE(err);
2334 	return err;
2335 }
2336 
2337 static enum ia_css_err
2338 init_pipe_defaults(enum ia_css_pipe_mode mode,
2339 		   struct ia_css_pipe *pipe,
2340 		   bool copy_pipe) {
2341 	if (!pipe)
2342 	{
2343 		IA_CSS_ERROR("NULL pipe parameter");
2344 		return IA_CSS_ERR_INVALID_ARGUMENTS;
2345 	}
2346 
2347 	/* Initialize pipe to pre-defined defaults */
2348 	*pipe = IA_CSS_DEFAULT_PIPE;
2349 
2350 	/* TODO: JB should not be needed, but temporary backward reference */
2351 	switch (mode)
2352 	{
2353 	case IA_CSS_PIPE_MODE_PREVIEW:
2354 		pipe->mode = IA_CSS_PIPE_ID_PREVIEW;
2355 		pipe->pipe_settings.preview = IA_CSS_DEFAULT_PREVIEW_SETTINGS;
2356 		break;
2357 	case IA_CSS_PIPE_MODE_CAPTURE:
2358 		if (copy_pipe) {
2359 			pipe->mode = IA_CSS_PIPE_ID_COPY;
2360 		} else {
2361 			pipe->mode = IA_CSS_PIPE_ID_CAPTURE;
2362 		}
2363 		pipe->pipe_settings.capture = IA_CSS_DEFAULT_CAPTURE_SETTINGS;
2364 		break;
2365 	case IA_CSS_PIPE_MODE_VIDEO:
2366 		pipe->mode = IA_CSS_PIPE_ID_VIDEO;
2367 		pipe->pipe_settings.video = IA_CSS_DEFAULT_VIDEO_SETTINGS;
2368 		break;
2369 	case IA_CSS_PIPE_MODE_ACC:
2370 		pipe->mode = IA_CSS_PIPE_ID_ACC;
2371 		break;
2372 	case IA_CSS_PIPE_MODE_COPY:
2373 		pipe->mode = IA_CSS_PIPE_ID_CAPTURE;
2374 		break;
2375 	case IA_CSS_PIPE_MODE_YUVPP:
2376 		pipe->mode = IA_CSS_PIPE_ID_YUVPP;
2377 		pipe->pipe_settings.yuvpp = IA_CSS_DEFAULT_YUVPP_SETTINGS;
2378 		break;
2379 	default:
2380 		return IA_CSS_ERR_INVALID_ARGUMENTS;
2381 	}
2382 
2383 	return IA_CSS_SUCCESS;
2384 }
2385 
2386 static void
2387 pipe_global_init(void)
2388 {
2389 	u8 i;
2390 
2391 	my_css.pipe_counter = 0;
2392 	for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) {
2393 		my_css.all_pipes[i] = NULL;
2394 	}
2395 }
2396 
2397 static enum ia_css_err
2398 pipe_generate_pipe_num(const struct ia_css_pipe *pipe,
2399 		       unsigned int *pipe_number) {
2400 	const u8 INVALID_PIPE_NUM = (uint8_t)~(0);
2401 	u8 pipe_num = INVALID_PIPE_NUM;
2402 	u8 i;
2403 
2404 	if (!pipe)
2405 	{
2406 		IA_CSS_ERROR("NULL pipe parameter");
2407 		return IA_CSS_ERR_INVALID_ARGUMENTS;
2408 	}
2409 
2410 	/* Assign a new pipe_num .... search for empty place */
2411 	for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++)
2412 	{
2413 		if (!my_css.all_pipes[i]) {
2414 			/*position is reserved */
2415 			my_css.all_pipes[i] = (struct ia_css_pipe *)pipe;
2416 			pipe_num = i;
2417 			break;
2418 		}
2419 	}
2420 	if (pipe_num == INVALID_PIPE_NUM)
2421 	{
2422 		/* Max number of pipes already allocated */
2423 		IA_CSS_ERROR("Max number of pipes already created");
2424 		return IA_CSS_ERR_RESOURCE_EXHAUSTED;
2425 	}
2426 
2427 	my_css.pipe_counter++;
2428 
2429 	IA_CSS_LOG("pipe_num (%d)", pipe_num);
2430 
2431 	*pipe_number = pipe_num;
2432 	return IA_CSS_SUCCESS;
2433 }
2434 
2435 static void
2436 pipe_release_pipe_num(unsigned int pipe_num)
2437 {
2438 	my_css.all_pipes[pipe_num] = NULL;
2439 	my_css.pipe_counter--;
2440 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2441 			    "pipe_release_pipe_num (%d)\n", pipe_num);
2442 }
2443 
2444 static enum ia_css_err
2445 create_pipe(enum ia_css_pipe_mode mode,
2446 	    struct ia_css_pipe **pipe,
2447 	    bool copy_pipe) {
2448 	enum ia_css_err err = IA_CSS_SUCCESS;
2449 	struct ia_css_pipe *me;
2450 
2451 	if (!pipe)
2452 	{
2453 		IA_CSS_ERROR("NULL pipe parameter");
2454 		return IA_CSS_ERR_INVALID_ARGUMENTS;
2455 	}
2456 
2457 	me = kmalloc(sizeof(*me), GFP_KERNEL);
2458 	if (!me)
2459 		return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
2460 
2461 	err = init_pipe_defaults(mode, me, copy_pipe);
2462 	if (err != IA_CSS_SUCCESS)
2463 	{
2464 		kfree(me);
2465 		return err;
2466 	}
2467 
2468 	err = pipe_generate_pipe_num(me, &me->pipe_num);
2469 	if (err != IA_CSS_SUCCESS)
2470 	{
2471 		kfree(me);
2472 		return err;
2473 	}
2474 
2475 	*pipe = me;
2476 	return IA_CSS_SUCCESS;
2477 }
2478 
2479 struct ia_css_pipe *
2480 find_pipe_by_num(uint32_t pipe_num)
2481 {
2482 	unsigned int i;
2483 
2484 	for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) {
2485 		if (my_css.all_pipes[i] &&
2486 		    ia_css_pipe_get_pipe_num(my_css.all_pipes[i]) == pipe_num) {
2487 			return my_css.all_pipes[i];
2488 		}
2489 	}
2490 	return NULL;
2491 }
2492 
2493 static void sh_css_pipe_free_acc_binaries(
2494     struct ia_css_pipe *pipe)
2495 {
2496 	struct ia_css_pipeline *pipeline;
2497 	struct ia_css_pipeline_stage *stage;
2498 
2499 	assert(pipe);
2500 	if (!pipe) {
2501 		IA_CSS_ERROR("NULL input pointer");
2502 		return;
2503 	}
2504 	pipeline = &pipe->pipeline;
2505 
2506 	/* loop through the stages and unload them */
2507 	for (stage = pipeline->stages; stage; stage = stage->next) {
2508 		struct ia_css_fw_info *firmware = (struct ia_css_fw_info *)
2509 						  stage->firmware;
2510 		if (firmware)
2511 			ia_css_pipe_unload_extension(pipe, firmware);
2512 	}
2513 }
2514 
2515 enum ia_css_err
2516 ia_css_pipe_destroy(struct ia_css_pipe *pipe) {
2517 	enum ia_css_err err = IA_CSS_SUCCESS;
2518 
2519 	IA_CSS_ENTER("pipe = %p", pipe);
2520 
2521 	if (!pipe)
2522 	{
2523 		IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
2524 		return IA_CSS_ERR_INVALID_ARGUMENTS;
2525 	}
2526 
2527 	if (pipe->stream)
2528 	{
2529 		IA_CSS_LOG("ia_css_stream_destroy not called!");
2530 		IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
2531 		return IA_CSS_ERR_INVALID_ARGUMENTS;
2532 	}
2533 
2534 	switch (pipe->config.mode)
2535 	{
2536 	case IA_CSS_PIPE_MODE_PREVIEW:
2537 		/* need to take into account that this function is also called
2538 		   on the internal copy pipe */
2539 		if (pipe->mode == IA_CSS_PIPE_ID_PREVIEW) {
2540 			ia_css_frame_free_multiple(NUM_CONTINUOUS_FRAMES,
2541 						   pipe->continuous_frames);
2542 			ia_css_metadata_free_multiple(NUM_CONTINUOUS_FRAMES,
2543 						      pipe->cont_md_buffers);
2544 			if (pipe->pipe_settings.preview.copy_pipe) {
2545 				err = ia_css_pipe_destroy(pipe->pipe_settings.preview.copy_pipe);
2546 				ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2547 						    "ia_css_pipe_destroy(): destroyed internal copy pipe err=%d\n",
2548 						    err);
2549 			}
2550 		}
2551 		break;
2552 	case IA_CSS_PIPE_MODE_VIDEO:
2553 		if (pipe->mode == IA_CSS_PIPE_ID_VIDEO) {
2554 			ia_css_frame_free_multiple(NUM_CONTINUOUS_FRAMES,
2555 						   pipe->continuous_frames);
2556 			ia_css_metadata_free_multiple(NUM_CONTINUOUS_FRAMES,
2557 						      pipe->cont_md_buffers);
2558 			if (pipe->pipe_settings.video.copy_pipe) {
2559 				err = ia_css_pipe_destroy(pipe->pipe_settings.video.copy_pipe);
2560 				ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2561 						    "ia_css_pipe_destroy(): destroyed internal copy pipe err=%d\n",
2562 						    err);
2563 			}
2564 		}
2565 #ifndef ISP2401
2566 		ia_css_frame_free_multiple(NUM_TNR_FRAMES,
2567 					   pipe->pipe_settings.video.tnr_frames);
2568 #else
2569 		ia_css_frame_free_multiple(NUM_TNR_FRAMES,
2570 					   pipe->pipe_settings.video.tnr_frames);
2571 #endif
2572 		ia_css_frame_free_multiple(MAX_NUM_VIDEO_DELAY_FRAMES,
2573 					   pipe->pipe_settings.video.delay_frames);
2574 		break;
2575 	case IA_CSS_PIPE_MODE_CAPTURE:
2576 		ia_css_frame_free_multiple(MAX_NUM_VIDEO_DELAY_FRAMES,
2577 					   pipe->pipe_settings.capture.delay_frames);
2578 		break;
2579 	case IA_CSS_PIPE_MODE_ACC:
2580 		sh_css_pipe_free_acc_binaries(pipe);
2581 		break;
2582 	case IA_CSS_PIPE_MODE_COPY:
2583 		break;
2584 	case IA_CSS_PIPE_MODE_YUVPP:
2585 		break;
2586 	}
2587 
2588 	sh_css_params_free_gdc_lut(pipe->scaler_pp_lut);
2589 	pipe->scaler_pp_lut = mmgr_NULL;
2590 
2591 	my_css.active_pipes[ia_css_pipe_get_pipe_num(pipe)] = NULL;
2592 	sh_css_pipe_free_shading_table(pipe);
2593 
2594 	ia_css_pipeline_destroy(&pipe->pipeline);
2595 	pipe_release_pipe_num(ia_css_pipe_get_pipe_num(pipe));
2596 
2597 	/* Temporarily, not every sh_css_pipe has an acc_extension. */
2598 	if (pipe->config.acc_extension)
2599 	{
2600 		ia_css_pipe_unload_extension(pipe, pipe->config.acc_extension);
2601 	}
2602 	kfree(pipe);
2603 	IA_CSS_LEAVE("err = %d", err);
2604 	return err;
2605 }
2606 
2607 void
2608 ia_css_uninit(void)
2609 {
2610 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_uninit() enter: void\n");
2611 #if WITH_PC_MONITORING
2612 	sh_css_print("PC_MONITORING: %s() -- started\n", __func__);
2613 	print_pc_histogram();
2614 #endif
2615 
2616 	sh_css_params_free_default_gdc_lut();
2617 
2618 	/* TODO: JB: implement decent check and handling of freeing mipi frames */
2619 	//assert(ref_count_mipi_allocation == 0); //mipi frames are not freed
2620 	/* cleanup generic data */
2621 	sh_css_params_uninit();
2622 	ia_css_refcount_uninit();
2623 
2624 	ia_css_rmgr_uninit();
2625 
2626 #if !defined(HAS_NO_INPUT_FORMATTER)
2627 	/* needed for reprogramming the inputformatter after power cycle of css */
2628 	ifmtr_set_if_blocking_mode_reset = true;
2629 #endif
2630 
2631 	if (!fw_explicitly_loaded) {
2632 		ia_css_unload_firmware();
2633 	}
2634 	ia_css_spctrl_unload_fw(SP0_ID);
2635 	sh_css_sp_set_sp_running(false);
2636 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
2637 	/* check and free any remaining mipi frames */
2638 	free_mipi_frames(NULL);
2639 #endif
2640 
2641 	sh_css_sp_reset_global_vars();
2642 
2643 #if !defined(HAS_NO_INPUT_SYSTEM)
2644 	ia_css_isys_uninit();
2645 #endif
2646 
2647 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_uninit() leave: return_void\n");
2648 }
2649 
2650 #if defined(HAS_IRQ_MAP_VERSION_2)
2651 enum ia_css_err ia_css_irq_translate(
2652     unsigned int *irq_infos)
2653 {
2654 	virq_id_t	irq;
2655 	enum hrt_isp_css_irq_status status = hrt_isp_css_irq_status_more_irqs;
2656 	unsigned int infos = 0;
2657 
2658 	/* irq_infos can be NULL, but that would make the function useless */
2659 	/* assert(irq_infos != NULL); */
2660 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2661 			    "ia_css_irq_translate() enter: irq_infos=%p\n", irq_infos);
2662 
2663 	while (status == hrt_isp_css_irq_status_more_irqs) {
2664 		status = virq_get_channel_id(&irq);
2665 		if (status == hrt_isp_css_irq_status_error)
2666 			return IA_CSS_ERR_INTERNAL_ERROR;
2667 
2668 #if WITH_PC_MONITORING
2669 		sh_css_print("PC_MONITORING: %s() irq = %d, sh_binary_running set to 0\n",
2670 			     __func__, irq);
2671 		sh_binary_running = 0;
2672 #endif
2673 
2674 		switch (irq) {
2675 		case virq_sp:
2676 			/* When SP goes to idle, info is available in the
2677 			 * event queue. */
2678 			infos |= IA_CSS_IRQ_INFO_EVENTS_READY;
2679 			break;
2680 		case virq_isp:
2681 			break;
2682 #if !defined(HAS_NO_INPUT_SYSTEM)
2683 		case virq_isys_sof:
2684 			infos |= IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF;
2685 			break;
2686 		case virq_isys_eof:
2687 			infos |= IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF;
2688 			break;
2689 		case virq_isys_csi:
2690 			infos |= IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR;
2691 			break;
2692 #endif
2693 #if !defined(HAS_NO_INPUT_FORMATTER)
2694 		case virq_ifmt0_id:
2695 			infos |= IA_CSS_IRQ_INFO_IF_ERROR;
2696 			break;
2697 #endif
2698 		case virq_dma:
2699 			infos |= IA_CSS_IRQ_INFO_DMA_ERROR;
2700 			break;
2701 		case virq_sw_pin_0:
2702 			infos |= sh_css_get_sw_interrupt_value(0);
2703 			break;
2704 		case virq_sw_pin_1:
2705 			infos |= sh_css_get_sw_interrupt_value(1);
2706 			/* pqiao TODO: also assumption here */
2707 			break;
2708 		default:
2709 			break;
2710 		}
2711 	}
2712 
2713 	if (irq_infos)
2714 		*irq_infos = infos;
2715 
2716 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2717 			    "ia_css_irq_translate() leave: irq_infos=%u\n",
2718 			    infos);
2719 
2720 	return IA_CSS_SUCCESS;
2721 }
2722 
2723 enum ia_css_err ia_css_irq_enable(
2724     enum ia_css_irq_info info,
2725     bool enable)
2726 {
2727 	virq_id_t	irq = N_virq_id;
2728 
2729 	IA_CSS_ENTER("info=%d, enable=%d", info, enable);
2730 
2731 	switch (info) {
2732 #if !defined(HAS_NO_INPUT_FORMATTER)
2733 	case IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF:
2734 		irq = virq_isys_sof;
2735 		break;
2736 	case IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF:
2737 		irq = virq_isys_eof;
2738 		break;
2739 	case IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR:
2740 		irq = virq_isys_csi;
2741 		break;
2742 #endif
2743 #if !defined(HAS_NO_INPUT_FORMATTER)
2744 	case IA_CSS_IRQ_INFO_IF_ERROR:
2745 		irq = virq_ifmt0_id;
2746 		break;
2747 #endif
2748 	case IA_CSS_IRQ_INFO_DMA_ERROR:
2749 		irq = virq_dma;
2750 		break;
2751 	case IA_CSS_IRQ_INFO_SW_0:
2752 		irq = virq_sw_pin_0;
2753 		break;
2754 	case IA_CSS_IRQ_INFO_SW_1:
2755 		irq = virq_sw_pin_1;
2756 		break;
2757 	default:
2758 		IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
2759 		return IA_CSS_ERR_INVALID_ARGUMENTS;
2760 	}
2761 
2762 	cnd_virq_enable_channel(irq, enable);
2763 
2764 	IA_CSS_LEAVE_ERR(IA_CSS_SUCCESS);
2765 	return IA_CSS_SUCCESS;
2766 }
2767 
2768 #else
2769 #error "sh_css.c: IRQ MAP must be one of { IRQ_MAP_VERSION_2 }"
2770 #endif
2771 
2772 static unsigned int
2773 sh_css_get_sw_interrupt_value(unsigned int irq)
2774 {
2775 	unsigned int irq_value;
2776 
2777 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2778 			    "sh_css_get_sw_interrupt_value() enter: irq=%d\n", irq);
2779 	irq_value = sh_css_sp_get_sw_interrupt_value(irq);
2780 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2781 			    "sh_css_get_sw_interrupt_value() leave: irq_value=%d\n", irq_value);
2782 	return irq_value;
2783 }
2784 
2785 /* configure and load the copy binary, the next binary is used to
2786    determine whether the copy binary needs to do left padding. */
2787 static enum ia_css_err load_copy_binary(
2788     struct ia_css_pipe *pipe,
2789     struct ia_css_binary *copy_binary,
2790     struct ia_css_binary *next_binary)
2791 {
2792 	struct ia_css_frame_info copy_out_info, copy_in_info, copy_vf_info;
2793 	unsigned int left_padding;
2794 	enum ia_css_err err;
2795 	struct ia_css_binary_descr copy_descr;
2796 
2797 	/* next_binary can be NULL */
2798 	assert(pipe);
2799 	assert(copy_binary);
2800 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2801 			    "load_copy_binary() enter:\n");
2802 
2803 	if (next_binary) {
2804 		copy_out_info = next_binary->in_frame_info;
2805 		left_padding = next_binary->left_padding;
2806 	} else {
2807 		copy_out_info = pipe->output_info[0];
2808 		copy_vf_info = pipe->vf_output_info[0];
2809 		ia_css_frame_info_set_format(&copy_vf_info, IA_CSS_FRAME_FORMAT_YUV_LINE);
2810 		left_padding = 0;
2811 	}
2812 
2813 	ia_css_pipe_get_copy_binarydesc(pipe, &copy_descr,
2814 					&copy_in_info, &copy_out_info,
2815 					(next_binary) ? NULL : NULL/*TODO: &copy_vf_info*/);
2816 	err = ia_css_binary_find(&copy_descr, copy_binary);
2817 	if (err != IA_CSS_SUCCESS)
2818 		return err;
2819 	copy_binary->left_padding = left_padding;
2820 	return IA_CSS_SUCCESS;
2821 }
2822 
2823 static enum ia_css_err
2824 alloc_continuous_frames(
2825     struct ia_css_pipe *pipe, bool init_time) {
2826 	enum ia_css_err err = IA_CSS_SUCCESS;
2827 	struct ia_css_frame_info ref_info;
2828 	enum ia_css_pipe_id pipe_id;
2829 	bool continuous;
2830 	unsigned int i, idx;
2831 	unsigned int num_frames;
2832 	struct ia_css_pipe *capture_pipe = NULL;
2833 
2834 	IA_CSS_ENTER_PRIVATE("pipe = %p, init_time = %d", pipe, init_time);
2835 
2836 	if ((!pipe) || (!pipe->stream))
2837 	{
2838 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
2839 		return IA_CSS_ERR_INVALID_ARGUMENTS;
2840 	}
2841 
2842 	pipe_id = pipe->mode;
2843 	continuous = pipe->stream->config.continuous;
2844 
2845 	if (continuous)
2846 	{
2847 		if (init_time) {
2848 			num_frames = pipe->stream->config.init_num_cont_raw_buf;
2849 			pipe->stream->continuous_pipe = pipe;
2850 		} else
2851 			num_frames = pipe->stream->config.target_num_cont_raw_buf;
2852 	} else
2853 	{
2854 		num_frames = NUM_ONLINE_INIT_CONTINUOUS_FRAMES;
2855 	}
2856 
2857 	if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
2858 	{
2859 		ref_info = pipe->pipe_settings.preview.preview_binary.in_frame_info;
2860 	} else if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
2861 	{
2862 		ref_info = pipe->pipe_settings.video.video_binary.in_frame_info;
2863 	} else
2864 	{
2865 		/* should not happen */
2866 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR);
2867 		return IA_CSS_ERR_INTERNAL_ERROR;
2868 	}
2869 
2870 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
2871 	/* For CSI2+, the continuous frame will hold the full input frame */
2872 	ref_info.res.width = pipe->stream->config.input_config.input_res.width;
2873 	ref_info.res.height = pipe->stream->config.input_config.input_res.height;
2874 
2875 	/* Ensure padded width is aligned for 2401 */
2876 	ref_info.padded_width = CEIL_MUL(ref_info.res.width, 2 * ISP_VEC_NELEMS);
2877 #endif
2878 
2879 #if !defined(HAS_NO_PACKED_RAW_PIXELS)
2880 	if (pipe->stream->config.pack_raw_pixels)
2881 	{
2882 		ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2883 				    "alloc_continuous_frames() IA_CSS_FRAME_FORMAT_RAW_PACKED\n");
2884 		ref_info.format = IA_CSS_FRAME_FORMAT_RAW_PACKED;
2885 	} else
2886 #endif
2887 	{
2888 		ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2889 				    "alloc_continuous_frames() IA_CSS_FRAME_FORMAT_RAW\n");
2890 		ref_info.format = IA_CSS_FRAME_FORMAT_RAW;
2891 	}
2892 
2893 	/* Write format back to binary */
2894 	if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
2895 	{
2896 		pipe->pipe_settings.preview.preview_binary.in_frame_info.format =
2897 		    ref_info.format;
2898 		capture_pipe = pipe->pipe_settings.preview.capture_pipe;
2899 	} else if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
2900 	{
2901 		pipe->pipe_settings.video.video_binary.in_frame_info.format = ref_info.format;
2902 		capture_pipe = pipe->pipe_settings.video.capture_pipe;
2903 	} else
2904 	{
2905 		/* should not happen */
2906 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR);
2907 		return IA_CSS_ERR_INTERNAL_ERROR;
2908 	}
2909 
2910 	if (init_time)
2911 		idx = 0;
2912 	else
2913 		idx = pipe->stream->config.init_num_cont_raw_buf;
2914 
2915 	for (i = idx; i < NUM_CONTINUOUS_FRAMES; i++)
2916 	{
2917 		/* free previous frame */
2918 		if (pipe->continuous_frames[i]) {
2919 			ia_css_frame_free(pipe->continuous_frames[i]);
2920 			pipe->continuous_frames[i] = NULL;
2921 		}
2922 		/* free previous metadata buffer */
2923 		ia_css_metadata_free(pipe->cont_md_buffers[i]);
2924 		pipe->cont_md_buffers[i] = NULL;
2925 
2926 		/* check if new frame needed */
2927 		if (i < num_frames) {
2928 			/* allocate new frame */
2929 			err = ia_css_frame_allocate_from_info(
2930 				  &pipe->continuous_frames[i],
2931 				  &ref_info);
2932 			if (err != IA_CSS_SUCCESS) {
2933 				IA_CSS_LEAVE_ERR_PRIVATE(err);
2934 				return err;
2935 			}
2936 			/* allocate metadata buffer */
2937 			pipe->cont_md_buffers[i] = ia_css_metadata_allocate(
2938 						       &pipe->stream->info.metadata_info);
2939 		}
2940 	}
2941 	IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
2942 	return IA_CSS_SUCCESS;
2943 }
2944 
2945 enum ia_css_err
2946 ia_css_alloc_continuous_frame_remain(struct ia_css_stream *stream) {
2947 	if (!stream)
2948 		return IA_CSS_ERR_INVALID_ARGUMENTS;
2949 	return alloc_continuous_frames(stream->continuous_pipe, false);
2950 }
2951 
2952 static enum ia_css_err
2953 load_preview_binaries(struct ia_css_pipe *pipe) {
2954 	struct ia_css_frame_info prev_in_info,
2955 		prev_bds_out_info,
2956 		prev_out_info,
2957 		prev_vf_info;
2958 	struct ia_css_binary_descr preview_descr;
2959 	bool online;
2960 	enum ia_css_err err = IA_CSS_SUCCESS;
2961 	bool continuous, need_vf_pp = false;
2962 	bool need_isp_copy_binary = false;
2963 #ifdef USE_INPUT_SYSTEM_VERSION_2401
2964 	bool sensor = false;
2965 #endif
2966 	/* preview only have 1 output pin now */
2967 	struct ia_css_frame_info *pipe_out_info = &pipe->output_info[0];
2968 	struct ia_css_preview_settings *mycs  = &pipe->pipe_settings.preview;
2969 
2970 	IA_CSS_ENTER_PRIVATE("");
2971 	assert(pipe);
2972 	assert(pipe->stream);
2973 	assert(pipe->mode == IA_CSS_PIPE_ID_PREVIEW);
2974 
2975 	online = pipe->stream->config.online;
2976 	continuous = pipe->stream->config.continuous;
2977 #ifdef USE_INPUT_SYSTEM_VERSION_2401
2978 	sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
2979 #endif
2980 
2981 	if (mycs->preview_binary.info)
2982 		return IA_CSS_SUCCESS;
2983 
2984 	err = ia_css_util_check_input(&pipe->stream->config, false, false);
2985 	if (err != IA_CSS_SUCCESS)
2986 		return err;
2987 	err = ia_css_frame_check_info(pipe_out_info);
2988 	if (err != IA_CSS_SUCCESS)
2989 		return err;
2990 
2991 	/* Note: the current selection of vf_pp binary and
2992 	 * parameterization of the preview binary contains a few pieces
2993 	 * of hardcoded knowledge. This needs to be cleaned up such that
2994 	 * the binary selection becomes more generic.
2995 	 * The vf_pp binary is needed if one or more of the following features
2996 	 * are required:
2997 	 * 1. YUV downscaling.
2998 	 * 2. Digital zoom.
2999 	 * 3. An output format that is not supported by the preview binary.
3000 	 *    In practice this means something other than yuv_line or nv12.
3001 	 * The decision if the vf_pp binary is needed for YUV downscaling is
3002 	 * made after the preview binary selection, since some preview binaries
3003 	 * can perform the requested YUV downscaling.
3004 	 * */
3005 	need_vf_pp = pipe->config.enable_dz;
3006 	need_vf_pp |= pipe_out_info->format != IA_CSS_FRAME_FORMAT_YUV_LINE &&
3007 	!(pipe_out_info->format == IA_CSS_FRAME_FORMAT_NV12 ||
3008 	  pipe_out_info->format == IA_CSS_FRAME_FORMAT_NV12_16 ||
3009 	  pipe_out_info->format == IA_CSS_FRAME_FORMAT_NV12_TILEY);
3010 
3011 	/* Preview step 1 */
3012 	if (pipe->vf_yuv_ds_input_info.res.width)
3013 		prev_vf_info = pipe->vf_yuv_ds_input_info;
3014 	else
3015 		prev_vf_info = *pipe_out_info;
3016 	/* If vf_pp is needed, then preview must output yuv_line.
3017 	 * The exception is when vf_pp is manually disabled, that is only
3018 	 * used in combination with a pipeline extension that requires
3019 	 * yuv_line as input.
3020 	 * */
3021 	if (need_vf_pp)
3022 		ia_css_frame_info_set_format(&prev_vf_info,
3023 					     IA_CSS_FRAME_FORMAT_YUV_LINE);
3024 
3025 	err = ia_css_pipe_get_preview_binarydesc(
3026 	    pipe,
3027 	    &preview_descr,
3028 	    &prev_in_info,
3029 	    &prev_bds_out_info,
3030 	    &prev_out_info,
3031 	    &prev_vf_info);
3032 	if (err != IA_CSS_SUCCESS)
3033 		return err;
3034 	err = ia_css_binary_find(&preview_descr, &mycs->preview_binary);
3035 	if (err != IA_CSS_SUCCESS)
3036 		return err;
3037 
3038 	if (atomisp_hw_is_isp2401) {
3039 		/* The delay latency determines the number of invalid frames after
3040 		* a stream is started. */
3041 		pipe->num_invalid_frames = pipe->dvs_frame_delay;
3042 		pipe->info.num_invalid_frames = pipe->num_invalid_frames;
3043 
3044 		ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
3045 				    "load_preview_binaries() num_invalid_frames=%d dvs_frame_delay=%d\n",
3046 				    pipe->num_invalid_frames, pipe->dvs_frame_delay);
3047 	}
3048 
3049 	/* The vf_pp binary is needed when (further) YUV downscaling is required */
3050 	need_vf_pp |= mycs->preview_binary.out_frame_info[0].res.width != pipe_out_info->res.width;
3051 	need_vf_pp |= mycs->preview_binary.out_frame_info[0].res.height != pipe_out_info->res.height;
3052 
3053 	/* When vf_pp is needed, then the output format of the selected
3054 	 * preview binary must be yuv_line. If this is not the case,
3055 	 * then the preview binary selection is done again.
3056 	 */
3057 	if (need_vf_pp &&
3058 	    (mycs->preview_binary.out_frame_info[0].format != IA_CSS_FRAME_FORMAT_YUV_LINE))
3059 	{
3060 		/* Preview step 2 */
3061 		if (pipe->vf_yuv_ds_input_info.res.width)
3062 			prev_vf_info = pipe->vf_yuv_ds_input_info;
3063 		else
3064 			prev_vf_info = *pipe_out_info;
3065 
3066 		ia_css_frame_info_set_format(&prev_vf_info,
3067 					     IA_CSS_FRAME_FORMAT_YUV_LINE);
3068 
3069 		err = ia_css_pipe_get_preview_binarydesc(
3070 		    pipe,
3071 		    &preview_descr,
3072 		    &prev_in_info,
3073 		    &prev_bds_out_info,
3074 		    &prev_out_info,
3075 		    &prev_vf_info);
3076 		if (err != IA_CSS_SUCCESS)
3077 			return err;
3078 		err = ia_css_binary_find(&preview_descr,
3079 					 &mycs->preview_binary);
3080 		if (err != IA_CSS_SUCCESS)
3081 			return err;
3082 	}
3083 
3084 	if (need_vf_pp)
3085 	{
3086 		struct ia_css_binary_descr vf_pp_descr;
3087 
3088 		/* Viewfinder post-processing */
3089 		ia_css_pipe_get_vfpp_binarydesc(pipe, &vf_pp_descr,
3090 						&mycs->preview_binary.out_frame_info[0],
3091 						pipe_out_info);
3092 		err = ia_css_binary_find(&vf_pp_descr,
3093 					 &mycs->vf_pp_binary);
3094 		if (err != IA_CSS_SUCCESS)
3095 			return err;
3096 	}
3097 
3098 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3099 	/* When the input system is 2401, only the Direct Sensor Mode
3100 	 * Offline Preview uses the ISP copy binary.
3101 	 */
3102 	need_isp_copy_binary = !online && sensor;
3103 #else
3104 	/* About pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY:
3105 	 * This is typical the case with SkyCam (which has no input system) but it also applies to all cases
3106 	 * where the driver chooses for memory based input frames. In these cases, a copy binary (which typical
3107 	 * copies sensor data to DDR) does not have much use.
3108 	 */
3109 	if (!atomisp_hw_is_isp2401)
3110 		need_isp_copy_binary = !online && !continuous;
3111 	else
3112 		need_isp_copy_binary = !online && !continuous && !(pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY);
3113 #endif
3114 
3115 	/* Copy */
3116 	if (need_isp_copy_binary)
3117 	{
3118 		err = load_copy_binary(pipe,
3119 				       &mycs->copy_binary,
3120 				       &mycs->preview_binary);
3121 		if (err != IA_CSS_SUCCESS)
3122 			return err;
3123 	}
3124 
3125 	if (pipe->shading_table)
3126 	{
3127 		ia_css_shading_table_free(pipe->shading_table);
3128 		pipe->shading_table = NULL;
3129 	}
3130 
3131 	return IA_CSS_SUCCESS;
3132 }
3133 
3134 static void
3135 ia_css_binary_unload(struct ia_css_binary *binary)
3136 {
3137 	ia_css_binary_destroy_isp_parameters(binary);
3138 }
3139 
3140 static enum ia_css_err
3141 unload_preview_binaries(struct ia_css_pipe *pipe) {
3142 	IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3143 
3144 	if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW))
3145 	{
3146 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
3147 		return IA_CSS_ERR_INVALID_ARGUMENTS;
3148 	}
3149 	ia_css_binary_unload(&pipe->pipe_settings.preview.copy_binary);
3150 	ia_css_binary_unload(&pipe->pipe_settings.preview.preview_binary);
3151 	ia_css_binary_unload(&pipe->pipe_settings.preview.vf_pp_binary);
3152 
3153 	IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
3154 	return IA_CSS_SUCCESS;
3155 }
3156 
3157 static const struct ia_css_fw_info *last_output_firmware(
3158     const struct ia_css_fw_info *fw)
3159 {
3160 	const struct ia_css_fw_info *last_fw = NULL;
3161 	/* fw can be NULL */
3162 	IA_CSS_ENTER_LEAVE_PRIVATE("");
3163 
3164 	for (; fw; fw = fw->next) {
3165 		const struct ia_css_fw_info *info = fw;
3166 
3167 		if (info->info.isp.sp.enable.output)
3168 			last_fw = fw;
3169 	}
3170 	return last_fw;
3171 }
3172 
3173 static enum ia_css_err add_firmwares(
3174     struct ia_css_pipeline *me,
3175     struct ia_css_binary *binary,
3176     const struct ia_css_fw_info *fw,
3177     const struct ia_css_fw_info *last_fw,
3178     unsigned int binary_mode,
3179     struct ia_css_frame *in_frame,
3180     struct ia_css_frame *out_frame,
3181     struct ia_css_frame *vf_frame,
3182     struct ia_css_pipeline_stage **my_stage,
3183     struct ia_css_pipeline_stage **vf_stage)
3184 {
3185 	enum ia_css_err err = IA_CSS_SUCCESS;
3186 	struct ia_css_pipeline_stage *extra_stage = NULL;
3187 	struct ia_css_pipeline_stage_desc stage_desc;
3188 
3189 	/* all args can be NULL ??? */
3190 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3191 			    "add_firmwares() enter:\n");
3192 
3193 	for (; fw; fw = fw->next) {
3194 		struct ia_css_frame *out[IA_CSS_BINARY_MAX_OUTPUT_PORTS] = {NULL};
3195 		struct ia_css_frame *in = NULL;
3196 		struct ia_css_frame *vf = NULL;
3197 
3198 		if ((fw == last_fw) && (fw->info.isp.sp.enable.out_frame  != 0)) {
3199 			out[0] = out_frame;
3200 		}
3201 		if (fw->info.isp.sp.enable.in_frame != 0) {
3202 			in = in_frame;
3203 		}
3204 		if (fw->info.isp.sp.enable.out_frame != 0) {
3205 			vf = vf_frame;
3206 		}
3207 		ia_css_pipe_get_firmwares_stage_desc(&stage_desc, binary,
3208 						     out, in, vf, fw, binary_mode);
3209 		err = ia_css_pipeline_create_and_add_stage(me,
3210 			&stage_desc,
3211 			&extra_stage);
3212 		if (err != IA_CSS_SUCCESS)
3213 			return err;
3214 		if (fw->info.isp.sp.enable.output != 0)
3215 			in_frame = extra_stage->args.out_frame[0];
3216 		if (my_stage && !*my_stage && extra_stage)
3217 			*my_stage = extra_stage;
3218 		if (vf_stage && !*vf_stage && extra_stage &&
3219 		    fw->info.isp.sp.enable.vf_veceven)
3220 			*vf_stage = extra_stage;
3221 	}
3222 	return err;
3223 }
3224 
3225 static enum ia_css_err add_vf_pp_stage(
3226     struct ia_css_pipe *pipe,
3227     struct ia_css_frame *in_frame,
3228     struct ia_css_frame *out_frame,
3229     struct ia_css_binary *vf_pp_binary,
3230     struct ia_css_pipeline_stage **vf_pp_stage)
3231 {
3232 	struct ia_css_pipeline *me = NULL;
3233 	const struct ia_css_fw_info *last_fw = NULL;
3234 	enum ia_css_err err = IA_CSS_SUCCESS;
3235 	struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3236 	struct ia_css_pipeline_stage_desc stage_desc;
3237 
3238 	/* out_frame can be NULL ??? */
3239 
3240 	if (!pipe)
3241 		return IA_CSS_ERR_INVALID_ARGUMENTS;
3242 	if (!in_frame)
3243 		return IA_CSS_ERR_INVALID_ARGUMENTS;
3244 	if (!vf_pp_binary)
3245 		return IA_CSS_ERR_INVALID_ARGUMENTS;
3246 	if (!vf_pp_stage)
3247 		return IA_CSS_ERR_INVALID_ARGUMENTS;
3248 
3249 	ia_css_pipe_util_create_output_frames(out_frames);
3250 	me = &pipe->pipeline;
3251 
3252 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3253 			    "add_vf_pp_stage() enter:\n");
3254 
3255 	*vf_pp_stage = NULL;
3256 
3257 	last_fw = last_output_firmware(pipe->vf_stage);
3258 	if (!pipe->extra_config.disable_vf_pp) {
3259 		if (last_fw) {
3260 			ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3261 			ia_css_pipe_get_generic_stage_desc(&stage_desc, vf_pp_binary,
3262 							   out_frames, in_frame, NULL);
3263 		} else {
3264 			ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
3265 			ia_css_pipe_get_generic_stage_desc(&stage_desc, vf_pp_binary,
3266 							   out_frames, in_frame, NULL);
3267 		}
3268 		err = ia_css_pipeline_create_and_add_stage(me, &stage_desc, vf_pp_stage);
3269 		if (err != IA_CSS_SUCCESS)
3270 			return err;
3271 		in_frame = (*vf_pp_stage)->args.out_frame[0];
3272 	}
3273 	err = add_firmwares(me, vf_pp_binary, pipe->vf_stage, last_fw,
3274 			    IA_CSS_BINARY_MODE_VF_PP,
3275 			    in_frame, out_frame, NULL,
3276 			    vf_pp_stage, NULL);
3277 	return err;
3278 }
3279 
3280 static enum ia_css_err add_yuv_scaler_stage(
3281     struct ia_css_pipe *pipe,
3282     struct ia_css_pipeline *me,
3283     struct ia_css_frame *in_frame,
3284     struct ia_css_frame *out_frame,
3285     struct ia_css_frame *internal_out_frame,
3286     struct ia_css_binary *yuv_scaler_binary,
3287     struct ia_css_pipeline_stage **pre_vf_pp_stage)
3288 {
3289 	const struct ia_css_fw_info *last_fw;
3290 	enum ia_css_err err = IA_CSS_SUCCESS;
3291 	struct ia_css_frame *vf_frame = NULL;
3292 	struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3293 	struct ia_css_pipeline_stage_desc stage_desc;
3294 
3295 	/* out_frame can be NULL ??? */
3296 	assert(in_frame);
3297 	assert(pipe);
3298 	assert(me);
3299 	assert(yuv_scaler_binary);
3300 	assert(pre_vf_pp_stage);
3301 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3302 			    "add_yuv_scaler_stage() enter:\n");
3303 
3304 	*pre_vf_pp_stage = NULL;
3305 	ia_css_pipe_util_create_output_frames(out_frames);
3306 
3307 	last_fw = last_output_firmware(pipe->output_stage);
3308 
3309 	if (last_fw) {
3310 		ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3311 		ia_css_pipe_get_generic_stage_desc(&stage_desc,
3312 						   yuv_scaler_binary, out_frames, in_frame, vf_frame);
3313 	} else {
3314 		ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
3315 		ia_css_pipe_util_set_output_frames(out_frames, 1, internal_out_frame);
3316 		ia_css_pipe_get_generic_stage_desc(&stage_desc,
3317 						   yuv_scaler_binary, out_frames, in_frame, vf_frame);
3318 	}
3319 	err = ia_css_pipeline_create_and_add_stage(me,
3320 		&stage_desc,
3321 		pre_vf_pp_stage);
3322 	if (err != IA_CSS_SUCCESS)
3323 		return err;
3324 	in_frame = (*pre_vf_pp_stage)->args.out_frame[0];
3325 
3326 	err = add_firmwares(me, yuv_scaler_binary, pipe->output_stage, last_fw,
3327 			    IA_CSS_BINARY_MODE_CAPTURE_PP,
3328 			    in_frame, out_frame, vf_frame,
3329 			    NULL, pre_vf_pp_stage);
3330 	/* If a firmware produce vf_pp output, we set that as vf_pp input */
3331 	(*pre_vf_pp_stage)->args.vf_downscale_log2 =
3332 	    yuv_scaler_binary->vf_downscale_log2;
3333 
3334 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3335 			    "add_yuv_scaler_stage() leave:\n");
3336 	return err;
3337 }
3338 
3339 static enum ia_css_err add_capture_pp_stage(
3340     struct ia_css_pipe *pipe,
3341     struct ia_css_pipeline *me,
3342     struct ia_css_frame *in_frame,
3343     struct ia_css_frame *out_frame,
3344     struct ia_css_binary *capture_pp_binary,
3345     struct ia_css_pipeline_stage **capture_pp_stage)
3346 {
3347 	const struct ia_css_fw_info *last_fw = NULL;
3348 	enum ia_css_err err = IA_CSS_SUCCESS;
3349 	struct ia_css_frame *vf_frame = NULL;
3350 	struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3351 	struct ia_css_pipeline_stage_desc stage_desc;
3352 
3353 	/* out_frame can be NULL ??? */
3354 	assert(in_frame);
3355 	assert(pipe);
3356 	assert(me);
3357 	assert(capture_pp_binary);
3358 	assert(capture_pp_stage);
3359 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3360 			    "add_capture_pp_stage() enter:\n");
3361 
3362 	*capture_pp_stage = NULL;
3363 	ia_css_pipe_util_create_output_frames(out_frames);
3364 
3365 	last_fw = last_output_firmware(pipe->output_stage);
3366 	err = ia_css_frame_allocate_from_info(&vf_frame,
3367 					      &capture_pp_binary->vf_frame_info);
3368 	if (err != IA_CSS_SUCCESS)
3369 		return err;
3370 	if (last_fw)	{
3371 		ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3372 		ia_css_pipe_get_generic_stage_desc(&stage_desc,
3373 						   capture_pp_binary, out_frames, NULL, vf_frame);
3374 	} else {
3375 		ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
3376 		ia_css_pipe_get_generic_stage_desc(&stage_desc,
3377 						   capture_pp_binary, out_frames, NULL, vf_frame);
3378 	}
3379 	err = ia_css_pipeline_create_and_add_stage(me,
3380 		&stage_desc,
3381 		capture_pp_stage);
3382 	if (err != IA_CSS_SUCCESS)
3383 		return err;
3384 	err = add_firmwares(me, capture_pp_binary, pipe->output_stage, last_fw,
3385 			    IA_CSS_BINARY_MODE_CAPTURE_PP,
3386 			    in_frame, out_frame, vf_frame,
3387 			    NULL, capture_pp_stage);
3388 	/* If a firmware produce vf_pp output, we set that as vf_pp input */
3389 	if (*capture_pp_stage) {
3390 		(*capture_pp_stage)->args.vf_downscale_log2 =
3391 		    capture_pp_binary->vf_downscale_log2;
3392 	}
3393 	return err;
3394 }
3395 
3396 static void sh_css_setup_queues(void)
3397 {
3398 	const struct ia_css_fw_info *fw;
3399 	unsigned int HIVE_ADDR_host_sp_queues_initialized;
3400 
3401 	sh_css_hmm_buffer_record_init();
3402 
3403 	sh_css_event_init_irq_mask();
3404 
3405 	fw = &sh_css_sp_fw;
3406 	HIVE_ADDR_host_sp_queues_initialized =
3407 	    fw->info.sp.host_sp_queues_initialized;
3408 
3409 	ia_css_bufq_init();
3410 
3411 	/* set "host_sp_queues_initialized" to "true" */
3412 	sp_dmem_store_uint32(SP0_ID,
3413 			     (unsigned int)sp_address_of(host_sp_queues_initialized),
3414 			     (uint32_t)(1));
3415 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_setup_queues() leave:\n");
3416 }
3417 
3418 static enum ia_css_err
3419 init_vf_frameinfo_defaults(struct ia_css_pipe *pipe,
3420 			   struct ia_css_frame *vf_frame, unsigned int idx) {
3421 	enum ia_css_err err = IA_CSS_SUCCESS;
3422 	unsigned int thread_id;
3423 	enum sh_css_queue_id queue_id;
3424 
3425 	assert(vf_frame);
3426 
3427 	sh_css_pipe_get_viewfinder_frame_info(pipe, &vf_frame->info, idx);
3428 	vf_frame->contiguous = false;
3429 	vf_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
3430 	ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
3431 	ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx, thread_id, &queue_id);
3432 	vf_frame->dynamic_queue_id = queue_id;
3433 	vf_frame->buf_type = IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx;
3434 
3435 	err = ia_css_frame_init_planes(vf_frame);
3436 	return err;
3437 }
3438 
3439 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3440 static unsigned int
3441 get_crop_lines_for_bayer_order(
3442     const struct ia_css_stream_config *config)
3443 {
3444 	assert(config);
3445 	if ((config->input_config.bayer_order == IA_CSS_BAYER_ORDER_BGGR)
3446 	    || (config->input_config.bayer_order == IA_CSS_BAYER_ORDER_GBRG))
3447 		return 1;
3448 
3449 	return 0;
3450 }
3451 
3452 static unsigned int
3453 get_crop_columns_for_bayer_order(
3454     const struct ia_css_stream_config *config)
3455 {
3456 	assert(config);
3457 	if ((config->input_config.bayer_order == IA_CSS_BAYER_ORDER_RGGB)
3458 	    || (config->input_config.bayer_order == IA_CSS_BAYER_ORDER_GBRG))
3459 		return 1;
3460 
3461 	return 0;
3462 }
3463 
3464 /* This function is to get the sum of all extra pixels in addition to the effective
3465  * input, it includes dvs envelop and filter run-in */
3466 static void get_pipe_extra_pixel(struct ia_css_pipe *pipe,
3467 				 unsigned int *extra_row, unsigned int *extra_column)
3468 {
3469 	enum ia_css_pipe_id pipe_id = pipe->mode;
3470 	unsigned int left_cropping = 0, top_cropping = 0;
3471 	unsigned int i;
3472 	struct ia_css_resolution dvs_env = pipe->config.dvs_envelope;
3473 
3474 	/* The dvs envelope info may not be correctly sent down via pipe config
3475 	 * The check is made and the correct value is populated in the binary info
3476 	 * Use this value when computing crop, else excess lines may get trimmed
3477 	 */
3478 	switch (pipe_id) {
3479 	case IA_CSS_PIPE_ID_PREVIEW:
3480 		if (pipe->pipe_settings.preview.preview_binary.info) {
3481 			left_cropping =
3482 			    pipe->pipe_settings.preview.preview_binary.info->sp.pipeline.left_cropping;
3483 			top_cropping =
3484 			    pipe->pipe_settings.preview.preview_binary.info->sp.pipeline.top_cropping;
3485 		}
3486 		dvs_env = pipe->pipe_settings.preview.preview_binary.dvs_envelope;
3487 		break;
3488 	case IA_CSS_PIPE_ID_VIDEO:
3489 		if (pipe->pipe_settings.video.video_binary.info) {
3490 			left_cropping =
3491 			    pipe->pipe_settings.video.video_binary.info->sp.pipeline.left_cropping;
3492 			top_cropping =
3493 			    pipe->pipe_settings.video.video_binary.info->sp.pipeline.top_cropping;
3494 		}
3495 		dvs_env = pipe->pipe_settings.video.video_binary.dvs_envelope;
3496 		break;
3497 	case IA_CSS_PIPE_ID_CAPTURE:
3498 		for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
3499 			if (pipe->pipe_settings.capture.primary_binary[i].info) {
3500 				left_cropping +=
3501 				    pipe->pipe_settings.capture.primary_binary[i].info->sp.pipeline.left_cropping;
3502 				top_cropping +=
3503 				    pipe->pipe_settings.capture.primary_binary[i].info->sp.pipeline.top_cropping;
3504 			}
3505 			dvs_env.width +=
3506 			    pipe->pipe_settings.capture.primary_binary[i].dvs_envelope.width;
3507 			dvs_env.height +=
3508 			    pipe->pipe_settings.capture.primary_binary[i].dvs_envelope.height;
3509 		}
3510 		break;
3511 	default:
3512 		break;
3513 	}
3514 
3515 	*extra_row = top_cropping + dvs_env.height;
3516 	*extra_column = left_cropping + dvs_env.width;
3517 }
3518 
3519 void
3520 ia_css_get_crop_offsets(
3521     struct ia_css_pipe *pipe,
3522     struct ia_css_frame_info *in_frame)
3523 {
3524 	unsigned int row = 0;
3525 	unsigned int column = 0;
3526 	struct ia_css_resolution *input_res;
3527 	struct ia_css_resolution *effective_res;
3528 	unsigned int extra_row = 0, extra_col = 0;
3529 	unsigned int min_reqd_height, min_reqd_width;
3530 
3531 	assert(pipe);
3532 	assert(pipe->stream);
3533 	assert(in_frame);
3534 
3535 	IA_CSS_ENTER_PRIVATE("pipe = %p effective_wd = %u effective_ht = %u",
3536 			     pipe, pipe->config.input_effective_res.width,
3537 			     pipe->config.input_effective_res.height);
3538 
3539 	input_res = &pipe->stream->config.input_config.input_res;
3540 #ifndef ISP2401
3541 	effective_res = &pipe->stream->config.input_config.effective_res;
3542 #else
3543 	effective_res = &pipe->config.input_effective_res;
3544 #endif
3545 
3546 	get_pipe_extra_pixel(pipe, &extra_row, &extra_col);
3547 
3548 	in_frame->raw_bayer_order = pipe->stream->config.input_config.bayer_order;
3549 
3550 	min_reqd_height = effective_res->height + extra_row;
3551 	min_reqd_width = effective_res->width + extra_col;
3552 
3553 	if (input_res->height > min_reqd_height) {
3554 		row = (input_res->height - min_reqd_height) / 2;
3555 		row &= ~0x1;
3556 	}
3557 	if (input_res->width > min_reqd_width) {
3558 		column = (input_res->width - min_reqd_width) / 2;
3559 		column &= ~0x1;
3560 	}
3561 
3562 	/*
3563 	 * TODO:
3564 	 * 1. Require the special support for RAW10 packed mode.
3565 	 * 2. Require the special support for the online use cases.
3566 	 */
3567 
3568 	/* ISP expects GRBG bayer order, we skip one line and/or one row
3569 	 * to correct in case the input bayer order is different.
3570 	 */
3571 	column += get_crop_columns_for_bayer_order(&pipe->stream->config);
3572 	row += get_crop_lines_for_bayer_order(&pipe->stream->config);
3573 
3574 	in_frame->crop_info.start_column = column;
3575 	in_frame->crop_info.start_line = row;
3576 
3577 	IA_CSS_LEAVE_PRIVATE("void start_col: %u start_row: %u", column, row);
3578 
3579 	return;
3580 }
3581 #endif
3582 
3583 static enum ia_css_err
3584 init_in_frameinfo_memory_defaults(struct ia_css_pipe *pipe,
3585 				  struct ia_css_frame *frame, enum ia_css_frame_format format) {
3586 	struct ia_css_frame *in_frame;
3587 	enum ia_css_err err = IA_CSS_SUCCESS;
3588 	unsigned int thread_id;
3589 	enum sh_css_queue_id queue_id;
3590 
3591 	assert(frame);
3592 	in_frame = frame;
3593 
3594 	in_frame->info.format = format;
3595 
3596 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3597 	if (format == IA_CSS_FRAME_FORMAT_RAW)
3598 		in_frame->info.format = (pipe->stream->config.pack_raw_pixels) ?
3599 		IA_CSS_FRAME_FORMAT_RAW_PACKED : IA_CSS_FRAME_FORMAT_RAW;
3600 #endif
3601 
3602 	in_frame->info.res.width = pipe->stream->config.input_config.input_res.width;
3603 	in_frame->info.res.height = pipe->stream->config.input_config.input_res.height;
3604 	in_frame->info.raw_bit_depth =
3605 	ia_css_pipe_util_pipe_input_format_bpp(pipe);
3606 	ia_css_frame_info_set_width(&in_frame->info, pipe->stream->config.input_config.input_res.width, 0);
3607 	in_frame->contiguous = false;
3608 	in_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
3609 	ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
3610 	ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_INPUT_FRAME, thread_id, &queue_id);
3611 	in_frame->dynamic_queue_id = queue_id;
3612 	in_frame->buf_type = IA_CSS_BUFFER_TYPE_INPUT_FRAME;
3613 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3614 	ia_css_get_crop_offsets(pipe, &in_frame->info);
3615 #endif
3616 	err = ia_css_frame_init_planes(in_frame);
3617 
3618 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3619 			    "init_in_frameinfo_memory_defaults() bayer_order = %d:\n", in_frame->info.raw_bayer_order);
3620 
3621 	return err;
3622 }
3623 
3624 static enum ia_css_err
3625 init_out_frameinfo_defaults(struct ia_css_pipe *pipe,
3626 			    struct ia_css_frame *out_frame, unsigned int idx) {
3627 	enum ia_css_err err = IA_CSS_SUCCESS;
3628 	unsigned int thread_id;
3629 	enum sh_css_queue_id queue_id;
3630 
3631 	assert(out_frame);
3632 
3633 	sh_css_pipe_get_output_frame_info(pipe, &out_frame->info, idx);
3634 	out_frame->contiguous = false;
3635 	out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
3636 	ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
3637 	ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx, thread_id, &queue_id);
3638 	out_frame->dynamic_queue_id = queue_id;
3639 	out_frame->buf_type = IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx;
3640 	err = ia_css_frame_init_planes(out_frame);
3641 
3642 	return err;
3643 }
3644 
3645 /* Create stages for video pipe */
3646 static enum ia_css_err create_host_video_pipeline(struct ia_css_pipe *pipe)
3647 {
3648 	struct ia_css_pipeline_stage_desc stage_desc;
3649 	struct ia_css_binary *copy_binary, *video_binary,
3650 		       *yuv_scaler_binary, *vf_pp_binary;
3651 	struct ia_css_pipeline_stage *copy_stage  = NULL;
3652 	struct ia_css_pipeline_stage *video_stage = NULL;
3653 	struct ia_css_pipeline_stage *yuv_scaler_stage  = NULL;
3654 	struct ia_css_pipeline_stage *vf_pp_stage = NULL;
3655 	struct ia_css_pipeline *me;
3656 	struct ia_css_frame *in_frame = NULL;
3657 	struct ia_css_frame *out_frame;
3658 	struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3659 	struct ia_css_frame *vf_frame = NULL;
3660 	enum ia_css_err err = IA_CSS_SUCCESS;
3661 	bool need_copy   = false;
3662 	bool need_vf_pp  = false;
3663 	bool need_yuv_pp = false;
3664 	unsigned int num_output_pins;
3665 	bool need_in_frameinfo_memory = false;
3666 
3667 	unsigned int i, num_yuv_scaler;
3668 	bool *is_output_stage = NULL;
3669 
3670 	IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3671 	if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) {
3672 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
3673 		return IA_CSS_ERR_INVALID_ARGUMENTS;
3674 	}
3675 	ia_css_pipe_util_create_output_frames(out_frames);
3676 	out_frame = &pipe->out_frame_struct;
3677 
3678 	/* pipeline already created as part of create_host_pipeline_structure */
3679 	me = &pipe->pipeline;
3680 	ia_css_pipeline_clean(me);
3681 
3682 	me->dvs_frame_delay = pipe->dvs_frame_delay;
3683 
3684 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3685 	/* When the input system is 2401, always enable 'in_frameinfo_memory'
3686 	 * except for the following: online or continuous
3687 	 */
3688 	need_in_frameinfo_memory = !(pipe->stream->config.online ||
3689 				     pipe->stream->config.continuous);
3690 #else
3691 	/* Construct in_frame info (only in case we have dynamic input */
3692 	need_in_frameinfo_memory = pipe->stream->config.mode ==
3693 				   IA_CSS_INPUT_MODE_MEMORY;
3694 #endif
3695 
3696 	/* Construct in_frame info (only in case we have dynamic input */
3697 	if (need_in_frameinfo_memory) {
3698 		in_frame = &pipe->in_frame_struct;
3699 		err = init_in_frameinfo_memory_defaults(pipe, in_frame,
3700 							IA_CSS_FRAME_FORMAT_RAW);
3701 		if (err != IA_CSS_SUCCESS)
3702 			goto ERR;
3703 	}
3704 
3705 	out_frame->data = 0;
3706 	err = init_out_frameinfo_defaults(pipe, out_frame, 0);
3707 	if (err != IA_CSS_SUCCESS)
3708 		goto ERR;
3709 
3710 	if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
3711 		vf_frame = &pipe->vf_frame_struct;
3712 		vf_frame->data = 0;
3713 		err = init_vf_frameinfo_defaults(pipe, vf_frame, 0);
3714 		if (err != IA_CSS_SUCCESS)
3715 			goto ERR;
3716 	}
3717 
3718 	copy_binary  = &pipe->pipe_settings.video.copy_binary;
3719 	video_binary = &pipe->pipe_settings.video.video_binary;
3720 	vf_pp_binary = &pipe->pipe_settings.video.vf_pp_binary;
3721 	num_output_pins = video_binary->info->num_output_pins;
3722 
3723 	yuv_scaler_binary = pipe->pipe_settings.video.yuv_scaler_binary;
3724 	num_yuv_scaler  = pipe->pipe_settings.video.num_yuv_scaler;
3725 	is_output_stage = pipe->pipe_settings.video.is_output_stage;
3726 
3727 	need_copy   = (copy_binary && copy_binary->info);
3728 	need_vf_pp  = (vf_pp_binary && vf_pp_binary->info);
3729 	need_yuv_pp = (yuv_scaler_binary && yuv_scaler_binary->info);
3730 
3731 	if (need_copy) {
3732 		ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3733 		ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
3734 						   out_frames, NULL, NULL);
3735 		err = ia_css_pipeline_create_and_add_stage(me,
3736 			&stage_desc,
3737 			&copy_stage);
3738 		if (err != IA_CSS_SUCCESS)
3739 			goto ERR;
3740 		in_frame = me->stages->args.out_frame[0];
3741 	} else if (pipe->stream->config.continuous) {
3742 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3743 		/* When continuous is enabled, configure in_frame with the
3744 		 * last pipe, which is the copy pipe.
3745 		 */
3746 		in_frame = pipe->stream->last_pipe->continuous_frames[0];
3747 #else
3748 		in_frame = pipe->continuous_frames[0];
3749 #endif
3750 	}
3751 
3752 	ia_css_pipe_util_set_output_frames(out_frames, 0,
3753 					   need_yuv_pp ? NULL : out_frame);
3754 
3755 	/* when the video binary supports a second output pin,
3756 	   it can directly produce the vf_frame.  */
3757 	if (need_vf_pp) {
3758 		ia_css_pipe_get_generic_stage_desc(&stage_desc, video_binary,
3759 						   out_frames, in_frame, NULL);
3760 	} else {
3761 		ia_css_pipe_get_generic_stage_desc(&stage_desc, video_binary,
3762 						   out_frames, in_frame, vf_frame);
3763 	}
3764 	err = ia_css_pipeline_create_and_add_stage(me,
3765 		&stage_desc,
3766 		&video_stage);
3767 	if (err != IA_CSS_SUCCESS)
3768 		goto ERR;
3769 
3770 	/* If we use copy iso video, the input must be yuv iso raw */
3771 	if (video_stage) {
3772 		video_stage->args.copy_vf =
3773 		    video_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY;
3774 		video_stage->args.copy_output = video_stage->args.copy_vf;
3775 	}
3776 
3777 	/* when the video binary supports only 1 output pin, vf_pp is needed to
3778 	produce the vf_frame.*/
3779 	if (need_vf_pp && video_stage) {
3780 		in_frame = video_stage->args.out_vf_frame;
3781 		err = add_vf_pp_stage(pipe, in_frame, vf_frame, vf_pp_binary,
3782 				      &vf_pp_stage);
3783 		if (err != IA_CSS_SUCCESS)
3784 			goto ERR;
3785 	}
3786 	if (video_stage) {
3787 		int frm;
3788 #ifndef ISP2401
3789 		for (frm = 0; frm < NUM_TNR_FRAMES; frm++) {
3790 #else
3791 		for (frm = 0; frm < NUM_TNR_FRAMES; frm++) {
3792 #endif
3793 			video_stage->args.tnr_frames[frm] =
3794 			    pipe->pipe_settings.video.tnr_frames[frm];
3795 		}
3796 		for (frm = 0; frm < MAX_NUM_VIDEO_DELAY_FRAMES; frm++) {
3797 			video_stage->args.delay_frames[frm] =
3798 			    pipe->pipe_settings.video.delay_frames[frm];
3799 		}
3800 	}
3801 
3802 	/* Append Extension on Video out, if enabled */
3803 	if (!need_vf_pp && video_stage && pipe->config.acc_extension &&
3804 	    (pipe->config.acc_extension->info.isp.type == IA_CSS_ACC_OUTPUT)) {
3805 		struct ia_css_frame *out = NULL;
3806 		struct ia_css_frame *in = NULL;
3807 
3808 		if ((pipe->config.acc_extension->info.isp.sp.enable.output) &&
3809 		    (pipe->config.acc_extension->info.isp.sp.enable.in_frame) &&
3810 		    (pipe->config.acc_extension->info.isp.sp.enable.out_frame)) {
3811 			/* In/Out Frame mapping to support output frame extension.*/
3812 			out = video_stage->args.out_frame[0];
3813 			err = ia_css_frame_allocate_from_info(&in, &pipe->output_info[0]);
3814 			if (err != IA_CSS_SUCCESS)
3815 				goto ERR;
3816 			video_stage->args.out_frame[0] = in;
3817 		}
3818 
3819 		err = add_firmwares(me, video_binary, pipe->output_stage,
3820 				    last_output_firmware(pipe->output_stage),
3821 				    IA_CSS_BINARY_MODE_VIDEO,
3822 				    in, out, NULL, &video_stage, NULL);
3823 		if (err != IA_CSS_SUCCESS)
3824 			goto ERR;
3825 	}
3826 
3827 	if (need_yuv_pp && video_stage) {
3828 		struct ia_css_frame *tmp_in_frame = video_stage->args.out_frame[0];
3829 		struct ia_css_frame *tmp_out_frame = NULL;
3830 
3831 		for (i = 0; i < num_yuv_scaler; i++) {
3832 			if (is_output_stage[i] == true) {
3833 				tmp_out_frame = out_frame;
3834 			} else {
3835 				tmp_out_frame = NULL;
3836 			}
3837 			err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame,
3838 						   NULL,
3839 						   &yuv_scaler_binary[i],
3840 						   &yuv_scaler_stage);
3841 
3842 			if (err != IA_CSS_SUCCESS) {
3843 				IA_CSS_LEAVE_ERR_PRIVATE(err);
3844 				return err;
3845 			}
3846 			/* we use output port 1 as internal output port */
3847 			if (yuv_scaler_stage)
3848 				tmp_in_frame = yuv_scaler_stage->args.out_frame[1];
3849 		}
3850 	}
3851 
3852 	pipe->pipeline.acquire_isp_each_stage = false;
3853 	ia_css_pipeline_finalize_stages(&pipe->pipeline,
3854 					pipe->stream->config.continuous);
3855 
3856 ERR:
3857 	IA_CSS_LEAVE_ERR_PRIVATE(err);
3858 	return err;
3859 }
3860 
3861 static enum ia_css_err
3862 create_host_acc_pipeline(struct ia_css_pipe *pipe) {
3863 	enum ia_css_err err = IA_CSS_SUCCESS;
3864 	const struct ia_css_fw_info *fw;
3865 	unsigned int i;
3866 
3867 	IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3868 	if ((!pipe) || (!pipe->stream))
3869 	{
3870 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
3871 		return IA_CSS_ERR_INVALID_ARGUMENTS;
3872 	}
3873 
3874 	pipe->pipeline.num_execs = pipe->config.acc_num_execs;
3875 	/* Reset pipe_qos_config to default disable all QOS extension stages */
3876 	if (pipe->config.acc_extension)
3877 		pipe->pipeline.pipe_qos_config = 0;
3878 
3879 	fw = pipe->vf_stage;
3880 	for (i = 0; fw; fw = fw->next)
3881 	{
3882 		err = sh_css_pipeline_add_acc_stage(&pipe->pipeline, fw);
3883 		if (err != IA_CSS_SUCCESS)
3884 			goto ERR;
3885 	}
3886 
3887 	for (i = 0; i < pipe->config.num_acc_stages; i++)
3888 	{
3889 		struct ia_css_fw_info *fw = pipe->config.acc_stages[i];
3890 
3891 		err = sh_css_pipeline_add_acc_stage(&pipe->pipeline, fw);
3892 		if (err != IA_CSS_SUCCESS)
3893 			goto ERR;
3894 	}
3895 
3896 	ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
3897 
3898 ERR:
3899 	IA_CSS_LEAVE_ERR_PRIVATE(err);
3900 	return err;
3901 }
3902 
3903 /* Create stages for preview */
3904 static enum ia_css_err
3905 create_host_preview_pipeline(struct ia_css_pipe *pipe) {
3906 	struct ia_css_pipeline_stage *copy_stage = NULL;
3907 	struct ia_css_pipeline_stage *preview_stage = NULL;
3908 	struct ia_css_pipeline_stage *vf_pp_stage = NULL;
3909 	struct ia_css_pipeline_stage_desc stage_desc;
3910 	struct ia_css_pipeline *me = NULL;
3911 	struct ia_css_binary *copy_binary, *preview_binary, *vf_pp_binary = NULL;
3912 	struct ia_css_frame *in_frame = NULL;
3913 	enum ia_css_err err = IA_CSS_SUCCESS;
3914 	struct ia_css_frame *out_frame;
3915 	struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3916 	bool need_in_frameinfo_memory = false;
3917 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3918 	bool sensor = false;
3919 	bool buffered_sensor = false;
3920 	bool online = false;
3921 	bool continuous = false;
3922 #endif
3923 
3924 	IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3925 	if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW))
3926 	{
3927 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
3928 		return IA_CSS_ERR_INVALID_ARGUMENTS;
3929 	}
3930 
3931 	ia_css_pipe_util_create_output_frames(out_frames);
3932 	/* pipeline already created as part of create_host_pipeline_structure */
3933 	me = &pipe->pipeline;
3934 	ia_css_pipeline_clean(me);
3935 
3936 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3937 	/* When the input system is 2401, always enable 'in_frameinfo_memory'
3938 	 * except for the following:
3939 	 * - Direct Sensor Mode Online Preview
3940 	 * - Buffered Sensor Mode Online Preview
3941 	 * - Direct Sensor Mode Continuous Preview
3942 	 * - Buffered Sensor Mode Continuous Preview
3943 	 */
3944 	sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR);
3945 	buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR);
3946 	online = pipe->stream->config.online;
3947 	continuous = pipe->stream->config.continuous;
3948 	need_in_frameinfo_memory =
3949 	!((sensor && (online || continuous)) || (buffered_sensor && (online || continuous)));
3950 #else
3951 	/* Construct in_frame info (only in case we have dynamic input */
3952 	need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
3953 #endif
3954 	if (need_in_frameinfo_memory)
3955 	{
3956 		err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame,
3957 							IA_CSS_FRAME_FORMAT_RAW);
3958 		if (err != IA_CSS_SUCCESS)
3959 			goto ERR;
3960 
3961 		in_frame = &me->in_frame;
3962 	} else
3963 	{
3964 		in_frame = NULL;
3965 	}
3966 
3967 	err = init_out_frameinfo_defaults(pipe, &me->out_frame[0], 0);
3968 	if (err != IA_CSS_SUCCESS)
3969 		goto ERR;
3970 	out_frame = &me->out_frame[0];
3971 
3972 	copy_binary    = &pipe->pipe_settings.preview.copy_binary;
3973 	preview_binary = &pipe->pipe_settings.preview.preview_binary;
3974 	if (pipe->pipe_settings.preview.vf_pp_binary.info)
3975 		vf_pp_binary = &pipe->pipe_settings.preview.vf_pp_binary;
3976 
3977 	if (pipe->pipe_settings.preview.copy_binary.info)
3978 	{
3979 		ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3980 		ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
3981 						   out_frames, NULL, NULL);
3982 		err = ia_css_pipeline_create_and_add_stage(me,
3983 			&stage_desc,
3984 			&copy_stage);
3985 		if (err != IA_CSS_SUCCESS)
3986 			goto ERR;
3987 		in_frame = me->stages->args.out_frame[0];
3988 #ifndef ISP2401
3989 	} else
3990 	{
3991 #else
3992 	} else if (pipe->stream->config.continuous)
3993 	{
3994 #endif
3995 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3996 		/* When continuous is enabled, configure in_frame with the
3997 		 * last pipe, which is the copy pipe.
3998 		 */
3999 		if (continuous || !online) {
4000 			in_frame = pipe->stream->last_pipe->continuous_frames[0];
4001 		}
4002 #else
4003 		in_frame = pipe->continuous_frames[0];
4004 #endif
4005 	}
4006 
4007 	if (vf_pp_binary)
4008 	{
4009 		ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
4010 		ia_css_pipe_get_generic_stage_desc(&stage_desc, preview_binary,
4011 						   out_frames, in_frame, NULL);
4012 	} else
4013 	{
4014 		ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
4015 		ia_css_pipe_get_generic_stage_desc(&stage_desc, preview_binary,
4016 						   out_frames, in_frame, NULL);
4017 	}
4018 	err = ia_css_pipeline_create_and_add_stage(me,
4019 		&stage_desc,
4020 		&preview_stage);
4021 	if (err != IA_CSS_SUCCESS)
4022 		goto ERR;
4023 	/* If we use copy iso preview, the input must be yuv iso raw */
4024 	preview_stage->args.copy_vf =
4025 	    preview_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY;
4026 	preview_stage->args.copy_output = !preview_stage->args.copy_vf;
4027 	if (preview_stage->args.copy_vf && !preview_stage->args.out_vf_frame)
4028 	{
4029 		/* in case of copy, use the vf frame as output frame */
4030 		preview_stage->args.out_vf_frame =
4031 		    preview_stage->args.out_frame[0];
4032 	}
4033 	if (vf_pp_binary)
4034 	{
4035 		if (preview_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY)
4036 			in_frame = preview_stage->args.out_vf_frame;
4037 		else
4038 			in_frame = preview_stage->args.out_frame[0];
4039 		err = add_vf_pp_stage(pipe, in_frame, out_frame, vf_pp_binary,
4040 				      &vf_pp_stage);
4041 		if (err != IA_CSS_SUCCESS)
4042 			goto ERR;
4043 	}
4044 
4045 	pipe->pipeline.acquire_isp_each_stage = false;
4046 	ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
4047 
4048 ERR:
4049 	IA_CSS_LEAVE_ERR_PRIVATE(err);
4050 	return err;
4051 }
4052 
4053 static void send_raw_frames(struct ia_css_pipe *pipe)
4054 {
4055 	if (pipe->stream->config.continuous) {
4056 		unsigned int i;
4057 
4058 		sh_css_update_host2sp_cont_num_raw_frames
4059 		(pipe->stream->config.init_num_cont_raw_buf, true);
4060 		sh_css_update_host2sp_cont_num_raw_frames
4061 		(pipe->stream->config.target_num_cont_raw_buf, false);
4062 
4063 		/* Hand-over all the SP-internal buffers */
4064 		for (i = 0; i < pipe->stream->config.init_num_cont_raw_buf; i++) {
4065 			sh_css_update_host2sp_offline_frame(i,
4066 							    pipe->continuous_frames[i], pipe->cont_md_buffers[i]);
4067 		}
4068 	}
4069 
4070 	return;
4071 }
4072 
4073 static enum ia_css_err
4074 preview_start(struct ia_css_pipe *pipe) {
4075 	struct ia_css_pipeline *me;
4076 	struct ia_css_binary *copy_binary, *preview_binary, *vf_pp_binary = NULL;
4077 	enum ia_css_err err = IA_CSS_SUCCESS;
4078 	struct ia_css_pipe *copy_pipe, *capture_pipe;
4079 	struct ia_css_pipe *acc_pipe;
4080 	enum sh_css_pipe_config_override copy_ovrd;
4081 	enum ia_css_input_mode preview_pipe_input_mode;
4082 	const struct ia_css_coordinate *coord = NULL;
4083 	const struct ia_css_isp_parameters *params = NULL;
4084 
4085 	IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
4086 	if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW))
4087 	{
4088 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
4089 		return IA_CSS_ERR_INVALID_ARGUMENTS;
4090 	}
4091 
4092 	me = &pipe->pipeline;
4093 
4094 	preview_pipe_input_mode = pipe->stream->config.mode;
4095 
4096 	copy_pipe    = pipe->pipe_settings.preview.copy_pipe;
4097 	capture_pipe = pipe->pipe_settings.preview.capture_pipe;
4098 	acc_pipe     = pipe->pipe_settings.preview.acc_pipe;
4099 
4100 	copy_binary    = &pipe->pipe_settings.preview.copy_binary;
4101 	preview_binary = &pipe->pipe_settings.preview.preview_binary;
4102 	if (pipe->pipe_settings.preview.vf_pp_binary.info)
4103 		vf_pp_binary = &pipe->pipe_settings.preview.vf_pp_binary;
4104 
4105 	sh_css_metrics_start_frame();
4106 
4107 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
4108 	/* multi stream video needs mipi buffers */
4109 	err = send_mipi_frames(pipe);
4110 	if (err != IA_CSS_SUCCESS) {
4111 	    	IA_CSS_LEAVE_ERR_PRIVATE(err);
4112 		return err;
4113 	}
4114 #endif
4115 	send_raw_frames(pipe);
4116 
4117 	{
4118 		unsigned int thread_id;
4119 
4120 		ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
4121 		copy_ovrd = 1 << thread_id;
4122 
4123 		if (pipe->stream->cont_capt)
4124 		{
4125 			ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe),
4126 							 &thread_id);
4127 			copy_ovrd |= 1 << thread_id;
4128 		}
4129 	}
4130 
4131 	if (atomisp_hw_is_isp2401) {
4132 		coord = &pipe->config.internal_frame_origin_bqs_on_sctbl;
4133 		params = pipe->stream->isp_params_configs;
4134 	}
4135 
4136 	/* Construct and load the copy pipe */
4137 	if (pipe->stream->config.continuous)
4138 	{
4139 		sh_css_sp_init_pipeline(&copy_pipe->pipeline,
4140 					IA_CSS_PIPE_ID_COPY,
4141 					(uint8_t)ia_css_pipe_get_pipe_num(copy_pipe),
4142 					false,
4143 					pipe->stream->config.pixels_per_clock == 2, false,
4144 					false, pipe->required_bds_factor,
4145 					copy_ovrd,
4146 					pipe->stream->config.mode,
4147 					&pipe->stream->config.metadata_config,
4148 					&pipe->stream->info.metadata_info,
4149 #if !defined(HAS_NO_INPUT_SYSTEM)
4150 					pipe->stream->config.source.port.port,
4151 #endif
4152 					coord,
4153 					params);
4154 
4155 		/* make the preview pipe start with mem mode input, copy handles
4156 		   the actual mode */
4157 		preview_pipe_input_mode = IA_CSS_INPUT_MODE_MEMORY;
4158 	}
4159 
4160 	/* Construct and load the capture pipe */
4161 	if (pipe->stream->cont_capt)
4162 	{
4163 		sh_css_sp_init_pipeline(&capture_pipe->pipeline,
4164 					IA_CSS_PIPE_ID_CAPTURE,
4165 					(uint8_t)ia_css_pipe_get_pipe_num(capture_pipe),
4166 					capture_pipe->config.default_capture_config.enable_xnr != 0,
4167 					capture_pipe->stream->config.pixels_per_clock == 2,
4168 					true, /* continuous */
4169 					false, /* offline */
4170 					capture_pipe->required_bds_factor,
4171 					0,
4172 					IA_CSS_INPUT_MODE_MEMORY,
4173 					&pipe->stream->config.metadata_config,
4174 					&pipe->stream->info.metadata_info,
4175 #if !defined(HAS_NO_INPUT_SYSTEM)
4176 					(enum mipi_port_id)0,
4177 #endif
4178 					coord,
4179 					params);
4180 	}
4181 
4182 	if (acc_pipe)
4183 	{
4184 		sh_css_sp_init_pipeline(&acc_pipe->pipeline,
4185 					IA_CSS_PIPE_ID_ACC,
4186 					(uint8_t)ia_css_pipe_get_pipe_num(acc_pipe),
4187 					false,
4188 					pipe->stream->config.pixels_per_clock == 2,
4189 					false, /* continuous */
4190 					false, /* offline */
4191 					pipe->required_bds_factor,
4192 					0,
4193 					IA_CSS_INPUT_MODE_MEMORY,
4194 					NULL,
4195 					NULL,
4196 #if !defined(HAS_NO_INPUT_SYSTEM)
4197 					(enum mipi_port_id)0,
4198 #endif
4199 					coord,
4200 					params);
4201 	}
4202 
4203 	start_pipe(pipe, copy_ovrd, preview_pipe_input_mode);
4204 
4205 	IA_CSS_LEAVE_ERR_PRIVATE(err);
4206 	return err;
4207 }
4208 
4209 enum ia_css_err
4210 ia_css_pipe_enqueue_buffer(struct ia_css_pipe *pipe,
4211 			   const struct ia_css_buffer *buffer) {
4212 	enum ia_css_err return_err = IA_CSS_SUCCESS;
4213 	unsigned int thread_id;
4214 	enum sh_css_queue_id queue_id;
4215 	struct ia_css_pipeline *pipeline;
4216 	struct ia_css_pipeline_stage *stage;
4217 	struct ia_css_rmgr_vbuf_handle p_vbuf;
4218 	struct ia_css_rmgr_vbuf_handle *h_vbuf;
4219 	struct sh_css_hmm_buffer ddr_buffer;
4220 	enum ia_css_buffer_type buf_type;
4221 	enum ia_css_pipe_id pipe_id;
4222 	bool ret_err;
4223 
4224 	IA_CSS_ENTER("pipe=%p, buffer=%p", pipe, buffer);
4225 
4226 	if ((!pipe) || (!buffer))
4227 	{
4228 		IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4229 		return IA_CSS_ERR_INVALID_ARGUMENTS;
4230 	}
4231 
4232 	buf_type = buffer->type;
4233 	/* following code will be enabled when IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME
4234 	   is removed */
4235 #if 0
4236 	if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
4237 	{
4238 		bool found_pipe = false;
4239 
4240 		for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
4241 			if ((buffer->data.frame->info.res.width == pipe->output_info[i].res.width) &&
4242 			    (buffer->data.frame->info.res.height == pipe->output_info[i].res.height)) {
4243 				buf_type += i;
4244 				found_pipe = true;
4245 				break;
4246 			}
4247 		}
4248 		if (!found_pipe)
4249 			return IA_CSS_ERR_INVALID_ARGUMENTS;
4250 	}
4251 	if (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME)
4252 	{
4253 		bool found_pipe = false;
4254 
4255 		for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
4256 			if ((buffer->data.frame->info.res.width == pipe->vf_output_info[i].res.width) &&
4257 			    (buffer->data.frame->info.res.height == pipe->vf_output_info[i].res.height)) {
4258 				buf_type += i;
4259 				found_pipe = true;
4260 				break;
4261 			}
4262 		}
4263 		if (!found_pipe)
4264 			return IA_CSS_ERR_INVALID_ARGUMENTS;
4265 	}
4266 #endif
4267 	pipe_id = pipe->mode;
4268 
4269 	IA_CSS_LOG("pipe_id=%d, buf_type=%d", pipe_id, buf_type);
4270 
4271 	assert(pipe_id < IA_CSS_PIPE_ID_NUM);
4272 	assert(buf_type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE);
4273 	if ((buf_type == IA_CSS_BUFFER_TYPE_INVALID) ||
4274 	    (buf_type >= IA_CSS_NUM_DYNAMIC_BUFFER_TYPE) ||
4275 	    (pipe_id >= IA_CSS_PIPE_ID_NUM))
4276 	{
4277 		IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR);
4278 		return IA_CSS_ERR_INTERNAL_ERROR;
4279 	}
4280 
4281 	ret_err = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
4282 	if (!ret_err)
4283 	{
4284 		IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4285 		return IA_CSS_ERR_INVALID_ARGUMENTS;
4286 	}
4287 
4288 	ret_err = ia_css_query_internal_queue_id(buf_type, thread_id, &queue_id);
4289 	if (!ret_err)
4290 	{
4291 		IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4292 		return IA_CSS_ERR_INVALID_ARGUMENTS;
4293 	}
4294 
4295 	if ((queue_id <= SH_CSS_INVALID_QUEUE_ID) || (queue_id >= SH_CSS_MAX_NUM_QUEUES))
4296 	{
4297 		IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4298 		return IA_CSS_ERR_INVALID_ARGUMENTS;
4299 	}
4300 
4301 	if (!sh_css_sp_is_running())
4302 	{
4303 		IA_CSS_LOG("SP is not running!");
4304 		IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE);
4305 		/* SP is not running. The queues are not valid */
4306 		return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4307 	}
4308 
4309 	pipeline = &pipe->pipeline;
4310 
4311 	assert(pipeline ||
4312 	       pipe_id == IA_CSS_PIPE_ID_COPY ||
4313 	       pipe_id == IA_CSS_PIPE_ID_ACC);
4314 
4315 	assert(sizeof(NULL) <= sizeof(ddr_buffer.kernel_ptr));
4316 	ddr_buffer.kernel_ptr = HOST_ADDRESS(NULL);
4317 	ddr_buffer.cookie_ptr = buffer->driver_cookie;
4318 	ddr_buffer.timing_data = buffer->timing_data;
4319 
4320 	if (buf_type == IA_CSS_BUFFER_TYPE_3A_STATISTICS)
4321 	{
4322 		if (!buffer->data.stats_3a) {
4323 			IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4324 			return IA_CSS_ERR_INVALID_ARGUMENTS;
4325 		}
4326 		ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.stats_3a);
4327 		ddr_buffer.payload.s3a = *buffer->data.stats_3a;
4328 	} else if (buf_type == IA_CSS_BUFFER_TYPE_DIS_STATISTICS)
4329 	{
4330 		if (!buffer->data.stats_dvs) {
4331 			IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4332 			return IA_CSS_ERR_INVALID_ARGUMENTS;
4333 		}
4334 		ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.stats_dvs);
4335 		ddr_buffer.payload.dis = *buffer->data.stats_dvs;
4336 	} else if (buf_type == IA_CSS_BUFFER_TYPE_METADATA)
4337 	{
4338 		if (!buffer->data.metadata) {
4339 			IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4340 			return IA_CSS_ERR_INVALID_ARGUMENTS;
4341 		}
4342 		ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.metadata);
4343 		ddr_buffer.payload.metadata = *buffer->data.metadata;
4344 	} else if ((buf_type == IA_CSS_BUFFER_TYPE_INPUT_FRAME)
4345 		   || (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
4346 		   || (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME)
4347 		   || (buf_type == IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME)
4348 		   || (buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME))
4349 	{
4350 		if (!buffer->data.frame) {
4351 			IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4352 			return IA_CSS_ERR_INVALID_ARGUMENTS;
4353 		}
4354 		ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.frame);
4355 		ddr_buffer.payload.frame.frame_data = buffer->data.frame->data;
4356 		ddr_buffer.payload.frame.flashed = 0;
4357 
4358 		ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
4359 				    "ia_css_pipe_enqueue_buffer() buf_type=%d, data(DDR address)=0x%x\n",
4360 				    buf_type, buffer->data.frame->data);
4361 
4362 #if CONFIG_ON_FRAME_ENQUEUE()
4363 		return_err = set_config_on_frame_enqueue(
4364 				 &buffer->data.frame->info,
4365 				 &ddr_buffer.payload.frame);
4366 		if (return_err != IA_CSS_SUCCESS) {
4367 			IA_CSS_LEAVE_ERR(return_err);
4368 			return return_err;
4369 		}
4370 #endif
4371 	}
4372 
4373 	/* start of test for using rmgr for acq/rel memory */
4374 	p_vbuf.vptr = 0;
4375 	p_vbuf.count = 0;
4376 	p_vbuf.size = sizeof(struct sh_css_hmm_buffer);
4377 	h_vbuf = &p_vbuf;
4378 	/* TODO: change next to correct pool for optimization */
4379 	ia_css_rmgr_acq_vbuf(hmm_buffer_pool, &h_vbuf);
4380 
4381 	assert(h_vbuf);
4382 	assert(h_vbuf->vptr != 0x0);
4383 
4384 	if ((!h_vbuf) || (h_vbuf->vptr == 0x0))
4385 	{
4386 		IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR);
4387 		return IA_CSS_ERR_INTERNAL_ERROR;
4388 	}
4389 
4390 	mmgr_store(h_vbuf->vptr,
4391 		   (void *)(&ddr_buffer),
4392 		   sizeof(struct sh_css_hmm_buffer));
4393 	if ((buf_type == IA_CSS_BUFFER_TYPE_3A_STATISTICS)
4394 	    || (buf_type == IA_CSS_BUFFER_TYPE_DIS_STATISTICS)
4395 	    || (buf_type == IA_CSS_BUFFER_TYPE_LACE_STATISTICS))
4396 	{
4397 		if (!pipeline) {
4398 			ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &h_vbuf);
4399 			IA_CSS_LOG("pipeline is empty!");
4400 			IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR);
4401 			return IA_CSS_ERR_INTERNAL_ERROR;
4402 		}
4403 
4404 		for (stage = pipeline->stages; stage; stage = stage->next) {
4405 			/* The SP will read the params
4406 				after it got empty 3a and dis */
4407 			if (STATS_ENABLED(stage)) {
4408 				/* there is a stage that needs it */
4409 				return_err = ia_css_bufq_enqueue_buffer(thread_id,
4410 									queue_id,
4411 									(uint32_t)h_vbuf->vptr);
4412 			}
4413 		}
4414 	} else if ((buf_type == IA_CSS_BUFFER_TYPE_INPUT_FRAME)
4415 		   || (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
4416 		   || (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME)
4417 		   || (buf_type == IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME)
4418 		   || (buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME)
4419 		   || (buf_type == IA_CSS_BUFFER_TYPE_METADATA))
4420 	{
4421 		return_err = ia_css_bufq_enqueue_buffer(thread_id,
4422 							queue_id,
4423 							(uint32_t)h_vbuf->vptr);
4424 #if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS)
4425 		if ((return_err == IA_CSS_SUCCESS) &&
4426 		    (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)) {
4427 			IA_CSS_LOG("pfp: enqueued OF %d to q %d thread %d",
4428 				   ddr_buffer.payload.frame.frame_data,
4429 				   queue_id, thread_id);
4430 		}
4431 #endif
4432 	}
4433 
4434 	if (return_err == IA_CSS_SUCCESS)
4435 	{
4436 		if (sh_css_hmm_buffer_record_acquire(
4437 			h_vbuf, buf_type,
4438 			HOST_ADDRESS(ddr_buffer.kernel_ptr))) {
4439 			IA_CSS_LOG("send vbuf=%p", h_vbuf);
4440 		} else {
4441 			return_err = IA_CSS_ERR_INTERNAL_ERROR;
4442 			IA_CSS_ERROR("hmm_buffer_record[]: no available slots\n");
4443 		}
4444 	}
4445 
4446 	/*
4447 	 * Tell the SP which queues are not empty,
4448 	 * by sending the software event.
4449 	 */
4450 	if (return_err == IA_CSS_SUCCESS)
4451 	{
4452 		if (!sh_css_sp_is_running()) {
4453 			/* SP is not running. The queues are not valid */
4454 			IA_CSS_LOG("SP is not running!");
4455 			IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE);
4456 			return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4457 		}
4458 		return_err = ia_css_bufq_enqueue_psys_event(
4459 				 IA_CSS_PSYS_SW_EVENT_BUFFER_ENQUEUED,
4460 				 (uint8_t)thread_id,
4461 				 queue_id,
4462 				 0);
4463 	} else
4464 	{
4465 		ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &h_vbuf);
4466 		IA_CSS_ERROR("buffer not enqueued");
4467 	}
4468 
4469 	IA_CSS_LEAVE("return value = %d", return_err);
4470 
4471 	return return_err;
4472 }
4473 
4474 /*
4475  * TODO: Free up the hmm memory space.
4476 	 */
4477 enum ia_css_err
4478 ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe,
4479 			   struct ia_css_buffer *buffer) {
4480 	enum ia_css_err return_err;
4481 	enum sh_css_queue_id queue_id;
4482 	hrt_vaddress ddr_buffer_addr = (hrt_vaddress)0;
4483 	struct sh_css_hmm_buffer ddr_buffer;
4484 	enum ia_css_buffer_type buf_type;
4485 	enum ia_css_pipe_id pipe_id;
4486 	unsigned int thread_id;
4487 	hrt_address kernel_ptr = 0;
4488 	bool ret_err;
4489 
4490 	IA_CSS_ENTER("pipe=%p, buffer=%p", pipe, buffer);
4491 
4492 	if ((!pipe) || (!buffer))
4493 	{
4494 		IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4495 		return IA_CSS_ERR_INVALID_ARGUMENTS;
4496 	}
4497 
4498 	pipe_id = pipe->mode;
4499 
4500 	buf_type = buffer->type;
4501 
4502 	IA_CSS_LOG("pipe_id=%d, buf_type=%d", pipe_id, buf_type);
4503 
4504 	ddr_buffer.kernel_ptr = 0;
4505 
4506 	ret_err = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
4507 	if (!ret_err)
4508 	{
4509 		IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4510 		return IA_CSS_ERR_INVALID_ARGUMENTS;
4511 	}
4512 
4513 	ret_err = ia_css_query_internal_queue_id(buf_type, thread_id, &queue_id);
4514 	if (!ret_err)
4515 	{
4516 		IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4517 		return IA_CSS_ERR_INVALID_ARGUMENTS;
4518 	}
4519 
4520 	if ((queue_id <= SH_CSS_INVALID_QUEUE_ID) || (queue_id >= SH_CSS_MAX_NUM_QUEUES))
4521 	{
4522 		IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4523 		return IA_CSS_ERR_INVALID_ARGUMENTS;
4524 	}
4525 
4526 	if (!sh_css_sp_is_running())
4527 	{
4528 		IA_CSS_LOG("SP is not running!");
4529 		IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE);
4530 		/* SP is not running. The queues are not valid */
4531 		return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4532 	}
4533 
4534 	return_err = ia_css_bufq_dequeue_buffer(queue_id,
4535 						(uint32_t *)&ddr_buffer_addr);
4536 
4537 	if (return_err == IA_CSS_SUCCESS)
4538 	{
4539 		struct ia_css_frame *frame;
4540 		struct sh_css_hmm_buffer_record *hmm_buffer_record = NULL;
4541 
4542 		IA_CSS_LOG("receive vbuf=%x", (int)ddr_buffer_addr);
4543 
4544 		/* Validate the ddr_buffer_addr and buf_type */
4545 		hmm_buffer_record = sh_css_hmm_buffer_record_validate(
4546 		    ddr_buffer_addr, buf_type);
4547 		if (hmm_buffer_record) {
4548 			/* valid hmm_buffer_record found. Save the kernel_ptr
4549 			 * for validation after performing mmgr_load.  The
4550 			 * vbuf handle and buffer_record can be released.
4551 			 */
4552 			kernel_ptr = hmm_buffer_record->kernel_ptr;
4553 			ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &hmm_buffer_record->h_vbuf);
4554 			sh_css_hmm_buffer_record_reset(hmm_buffer_record);
4555 		} else {
4556 			IA_CSS_ERROR("hmm_buffer_record not found (0x%x) buf_type(%d)",
4557 				     ddr_buffer_addr, buf_type);
4558 			IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR);
4559 			return IA_CSS_ERR_INTERNAL_ERROR;
4560 		}
4561 
4562 		mmgr_load(ddr_buffer_addr,
4563 			  &ddr_buffer,
4564 			  sizeof(struct sh_css_hmm_buffer));
4565 
4566 		/* if the kernel_ptr is 0 or an invalid, return an error.
4567 		 * do not access the buffer via the kernal_ptr.
4568 		 */
4569 		if ((ddr_buffer.kernel_ptr == 0) ||
4570 		    (kernel_ptr != HOST_ADDRESS(ddr_buffer.kernel_ptr))) {
4571 			IA_CSS_ERROR("kernel_ptr invalid");
4572 			IA_CSS_ERROR("expected: (0x%llx)", (u64)kernel_ptr);
4573 			IA_CSS_ERROR("actual: (0x%llx)", (u64)HOST_ADDRESS(ddr_buffer.kernel_ptr));
4574 			IA_CSS_ERROR("buf_type: %d\n", buf_type);
4575 			IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR);
4576 			return IA_CSS_ERR_INTERNAL_ERROR;
4577 		}
4578 
4579 		if (ddr_buffer.kernel_ptr != 0) {
4580 			/* buffer->exp_id : all instances to be removed later once the driver change
4581 			 * is completed. See patch #5758 for reference */
4582 			buffer->exp_id = 0;
4583 			buffer->driver_cookie = ddr_buffer.cookie_ptr;
4584 			buffer->timing_data = ddr_buffer.timing_data;
4585 
4586 			if ((buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) ||
4587 			    (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME)) {
4588 				buffer->isys_eof_clock_tick.ticks = ddr_buffer.isys_eof_clock_tick;
4589 			}
4590 
4591 			switch (buf_type) {
4592 			case IA_CSS_BUFFER_TYPE_INPUT_FRAME:
4593 			case IA_CSS_BUFFER_TYPE_OUTPUT_FRAME:
4594 			case IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME:
4595 				if ((pipe) && (pipe->stop_requested == true)) {
4596 #if defined(USE_INPUT_SYSTEM_VERSION_2)
4597 					/* free mipi frames only for old input system
4598 					 * for 2401 it is done in ia_css_stream_destroy call
4599 					 */
4600 					return_err = free_mipi_frames(pipe);
4601 					if (return_err != IA_CSS_SUCCESS) {
4602 						IA_CSS_LOG("free_mipi_frames() failed");
4603 						IA_CSS_LEAVE_ERR(return_err);
4604 						return return_err;
4605 					}
4606 #endif
4607 					pipe->stop_requested = false;
4608 				}
4609 			case IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME:
4610 			case IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME:
4611 				frame = (struct ia_css_frame *)HOST_ADDRESS(ddr_buffer.kernel_ptr);
4612 				buffer->data.frame = frame;
4613 				buffer->exp_id = ddr_buffer.payload.frame.exp_id;
4614 				frame->exp_id = ddr_buffer.payload.frame.exp_id;
4615 				frame->isp_config_id = ddr_buffer.payload.frame.isp_parameters_id;
4616 				if (ddr_buffer.payload.frame.flashed == 1)
4617 					frame->flash_state =
4618 					    IA_CSS_FRAME_FLASH_STATE_PARTIAL;
4619 				if (ddr_buffer.payload.frame.flashed == 2)
4620 					frame->flash_state =
4621 					    IA_CSS_FRAME_FLASH_STATE_FULL;
4622 				frame->valid = pipe->num_invalid_frames == 0;
4623 				if (!frame->valid)
4624 					pipe->num_invalid_frames--;
4625 
4626 				if (frame->info.format == IA_CSS_FRAME_FORMAT_BINARY_8) {
4627 #ifdef USE_INPUT_SYSTEM_VERSION_2401
4628 					frame->planes.binary.size = frame->data_bytes;
4629 #else
4630 					frame->planes.binary.size =
4631 					    sh_css_sp_get_binary_copy_size();
4632 #endif
4633 				}
4634 #if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS)
4635 				if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) {
4636 					IA_CSS_LOG("pfp: dequeued OF %d with config id %d thread %d",
4637 						   frame->data, frame->isp_config_id, thread_id);
4638 				}
4639 #endif
4640 
4641 				ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
4642 						    "ia_css_pipe_dequeue_buffer() buf_type=%d, data(DDR address)=0x%x\n",
4643 						    buf_type, buffer->data.frame->data);
4644 
4645 				break;
4646 			case IA_CSS_BUFFER_TYPE_3A_STATISTICS:
4647 				buffer->data.stats_3a =
4648 				    (struct ia_css_isp_3a_statistics *)HOST_ADDRESS(ddr_buffer.kernel_ptr);
4649 				buffer->exp_id = ddr_buffer.payload.s3a.exp_id;
4650 				buffer->data.stats_3a->exp_id = ddr_buffer.payload.s3a.exp_id;
4651 				buffer->data.stats_3a->isp_config_id = ddr_buffer.payload.s3a.isp_config_id;
4652 				break;
4653 			case IA_CSS_BUFFER_TYPE_DIS_STATISTICS:
4654 				buffer->data.stats_dvs =
4655 				    (struct ia_css_isp_dvs_statistics *)
4656 				    HOST_ADDRESS(ddr_buffer.kernel_ptr);
4657 				buffer->exp_id = ddr_buffer.payload.dis.exp_id;
4658 				buffer->data.stats_dvs->exp_id = ddr_buffer.payload.dis.exp_id;
4659 				break;
4660 			case IA_CSS_BUFFER_TYPE_LACE_STATISTICS:
4661 				break;
4662 			case IA_CSS_BUFFER_TYPE_METADATA:
4663 				buffer->data.metadata =
4664 				    (struct ia_css_metadata *)HOST_ADDRESS(ddr_buffer.kernel_ptr);
4665 				buffer->exp_id = ddr_buffer.payload.metadata.exp_id;
4666 				buffer->data.metadata->exp_id = ddr_buffer.payload.metadata.exp_id;
4667 				break;
4668 			default:
4669 				return_err = IA_CSS_ERR_INTERNAL_ERROR;
4670 				break;
4671 			}
4672 		}
4673 	}
4674 
4675 	/*
4676 	 * Tell the SP which queues are not full,
4677 	 * by sending the software event.
4678 	 */
4679 	if (return_err == IA_CSS_SUCCESS)
4680 	{
4681 		if (!sh_css_sp_is_running()) {
4682 			IA_CSS_LOG("SP is not running!");
4683 			IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE);
4684 			/* SP is not running. The queues are not valid */
4685 			return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4686 		}
4687 		ia_css_bufq_enqueue_psys_event(
4688 		    IA_CSS_PSYS_SW_EVENT_BUFFER_DEQUEUED,
4689 		    0,
4690 		    queue_id,
4691 		    0);
4692 	}
4693 	IA_CSS_LEAVE("buffer=%p", buffer);
4694 
4695 	return return_err;
4696 }
4697 
4698 /*
4699  * Cannot Move this to event module as it is of ia_css_event_type which is declared in ia_css.h
4700  * TODO: modify and move it if possible.
4701  *
4702  * !!!IMPORTANT!!! KEEP THE FOLLOWING IN SYNC:
4703  * 1) "enum ia_css_event_type"					(ia_css_event_public.h)
4704  * 2) "enum sh_css_sp_event_type"				(sh_css_internal.h)
4705  * 3) "enum ia_css_event_type event_id_2_event_mask"		(event_handler.sp.c)
4706  * 4) "enum ia_css_event_type convert_event_sp_to_host_domain"	(sh_css.c)
4707  */
4708 static enum ia_css_event_type convert_event_sp_to_host_domain[] = {
4709 	IA_CSS_EVENT_TYPE_OUTPUT_FRAME_DONE,	/** Output frame ready. */
4710 	IA_CSS_EVENT_TYPE_SECOND_OUTPUT_FRAME_DONE,	/** Second output frame ready. */
4711 	IA_CSS_EVENT_TYPE_VF_OUTPUT_FRAME_DONE,	/** Viewfinder Output frame ready. */
4712 	IA_CSS_EVENT_TYPE_SECOND_VF_OUTPUT_FRAME_DONE,	/** Second viewfinder Output frame ready. */
4713 	IA_CSS_EVENT_TYPE_3A_STATISTICS_DONE,	/** Indication that 3A statistics are available. */
4714 	IA_CSS_EVENT_TYPE_DIS_STATISTICS_DONE,	/** Indication that DIS statistics are available. */
4715 	IA_CSS_EVENT_TYPE_PIPELINE_DONE,	/** Pipeline Done event, sent after last pipeline stage. */
4716 	IA_CSS_EVENT_TYPE_FRAME_TAGGED,		/** Frame tagged. */
4717 	IA_CSS_EVENT_TYPE_INPUT_FRAME_DONE,	/** Input frame ready. */
4718 	IA_CSS_EVENT_TYPE_METADATA_DONE,	/** Metadata ready. */
4719 	IA_CSS_EVENT_TYPE_LACE_STATISTICS_DONE,	/** Indication that LACE statistics are available. */
4720 	IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE,	/** Extension stage executed. */
4721 	IA_CSS_EVENT_TYPE_TIMER,		/** Timing measurement data. */
4722 	IA_CSS_EVENT_TYPE_PORT_EOF,		/** End Of Frame event, sent when in buffered sensor mode. */
4723 	IA_CSS_EVENT_TYPE_FW_WARNING,		/** Performance warning encountered by FW */
4724 	IA_CSS_EVENT_TYPE_FW_ASSERT,		/** Assertion hit by FW */
4725 	0,					/* error if sp passes  SH_CSS_SP_EVENT_NR_OF_TYPES as a valid event. */
4726 };
4727 
4728 enum ia_css_err
4729 ia_css_dequeue_event(struct ia_css_event *event) {
4730 	return ia_css_dequeue_psys_event(event);
4731 }
4732 
4733 enum ia_css_err
4734 ia_css_dequeue_psys_event(struct ia_css_event *event) {
4735 	enum ia_css_pipe_id pipe_id = 0;
4736 	u8 payload[4] = {0, 0, 0, 0};
4737 	enum ia_css_err ret_err;
4738 
4739 	/*TODO:
4740 	 * a) use generic decoding function , same as the one used by sp.
4741 	 * b) group decode and dequeue into eventQueue module
4742 	 *
4743 	 * We skip the IA_CSS_ENTER logging call
4744 	 * to avoid flooding the logs when the host application
4745 	 * uses polling. */
4746 	if (!event)
4747 		return IA_CSS_ERR_INVALID_ARGUMENTS;
4748 
4749 	if (!sh_css_sp_is_running())
4750 	{
4751 		/* SP is not running. The queues are not valid */
4752 		return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4753 	}
4754 
4755 	/* dequeue the event (if any) from the psys event queue */
4756 	ret_err = ia_css_bufq_dequeue_psys_event(payload);
4757 	if (ret_err != IA_CSS_SUCCESS)
4758 		return ret_err;
4759 
4760 	IA_CSS_LOG("event dequeued from psys event queue");
4761 
4762 	/* Tell the SP that we dequeued an event from the event queue. */
4763 	ia_css_bufq_enqueue_psys_event(
4764 	    IA_CSS_PSYS_SW_EVENT_EVENT_DEQUEUED, 0, 0, 0);
4765 
4766 	/* Events are decoded into 4 bytes of payload, the first byte
4767 	 * contains the sp event type. This is converted to a host enum.
4768 	 * TODO: can this enum conversion be eliminated */
4769 	event->type = convert_event_sp_to_host_domain[payload[0]];
4770 	/* Some sane default values since not all events use all fields. */
4771 	event->pipe = NULL;
4772 	event->port = MIPI_PORT0_ID;
4773 	event->exp_id = 0;
4774 	event->fw_warning = IA_CSS_FW_WARNING_NONE;
4775 	event->fw_handle = 0;
4776 	event->timer_data = 0;
4777 	event->timer_code = 0;
4778 	event->timer_subcode = 0;
4779 
4780 	if (event->type == IA_CSS_EVENT_TYPE_TIMER)
4781 	{
4782 		/* timer event ??? get the 2nd event and decode the data into the event struct */
4783 		u32 tmp_data;
4784 		/* 1st event: LSB 16-bit timer data and code */
4785 		event->timer_data = ((payload[1] & 0xFF) | ((payload[3] & 0xFF) << 8));
4786 		event->timer_code = payload[2];
4787 		payload[0] = payload[1] = payload[2] = payload[3] = 0;
4788 		ret_err = ia_css_bufq_dequeue_psys_event(payload);
4789 		if (ret_err != IA_CSS_SUCCESS) {
4790 			/* no 2nd event ??? an error */
4791 			/* Putting IA_CSS_ERROR is resulting in failures in
4792 			 * Merrifield smoke testing  */
4793 			IA_CSS_WARNING("Timer: Error de-queuing the 2nd TIMER event!!!\n");
4794 			return ret_err;
4795 		}
4796 		ia_css_bufq_enqueue_psys_event(
4797 		    IA_CSS_PSYS_SW_EVENT_EVENT_DEQUEUED, 0, 0, 0);
4798 		event->type = convert_event_sp_to_host_domain[payload[0]];
4799 		/* It's a timer */
4800 		if (event->type == IA_CSS_EVENT_TYPE_TIMER) {
4801 			/* 2nd event data: MSB 16-bit timer and subcode */
4802 			tmp_data = ((payload[1] & 0xFF) | ((payload[3] & 0xFF) << 8));
4803 			event->timer_data |= (tmp_data << 16);
4804 			event->timer_subcode = payload[2];
4805 		}
4806 		/* It's a non timer event. So clear first half of the timer event data.
4807 		* If the second part of the TIMER event is not received, we discard
4808 		* the first half of the timer data and process the non timer event without
4809 		* affecting the flow. So the non timer event falls through
4810 		* the code. */
4811 		else {
4812 			event->timer_data = 0;
4813 			event->timer_code = 0;
4814 			event->timer_subcode = 0;
4815 			IA_CSS_ERROR("Missing 2nd timer event. Timer event discarded");
4816 		}
4817 	}
4818 	if (event->type == IA_CSS_EVENT_TYPE_PORT_EOF)
4819 	{
4820 		event->port = (enum mipi_port_id)payload[1];
4821 		event->exp_id = payload[3];
4822 	} else if (event->type == IA_CSS_EVENT_TYPE_FW_WARNING)
4823 	{
4824 		event->fw_warning = (enum ia_css_fw_warning)payload[1];
4825 		/* exp_id is only available in these warning types */
4826 		if (event->fw_warning == IA_CSS_FW_WARNING_EXP_ID_LOCKED ||
4827 		    event->fw_warning == IA_CSS_FW_WARNING_TAG_EXP_ID_FAILED)
4828 			event->exp_id = payload[3];
4829 	} else if (event->type == IA_CSS_EVENT_TYPE_FW_ASSERT)
4830 	{
4831 		event->fw_assert_module_id = payload[1]; /* module */
4832 		event->fw_assert_line_no = (payload[2] << 8) + payload[3];
4833 		/* payload[2] is line_no>>8, payload[3] is line_no&0xff */
4834 	} else if (event->type != IA_CSS_EVENT_TYPE_TIMER)
4835 	{
4836 		/* pipe related events.
4837 		 * payload[1] contains the pipe_num,
4838 		 * payload[2] contains the pipe_id. These are different. */
4839 		event->pipe = find_pipe_by_num(payload[1]);
4840 		pipe_id = (enum ia_css_pipe_id)payload[2];
4841 		/* Check to see if pipe still exists */
4842 		if (!event->pipe)
4843 			return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4844 
4845 		if (event->type == IA_CSS_EVENT_TYPE_FRAME_TAGGED) {
4846 			/* find the capture pipe that goes with this */
4847 			int i, n;
4848 
4849 			n = event->pipe->stream->num_pipes;
4850 			for (i = 0; i < n; i++) {
4851 				struct ia_css_pipe *p =
4852 					    event->pipe->stream->pipes[i];
4853 				if (p->config.mode == IA_CSS_PIPE_MODE_CAPTURE) {
4854 					event->pipe = p;
4855 					break;
4856 				}
4857 			}
4858 			event->exp_id = payload[3];
4859 		}
4860 		if (event->type == IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE) {
4861 			/* payload[3] contains the acc fw handle. */
4862 			u32 stage_num = (uint32_t)payload[3];
4863 
4864 			ret_err = ia_css_pipeline_get_fw_from_stage(
4865 				      &event->pipe->pipeline,
4866 				      stage_num,
4867 				      &event->fw_handle);
4868 			if (ret_err != IA_CSS_SUCCESS) {
4869 				IA_CSS_ERROR("Invalid stage num received for ACC event. stage_num:%u",
4870 					     stage_num);
4871 				return ret_err;
4872 			}
4873 		}
4874 	}
4875 
4876 	if (event->pipe)
4877 		IA_CSS_LEAVE("event_id=%d, pipe_id=%d", event->type, pipe_id);
4878 	else
4879 		IA_CSS_LEAVE("event_id=%d", event->type);
4880 
4881 	return IA_CSS_SUCCESS;
4882 }
4883 
4884 enum ia_css_err
4885 ia_css_dequeue_isys_event(struct ia_css_event *event) {
4886 	u8 payload[4] = {0, 0, 0, 0};
4887 	enum ia_css_err err = IA_CSS_SUCCESS;
4888 
4889 	/* We skip the IA_CSS_ENTER logging call
4890 	 * to avoid flooding the logs when the host application
4891 	 * uses polling. */
4892 	if (!event)
4893 		return IA_CSS_ERR_INVALID_ARGUMENTS;
4894 
4895 	if (!sh_css_sp_is_running())
4896 	{
4897 		/* SP is not running. The queues are not valid */
4898 		return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4899 	}
4900 
4901 	err = ia_css_bufq_dequeue_isys_event(payload);
4902 	if (err != IA_CSS_SUCCESS)
4903 		return err;
4904 
4905 	IA_CSS_LOG("event dequeued from isys event queue");
4906 
4907 	/* Update SP state to indicate that element was dequeued. */
4908 	ia_css_bufq_enqueue_isys_event(IA_CSS_ISYS_SW_EVENT_EVENT_DEQUEUED);
4909 
4910 	/* Fill return struct with appropriate info */
4911 	event->type = IA_CSS_EVENT_TYPE_PORT_EOF;
4912 	/* EOF events are associated with a CSI port, not with a pipe */
4913 	event->pipe = NULL;
4914 	event->port = payload[1];
4915 	event->exp_id = payload[3];
4916 
4917 	IA_CSS_LEAVE_ERR(err);
4918 	return err;
4919 }
4920 
4921 static void
4922 acc_start(struct ia_css_pipe *pipe)
4923 {
4924 	assert(pipe);
4925 	assert(pipe->stream);
4926 
4927 	start_pipe(pipe, SH_CSS_PIPE_CONFIG_OVRD_NO_OVRD,
4928 		   pipe->stream->config.mode);
4929 }
4930 
4931 static enum ia_css_err
4932 sh_css_pipe_start(struct ia_css_stream *stream) {
4933 	enum ia_css_err err = IA_CSS_SUCCESS;
4934 
4935 	struct ia_css_pipe *pipe;
4936 	enum ia_css_pipe_id pipe_id;
4937 	unsigned int thread_id;
4938 
4939 	IA_CSS_ENTER_PRIVATE("stream = %p", stream);
4940 
4941 	if (!stream)
4942 	{
4943 		IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4944 		return IA_CSS_ERR_INVALID_ARGUMENTS;
4945 	}
4946 	pipe = stream->last_pipe;
4947 	if (!pipe)
4948 	{
4949 		IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4950 		return IA_CSS_ERR_INVALID_ARGUMENTS;
4951 	}
4952 
4953 	pipe_id = pipe->mode;
4954 
4955 	if (stream->started == true)
4956 	{
4957 		IA_CSS_WARNING("Cannot start stream that is already started");
4958 		IA_CSS_LEAVE_ERR(err);
4959 		return err;
4960 	}
4961 
4962 	pipe->stop_requested = false;
4963 
4964 	switch (pipe_id)
4965 	{
4966 	case IA_CSS_PIPE_ID_PREVIEW:
4967 		err = preview_start(pipe);
4968 		break;
4969 	case IA_CSS_PIPE_ID_VIDEO:
4970 		err = video_start(pipe);
4971 		break;
4972 	case IA_CSS_PIPE_ID_CAPTURE:
4973 		err = capture_start(pipe);
4974 		break;
4975 	case IA_CSS_PIPE_ID_YUVPP:
4976 		err = yuvpp_start(pipe);
4977 		break;
4978 	case IA_CSS_PIPE_ID_ACC:
4979 		acc_start(pipe);
4980 		break;
4981 	default:
4982 		err = IA_CSS_ERR_INVALID_ARGUMENTS;
4983 	}
4984 	/* DH regular multi pipe - not continuous mode: start the next pipes too */
4985 	if (!stream->config.continuous)
4986 	{
4987 		int i;
4988 
4989 		for (i = 1; i < stream->num_pipes && IA_CSS_SUCCESS == err ; i++) {
4990 			switch (stream->pipes[i]->mode) {
4991 			case IA_CSS_PIPE_ID_PREVIEW:
4992 				stream->pipes[i]->stop_requested = false;
4993 				err = preview_start(stream->pipes[i]);
4994 				break;
4995 			case IA_CSS_PIPE_ID_VIDEO:
4996 				stream->pipes[i]->stop_requested = false;
4997 				err = video_start(stream->pipes[i]);
4998 				break;
4999 			case IA_CSS_PIPE_ID_CAPTURE:
5000 				stream->pipes[i]->stop_requested = false;
5001 				err = capture_start(stream->pipes[i]);
5002 				break;
5003 			case IA_CSS_PIPE_ID_YUVPP:
5004 				stream->pipes[i]->stop_requested = false;
5005 				err = yuvpp_start(stream->pipes[i]);
5006 				break;
5007 			case IA_CSS_PIPE_ID_ACC:
5008 				stream->pipes[i]->stop_requested = false;
5009 				acc_start(stream->pipes[i]);
5010 				break;
5011 			default:
5012 				err = IA_CSS_ERR_INVALID_ARGUMENTS;
5013 			}
5014 		}
5015 	}
5016 	if (err != IA_CSS_SUCCESS)
5017 	{
5018 		IA_CSS_LEAVE_ERR_PRIVATE(err);
5019 		return err;
5020 	}
5021 
5022 	/* Force ISP parameter calculation after a mode change
5023 	 * Acceleration API examples pass NULL for stream but they
5024 	 * don't use ISP parameters anyway. So this should be okay.
5025 	 * The SP binary (jpeg) copy does not use any parameters.
5026 	 */
5027 	if (!copy_on_sp(pipe))
5028 	{
5029 		sh_css_invalidate_params(stream);
5030 		err = sh_css_param_update_isp_params(pipe,
5031 						     stream->isp_params_configs, true, NULL);
5032 		if (err != IA_CSS_SUCCESS) {
5033 			IA_CSS_LEAVE_ERR_PRIVATE(err);
5034 			return err;
5035 		}
5036 	}
5037 
5038 	ia_css_debug_pipe_graph_dump_epilogue();
5039 
5040 	ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
5041 
5042 	if (!sh_css_sp_is_running())
5043 	{
5044 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE);
5045 		/* SP is not running. The queues are not valid */
5046 		return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
5047 	}
5048 	ia_css_bufq_enqueue_psys_event(IA_CSS_PSYS_SW_EVENT_START_STREAM,
5049 				       (uint8_t)thread_id, 0, 0);
5050 
5051 	/* DH regular multi pipe - not continuous mode: enqueue event to the next pipes too */
5052 	if (!stream->config.continuous)
5053 	{
5054 		int i;
5055 
5056 		for (i = 1; i < stream->num_pipes; i++) {
5057 			ia_css_pipeline_get_sp_thread_id(
5058 			    ia_css_pipe_get_pipe_num(stream->pipes[i]),
5059 			    &thread_id);
5060 			ia_css_bufq_enqueue_psys_event(
5061 			    IA_CSS_PSYS_SW_EVENT_START_STREAM,
5062 			    (uint8_t)thread_id, 0, 0);
5063 		}
5064 	}
5065 
5066 	/* in case of continuous capture mode, we also start capture thread and copy thread*/
5067 	if (pipe->stream->config.continuous)
5068 	{
5069 		struct ia_css_pipe *copy_pipe = NULL;
5070 
5071 		if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
5072 			copy_pipe = pipe->pipe_settings.preview.copy_pipe;
5073 		else if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
5074 			copy_pipe = pipe->pipe_settings.video.copy_pipe;
5075 
5076 		if (!copy_pipe) {
5077 			IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR);
5078 			return IA_CSS_ERR_INTERNAL_ERROR;
5079 		}
5080 		ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(copy_pipe),
5081 						 &thread_id);
5082 		/* by the time we reach here q is initialized and handle is available.*/
5083 		ia_css_bufq_enqueue_psys_event(
5084 		    IA_CSS_PSYS_SW_EVENT_START_STREAM,
5085 		    (uint8_t)thread_id, 0,  0);
5086 	}
5087 	if (pipe->stream->cont_capt)
5088 	{
5089 		struct ia_css_pipe *capture_pipe = NULL;
5090 
5091 		if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
5092 			capture_pipe = pipe->pipe_settings.preview.capture_pipe;
5093 		else if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
5094 			capture_pipe = pipe->pipe_settings.video.capture_pipe;
5095 
5096 		if (!capture_pipe) {
5097 			IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR);
5098 			return IA_CSS_ERR_INTERNAL_ERROR;
5099 		}
5100 		ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe),
5101 						 &thread_id);
5102 		/* by the time we reach here q is initialized and handle is available.*/
5103 		ia_css_bufq_enqueue_psys_event(
5104 		    IA_CSS_PSYS_SW_EVENT_START_STREAM,
5105 		    (uint8_t)thread_id, 0,  0);
5106 	}
5107 
5108 	/* in case of PREVIEW mode, check whether QOS acc_pipe is available, then start the qos pipe */
5109 	if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
5110 	{
5111 		struct ia_css_pipe *acc_pipe = NULL;
5112 
5113 		acc_pipe = pipe->pipe_settings.preview.acc_pipe;
5114 
5115 		if (acc_pipe) {
5116 			ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(acc_pipe),
5117 							 &thread_id);
5118 			/* by the time we reach here q is initialized and handle is available.*/
5119 			ia_css_bufq_enqueue_psys_event(
5120 			    IA_CSS_PSYS_SW_EVENT_START_STREAM,
5121 			    (uint8_t)thread_id, 0, 0);
5122 		}
5123 	}
5124 
5125 	stream->started = true;
5126 
5127 	IA_CSS_LEAVE_ERR_PRIVATE(err);
5128 	return err;
5129 }
5130 
5131 /* ISP2400 */
5132 void
5133 sh_css_enable_cont_capt(bool enable, bool stop_copy_preview)
5134 {
5135 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5136 			    "sh_css_enable_cont_capt() enter: enable=%d\n", enable);
5137 //my_css.cont_capt = enable;
5138 	my_css.stop_copy_preview = stop_copy_preview;
5139 }
5140 
5141 bool
5142 sh_css_continuous_is_enabled(uint8_t pipe_num)
5143 {
5144 	struct ia_css_pipe *pipe;
5145 	bool continuous;
5146 
5147 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5148 			    "sh_css_continuous_is_enabled() enter: pipe_num=%d\n", pipe_num);
5149 
5150 	pipe = find_pipe_by_num(pipe_num);
5151 	continuous = pipe && pipe->stream->config.continuous;
5152 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5153 			    "sh_css_continuous_is_enabled() leave: enable=%d\n",
5154 			    continuous);
5155 	return continuous;
5156 }
5157 
5158 /* ISP2400 */
5159 enum ia_css_err
5160 ia_css_stream_get_max_buffer_depth(struct ia_css_stream *stream,
5161 				   int *buffer_depth) {
5162 	if (!buffer_depth)
5163 		return IA_CSS_ERR_INVALID_ARGUMENTS;
5164 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_max_buffer_depth() enter: void\n");
5165 	(void)stream;
5166 	*buffer_depth = NUM_CONTINUOUS_FRAMES;
5167 	return IA_CSS_SUCCESS;
5168 }
5169 
5170 enum ia_css_err
5171 ia_css_stream_set_buffer_depth(struct ia_css_stream *stream, int buffer_depth) {
5172 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_set_buffer_depth() enter: num_frames=%d\n", buffer_depth);
5173 	(void)stream;
5174 	if (buffer_depth > NUM_CONTINUOUS_FRAMES || buffer_depth < 1)
5175 		return IA_CSS_ERR_INVALID_ARGUMENTS;
5176 	/* ok, value allowed */
5177 	stream->config.target_num_cont_raw_buf = buffer_depth;
5178 	/* TODO: check what to regarding initialization */
5179 	return IA_CSS_SUCCESS;
5180 }
5181 
5182 /* ISP2401 */
5183 enum ia_css_err
5184 ia_css_stream_get_buffer_depth(struct ia_css_stream *stream,
5185 			       int *buffer_depth) {
5186 	if (!buffer_depth)
5187 		return IA_CSS_ERR_INVALID_ARGUMENTS;
5188 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_buffer_depth() enter: void\n");
5189 	(void)stream;
5190 	*buffer_depth = stream->config.target_num_cont_raw_buf;
5191 	return IA_CSS_SUCCESS;
5192 }
5193 
5194 /*
5195  * @brief Stop all "ia_css_pipe" instances in the target
5196  * "ia_css_stream" instance.
5197  *
5198  * Refer to "Local prototypes" for more info.
5199  */
5200 /* ISP2401 */
5201 static enum ia_css_err
5202 sh_css_pipes_stop(struct ia_css_stream *stream)
5203 {
5204 	enum ia_css_err err = IA_CSS_SUCCESS;
5205 	struct ia_css_pipe *main_pipe;
5206 	enum ia_css_pipe_id main_pipe_id;
5207 	int i;
5208 
5209 	assert(stream);
5210 	if (!stream)
5211 	{
5212 		IA_CSS_LOG("stream does NOT exist!");
5213 		err = IA_CSS_ERR_INTERNAL_ERROR;
5214 		goto ERR;
5215 	}
5216 
5217 	main_pipe = stream->last_pipe;
5218 	assert(main_pipe);
5219 	if (!main_pipe)
5220 	{
5221 		IA_CSS_LOG("main_pipe does NOT exist!");
5222 		err = IA_CSS_ERR_INTERNAL_ERROR;
5223 		goto ERR;
5224 	}
5225 
5226 	main_pipe_id = main_pipe->mode;
5227 	IA_CSS_ENTER_PRIVATE("main_pipe_id=%d", main_pipe_id);
5228 
5229 	/*
5230 	 * Stop all "ia_css_pipe" instances in this target
5231 	 * "ia_css_stream" instance.
5232 	 */
5233 	for (i = 0; i < stream->num_pipes; i++)
5234 	{
5235 		/* send the "stop" request to the "ia_css_pipe" instance */
5236 		IA_CSS_LOG("Send the stop-request to the pipe: pipe_id=%d",
5237 			stream->pipes[i]->pipeline.pipe_id);
5238 		err = ia_css_pipeline_request_stop(&stream->pipes[i]->pipeline);
5239 
5240 	/*
5241 	 * Exit this loop if "ia_css_pipeline_request_stop()"
5242 	 * returns the error code.
5243 	 *
5244 	 * The error code would be generated in the following
5245 	 * two cases:
5246 	 * (1) The Scalar Processor has already been stopped.
5247 	 * (2) The "Host->SP" event queue is full.
5248 	 *
5249 	 * As the convention of using CSS API 2.0/2.1, such CSS
5250 	 * error code would be propogated from the CSS-internal
5251 	 * API returned value to the CSS API returned value. Then
5252 	 * the CSS driver should capture these error code and
5253 	 * handle it in the driver exception handling mechanism.
5254 	 */
5255 	if (err != IA_CSS_SUCCESS) {
5256 		goto ERR;
5257 	}
5258 	}
5259 
5260 	/*
5261 	 * In the CSS firmware use scenario "Continuous Preview"
5262 	 * as well as "Continuous Video", the "ia_css_pipe" instance
5263 	 * "Copy Pipe" is activated. This "Copy Pipe" is private to
5264 	 * the CSS firmware so that it is not listed in the target
5265 	 * "ia_css_stream" instance.
5266 	 *
5267 	 * We need to stop this "Copy Pipe", as well.
5268 	 */
5269 	if (main_pipe->stream->config.continuous)
5270 	{
5271 		struct ia_css_pipe *copy_pipe = NULL;
5272 
5273 		/* get the reference to "Copy Pipe" */
5274 		if (main_pipe_id == IA_CSS_PIPE_ID_PREVIEW)
5275 			copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
5276 		else if (main_pipe_id == IA_CSS_PIPE_ID_VIDEO)
5277 			copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
5278 
5279 		/* return the error code if "Copy Pipe" does NOT exist */
5280 		assert(copy_pipe);
5281 		if (!copy_pipe) {
5282 			IA_CSS_LOG("Copy Pipe does NOT exist!");
5283 			err = IA_CSS_ERR_INTERNAL_ERROR;
5284 			goto ERR;
5285 		}
5286 
5287 		/* send the "stop" request to "Copy Pipe" */
5288 		IA_CSS_LOG("Send the stop-request to the pipe: pipe_id=%d",
5289 			copy_pipe->pipeline.pipe_id);
5290 		err = ia_css_pipeline_request_stop(&copy_pipe->pipeline);
5291 	}
5292 
5293 ERR:
5294 	IA_CSS_LEAVE_ERR_PRIVATE(err);
5295 	return err;
5296 }
5297 
5298 /*
5299  * @brief Check if all "ia_css_pipe" instances in the target
5300  * "ia_css_stream" instance have stopped.
5301  *
5302  * Refer to "Local prototypes" for more info.
5303  */
5304 /* ISP2401 */
5305 static bool
5306 sh_css_pipes_have_stopped(struct ia_css_stream *stream)
5307 {
5308 	bool rval = true;
5309 
5310 	struct ia_css_pipe *main_pipe;
5311 	enum ia_css_pipe_id main_pipe_id;
5312 
5313 	int i;
5314 
5315 	assert(stream);
5316 	if (!stream) {
5317 		IA_CSS_LOG("stream does NOT exist!");
5318 		rval = false;
5319 		goto RET;
5320 	}
5321 
5322 	main_pipe = stream->last_pipe;
5323 	assert(main_pipe);
5324 
5325 	if (!main_pipe) {
5326 		IA_CSS_LOG("main_pipe does NOT exist!");
5327 		rval = false;
5328 		goto RET;
5329 	}
5330 
5331 	main_pipe_id = main_pipe->mode;
5332 	IA_CSS_ENTER_PRIVATE("main_pipe_id=%d", main_pipe_id);
5333 
5334 	/*
5335 	 * Check if every "ia_css_pipe" instance in this target
5336 	 * "ia_css_stream" instance has stopped.
5337 	 */
5338 	for (i = 0; i < stream->num_pipes; i++) {
5339 		rval = rval && ia_css_pipeline_has_stopped(&stream->pipes[i]->pipeline);
5340 		IA_CSS_LOG("Pipe has stopped: pipe_id=%d, stopped=%d",
5341 			   stream->pipes[i]->pipeline.pipe_id,
5342 			   rval);
5343 	}
5344 
5345 	/*
5346 	 * In the CSS firmware use scenario "Continuous Preview"
5347 	 * as well as "Continuous Video", the "ia_css_pipe" instance
5348 	 * "Copy Pipe" is activated. This "Copy Pipe" is private to
5349 	 * the CSS firmware so that it is not listed in the target
5350 	 * "ia_css_stream" instance.
5351 	 *
5352 	 * We need to check if this "Copy Pipe" has stopped, as well.
5353 	 */
5354 	if (main_pipe->stream->config.continuous) {
5355 		struct ia_css_pipe *copy_pipe = NULL;
5356 
5357 		/* get the reference to "Copy Pipe" */
5358 		if (main_pipe_id == IA_CSS_PIPE_ID_PREVIEW)
5359 			copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
5360 		else if (main_pipe_id == IA_CSS_PIPE_ID_VIDEO)
5361 			copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
5362 
5363 		/* return if "Copy Pipe" does NOT exist */
5364 		assert(copy_pipe);
5365 		if (!copy_pipe) {
5366 			IA_CSS_LOG("Copy Pipe does NOT exist!");
5367 
5368 			rval = false;
5369 			goto RET;
5370 		}
5371 
5372 		/* check if "Copy Pipe" has stopped or not */
5373 		rval = rval && ia_css_pipeline_has_stopped(&copy_pipe->pipeline);
5374 		IA_CSS_LOG("Pipe has stopped: pipe_id=%d, stopped=%d",
5375 			   copy_pipe->pipeline.pipe_id,
5376 			   rval);
5377 	}
5378 
5379 RET:
5380 	IA_CSS_LEAVE_PRIVATE("rval=%d", rval);
5381 	return rval;
5382 }
5383 
5384 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
5385 unsigned int
5386 sh_css_get_mipi_sizes_for_check(const unsigned int port, const unsigned int idx)
5387 {
5388 	OP___assert(port < N_CSI_PORTS);
5389 	OP___assert(idx  < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT);
5390 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
5391 			    "sh_css_get_mipi_sizes_for_check(port %d, idx %d): %d\n",
5392 			    port, idx, my_css.mipi_sizes_for_check[port][idx]);
5393 	return my_css.mipi_sizes_for_check[port][idx];
5394 }
5395 #endif
5396 
5397 static enum ia_css_err sh_css_pipe_configure_output(
5398     struct ia_css_pipe *pipe,
5399     unsigned int width,
5400     unsigned int height,
5401     unsigned int padded_width,
5402     enum ia_css_frame_format format,
5403     unsigned int idx)
5404 {
5405 	enum ia_css_err err = IA_CSS_SUCCESS;
5406 
5407 	IA_CSS_ENTER_PRIVATE("pipe = %p, width = %d, height = %d, paddaed width = %d, format = %d, idx = %d",
5408 			     pipe, width, height, padded_width, format, idx);
5409 	if (!pipe) {
5410 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
5411 		return IA_CSS_ERR_INVALID_ARGUMENTS;
5412 	}
5413 
5414 	err = ia_css_util_check_res(width, height);
5415 	if (err != IA_CSS_SUCCESS) {
5416 		IA_CSS_LEAVE_ERR_PRIVATE(err);
5417 		return err;
5418 	}
5419 	if (pipe->output_info[idx].res.width != width ||
5420 	    pipe->output_info[idx].res.height != height ||
5421 	    pipe->output_info[idx].format != format) {
5422 		ia_css_frame_info_init(
5423 		    &pipe->output_info[idx],
5424 		    width,
5425 		    height,
5426 		    format,
5427 		    padded_width);
5428 	}
5429 	IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
5430 	return IA_CSS_SUCCESS;
5431 }
5432 
5433 static enum ia_css_err
5434 sh_css_pipe_get_shading_info(struct ia_css_pipe *pipe,
5435 			     struct ia_css_shading_info *shading_info,
5436 			     struct ia_css_pipe_config *pipe_config)
5437 {
5438 	enum ia_css_err err = IA_CSS_SUCCESS;
5439 	struct ia_css_binary *binary = NULL;
5440 
5441 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
5442 			    "sh_css_pipe_get_shading_info() enter:\n");
5443 
5444 	binary = ia_css_pipe_get_shading_correction_binary(pipe);
5445 
5446 	if (binary)
5447 	{
5448 		err = ia_css_binary_get_shading_info(binary,
5449 						     IA_CSS_SHADING_CORRECTION_TYPE_1,
5450 						     pipe->required_bds_factor,
5451 						     (const struct ia_css_stream_config *)&pipe->stream->config,
5452 						     shading_info, pipe_config);
5453 
5454 		/* Other function calls can be added here when other shading correction types will be added
5455 		 * in the future.
5456 		 */
5457 	} else
5458 	{
5459 		/* When the pipe does not have a binary which has the shading
5460 		 * correction, this function does not need to fill the shading
5461 		 * information. It is not a error case, and then
5462 		 * this function should return IA_CSS_SUCCESS.
5463 		 */
5464 		memset(shading_info, 0, sizeof(*shading_info));
5465 	}
5466 	return err;
5467 }
5468 
5469 static enum ia_css_err
5470 sh_css_pipe_get_grid_info(struct ia_css_pipe *pipe,
5471 			  struct ia_css_grid_info *info) {
5472 	enum ia_css_err err = IA_CSS_SUCCESS;
5473 	struct ia_css_binary *binary = NULL;
5474 
5475 	assert(pipe);
5476 	assert(info);
5477 
5478 	IA_CSS_ENTER_PRIVATE("");
5479 
5480 	binary = ia_css_pipe_get_s3a_binary(pipe);
5481 
5482 	if (binary)
5483 	{
5484 		err = ia_css_binary_3a_grid_info(binary, info, pipe);
5485 		if (err != IA_CSS_SUCCESS)
5486 			goto ERR;
5487 	} else
5488 		memset(&info->s3a_grid, 0, sizeof(info->s3a_grid));
5489 
5490 	binary = ia_css_pipe_get_sdis_binary(pipe);
5491 
5492 	if (binary)
5493 	{
5494 		ia_css_binary_dvs_grid_info(binary, info, pipe);
5495 		ia_css_binary_dvs_stat_grid_info(binary, info, pipe);
5496 	} else
5497 	{
5498 		memset(&info->dvs_grid.dvs_grid_info, 0,
5499 		       sizeof(info->dvs_grid.dvs_grid_info));
5500 		memset(&info->dvs_grid.dvs_stat_grid_info, 0,
5501 		       sizeof(info->dvs_grid.dvs_stat_grid_info));
5502 	}
5503 
5504 	if (binary)
5505 	{
5506 		/* copy pipe does not have ISP binary*/
5507 		info->isp_in_width = binary->internal_frame_info.res.width;
5508 		info->isp_in_height = binary->internal_frame_info.res.height;
5509 	}
5510 
5511 #if defined(HAS_VAMEM_VERSION_2)
5512 	info->vamem_type = IA_CSS_VAMEM_TYPE_2;
5513 #elif defined(HAS_VAMEM_VERSION_1)
5514 	info->vamem_type = IA_CSS_VAMEM_TYPE_1;
5515 #else
5516 #error "Unknown VAMEM version"
5517 #endif
5518 
5519 ERR :
5520 	IA_CSS_LEAVE_ERR_PRIVATE(err);
5521 	return err;
5522 }
5523 
5524 /* ISP2401 */
5525 /*
5526  * @brief Check if a format is supported by the pipe.
5527  *
5528  */
5529 static enum ia_css_err
5530 ia_css_pipe_check_format(struct ia_css_pipe *pipe,
5531 			 enum ia_css_frame_format format) {
5532 	const enum ia_css_frame_format *supported_formats;
5533 	int number_of_formats;
5534 	int found = 0;
5535 	int i;
5536 
5537 	IA_CSS_ENTER_PRIVATE("");
5538 
5539 	if (NULL == pipe || NULL == pipe->pipe_settings.video.video_binary.info)
5540 	{
5541 		IA_CSS_ERROR("Pipe or binary info is not set");
5542 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
5543 		return IA_CSS_ERR_INVALID_ARGUMENTS;
5544 	}
5545 
5546 	supported_formats = pipe->pipe_settings.video.video_binary.info->output_formats;
5547 	number_of_formats = sizeof(pipe->pipe_settings.video.video_binary.info->output_formats) / sizeof(enum ia_css_frame_format);
5548 
5549 	for (i = 0; i < number_of_formats && !found; i++)
5550 	{
5551 		if (supported_formats[i] == format) {
5552 			found = 1;
5553 			break;
5554 		}
5555 	}
5556 	if (!found)
5557 	{
5558 		IA_CSS_ERROR("Requested format is not supported by binary");
5559 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
5560 		return IA_CSS_ERR_INVALID_ARGUMENTS;
5561 	} else
5562 	{
5563 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
5564 		return IA_CSS_SUCCESS;
5565 	}
5566 }
5567 
5568 static enum ia_css_err load_video_binaries(struct ia_css_pipe *pipe)
5569 {
5570 	struct ia_css_frame_info video_in_info, tnr_info,
5571 		       *video_vf_info, video_bds_out_info, *pipe_out_info, *pipe_vf_out_info;
5572 	bool online;
5573 	enum ia_css_err err = IA_CSS_SUCCESS;
5574 	bool continuous = pipe->stream->config.continuous;
5575 	unsigned int i;
5576 	unsigned int num_output_pins;
5577 	struct ia_css_frame_info video_bin_out_info;
5578 	bool need_scaler = false;
5579 	bool vf_res_different_than_output = false;
5580 	bool need_vf_pp = false;
5581 	int vf_ds_log2;
5582 	struct ia_css_video_settings *mycs  = &pipe->pipe_settings.video;
5583 
5584 	IA_CSS_ENTER_PRIVATE("");
5585 	assert(pipe);
5586 	assert(pipe->mode == IA_CSS_PIPE_ID_VIDEO);
5587 	/* we only test the video_binary because offline video doesn't need a
5588 	 * vf_pp binary and online does not (always use) the copy_binary.
5589 	 * All are always reset at the same time anyway.
5590 	 */
5591 	if (mycs->video_binary.info)
5592 		return IA_CSS_SUCCESS;
5593 
5594 	online = pipe->stream->config.online;
5595 	pipe_out_info = &pipe->output_info[0];
5596 	pipe_vf_out_info = &pipe->vf_output_info[0];
5597 
5598 	assert(pipe_out_info);
5599 
5600 	/*
5601 	 * There is no explicit input format requirement for raw or yuv
5602 	 * What matters is that there is a binary that supports the stream format.
5603 	 * This is checked in the binary_find(), so no need to check it here
5604 	 */
5605 	err = ia_css_util_check_input(&pipe->stream->config, false, false);
5606 	if (err != IA_CSS_SUCCESS)
5607 		return err;
5608 	/* cannot have online video and input_mode memory */
5609 	if (online && pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY)
5610 		return IA_CSS_ERR_INVALID_ARGUMENTS;
5611 	if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
5612 		err = ia_css_util_check_vf_out_info(pipe_out_info,
5613 						    pipe_vf_out_info);
5614 		if (err != IA_CSS_SUCCESS)
5615 			return err;
5616 	} else {
5617 		err = ia_css_frame_check_info(pipe_out_info);
5618 		if (err != IA_CSS_SUCCESS)
5619 			return err;
5620 	}
5621 
5622 	if (pipe->out_yuv_ds_input_info.res.width)
5623 		video_bin_out_info = pipe->out_yuv_ds_input_info;
5624 	else
5625 		video_bin_out_info = *pipe_out_info;
5626 
5627 	/* Video */
5628 	if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
5629 		video_vf_info = pipe_vf_out_info;
5630 		vf_res_different_than_output = (video_vf_info->res.width !=
5631 						video_bin_out_info.res.width) ||
5632 					       (video_vf_info->res.height != video_bin_out_info.res.height);
5633 	} else {
5634 		video_vf_info = NULL;
5635 	}
5636 
5637 	need_scaler = need_downscaling(video_bin_out_info.res, pipe_out_info->res);
5638 
5639 	/* we build up the pipeline starting at the end */
5640 	/* YUV post-processing if needed */
5641 	if (need_scaler) {
5642 		struct ia_css_cas_binary_descr cas_scaler_descr = { };
5643 
5644 		/* NV12 is the common format that is supported by both */
5645 		/* yuv_scaler and the video_xx_isp2_min binaries. */
5646 		video_bin_out_info.format = IA_CSS_FRAME_FORMAT_NV12;
5647 
5648 		err = ia_css_pipe_create_cas_scaler_desc_single_output(
5649 			  &video_bin_out_info,
5650 			  pipe_out_info,
5651 			  NULL,
5652 			  &cas_scaler_descr);
5653 		if (err != IA_CSS_SUCCESS)
5654 			return err;
5655 		mycs->num_yuv_scaler = cas_scaler_descr.num_stage;
5656 		mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage *
5657 						  sizeof(struct ia_css_binary), GFP_KERNEL);
5658 		if (!mycs->yuv_scaler_binary) {
5659 			err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
5660 			return err;
5661 		}
5662 		mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage
5663 						* sizeof(bool), GFP_KERNEL);
5664 		if (!mycs->is_output_stage) {
5665 			err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
5666 			return err;
5667 		}
5668 		for (i = 0; i < cas_scaler_descr.num_stage; i++) {
5669 			struct ia_css_binary_descr yuv_scaler_descr;
5670 
5671 			mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i];
5672 			ia_css_pipe_get_yuvscaler_binarydesc(pipe,
5673 							     &yuv_scaler_descr, &cas_scaler_descr.in_info[i],
5674 							     &cas_scaler_descr.out_info[i],
5675 							     &cas_scaler_descr.internal_out_info[i],
5676 							     &cas_scaler_descr.vf_info[i]);
5677 			err = ia_css_binary_find(&yuv_scaler_descr,
5678 						 &mycs->yuv_scaler_binary[i]);
5679 			if (err != IA_CSS_SUCCESS) {
5680 				kfree(mycs->is_output_stage);
5681 				mycs->is_output_stage = NULL;
5682 				return err;
5683 			}
5684 		}
5685 		ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
5686 	}
5687 
5688 	{
5689 		struct ia_css_binary_descr video_descr;
5690 		enum ia_css_frame_format vf_info_format;
5691 
5692 		err = ia_css_pipe_get_video_binarydesc(pipe,
5693 						       &video_descr, &video_in_info, &video_bds_out_info, &video_bin_out_info,
5694 						       video_vf_info,
5695 						       pipe->stream->config.left_padding);
5696 		if (err != IA_CSS_SUCCESS)
5697 			return err;
5698 
5699 		/* In the case where video_vf_info is not NULL, this allows
5700 		 * us to find a potential video library with desired vf format.
5701 		 * If success, no vf_pp binary is needed.
5702 		 * If failed, we will look up video binary with YUV_LINE vf format
5703 		 */
5704 		err = ia_css_binary_find(&video_descr,
5705 					 &mycs->video_binary);
5706 
5707 		if (err != IA_CSS_SUCCESS) {
5708 			if (video_vf_info) {
5709 				/* This will do another video binary lookup later for YUV_LINE format*/
5710 				need_vf_pp = true;
5711 			} else
5712 				return err;
5713 		} else if (video_vf_info) {
5714 			/* The first video binary lookup is successful, but we may
5715 			 * still need vf_pp binary based on additiona check */
5716 			num_output_pins = mycs->video_binary.info->num_output_pins;
5717 			vf_ds_log2 = mycs->video_binary.vf_downscale_log2;
5718 
5719 			/* If the binary has dual output pins, we need vf_pp if the resolution
5720 			* is different. */
5721 			need_vf_pp |= ((num_output_pins == 2) && vf_res_different_than_output);
5722 
5723 			/* If the binary has single output pin, we need vf_pp if additional
5724 			* scaling is needed for vf */
5725 			need_vf_pp |= ((num_output_pins == 1) &&
5726 				       ((video_vf_info->res.width << vf_ds_log2 != pipe_out_info->res.width) ||
5727 					(video_vf_info->res.height << vf_ds_log2 != pipe_out_info->res.height)));
5728 		}
5729 
5730 		if (need_vf_pp) {
5731 			/* save the current vf_info format for restoration later */
5732 			ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5733 					    "load_video_binaries() need_vf_pp; find video binary with YUV_LINE again\n");
5734 
5735 			vf_info_format = video_vf_info->format;
5736 
5737 			if (!pipe->config.enable_vfpp_bci)
5738 				ia_css_frame_info_set_format(video_vf_info,
5739 							     IA_CSS_FRAME_FORMAT_YUV_LINE);
5740 
5741 			ia_css_binary_destroy_isp_parameters(&mycs->video_binary);
5742 
5743 			err = ia_css_binary_find(&video_descr,
5744 						 &mycs->video_binary);
5745 
5746 			/* restore original vf_info format */
5747 			ia_css_frame_info_set_format(video_vf_info,
5748 						     vf_info_format);
5749 			if (err != IA_CSS_SUCCESS)
5750 				return err;
5751 		}
5752 	}
5753 
5754 	/* If a video binary does not use a ref_frame, we set the frame delay
5755 	 * to 0. This is the case for the 1-stage low-power video binary. */
5756 	if (!mycs->video_binary.info->sp.enable.ref_frame)
5757 		pipe->dvs_frame_delay = 0;
5758 
5759 	/* The delay latency determines the number of invalid frames after
5760 	 * a stream is started. */
5761 	pipe->num_invalid_frames = pipe->dvs_frame_delay;
5762 	pipe->info.num_invalid_frames = pipe->num_invalid_frames;
5763 
5764 	/* Viewfinder frames also decrement num_invalid_frames. If the pipe
5765 	 * outputs a viewfinder output, then we need double the number of
5766 	 * invalid frames */
5767 	if (video_vf_info)
5768 		pipe->num_invalid_frames *= 2;
5769 
5770 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5771 			    "load_video_binaries() num_invalid_frames=%d dvs_frame_delay=%d\n",
5772 			    pipe->num_invalid_frames, pipe->dvs_frame_delay);
5773 
5774 	/* pqiao TODO: temp hack for PO, should be removed after offline YUVPP is enabled */
5775 #if !defined(USE_INPUT_SYSTEM_VERSION_2401)
5776 	/* Copy */
5777 	if (!online && !continuous) {
5778 		/* TODO: what exactly needs doing, prepend the copy binary to
5779 		 *	 video base this only on !online?
5780 		 */
5781 		err = load_copy_binary(pipe,
5782 				       &mycs->copy_binary,
5783 				       &mycs->video_binary);
5784 		if (err != IA_CSS_SUCCESS)
5785 			return err;
5786 	}
5787 #else
5788 	(void)continuous;
5789 #endif
5790 
5791 #if !defined(HAS_OUTPUT_SYSTEM)
5792 	if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] && need_vf_pp) {
5793 		struct ia_css_binary_descr vf_pp_descr;
5794 
5795 		if (mycs->video_binary.vf_frame_info.format
5796 		    == IA_CSS_FRAME_FORMAT_YUV_LINE) {
5797 			ia_css_pipe_get_vfpp_binarydesc(pipe, &vf_pp_descr,
5798 							&mycs->video_binary.vf_frame_info,
5799 							pipe_vf_out_info);
5800 		} else {
5801 			/* output from main binary is not yuv line. currently this is
5802 			 * possible only when bci is enabled on vfpp output */
5803 			assert(pipe->config.enable_vfpp_bci == true);
5804 			ia_css_pipe_get_yuvscaler_binarydesc(pipe, &vf_pp_descr,
5805 							     &mycs->video_binary.vf_frame_info,
5806 							     pipe_vf_out_info, NULL, NULL);
5807 		}
5808 
5809 		err = ia_css_binary_find(&vf_pp_descr,
5810 					 &mycs->vf_pp_binary);
5811 		if (err != IA_CSS_SUCCESS)
5812 			return err;
5813 	}
5814 #endif
5815 
5816 	err = allocate_delay_frames(pipe);
5817 
5818 	if (err != IA_CSS_SUCCESS)
5819 		return err;
5820 
5821 	if (mycs->video_binary.info->sp.enable.block_output) {
5822 		unsigned int tnr_width;
5823 		unsigned int tnr_height;
5824 
5825 		tnr_info = mycs->video_binary.out_frame_info[0];
5826 
5827 		if (atomisp_hw_is_isp2401) {
5828 			/* Select resolution for TNR. If
5829 			* output_system_in_resolution(GDC_out_resolution) is
5830 			* being used, then select that as it will also be in resolution for
5831 			* TNR. At present, it only make sense for Skycam */
5832 			if (pipe->config.output_system_in_res.width &&
5833 			    pipe->config.output_system_in_res.height) {
5834 				tnr_width = pipe->config.output_system_in_res.width;
5835 				tnr_height = pipe->config.output_system_in_res.height;
5836 			} else {
5837 				tnr_width = tnr_info.res.width;
5838 				tnr_height = tnr_info.res.height;
5839 			}
5840 
5841 			/* Make tnr reference buffers output block width(in pix) align */
5842 			tnr_info.res.width  = CEIL_MUL(tnr_width,
5843 						       (mycs->video_binary.info->sp.block.block_width * ISP_NWAY));
5844 			tnr_info.padded_width = tnr_info.res.width;
5845 		} else {
5846 			tnr_height = tnr_info.res.height;
5847 		}
5848 
5849 		/* Make tnr reference buffers output block height align */
5850 		tnr_info.res.height = CEIL_MUL(tnr_height,
5851 					       mycs->video_binary.info->sp.block.output_block_height);
5852 	} else {
5853 		tnr_info = mycs->video_binary.internal_frame_info;
5854 	}
5855 	tnr_info.format = IA_CSS_FRAME_FORMAT_YUV_LINE;
5856 	tnr_info.raw_bit_depth = SH_CSS_TNR_BIT_DEPTH;
5857 
5858 	for (i = 0; i < NUM_TNR_FRAMES; i++) {
5859 		if (mycs->tnr_frames[i]) {
5860 			ia_css_frame_free(mycs->tnr_frames[i]);
5861 			mycs->tnr_frames[i] = NULL;
5862 		}
5863 		err = ia_css_frame_allocate_from_info(
5864 			  &mycs->tnr_frames[i],
5865 			  &tnr_info);
5866 		if (err != IA_CSS_SUCCESS)
5867 			return err;
5868 	}
5869 	IA_CSS_LEAVE_PRIVATE("");
5870 	return IA_CSS_SUCCESS;
5871 }
5872 
5873 static enum ia_css_err
5874 unload_video_binaries(struct ia_css_pipe *pipe) {
5875 	unsigned int i;
5876 
5877 	IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
5878 
5879 	if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO))
5880 	{
5881 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
5882 		return IA_CSS_ERR_INVALID_ARGUMENTS;
5883 	}
5884 	ia_css_binary_unload(&pipe->pipe_settings.video.copy_binary);
5885 	ia_css_binary_unload(&pipe->pipe_settings.video.video_binary);
5886 	ia_css_binary_unload(&pipe->pipe_settings.video.vf_pp_binary);
5887 
5888 	for (i = 0; i < pipe->pipe_settings.video.num_yuv_scaler; i++)
5889 		ia_css_binary_unload(&pipe->pipe_settings.video.yuv_scaler_binary[i]);
5890 
5891 	kfree(pipe->pipe_settings.video.is_output_stage);
5892 	pipe->pipe_settings.video.is_output_stage = NULL;
5893 	kfree(pipe->pipe_settings.video.yuv_scaler_binary);
5894 	pipe->pipe_settings.video.yuv_scaler_binary = NULL;
5895 
5896 	IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
5897 	return IA_CSS_SUCCESS;
5898 }
5899 
5900 static enum ia_css_err video_start(struct ia_css_pipe *pipe)
5901 {
5902 	struct ia_css_binary *copy_binary;
5903 	enum ia_css_err err = IA_CSS_SUCCESS;
5904 	struct ia_css_pipe *copy_pipe, *capture_pipe;
5905 	enum sh_css_pipe_config_override copy_ovrd;
5906 	enum ia_css_input_mode video_pipe_input_mode;
5907 
5908 	const struct ia_css_coordinate *coord = NULL;
5909 	const struct ia_css_isp_parameters *params = NULL;
5910 
5911 	IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
5912 	if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) {
5913 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
5914 		return IA_CSS_ERR_INVALID_ARGUMENTS;
5915 	}
5916 
5917 	video_pipe_input_mode = pipe->stream->config.mode;
5918 
5919 	copy_pipe    = pipe->pipe_settings.video.copy_pipe;
5920 	capture_pipe = pipe->pipe_settings.video.capture_pipe;
5921 
5922 	copy_binary  = &pipe->pipe_settings.video.copy_binary;
5923 
5924 	sh_css_metrics_start_frame();
5925 
5926 	/* multi stream video needs mipi buffers */
5927 
5928 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
5929 	err = send_mipi_frames(pipe);
5930 	if (err != IA_CSS_SUCCESS)
5931 		return err;
5932 #endif
5933 
5934 	send_raw_frames(pipe);
5935 	{
5936 		unsigned int thread_id;
5937 
5938 		ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
5939 		copy_ovrd = 1 << thread_id;
5940 
5941 		if (pipe->stream->cont_capt) {
5942 			ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe),
5943 							 &thread_id);
5944 			copy_ovrd |= 1 << thread_id;
5945 		}
5946 	}
5947 
5948 	if (atomisp_hw_is_isp2401) {
5949 		coord = &pipe->config.internal_frame_origin_bqs_on_sctbl;
5950 		params = pipe->stream->isp_params_configs;
5951 	}
5952 
5953 	/* Construct and load the copy pipe */
5954 	if (pipe->stream->config.continuous) {
5955 		sh_css_sp_init_pipeline(&copy_pipe->pipeline,
5956 					IA_CSS_PIPE_ID_COPY,
5957 					(uint8_t)ia_css_pipe_get_pipe_num(copy_pipe),
5958 					false,
5959 					pipe->stream->config.pixels_per_clock == 2, false,
5960 					false, pipe->required_bds_factor,
5961 					copy_ovrd,
5962 					pipe->stream->config.mode,
5963 					&pipe->stream->config.metadata_config,
5964 					&pipe->stream->info.metadata_info,
5965 #if !defined(HAS_NO_INPUT_SYSTEM)
5966 					pipe->stream->config.source.port.port,
5967 #endif
5968 					coord,
5969 					params);
5970 
5971 		/* make the video pipe start with mem mode input, copy handles
5972 		   the actual mode */
5973 		video_pipe_input_mode = IA_CSS_INPUT_MODE_MEMORY;
5974 	}
5975 
5976 	/* Construct and load the capture pipe */
5977 	if (pipe->stream->cont_capt) {
5978 		sh_css_sp_init_pipeline(&capture_pipe->pipeline,
5979 					IA_CSS_PIPE_ID_CAPTURE,
5980 					(uint8_t)ia_css_pipe_get_pipe_num(capture_pipe),
5981 					capture_pipe->config.default_capture_config.enable_xnr != 0,
5982 					capture_pipe->stream->config.pixels_per_clock == 2,
5983 					true, /* continuous */
5984 					false, /* offline */
5985 					capture_pipe->required_bds_factor,
5986 					0,
5987 					IA_CSS_INPUT_MODE_MEMORY,
5988 					&pipe->stream->config.metadata_config,
5989 					&pipe->stream->info.metadata_info,
5990 #if !defined(HAS_NO_INPUT_SYSTEM)
5991 					(enum mipi_port_id)0,
5992 #endif
5993 					coord,
5994 					params);
5995 	}
5996 
5997 	start_pipe(pipe, copy_ovrd, video_pipe_input_mode);
5998 
5999 	IA_CSS_LEAVE_ERR_PRIVATE(err);
6000 	return err;
6001 }
6002 
6003 static
6004 enum ia_css_err sh_css_pipe_get_viewfinder_frame_info(
6005     struct ia_css_pipe *pipe,
6006     struct ia_css_frame_info *info,
6007     unsigned int idx)
6008 {
6009 	assert(pipe);
6010 	assert(info);
6011 
6012 	/* We could print the pointer as input arg, and the values as output */
6013 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
6014 			    "sh_css_pipe_get_viewfinder_frame_info() enter: void\n");
6015 
6016 	if (pipe->mode == IA_CSS_PIPE_ID_CAPTURE &&
6017 	    (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW ||
6018 	     pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER))
6019 		return IA_CSS_ERR_MODE_HAS_NO_VIEWFINDER;
6020 	/* offline video does not generate viewfinder output */
6021 	*info = pipe->vf_output_info[idx];
6022 
6023 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
6024 			    "sh_css_pipe_get_viewfinder_frame_info() leave: \
6025 		info.res.width=%d, info.res.height=%d, \
6026 		info.padded_width=%d, info.format=%d, \
6027 		info.raw_bit_depth=%d, info.raw_bayer_order=%d\n",
6028 			    info->res.width, info->res.height,
6029 			    info->padded_width, info->format,
6030 			    info->raw_bit_depth, info->raw_bayer_order);
6031 
6032 	return IA_CSS_SUCCESS;
6033 }
6034 
6035 static enum ia_css_err
6036 sh_css_pipe_configure_viewfinder(struct ia_css_pipe *pipe, unsigned int width,
6037 				 unsigned int height, unsigned int min_width,
6038 				 enum ia_css_frame_format format,
6039 				 unsigned int idx) {
6040 	enum ia_css_err err = IA_CSS_SUCCESS;
6041 
6042 	IA_CSS_ENTER_PRIVATE("pipe = %p, width = %d, height = %d, min_width = %d, format = %d, idx = %d\n",
6043 			     pipe, width, height, min_width, format, idx);
6044 
6045 	if (!pipe)
6046 	{
6047 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
6048 		return IA_CSS_ERR_INVALID_ARGUMENTS;
6049 	}
6050 
6051 	err = ia_css_util_check_res(width, height);
6052 	if (err != IA_CSS_SUCCESS)
6053 	{
6054 		IA_CSS_LEAVE_ERR_PRIVATE(err);
6055 		return err;
6056 	}
6057 	if (pipe->vf_output_info[idx].res.width != width ||
6058 	    pipe->vf_output_info[idx].res.height != height ||
6059 	    pipe->vf_output_info[idx].format != format)
6060 	{
6061 		ia_css_frame_info_init(&pipe->vf_output_info[idx], width, height,
6062 				       format, min_width);
6063 	}
6064 	IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
6065 	return IA_CSS_SUCCESS;
6066 }
6067 
6068 static enum ia_css_err load_copy_binaries(struct ia_css_pipe *pipe)
6069 {
6070 	enum ia_css_err err = IA_CSS_SUCCESS;
6071 
6072 	assert(pipe);
6073 	IA_CSS_ENTER_PRIVATE("");
6074 
6075 	assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
6076 	       pipe->mode == IA_CSS_PIPE_ID_COPY);
6077 	if (pipe->pipe_settings.capture.copy_binary.info)
6078 		return IA_CSS_SUCCESS;
6079 
6080 	err = ia_css_frame_check_info(&pipe->output_info[0]);
6081 	if (err != IA_CSS_SUCCESS)
6082 		goto ERR;
6083 
6084 	err = verify_copy_out_frame_format(pipe);
6085 	if (err != IA_CSS_SUCCESS)
6086 		goto ERR;
6087 
6088 	err = load_copy_binary(pipe,
6089 			       &pipe->pipe_settings.capture.copy_binary,
6090 			       NULL);
6091 
6092 ERR:
6093 	IA_CSS_LEAVE_ERR_PRIVATE(err);
6094 	return err;
6095 }
6096 
6097 static bool need_capture_pp(
6098     const struct ia_css_pipe *pipe)
6099 {
6100 	const struct ia_css_frame_info *out_info = &pipe->output_info[0];
6101 
6102 	IA_CSS_ENTER_LEAVE_PRIVATE("");
6103 	assert(pipe);
6104 	assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE);
6105 
6106 	if (atomisp_hw_is_isp2401) {
6107 		/* ldc and capture_pp are not supported in the same pipeline */
6108 		if (need_capt_ldc(pipe) == true)
6109 			return false;
6110 	}
6111 
6112 	/* determine whether we need to use the capture_pp binary.
6113 	 * This is needed for:
6114 	 *   1. XNR or
6115 	 *   2. Digital Zoom or
6116 	 *   3. YUV downscaling
6117 	 */
6118 	if (pipe->out_yuv_ds_input_info.res.width &&
6119 	    ((pipe->out_yuv_ds_input_info.res.width != out_info->res.width) ||
6120 	     (pipe->out_yuv_ds_input_info.res.height != out_info->res.height)))
6121 		return true;
6122 
6123 	if (pipe->config.default_capture_config.enable_xnr != 0)
6124 		return true;
6125 
6126 	if ((pipe->stream->isp_params_configs->dz_config.dx < HRT_GDC_N) ||
6127 	    (pipe->stream->isp_params_configs->dz_config.dy < HRT_GDC_N) ||
6128 	    pipe->config.enable_dz)
6129 		return true;
6130 
6131 	return false;
6132 }
6133 
6134 static bool need_capt_ldc(
6135     const struct ia_css_pipe *pipe)
6136 {
6137 	IA_CSS_ENTER_LEAVE_PRIVATE("");
6138 	assert(pipe);
6139 	assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE);
6140 	return (pipe->extra_config.enable_dvs_6axis) ? true : false;
6141 }
6142 
6143 static enum ia_css_err set_num_primary_stages(unsigned int *num,
6144 	enum ia_css_pipe_version version)
6145 {
6146 	enum ia_css_err err = IA_CSS_SUCCESS;
6147 
6148 	if (!num)
6149 		return IA_CSS_ERR_INVALID_ARGUMENTS;
6150 
6151 	switch (version) {
6152 	case IA_CSS_PIPE_VERSION_2_6_1:
6153 		*num = NUM_PRIMARY_HQ_STAGES;
6154 		break;
6155 	case IA_CSS_PIPE_VERSION_2_2:
6156 	case IA_CSS_PIPE_VERSION_1:
6157 		*num = NUM_PRIMARY_STAGES;
6158 		break;
6159 	default:
6160 		err = IA_CSS_ERR_INVALID_ARGUMENTS;
6161 		break;
6162 	}
6163 
6164 	return err;
6165 }
6166 
6167 static enum ia_css_err load_primary_binaries(
6168     struct ia_css_pipe *pipe)
6169 {
6170 	bool online = false;
6171 	bool memory = false;
6172 	bool continuous = false;
6173 	bool need_pp = false;
6174 	bool need_isp_copy_binary = false;
6175 	bool need_ldc = false;
6176 #ifdef USE_INPUT_SYSTEM_VERSION_2401
6177 	bool sensor = false;
6178 #endif
6179 	struct ia_css_frame_info prim_in_info,
6180 		       prim_out_info,
6181 		       capt_pp_out_info, vf_info,
6182 		       *vf_pp_in_info, *pipe_out_info,
6183 		       *pipe_vf_out_info, *capt_pp_in_info,
6184 		       capt_ldc_out_info;
6185 	enum ia_css_err err = IA_CSS_SUCCESS;
6186 	struct ia_css_capture_settings *mycs;
6187 	unsigned int i;
6188 	bool need_extra_yuv_scaler = false;
6189 
6190 	IA_CSS_ENTER_PRIVATE("");
6191 	assert(pipe);
6192 	assert(pipe->stream);
6193 	assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
6194 	       pipe->mode == IA_CSS_PIPE_ID_COPY);
6195 
6196 	online = pipe->stream->config.online;
6197 	memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
6198 	continuous = pipe->stream->config.continuous;
6199 #ifdef USE_INPUT_SYSTEM_VERSION_2401
6200 	sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR);
6201 #endif
6202 
6203 	mycs = &pipe->pipe_settings.capture;
6204 	pipe_out_info = &pipe->output_info[0];
6205 	pipe_vf_out_info = &pipe->vf_output_info[0];
6206 
6207 	if (mycs->primary_binary[0].info)
6208 		return IA_CSS_SUCCESS;
6209 
6210 	err = set_num_primary_stages(&mycs->num_primary_stage,
6211 				     pipe->config.isp_pipe_version);
6212 	if (err != IA_CSS_SUCCESS) {
6213 		IA_CSS_LEAVE_ERR_PRIVATE(err);
6214 		return err;
6215 	}
6216 
6217 	if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
6218 		err = ia_css_util_check_vf_out_info(pipe_out_info, pipe_vf_out_info);
6219 		if (err != IA_CSS_SUCCESS) {
6220 			IA_CSS_LEAVE_ERR_PRIVATE(err);
6221 			return err;
6222 		}
6223 	} else {
6224 		err = ia_css_frame_check_info(pipe_out_info);
6225 		if (err != IA_CSS_SUCCESS) {
6226 			IA_CSS_LEAVE_ERR_PRIVATE(err);
6227 			return err;
6228 		}
6229 	}
6230 	need_pp = need_capture_pp(pipe);
6231 
6232 	/* we use the vf output info to get the primary/capture_pp binary
6233 	   configured for vf_veceven. It will select the closest downscaling
6234 	   factor. */
6235 	vf_info = *pipe_vf_out_info;
6236 
6237 	/*
6238 	 * WARNING: The #if def flag has been added below as a
6239 	 * temporary solution to solve the problem of enabling the
6240 	 * view finder in a single binary in a capture flow. The
6241 	 * vf-pp stage has been removed for Skycam in the solution
6242 	 * provided. The vf-pp stage should be re-introduced when
6243 	 * required. This should not be considered as a clean solution.
6244 	 * Proper investigation should be done to come up with the clean
6245 	 * solution.
6246 	 * */
6247 	ia_css_frame_info_set_format(&vf_info, IA_CSS_FRAME_FORMAT_YUV_LINE);
6248 
6249 	/* TODO: All this yuv_scaler and capturepp calculation logic
6250 	 * can be shared later. Capture_pp is also a yuv_scale binary
6251 	 * with extra XNR funcionality. Therefore, it can be made as the
6252 	 * first step of the cascade. */
6253 	capt_pp_out_info = pipe->out_yuv_ds_input_info;
6254 	capt_pp_out_info.format = IA_CSS_FRAME_FORMAT_YUV420;
6255 	capt_pp_out_info.res.width  /= MAX_PREFERRED_YUV_DS_PER_STEP;
6256 	capt_pp_out_info.res.height /= MAX_PREFERRED_YUV_DS_PER_STEP;
6257 	ia_css_frame_info_set_width(&capt_pp_out_info, capt_pp_out_info.res.width, 0);
6258 
6259 	/*
6260 	 * WARNING: The #if def flag has been added below as a
6261 	 * temporary solution to solve the problem of enabling the
6262 	 * view finder in a single binary in a capture flow. The
6263 	 * vf-pp stage has been removed for Skycam in the solution
6264 	 * provided. The vf-pp stage should be re-introduced when
6265 	 * required. This should not be considered as a clean solution.
6266 	 * Proper investigation should be done to come up with the clean
6267 	 * solution.
6268 	 * */
6269 	need_extra_yuv_scaler = need_downscaling(capt_pp_out_info.res,
6270 				pipe_out_info->res);
6271 
6272 	if (need_extra_yuv_scaler) {
6273 		struct ia_css_cas_binary_descr cas_scaler_descr = { };
6274 
6275 		err = ia_css_pipe_create_cas_scaler_desc_single_output(
6276 			  &capt_pp_out_info,
6277 			  pipe_out_info,
6278 			  NULL,
6279 			  &cas_scaler_descr);
6280 		if (err != IA_CSS_SUCCESS) {
6281 			IA_CSS_LEAVE_ERR_PRIVATE(err);
6282 			return err;
6283 		}
6284 		mycs->num_yuv_scaler = cas_scaler_descr.num_stage;
6285 		mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage *
6286 						  sizeof(struct ia_css_binary), GFP_KERNEL);
6287 		if (!mycs->yuv_scaler_binary) {
6288 			err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
6289 			IA_CSS_LEAVE_ERR_PRIVATE(err);
6290 			return err;
6291 		}
6292 		mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage *
6293 						sizeof(bool), GFP_KERNEL);
6294 		if (!mycs->is_output_stage) {
6295 			err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
6296 			IA_CSS_LEAVE_ERR_PRIVATE(err);
6297 			return err;
6298 		}
6299 		for (i = 0; i < cas_scaler_descr.num_stage; i++) {
6300 			struct ia_css_binary_descr yuv_scaler_descr;
6301 
6302 			mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i];
6303 			ia_css_pipe_get_yuvscaler_binarydesc(pipe,
6304 							     &yuv_scaler_descr, &cas_scaler_descr.in_info[i],
6305 							     &cas_scaler_descr.out_info[i],
6306 							     &cas_scaler_descr.internal_out_info[i],
6307 							     &cas_scaler_descr.vf_info[i]);
6308 			err = ia_css_binary_find(&yuv_scaler_descr,
6309 						 &mycs->yuv_scaler_binary[i]);
6310 			if (err != IA_CSS_SUCCESS) {
6311 				IA_CSS_LEAVE_ERR_PRIVATE(err);
6312 				return err;
6313 			}
6314 		}
6315 		ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
6316 
6317 	} else {
6318 		capt_pp_out_info = pipe->output_info[0];
6319 	}
6320 
6321 	/* TODO Do we disable ldc for skycam */
6322 	need_ldc = need_capt_ldc(pipe);
6323 
6324 	if (atomisp_hw_is_isp2401 && need_ldc) {
6325 		/* ldc and capt_pp are not supported in the same pipeline */
6326 		struct ia_css_binary_descr capt_ldc_descr;
6327 
6328 		ia_css_pipe_get_ldc_binarydesc(pipe,
6329 					    &capt_ldc_descr, &prim_out_info,
6330 					    &capt_pp_out_info);
6331 
6332 		err = ia_css_binary_find(&capt_ldc_descr,
6333 					&mycs->capture_ldc_binary);
6334 		if (err != IA_CSS_SUCCESS) {
6335 			IA_CSS_LEAVE_ERR_PRIVATE(err);
6336 			return err;
6337 		}
6338 		need_pp = 0;
6339 		need_ldc = 0;
6340 	}
6341 	if (need_pp) {
6342 		struct ia_css_binary_descr capture_pp_descr;
6343 		struct ia_css_binary_descr prim_descr[MAX_NUM_PRIMARY_STAGES];
6344 
6345 		if (!atomisp_hw_is_isp2401)
6346 			capt_pp_in_info = need_ldc ? &capt_ldc_out_info : &prim_out_info;
6347 		else
6348 			capt_pp_in_info = &prim_out_info;
6349 
6350 		ia_css_pipe_get_capturepp_binarydesc(pipe,
6351 							&capture_pp_descr, capt_pp_in_info,
6352 							&capt_pp_out_info, &vf_info);
6353 		err = ia_css_binary_find(&capture_pp_descr,
6354 					    &mycs->capture_pp_binary);
6355 		if (err != IA_CSS_SUCCESS) {
6356 			IA_CSS_LEAVE_ERR_PRIVATE(err);
6357 			return err;
6358 		}
6359 
6360 		if (need_ldc) {
6361 			struct ia_css_binary_descr capt_ldc_descr;
6362 
6363 			ia_css_pipe_get_ldc_binarydesc(pipe,
6364 							&capt_ldc_descr, &prim_out_info,
6365 							&capt_ldc_out_info);
6366 
6367 			err = ia_css_binary_find(&capt_ldc_descr,
6368 						    &mycs->capture_ldc_binary);
6369 			if (err != IA_CSS_SUCCESS) {
6370 				IA_CSS_LEAVE_ERR_PRIVATE(err);
6371 				return err;
6372 			}
6373 		} else {
6374 			prim_out_info = *pipe_out_info;
6375 		}
6376 
6377 		/* Primary */
6378 		for (i = 0; i < mycs->num_primary_stage; i++) {
6379 			struct ia_css_frame_info *local_vf_info = NULL;
6380 
6381 			if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] &&
6382 			    (i == mycs->num_primary_stage - 1))
6383 				local_vf_info = &vf_info;
6384 			ia_css_pipe_get_primary_binarydesc(pipe, &prim_descr[i], &prim_in_info,
6385 							    &prim_out_info, local_vf_info, i);
6386 			err = ia_css_binary_find(&prim_descr[i], &mycs->primary_binary[i]);
6387 			if (err != IA_CSS_SUCCESS) {
6388 				IA_CSS_LEAVE_ERR_PRIVATE(err);
6389 				return err;
6390 			}
6391 		}
6392 
6393 		/* Viewfinder post-processing */
6394 		if (need_pp)
6395 			vf_pp_in_info = &mycs->capture_pp_binary.vf_frame_info;
6396 		else
6397 			vf_pp_in_info = &mycs->primary_binary[mycs->num_primary_stage - 1].vf_frame_info;
6398 
6399 		/*
6400 		 * WARNING: The #if def flag has been added below as a
6401 		 * temporary solution to solve the problem of enabling the
6402 		 * view finder in a single binary in a capture flow. The
6403 		 * vf-pp stage has been removed for Skycam in the solution
6404 		 * provided. The vf-pp stage should be re-introduced when
6405 		 * required. Thisshould not be considered as a clean solution.
6406 		 * Proper  * investigation should be done to come up with the clean
6407 		 * solution.
6408 		 * */
6409 		if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
6410 			struct ia_css_binary_descr vf_pp_descr;
6411 
6412 			ia_css_pipe_get_vfpp_binarydesc(pipe,
6413 							&vf_pp_descr, vf_pp_in_info, pipe_vf_out_info);
6414 			err = ia_css_binary_find(&vf_pp_descr, &mycs->vf_pp_binary);
6415 			if (err != IA_CSS_SUCCESS) {
6416 				IA_CSS_LEAVE_ERR_PRIVATE(err);
6417 				return err;
6418 			}
6419 		}
6420 		err = allocate_delay_frames(pipe);
6421 
6422 		if (err != IA_CSS_SUCCESS)
6423 			return err;
6424 
6425 #ifdef USE_INPUT_SYSTEM_VERSION_2401
6426 		/* When the input system is 2401, only the Direct Sensor Mode
6427 		 * Offline Capture uses the ISP copy binary.
6428 		 */
6429 		need_isp_copy_binary = !online && sensor;
6430 #else
6431 		need_isp_copy_binary = !online && !continuous && !memory;
6432 #endif
6433 
6434 		/* ISP Copy */
6435 		if (need_isp_copy_binary) {
6436 			err = load_copy_binary(pipe,
6437 					       &mycs->copy_binary,
6438 					       &mycs->primary_binary[0]);
6439 			if (err != IA_CSS_SUCCESS) {
6440 				IA_CSS_LEAVE_ERR_PRIVATE(err);
6441 				return err;
6442 			}
6443 		}
6444 	}
6445 
6446 	return IA_CSS_SUCCESS;
6447 }
6448 
6449 static enum ia_css_err
6450 allocate_delay_frames(struct ia_css_pipe *pipe) {
6451 	unsigned int num_delay_frames = 0, i = 0;
6452 	unsigned int dvs_frame_delay = 0;
6453 	struct ia_css_frame_info ref_info;
6454 	enum ia_css_err err = IA_CSS_SUCCESS;
6455 	enum ia_css_pipe_id mode = IA_CSS_PIPE_ID_VIDEO;
6456 	struct ia_css_frame **delay_frames = NULL;
6457 
6458 	IA_CSS_ENTER_PRIVATE("");
6459 
6460 	if (!pipe)
6461 	{
6462 		IA_CSS_ERROR("Invalid args - pipe %p", pipe);
6463 		return IA_CSS_ERR_INVALID_ARGUMENTS;
6464 	}
6465 
6466 	mode = pipe->mode;
6467 	dvs_frame_delay = pipe->dvs_frame_delay;
6468 
6469 	if (dvs_frame_delay > 0)
6470 		num_delay_frames = dvs_frame_delay + 1;
6471 
6472 	switch (mode)
6473 	{
6474 	case IA_CSS_PIPE_ID_CAPTURE: {
6475 		struct ia_css_capture_settings *mycs_capture = &pipe->pipe_settings.capture;
6476 		(void)mycs_capture;
6477 		return err;
6478 	}
6479 	break;
6480 	case IA_CSS_PIPE_ID_VIDEO: {
6481 		struct ia_css_video_settings *mycs_video = &pipe->pipe_settings.video;
6482 
6483 		ref_info = mycs_video->video_binary.internal_frame_info;
6484 		/*The ref frame expects
6485 		    *	1. Y plane
6486 		    *	2. UV plane with line interleaving, like below
6487 		    *		UUUUUU(width/2 times) VVVVVVVV..(width/2 times)
6488 		    *
6489 		    *	This format is not YUV420(which has Y, U and V planes).
6490 		    *	Its closer to NV12, except that the UV plane has UV
6491 		    *	interleaving, like UVUVUVUVUVUVUVUVU...
6492 		    *
6493 		    *	TODO: make this ref_frame format as a separate frame format
6494 		    */
6495 		ref_info.format        = IA_CSS_FRAME_FORMAT_NV12;
6496 		delay_frames = mycs_video->delay_frames;
6497 	}
6498 	break;
6499 	case IA_CSS_PIPE_ID_PREVIEW: {
6500 		struct ia_css_preview_settings *mycs_preview = &pipe->pipe_settings.preview;
6501 
6502 		ref_info = mycs_preview->preview_binary.internal_frame_info;
6503 		/*The ref frame expects
6504 		    *	1. Y plane
6505 		    *	2. UV plane with line interleaving, like below
6506 		    *		UUUUUU(width/2 times) VVVVVVVV..(width/2 times)
6507 		    *
6508 		    *	This format is not YUV420(which has Y, U and V planes).
6509 		    *	Its closer to NV12, except that the UV plane has UV
6510 		    *	interleaving, like UVUVUVUVUVUVUVUVU...
6511 		    *
6512 		    *	TODO: make this ref_frame format as a separate frame format
6513 		    */
6514 		ref_info.format        = IA_CSS_FRAME_FORMAT_NV12;
6515 		delay_frames = mycs_preview->delay_frames;
6516 	}
6517 	break;
6518 	default:
6519 		return IA_CSS_ERR_INVALID_ARGUMENTS;
6520 	}
6521 
6522 	ref_info.raw_bit_depth = SH_CSS_REF_BIT_DEPTH;
6523 
6524 	assert(num_delay_frames <= MAX_NUM_VIDEO_DELAY_FRAMES);
6525 	for (i = 0; i < num_delay_frames; i++)
6526 	{
6527 		err = ia_css_frame_allocate_from_info(&delay_frames[i],	&ref_info);
6528 		if (err != IA_CSS_SUCCESS)
6529 			return err;
6530 	}
6531 	IA_CSS_LEAVE_PRIVATE("");
6532 	return IA_CSS_SUCCESS;
6533 }
6534 
6535 static enum ia_css_err load_advanced_binaries(
6536     struct ia_css_pipe *pipe) {
6537 	struct ia_css_frame_info pre_in_info, gdc_in_info,
6538 			post_in_info, post_out_info,
6539 			vf_info, *vf_pp_in_info, *pipe_out_info,
6540 			*pipe_vf_out_info;
6541 	bool need_pp;
6542 	bool need_isp_copy = true;
6543 	enum ia_css_err err = IA_CSS_SUCCESS;
6544 
6545 	IA_CSS_ENTER_PRIVATE("");
6546 
6547 	assert(pipe);
6548 	assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
6549 		pipe->mode == IA_CSS_PIPE_ID_COPY);
6550 	if (pipe->pipe_settings.capture.pre_isp_binary.info)
6551 		return IA_CSS_SUCCESS;
6552 	pipe_out_info = &pipe->output_info[0];
6553 	pipe_vf_out_info = &pipe->vf_output_info[0];
6554 
6555 	vf_info = *pipe_vf_out_info;
6556 	err = ia_css_util_check_vf_out_info(pipe_out_info, &vf_info);
6557 	if (err != IA_CSS_SUCCESS)
6558 		return err;
6559 	need_pp = need_capture_pp(pipe);
6560 
6561 	ia_css_frame_info_set_format(&vf_info,
6562 					IA_CSS_FRAME_FORMAT_YUV_LINE);
6563 
6564 	/* we build up the pipeline starting at the end */
6565 	/* Capture post-processing */
6566 	if (need_pp) {
6567 		struct ia_css_binary_descr capture_pp_descr;
6568 
6569 		ia_css_pipe_get_capturepp_binarydesc(pipe,
6570 							&capture_pp_descr, &post_out_info, pipe_out_info, &vf_info);
6571 		err = ia_css_binary_find(&capture_pp_descr,
6572 					    &pipe->pipe_settings.capture.capture_pp_binary);
6573 		if (err != IA_CSS_SUCCESS)
6574 			return err;
6575 	} else {
6576 		post_out_info = *pipe_out_info;
6577 	}
6578 
6579 	/* Post-gdc */
6580 	{
6581 		struct ia_css_binary_descr post_gdc_descr;
6582 
6583 		ia_css_pipe_get_post_gdc_binarydesc(pipe,
6584 						    &post_gdc_descr, &post_in_info, &post_out_info, &vf_info);
6585 		err = ia_css_binary_find(&post_gdc_descr,
6586 					    &pipe->pipe_settings.capture.post_isp_binary);
6587 		if (err != IA_CSS_SUCCESS)
6588 			return err;
6589 	}
6590 
6591 	/* Gdc */
6592 	{
6593 		struct ia_css_binary_descr gdc_descr;
6594 
6595 		ia_css_pipe_get_gdc_binarydesc(pipe, &gdc_descr, &gdc_in_info,
6596 						&pipe->pipe_settings.capture.post_isp_binary.in_frame_info);
6597 		err = ia_css_binary_find(&gdc_descr,
6598 					    &pipe->pipe_settings.capture.anr_gdc_binary);
6599 		if (err != IA_CSS_SUCCESS)
6600 			return err;
6601 	}
6602 	pipe->pipe_settings.capture.anr_gdc_binary.left_padding =
6603 	    pipe->pipe_settings.capture.post_isp_binary.left_padding;
6604 
6605 	/* Pre-gdc */
6606 	{
6607 		struct ia_css_binary_descr pre_gdc_descr;
6608 
6609 		ia_css_pipe_get_pre_gdc_binarydesc(pipe, &pre_gdc_descr, &pre_in_info,
6610 						    &pipe->pipe_settings.capture.anr_gdc_binary.in_frame_info);
6611 		err = ia_css_binary_find(&pre_gdc_descr,
6612 					    &pipe->pipe_settings.capture.pre_isp_binary);
6613 		if (err != IA_CSS_SUCCESS)
6614 			return err;
6615 	}
6616 	pipe->pipe_settings.capture.pre_isp_binary.left_padding =
6617 	    pipe->pipe_settings.capture.anr_gdc_binary.left_padding;
6618 
6619 	/* Viewfinder post-processing */
6620 	if (need_pp) {
6621 		vf_pp_in_info =
6622 		    &pipe->pipe_settings.capture.capture_pp_binary.vf_frame_info;
6623 	} else {
6624 		vf_pp_in_info =
6625 		    &pipe->pipe_settings.capture.post_isp_binary.vf_frame_info;
6626 	}
6627 
6628 	{
6629 		struct ia_css_binary_descr vf_pp_descr;
6630 
6631 		ia_css_pipe_get_vfpp_binarydesc(pipe,
6632 						&vf_pp_descr, vf_pp_in_info, pipe_vf_out_info);
6633 		err = ia_css_binary_find(&vf_pp_descr,
6634 					    &pipe->pipe_settings.capture.vf_pp_binary);
6635 		if (err != IA_CSS_SUCCESS)
6636 			return err;
6637 	}
6638 
6639 	/* Copy */
6640 #ifdef USE_INPUT_SYSTEM_VERSION_2401
6641 	/* For CSI2+, only the direct sensor mode/online requires ISP copy */
6642 	need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
6643 #endif
6644 	if (need_isp_copy)
6645 		load_copy_binary(pipe,
6646 				    &pipe->pipe_settings.capture.copy_binary,
6647 				    &pipe->pipe_settings.capture.pre_isp_binary);
6648 
6649 	return err;
6650 }
6651 
6652 static enum ia_css_err load_bayer_isp_binaries(
6653     struct ia_css_pipe *pipe) {
6654 	struct ia_css_frame_info pre_isp_in_info, *pipe_out_info;
6655 	enum ia_css_err err = IA_CSS_SUCCESS;
6656 	struct ia_css_binary_descr pre_de_descr;
6657 
6658 	IA_CSS_ENTER_PRIVATE("");
6659 	assert(pipe);
6660 	assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
6661 		pipe->mode == IA_CSS_PIPE_ID_COPY);
6662 	pipe_out_info = &pipe->output_info[0];
6663 
6664 	if (pipe->pipe_settings.capture.pre_isp_binary.info)
6665 		return IA_CSS_SUCCESS;
6666 
6667 	err = ia_css_frame_check_info(pipe_out_info);
6668 	if (err != IA_CSS_SUCCESS)
6669 		return err;
6670 
6671 	ia_css_pipe_get_pre_de_binarydesc(pipe, &pre_de_descr,
6672 					    &pre_isp_in_info,
6673 					    pipe_out_info);
6674 
6675 	err = ia_css_binary_find(&pre_de_descr,
6676 				    &pipe->pipe_settings.capture.pre_isp_binary);
6677 
6678 	return err;
6679 }
6680 
6681 static enum ia_css_err load_low_light_binaries(
6682     struct ia_css_pipe *pipe) {
6683 	struct ia_css_frame_info pre_in_info, anr_in_info,
6684 			post_in_info, post_out_info,
6685 			vf_info, *pipe_vf_out_info, *pipe_out_info,
6686 			*vf_pp_in_info;
6687 	bool need_pp;
6688 	bool need_isp_copy = true;
6689 	enum ia_css_err err = IA_CSS_SUCCESS;
6690 
6691 	IA_CSS_ENTER_PRIVATE("");
6692 	assert(pipe);
6693 	assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
6694 		pipe->mode == IA_CSS_PIPE_ID_COPY);
6695 
6696 	if (pipe->pipe_settings.capture.pre_isp_binary.info)
6697 		return IA_CSS_SUCCESS;
6698 	pipe_vf_out_info = &pipe->vf_output_info[0];
6699 	pipe_out_info = &pipe->output_info[0];
6700 
6701 	vf_info = *pipe_vf_out_info;
6702 	err = ia_css_util_check_vf_out_info(pipe_out_info,
6703 					    &vf_info);
6704 	if (err != IA_CSS_SUCCESS)
6705 		return err;
6706 	need_pp = need_capture_pp(pipe);
6707 
6708 	ia_css_frame_info_set_format(&vf_info,
6709 					IA_CSS_FRAME_FORMAT_YUV_LINE);
6710 
6711 	/* we build up the pipeline starting at the end */
6712 	/* Capture post-processing */
6713 	if (need_pp) {
6714 		struct ia_css_binary_descr capture_pp_descr;
6715 
6716 		ia_css_pipe_get_capturepp_binarydesc(pipe,
6717 							&capture_pp_descr, &post_out_info, pipe_out_info, &vf_info);
6718 		err = ia_css_binary_find(&capture_pp_descr,
6719 					    &pipe->pipe_settings.capture.capture_pp_binary);
6720 		if (err != IA_CSS_SUCCESS)
6721 			return err;
6722 	} else {
6723 		post_out_info = *pipe_out_info;
6724 	}
6725 
6726 	/* Post-anr */
6727 	{
6728 		struct ia_css_binary_descr post_anr_descr;
6729 
6730 		ia_css_pipe_get_post_anr_binarydesc(pipe,
6731 						    &post_anr_descr, &post_in_info, &post_out_info, &vf_info);
6732 		err = ia_css_binary_find(&post_anr_descr,
6733 					    &pipe->pipe_settings.capture.post_isp_binary);
6734 		if (err != IA_CSS_SUCCESS)
6735 			return err;
6736 	}
6737 
6738 	/* Anr */
6739 	{
6740 		struct ia_css_binary_descr anr_descr;
6741 
6742 		ia_css_pipe_get_anr_binarydesc(pipe, &anr_descr, &anr_in_info,
6743 						&pipe->pipe_settings.capture.post_isp_binary.in_frame_info);
6744 		err = ia_css_binary_find(&anr_descr,
6745 					    &pipe->pipe_settings.capture.anr_gdc_binary);
6746 		if (err != IA_CSS_SUCCESS)
6747 			return err;
6748 	}
6749 	pipe->pipe_settings.capture.anr_gdc_binary.left_padding =
6750 	    pipe->pipe_settings.capture.post_isp_binary.left_padding;
6751 
6752 	/* Pre-anr */
6753 	{
6754 		struct ia_css_binary_descr pre_anr_descr;
6755 
6756 		ia_css_pipe_get_pre_anr_binarydesc(pipe, &pre_anr_descr, &pre_in_info,
6757 						    &pipe->pipe_settings.capture.anr_gdc_binary.in_frame_info);
6758 		err = ia_css_binary_find(&pre_anr_descr,
6759 					    &pipe->pipe_settings.capture.pre_isp_binary);
6760 		if (err != IA_CSS_SUCCESS)
6761 			return err;
6762 	}
6763 	pipe->pipe_settings.capture.pre_isp_binary.left_padding =
6764 	    pipe->pipe_settings.capture.anr_gdc_binary.left_padding;
6765 
6766 	/* Viewfinder post-processing */
6767 	if (need_pp) {
6768 		vf_pp_in_info =
6769 		    &pipe->pipe_settings.capture.capture_pp_binary.vf_frame_info;
6770 	} else {
6771 		vf_pp_in_info =
6772 		    &pipe->pipe_settings.capture.post_isp_binary.vf_frame_info;
6773 	}
6774 
6775 	{
6776 		struct ia_css_binary_descr vf_pp_descr;
6777 
6778 		ia_css_pipe_get_vfpp_binarydesc(pipe,
6779 						&vf_pp_descr, vf_pp_in_info, pipe_vf_out_info);
6780 		err = ia_css_binary_find(&vf_pp_descr,
6781 					    &pipe->pipe_settings.capture.vf_pp_binary);
6782 		if (err != IA_CSS_SUCCESS)
6783 			return err;
6784 	}
6785 
6786 	/* Copy */
6787 #ifdef USE_INPUT_SYSTEM_VERSION_2401
6788 	/* For CSI2+, only the direct sensor mode/online requires ISP copy */
6789 	need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
6790 #endif
6791 	if (need_isp_copy)
6792 		err = load_copy_binary(pipe,
6793 					&pipe->pipe_settings.capture.copy_binary,
6794 					&pipe->pipe_settings.capture.pre_isp_binary);
6795 
6796 	return err;
6797 }
6798 
6799 static bool copy_on_sp(struct ia_css_pipe *pipe) {
6800 	bool rval;
6801 
6802 	assert(pipe);
6803 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "copy_on_sp() enter:\n");
6804 
6805 	rval = true;
6806 
6807 	rval &=	(pipe->mode == IA_CSS_PIPE_ID_CAPTURE);
6808 
6809 	rval &= (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW);
6810 
6811 	rval &= ((pipe->stream->config.input_config.format ==
6812 		    ATOMISP_INPUT_FORMAT_BINARY_8) ||
6813 		    (pipe->config.mode == IA_CSS_PIPE_MODE_COPY));
6814 
6815 	return rval;
6816 }
6817 
6818 static enum ia_css_err load_capture_binaries(
6819     struct ia_css_pipe *pipe) {
6820 	enum ia_css_err err = IA_CSS_SUCCESS;
6821 	bool must_be_raw;
6822 
6823 	IA_CSS_ENTER_PRIVATE("");
6824 	assert(pipe);
6825 	assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
6826 		pipe->mode == IA_CSS_PIPE_ID_COPY);
6827 
6828 	if (pipe->pipe_settings.capture.primary_binary[0].info) {
6829 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
6830 		return IA_CSS_SUCCESS;
6831 	}
6832 
6833 	/* in primary, advanced,low light or bayer,
6834 						the input format must be raw */
6835 	must_be_raw =
6836 	    pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_ADVANCED ||
6837 	    pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER ||
6838 	    pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT;
6839 	err = ia_css_util_check_input(&pipe->stream->config, must_be_raw, false);
6840 	if (err != IA_CSS_SUCCESS) {
6841 		IA_CSS_LEAVE_ERR_PRIVATE(err);
6842 		return err;
6843 	}
6844 	if (copy_on_sp(pipe) &&
6845 	    pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) {
6846 		ia_css_frame_info_init(
6847 		    &pipe->output_info[0],
6848 		    JPEG_BYTES,
6849 		    1,
6850 		    IA_CSS_FRAME_FORMAT_BINARY_8,
6851 		    0);
6852 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
6853 		return IA_CSS_SUCCESS;
6854 	}
6855 
6856 	switch (pipe->config.default_capture_config.mode) {
6857 	case IA_CSS_CAPTURE_MODE_RAW:
6858 		err = load_copy_binaries(pipe);
6859 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2401)
6860 		if (err == IA_CSS_SUCCESS)
6861 			pipe->pipe_settings.capture.copy_binary.online = pipe->stream->config.online;
6862 #endif
6863 		break;
6864 	case IA_CSS_CAPTURE_MODE_BAYER:
6865 		err = load_bayer_isp_binaries(pipe);
6866 		break;
6867 	case IA_CSS_CAPTURE_MODE_PRIMARY:
6868 		err = load_primary_binaries(pipe);
6869 		break;
6870 	case IA_CSS_CAPTURE_MODE_ADVANCED:
6871 		err = load_advanced_binaries(pipe);
6872 		break;
6873 	case IA_CSS_CAPTURE_MODE_LOW_LIGHT:
6874 		err = load_low_light_binaries(pipe);
6875 		break;
6876 	}
6877 	if (err != IA_CSS_SUCCESS) {
6878 		IA_CSS_LEAVE_ERR_PRIVATE(err);
6879 		return err;
6880 	}
6881 
6882 	IA_CSS_LEAVE_ERR_PRIVATE(err);
6883 	return err;
6884 }
6885 
6886 static enum ia_css_err
6887 unload_capture_binaries(struct ia_css_pipe *pipe) {
6888 	unsigned int i;
6889 
6890 	IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
6891 
6892 	if ((!pipe) || ((pipe->mode != IA_CSS_PIPE_ID_CAPTURE) && (pipe->mode != IA_CSS_PIPE_ID_COPY)))
6893 	{
6894 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
6895 		return IA_CSS_ERR_INVALID_ARGUMENTS;
6896 	}
6897 	ia_css_binary_unload(&pipe->pipe_settings.capture.copy_binary);
6898 	for (i = 0; i < MAX_NUM_PRIMARY_STAGES; i++)
6899 		ia_css_binary_unload(&pipe->pipe_settings.capture.primary_binary[i]);
6900 	ia_css_binary_unload(&pipe->pipe_settings.capture.pre_isp_binary);
6901 	ia_css_binary_unload(&pipe->pipe_settings.capture.anr_gdc_binary);
6902 	ia_css_binary_unload(&pipe->pipe_settings.capture.post_isp_binary);
6903 	ia_css_binary_unload(&pipe->pipe_settings.capture.capture_pp_binary);
6904 	ia_css_binary_unload(&pipe->pipe_settings.capture.capture_ldc_binary);
6905 	ia_css_binary_unload(&pipe->pipe_settings.capture.vf_pp_binary);
6906 
6907 	for (i = 0; i < pipe->pipe_settings.capture.num_yuv_scaler; i++)
6908 		ia_css_binary_unload(&pipe->pipe_settings.capture.yuv_scaler_binary[i]);
6909 
6910 	kfree(pipe->pipe_settings.capture.is_output_stage);
6911 	pipe->pipe_settings.capture.is_output_stage = NULL;
6912 	kfree(pipe->pipe_settings.capture.yuv_scaler_binary);
6913 	pipe->pipe_settings.capture.yuv_scaler_binary = NULL;
6914 
6915 	IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
6916 	return IA_CSS_SUCCESS;
6917 }
6918 
6919 static bool
6920 need_downscaling(const struct ia_css_resolution in_res,
6921 		    const struct ia_css_resolution out_res) {
6922 	if (in_res.width > out_res.width || in_res.height > out_res.height)
6923 		return true;
6924 
6925 	return false;
6926 }
6927 
6928 static bool
6929 need_yuv_scaler_stage(const struct ia_css_pipe *pipe) {
6930 	unsigned int i;
6931 	struct ia_css_resolution in_res, out_res;
6932 
6933 	bool need_format_conversion = false;
6934 
6935 	IA_CSS_ENTER_PRIVATE("");
6936 	assert(pipe);
6937 	assert(pipe->mode == IA_CSS_PIPE_ID_YUVPP);
6938 
6939 	/* TODO: make generic function */
6940 	need_format_conversion =
6941 	    ((pipe->stream->config.input_config.format ==
6942 		ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY) &&
6943 		(pipe->output_info[0].format != IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8));
6944 
6945 	in_res = pipe->config.input_effective_res;
6946 
6947 	if (pipe->config.enable_dz)
6948 		return true;
6949 
6950 	if ((pipe->output_info[0].res.width != 0) && need_format_conversion)
6951 		return true;
6952 
6953 	for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
6954 		out_res = pipe->output_info[i].res;
6955 
6956 		/* A non-zero width means it is a valid output port */
6957 		if ((out_res.width != 0) && need_downscaling(in_res, out_res))
6958 			return true;
6959 	}
6960 
6961 	return false;
6962 }
6963 
6964 /* TODO: it is temporarily created from ia_css_pipe_create_cas_scaler_desc */
6965 /* which has some hard-coded knowledge which prevents reuse of the function. */
6966 /* Later, merge this with ia_css_pipe_create_cas_scaler_desc */
6967 static enum ia_css_err ia_css_pipe_create_cas_scaler_desc_single_output(
6968     struct ia_css_frame_info *cas_scaler_in_info,
6969     struct ia_css_frame_info *cas_scaler_out_info,
6970     struct ia_css_frame_info *cas_scaler_vf_info,
6971     struct ia_css_cas_binary_descr *descr) {
6972 	unsigned int i;
6973 	unsigned int hor_ds_factor = 0, ver_ds_factor = 0;
6974 	enum ia_css_err err = IA_CSS_SUCCESS;
6975 	struct ia_css_frame_info tmp_in_info;
6976 
6977 	unsigned int max_scale_factor_per_stage = MAX_PREFERRED_YUV_DS_PER_STEP;
6978 
6979 	assert(cas_scaler_in_info);
6980 	assert(cas_scaler_out_info);
6981 
6982 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
6983 			    "ia_css_pipe_create_cas_scaler_desc() enter:\n");
6984 
6985 	/* We assume that this function is used only for single output port case. */
6986 	descr->num_output_stage = 1;
6987 
6988 	hor_ds_factor = CEIL_DIV(cas_scaler_in_info->res.width,
6989 				    cas_scaler_out_info->res.width);
6990 	ver_ds_factor = CEIL_DIV(cas_scaler_in_info->res.height,
6991 				    cas_scaler_out_info->res.height);
6992 	/* use the same horizontal and vertical downscaling factor for simplicity */
6993 	assert(hor_ds_factor == ver_ds_factor);
6994 
6995 	i = 1;
6996 	while (i < hor_ds_factor) {
6997 		descr->num_stage++;
6998 		i *= max_scale_factor_per_stage;
6999 	}
7000 
7001 	descr->in_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info),
7002 				    GFP_KERNEL);
7003 	if (!descr->in_info) {
7004 		err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7005 		goto ERR;
7006 	}
7007 	descr->internal_out_info = kmalloc(descr->num_stage * sizeof(
7008 						struct ia_css_frame_info), GFP_KERNEL);
7009 	if (!descr->internal_out_info) {
7010 		err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7011 		goto ERR;
7012 	}
7013 	descr->out_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info),
7014 				    GFP_KERNEL);
7015 	if (!descr->out_info) {
7016 		err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7017 		goto ERR;
7018 	}
7019 	descr->vf_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info),
7020 				    GFP_KERNEL);
7021 	if (!descr->vf_info) {
7022 		err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7023 		goto ERR;
7024 	}
7025 	descr->is_output_stage = kmalloc(descr->num_stage * sizeof(bool), GFP_KERNEL);
7026 	if (!descr->is_output_stage) {
7027 		err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7028 		goto ERR;
7029 	}
7030 
7031 	tmp_in_info = *cas_scaler_in_info;
7032 	for (i = 0; i < descr->num_stage; i++) {
7033 		descr->in_info[i] = tmp_in_info;
7034 		if ((tmp_in_info.res.width / max_scale_factor_per_stage) <=
7035 		    cas_scaler_out_info->res.width) {
7036 			descr->is_output_stage[i] = true;
7037 			if ((descr->num_output_stage > 1) && (i != (descr->num_stage - 1))) {
7038 				descr->internal_out_info[i].res.width = cas_scaler_out_info->res.width;
7039 				descr->internal_out_info[i].res.height = cas_scaler_out_info->res.height;
7040 				descr->internal_out_info[i].padded_width = cas_scaler_out_info->padded_width;
7041 				descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
7042 			} else {
7043 				assert(i == (descr->num_stage - 1));
7044 				descr->internal_out_info[i].res.width = 0;
7045 				descr->internal_out_info[i].res.height = 0;
7046 			}
7047 			descr->out_info[i].res.width = cas_scaler_out_info->res.width;
7048 			descr->out_info[i].res.height = cas_scaler_out_info->res.height;
7049 			descr->out_info[i].padded_width = cas_scaler_out_info->padded_width;
7050 			descr->out_info[i].format = cas_scaler_out_info->format;
7051 			if (cas_scaler_vf_info) {
7052 				descr->vf_info[i].res.width = cas_scaler_vf_info->res.width;
7053 				descr->vf_info[i].res.height = cas_scaler_vf_info->res.height;
7054 				descr->vf_info[i].padded_width = cas_scaler_vf_info->padded_width;
7055 				ia_css_frame_info_set_format(&descr->vf_info[i], IA_CSS_FRAME_FORMAT_YUV_LINE);
7056 			} else {
7057 				descr->vf_info[i].res.width = 0;
7058 				descr->vf_info[i].res.height = 0;
7059 				descr->vf_info[i].padded_width = 0;
7060 			}
7061 		} else {
7062 			descr->is_output_stage[i] = false;
7063 			descr->internal_out_info[i].res.width = tmp_in_info.res.width /
7064 								max_scale_factor_per_stage;
7065 			descr->internal_out_info[i].res.height = tmp_in_info.res.height /
7066 				max_scale_factor_per_stage;
7067 			descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
7068 			ia_css_frame_info_init(&descr->internal_out_info[i],
7069 						tmp_in_info.res.width / max_scale_factor_per_stage,
7070 						tmp_in_info.res.height / max_scale_factor_per_stage,
7071 						IA_CSS_FRAME_FORMAT_YUV420, 0);
7072 			descr->out_info[i].res.width = 0;
7073 			descr->out_info[i].res.height = 0;
7074 			descr->vf_info[i].res.width = 0;
7075 			descr->vf_info[i].res.height = 0;
7076 		}
7077 		tmp_in_info = descr->internal_out_info[i];
7078 	}
7079 ERR:
7080 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7081 			    "ia_css_pipe_create_cas_scaler_desc() leave, err=%d\n",
7082 			    err);
7083 	return err;
7084 }
7085 
7086 /* FIXME: merge most of this and single output version */
7087 static enum ia_css_err ia_css_pipe_create_cas_scaler_desc(
7088     struct ia_css_pipe *pipe,
7089     struct ia_css_cas_binary_descr *descr) {
7090 	struct ia_css_frame_info in_info = IA_CSS_BINARY_DEFAULT_FRAME_INFO;
7091 	struct ia_css_frame_info *out_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
7092 	struct ia_css_frame_info *vf_out_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
7093 	struct ia_css_frame_info tmp_in_info = IA_CSS_BINARY_DEFAULT_FRAME_INFO;
7094 	unsigned int i, j;
7095 	unsigned int hor_scale_factor[IA_CSS_PIPE_MAX_OUTPUT_STAGE],
7096 		    ver_scale_factor[IA_CSS_PIPE_MAX_OUTPUT_STAGE],
7097 		    scale_factor = 0;
7098 	unsigned int num_stages = 0;
7099 	enum ia_css_err err = IA_CSS_SUCCESS;
7100 
7101 	unsigned int max_scale_factor_per_stage = MAX_PREFERRED_YUV_DS_PER_STEP;
7102 
7103 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7104 			    "ia_css_pipe_create_cas_scaler_desc() enter:\n");
7105 
7106 	for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
7107 		out_info[i] = NULL;
7108 		vf_out_info[i] = NULL;
7109 		hor_scale_factor[i] = 0;
7110 		ver_scale_factor[i] = 0;
7111 	}
7112 
7113 	in_info.res = pipe->config.input_effective_res;
7114 	in_info.padded_width = in_info.res.width;
7115 	descr->num_output_stage = 0;
7116 	/* Find out how much scaling we need for each output */
7117 	for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
7118 		if (pipe->output_info[i].res.width != 0) {
7119 			out_info[i] = &pipe->output_info[i];
7120 			if (pipe->vf_output_info[i].res.width != 0)
7121 				vf_out_info[i] = &pipe->vf_output_info[i];
7122 			descr->num_output_stage += 1;
7123 		}
7124 
7125 		if (out_info[i]) {
7126 			hor_scale_factor[i] = CEIL_DIV(in_info.res.width, out_info[i]->res.width);
7127 			ver_scale_factor[i] = CEIL_DIV(in_info.res.height, out_info[i]->res.height);
7128 			/* use the same horizontal and vertical scaling factor for simplicity */
7129 			assert(hor_scale_factor[i] == ver_scale_factor[i]);
7130 			scale_factor = 1;
7131 			do {
7132 				num_stages++;
7133 				scale_factor *= max_scale_factor_per_stage;
7134 			} while (scale_factor < hor_scale_factor[i]);
7135 
7136 			in_info.res = out_info[i]->res;
7137 		}
7138 	}
7139 
7140 	if (need_yuv_scaler_stage(pipe) && (num_stages == 0))
7141 		num_stages = 1;
7142 
7143 	descr->num_stage = num_stages;
7144 
7145 	descr->in_info = kmalloc_array(descr->num_stage,
7146 					sizeof(struct ia_css_frame_info), GFP_KERNEL);
7147 	if (!descr->in_info) {
7148 		err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7149 		goto ERR;
7150 	}
7151 	descr->internal_out_info = kmalloc(descr->num_stage * sizeof(
7152 						struct ia_css_frame_info), GFP_KERNEL);
7153 	if (!descr->internal_out_info) {
7154 		err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7155 		goto ERR;
7156 	}
7157 	descr->out_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info),
7158 				    GFP_KERNEL);
7159 	if (!descr->out_info) {
7160 		err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7161 		goto ERR;
7162 	}
7163 	descr->vf_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info),
7164 				    GFP_KERNEL);
7165 	if (!descr->vf_info) {
7166 		err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7167 		goto ERR;
7168 	}
7169 	descr->is_output_stage = kmalloc(descr->num_stage * sizeof(bool), GFP_KERNEL);
7170 	if (!descr->is_output_stage) {
7171 		err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7172 		goto ERR;
7173 	}
7174 
7175 	for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
7176 		if (out_info[i]) {
7177 			if (i > 0) {
7178 				assert((out_info[i - 1]->res.width >= out_info[i]->res.width) &&
7179 					(out_info[i - 1]->res.height >= out_info[i]->res.height));
7180 			}
7181 		}
7182 	}
7183 
7184 	tmp_in_info.res = pipe->config.input_effective_res;
7185 	tmp_in_info.format = IA_CSS_FRAME_FORMAT_YUV420;
7186 	for (i = 0, j = 0; i < descr->num_stage; i++) {
7187 		assert(j < 2);
7188 		assert(out_info[j]);
7189 
7190 		descr->in_info[i] = tmp_in_info;
7191 		if ((tmp_in_info.res.width / max_scale_factor_per_stage) <=
7192 		    out_info[j]->res.width) {
7193 			descr->is_output_stage[i] = true;
7194 			if ((descr->num_output_stage > 1) && (i != (descr->num_stage - 1))) {
7195 				descr->internal_out_info[i].res.width = out_info[j]->res.width;
7196 				descr->internal_out_info[i].res.height = out_info[j]->res.height;
7197 				descr->internal_out_info[i].padded_width = out_info[j]->padded_width;
7198 				descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
7199 			} else {
7200 				assert(i == (descr->num_stage - 1));
7201 				descr->internal_out_info[i].res.width = 0;
7202 				descr->internal_out_info[i].res.height = 0;
7203 			}
7204 			descr->out_info[i].res.width = out_info[j]->res.width;
7205 			descr->out_info[i].res.height = out_info[j]->res.height;
7206 			descr->out_info[i].padded_width = out_info[j]->padded_width;
7207 			descr->out_info[i].format = out_info[j]->format;
7208 			if (vf_out_info[j]) {
7209 				descr->vf_info[i].res.width = vf_out_info[j]->res.width;
7210 				descr->vf_info[i].res.height = vf_out_info[j]->res.height;
7211 				descr->vf_info[i].padded_width = vf_out_info[j]->padded_width;
7212 				ia_css_frame_info_set_format(&descr->vf_info[i], IA_CSS_FRAME_FORMAT_YUV_LINE);
7213 			} else {
7214 				descr->vf_info[i].res.width = 0;
7215 				descr->vf_info[i].res.height = 0;
7216 				descr->vf_info[i].padded_width = 0;
7217 			}
7218 			j++;
7219 		} else {
7220 			descr->is_output_stage[i] = false;
7221 			descr->internal_out_info[i].res.width = tmp_in_info.res.width /
7222 								max_scale_factor_per_stage;
7223 			descr->internal_out_info[i].res.height = tmp_in_info.res.height /
7224 				max_scale_factor_per_stage;
7225 			descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
7226 			ia_css_frame_info_init(&descr->internal_out_info[i],
7227 						tmp_in_info.res.width / max_scale_factor_per_stage,
7228 						tmp_in_info.res.height / max_scale_factor_per_stage,
7229 						IA_CSS_FRAME_FORMAT_YUV420, 0);
7230 			descr->out_info[i].res.width = 0;
7231 			descr->out_info[i].res.height = 0;
7232 			descr->vf_info[i].res.width = 0;
7233 			descr->vf_info[i].res.height = 0;
7234 		}
7235 		tmp_in_info = descr->internal_out_info[i];
7236 	}
7237 ERR:
7238 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7239 			    "ia_css_pipe_create_cas_scaler_desc() leave, err=%d\n",
7240 			    err);
7241 	return err;
7242 }
7243 
7244 static void ia_css_pipe_destroy_cas_scaler_desc(struct ia_css_cas_binary_descr
7245 	*descr) {
7246 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7247 			    "ia_css_pipe_destroy_cas_scaler_desc() enter:\n");
7248 	kfree(descr->in_info);
7249 	descr->in_info = NULL;
7250 	kfree(descr->internal_out_info);
7251 	descr->internal_out_info = NULL;
7252 	kfree(descr->out_info);
7253 	descr->out_info = NULL;
7254 	kfree(descr->vf_info);
7255 	descr->vf_info = NULL;
7256 	kfree(descr->is_output_stage);
7257 	descr->is_output_stage = NULL;
7258 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7259 			    "ia_css_pipe_destroy_cas_scaler_desc() leave\n");
7260 }
7261 
7262 static enum ia_css_err
7263 load_yuvpp_binaries(struct ia_css_pipe *pipe) {
7264 	enum ia_css_err err = IA_CSS_SUCCESS;
7265 	bool need_scaler = false;
7266 	struct ia_css_frame_info *vf_pp_in_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
7267 	struct ia_css_yuvpp_settings *mycs;
7268 	struct ia_css_binary *next_binary;
7269 	struct ia_css_cas_binary_descr cas_scaler_descr = { };
7270 	unsigned int i, j;
7271 	bool need_isp_copy_binary = false;
7272 
7273 	IA_CSS_ENTER_PRIVATE("");
7274 	assert(pipe);
7275 	assert(pipe->stream);
7276 	assert(pipe->mode == IA_CSS_PIPE_ID_YUVPP);
7277 
7278 	if (pipe->pipe_settings.yuvpp.copy_binary.info)
7279 		goto ERR;
7280 
7281 	/* Set both must_be_raw and must_be_yuv to false then yuvpp can take rgb inputs */
7282 	err = ia_css_util_check_input(&pipe->stream->config, false, false);
7283 	if (err != IA_CSS_SUCCESS)
7284 		goto ERR;
7285 
7286 	mycs = &pipe->pipe_settings.yuvpp;
7287 
7288 	for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++)
7289 	{
7290 		if (pipe->vf_output_info[i].res.width != 0) {
7291 			err = ia_css_util_check_vf_out_info(&pipe->output_info[i],
7292 							    &pipe->vf_output_info[i]);
7293 			if (err != IA_CSS_SUCCESS)
7294 				goto ERR;
7295 		}
7296 		vf_pp_in_info[i] = NULL;
7297 	}
7298 
7299 	need_scaler = need_yuv_scaler_stage(pipe);
7300 
7301 	/* we build up the pipeline starting at the end */
7302 	/* Capture post-processing */
7303 	if (need_scaler)
7304 	{
7305 		struct ia_css_binary_descr yuv_scaler_descr;
7306 
7307 		err = ia_css_pipe_create_cas_scaler_desc(pipe,
7308 			&cas_scaler_descr);
7309 		if (err != IA_CSS_SUCCESS)
7310 			goto ERR;
7311 		mycs->num_output = cas_scaler_descr.num_output_stage;
7312 		mycs->num_yuv_scaler = cas_scaler_descr.num_stage;
7313 		mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage *
7314 						    sizeof(struct ia_css_binary), GFP_KERNEL);
7315 		if (!mycs->yuv_scaler_binary) {
7316 			err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7317 			goto ERR;
7318 		}
7319 		mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage *
7320 						sizeof(bool), GFP_KERNEL);
7321 		if (!mycs->is_output_stage) {
7322 			err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7323 			goto ERR;
7324 		}
7325 		for (i = 0; i < cas_scaler_descr.num_stage; i++) {
7326 			mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i];
7327 			ia_css_pipe_get_yuvscaler_binarydesc(pipe,
7328 								&yuv_scaler_descr, &cas_scaler_descr.in_info[i],
7329 								&cas_scaler_descr.out_info[i],
7330 								&cas_scaler_descr.internal_out_info[i],
7331 								&cas_scaler_descr.vf_info[i]);
7332 			err = ia_css_binary_find(&yuv_scaler_descr,
7333 						    &mycs->yuv_scaler_binary[i]);
7334 			if (err != IA_CSS_SUCCESS)
7335 				goto ERR;
7336 		}
7337 		ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
7338 	} else
7339 	{
7340 		mycs->num_output = 1;
7341 	}
7342 
7343 	if (need_scaler)
7344 	{
7345 		next_binary = &mycs->yuv_scaler_binary[0];
7346 	} else
7347 	{
7348 		next_binary = NULL;
7349 	}
7350 
7351 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
7352 	/*
7353 	    * NOTES
7354 	    * - Why does the "yuvpp" pipe needs "isp_copy_binary" (i.e. ISP Copy) when
7355 	    *   its input is "ATOMISP_INPUT_FORMAT_YUV422_8"?
7356 	    *
7357 	    *   In most use cases, the first stage in the "yuvpp" pipe is the "yuv_scale_
7358 	    *   binary". However, the "yuv_scale_binary" does NOT support the input-frame
7359 	    *   format as "IA_CSS_STREAM _FORMAT_YUV422_8".
7360 	    *
7361 	    *   Hence, the "isp_copy_binary" is required to be present in front of the "yuv
7362 	    *   _scale_binary". It would translate the input-frame to the frame formats that
7363 	    *   are supported by the "yuv_scale_binary".
7364 	    *
7365 	    *   Please refer to "FrameWork/css/isp/pipes/capture_pp/capture_pp_1.0/capture_
7366 	    *   pp_defs.h" for the list of input-frame formats that are supported by the
7367 	    *   "yuv_scale_binary".
7368 	    */
7369 	need_isp_copy_binary =
7370 	    (pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_YUV422_8);
7371 #else  /* !USE_INPUT_SYSTEM_VERSION_2401 */
7372 	need_isp_copy_binary = true;
7373 #endif /*  USE_INPUT_SYSTEM_VERSION_2401 */
7374 
7375 	if (need_isp_copy_binary)
7376 	{
7377 		err = load_copy_binary(pipe,
7378 					&mycs->copy_binary,
7379 					next_binary);
7380 
7381 		if (err != IA_CSS_SUCCESS)
7382 			goto ERR;
7383 
7384 		/*
7385 		    * NOTES
7386 		    * - Why is "pipe->pipe_settings.capture.copy_binary.online" specified?
7387 		    *
7388 		    *   In some use cases, the first stage in the "yuvpp" pipe is the
7389 		    *   "isp_copy_binary". The "isp_copy_binary" is designed to process
7390 		    *   the input from either the system DDR or from the IPU internal VMEM.
7391 		    *   So it provides the flag "online" to specify where its input is from,
7392 		    *   i.e.:
7393 		    *
7394 		    *      (1) "online <= true", the input is from the IPU internal VMEM.
7395 		    *      (2) "online <= false", the input is from the system DDR.
7396 		    *
7397 		    *   In other use cases, the first stage in the "yuvpp" pipe is the
7398 		    *   "yuv_scale_binary". "The "yuv_scale_binary" is designed to process the
7399 		    *   input ONLY from the system DDR. So it does not provide the flag "online"
7400 		    *   to specify where its input is from.
7401 		    */
7402 		pipe->pipe_settings.capture.copy_binary.online = pipe->stream->config.online;
7403 	}
7404 
7405 	/* Viewfinder post-processing */
7406 	if (need_scaler)
7407 	{
7408 		for (i = 0, j = 0; i < mycs->num_yuv_scaler; i++) {
7409 			if (mycs->is_output_stage[i]) {
7410 				assert(j < 2);
7411 				vf_pp_in_info[j] =
7412 				    &mycs->yuv_scaler_binary[i].vf_frame_info;
7413 				j++;
7414 			}
7415 		}
7416 		mycs->num_vf_pp = j;
7417 	} else
7418 	{
7419 		vf_pp_in_info[0] =
7420 		    &mycs->copy_binary.vf_frame_info;
7421 		for (i = 1; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
7422 			vf_pp_in_info[i] = NULL;
7423 		}
7424 		mycs->num_vf_pp = 1;
7425 	}
7426 	mycs->vf_pp_binary = kzalloc(mycs->num_vf_pp * sizeof(struct ia_css_binary),
7427 					GFP_KERNEL);
7428 	if (!mycs->vf_pp_binary)
7429 	{
7430 		err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7431 		goto ERR;
7432 	}
7433 
7434 	{
7435 		struct ia_css_binary_descr vf_pp_descr;
7436 
7437 		for (i = 0; i < mycs->num_vf_pp; i++)
7438 		{
7439 			if (pipe->vf_output_info[i].res.width != 0) {
7440 				ia_css_pipe_get_vfpp_binarydesc(pipe,
7441 								&vf_pp_descr, vf_pp_in_info[i], &pipe->vf_output_info[i]);
7442 				err = ia_css_binary_find(&vf_pp_descr, &mycs->vf_pp_binary[i]);
7443 				if (err != IA_CSS_SUCCESS)
7444 					goto ERR;
7445 			}
7446 		}
7447 	}
7448 
7449 	if (err != IA_CSS_SUCCESS)
7450 		goto ERR;
7451 
7452 ERR:
7453 	if (need_scaler)
7454 	{
7455 		ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
7456 	}
7457 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "load_yuvpp_binaries() leave, err=%d\n",
7458 			    err);
7459 	return err;
7460 }
7461 
7462 static enum ia_css_err
7463 unload_yuvpp_binaries(struct ia_css_pipe *pipe) {
7464 	unsigned int i;
7465 
7466 	IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
7467 
7468 	if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP))
7469 	{
7470 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
7471 		return IA_CSS_ERR_INVALID_ARGUMENTS;
7472 	}
7473 	ia_css_binary_unload(&pipe->pipe_settings.yuvpp.copy_binary);
7474 	for (i = 0; i < pipe->pipe_settings.yuvpp.num_yuv_scaler; i++)
7475 	{
7476 		ia_css_binary_unload(&pipe->pipe_settings.yuvpp.yuv_scaler_binary[i]);
7477 	}
7478 	for (i = 0; i < pipe->pipe_settings.yuvpp.num_vf_pp; i++)
7479 	{
7480 		ia_css_binary_unload(&pipe->pipe_settings.yuvpp.vf_pp_binary[i]);
7481 	}
7482 	kfree(pipe->pipe_settings.yuvpp.is_output_stage);
7483 	pipe->pipe_settings.yuvpp.is_output_stage = NULL;
7484 	kfree(pipe->pipe_settings.yuvpp.yuv_scaler_binary);
7485 	pipe->pipe_settings.yuvpp.yuv_scaler_binary = NULL;
7486 	kfree(pipe->pipe_settings.yuvpp.vf_pp_binary);
7487 	pipe->pipe_settings.yuvpp.vf_pp_binary = NULL;
7488 
7489 	IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
7490 	return IA_CSS_SUCCESS;
7491 }
7492 
7493 static enum ia_css_err yuvpp_start(struct ia_css_pipe *pipe) {
7494 	struct ia_css_binary *copy_binary;
7495 	enum ia_css_err err = IA_CSS_SUCCESS;
7496 	enum sh_css_pipe_config_override copy_ovrd;
7497 	enum ia_css_input_mode yuvpp_pipe_input_mode;
7498 
7499 	IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
7500 	if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) {
7501 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
7502 		return IA_CSS_ERR_INVALID_ARGUMENTS;
7503 	}
7504 
7505 	yuvpp_pipe_input_mode = pipe->stream->config.mode;
7506 
7507 	copy_binary  = &pipe->pipe_settings.yuvpp.copy_binary;
7508 
7509 	sh_css_metrics_start_frame();
7510 
7511 	/* multi stream video needs mipi buffers */
7512 
7513 #if !defined(HAS_NO_INPUT_SYSTEM) && (defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401))
7514 	err = send_mipi_frames(pipe);
7515 	if (err != IA_CSS_SUCCESS) {
7516 		IA_CSS_LEAVE_ERR_PRIVATE(err);
7517 		return err;
7518 	}
7519 #endif
7520 
7521 	{
7522 		unsigned int thread_id;
7523 
7524 		ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
7525 		copy_ovrd = 1 << thread_id;
7526 	}
7527 
7528 	start_pipe(pipe, copy_ovrd, yuvpp_pipe_input_mode);
7529 
7530 	IA_CSS_LEAVE_ERR_PRIVATE(err);
7531 	return err;
7532 }
7533 
7534 static enum ia_css_err
7535 sh_css_pipe_unload_binaries(struct ia_css_pipe *pipe) {
7536 	enum ia_css_err err = IA_CSS_SUCCESS;
7537 
7538 	IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
7539 
7540 	if (!pipe)
7541 	{
7542 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
7543 		return IA_CSS_ERR_INVALID_ARGUMENTS;
7544 	}
7545 	/* PIPE_MODE_COPY has no binaries, but has output frames to outside*/
7546 	if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY)
7547 	{
7548 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
7549 		return IA_CSS_SUCCESS;
7550 	}
7551 
7552 	switch (pipe->mode)
7553 	{
7554 	case IA_CSS_PIPE_ID_PREVIEW:
7555 		err = unload_preview_binaries(pipe);
7556 		break;
7557 	case IA_CSS_PIPE_ID_VIDEO:
7558 		err = unload_video_binaries(pipe);
7559 		break;
7560 	case IA_CSS_PIPE_ID_CAPTURE:
7561 		err = unload_capture_binaries(pipe);
7562 		break;
7563 	case IA_CSS_PIPE_ID_YUVPP:
7564 		err = unload_yuvpp_binaries(pipe);
7565 		break;
7566 	default:
7567 		break;
7568 	}
7569 	IA_CSS_LEAVE_ERR_PRIVATE(err);
7570 	return err;
7571 }
7572 
7573 static enum ia_css_err
7574 sh_css_pipe_load_binaries(struct ia_css_pipe *pipe) {
7575 	enum ia_css_err err = IA_CSS_SUCCESS;
7576 
7577 	assert(pipe);
7578 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "sh_css_pipe_load_binaries() enter:\n");
7579 
7580 	/* PIPE_MODE_COPY has no binaries, but has output frames to outside*/
7581 	if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY)
7582 		return err;
7583 
7584 	switch (pipe->mode)
7585 	{
7586 	case IA_CSS_PIPE_ID_PREVIEW:
7587 		err = load_preview_binaries(pipe);
7588 		break;
7589 	case IA_CSS_PIPE_ID_VIDEO:
7590 		err = load_video_binaries(pipe);
7591 		break;
7592 	case IA_CSS_PIPE_ID_CAPTURE:
7593 		err = load_capture_binaries(pipe);
7594 		break;
7595 	case IA_CSS_PIPE_ID_YUVPP:
7596 		err = load_yuvpp_binaries(pipe);
7597 		break;
7598 	case IA_CSS_PIPE_ID_ACC:
7599 		break;
7600 	default:
7601 		err = IA_CSS_ERR_INTERNAL_ERROR;
7602 		break;
7603 	}
7604 	if (err != IA_CSS_SUCCESS)
7605 	{
7606 		if (sh_css_pipe_unload_binaries(pipe) != IA_CSS_SUCCESS) {
7607 			/* currently css does not support multiple error returns in a single function,
7608 			    * using IA_CSS_ERR_INTERNAL_ERROR in this case */
7609 			err = IA_CSS_ERR_INTERNAL_ERROR;
7610 		}
7611 	}
7612 	return err;
7613 }
7614 
7615 static enum ia_css_err
7616 create_host_yuvpp_pipeline(struct ia_css_pipe *pipe) {
7617 	struct ia_css_pipeline *me;
7618 	enum ia_css_err err = IA_CSS_SUCCESS;
7619 	struct ia_css_pipeline_stage *vf_pp_stage = NULL,
7620 		*copy_stage = NULL,
7621 		*yuv_scaler_stage = NULL;
7622 	struct ia_css_binary *copy_binary,
7623 		*vf_pp_binary,
7624 		*yuv_scaler_binary;
7625 	bool need_scaler = false;
7626 	unsigned int num_stage, num_vf_pp_stage, num_output_stage;
7627 	unsigned int i, j;
7628 
7629 	struct ia_css_frame *in_frame = NULL;
7630 	struct ia_css_frame *out_frame[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
7631 	struct ia_css_frame *bin_out_frame[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
7632 	struct ia_css_frame *vf_frame[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
7633 	struct ia_css_pipeline_stage_desc stage_desc;
7634 	bool need_in_frameinfo_memory = false;
7635 #ifdef USE_INPUT_SYSTEM_VERSION_2401
7636 	bool sensor = false;
7637 	bool buffered_sensor = false;
7638 	bool online = false;
7639 	bool continuous = false;
7640 #endif
7641 
7642 	IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
7643 	if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP))
7644 	{
7645 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
7646 		return IA_CSS_ERR_INVALID_ARGUMENTS;
7647 	}
7648 	me = &pipe->pipeline;
7649 	ia_css_pipeline_clean(me);
7650 	for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++)
7651 	{
7652 		out_frame[i] = NULL;
7653 		vf_frame[i] = NULL;
7654 	}
7655 	ia_css_pipe_util_create_output_frames(bin_out_frame);
7656 	num_stage  = pipe->pipe_settings.yuvpp.num_yuv_scaler;
7657 	num_vf_pp_stage   = pipe->pipe_settings.yuvpp.num_vf_pp;
7658 	num_output_stage   = pipe->pipe_settings.yuvpp.num_output;
7659 
7660 #ifdef USE_INPUT_SYSTEM_VERSION_2401
7661 	/* When the input system is 2401, always enable 'in_frameinfo_memory'
7662 	    * except for the following:
7663 	    * - Direct Sensor Mode Online Capture
7664 	    * - Direct Sensor Mode Continuous Capture
7665 	    * - Buffered Sensor Mode Continuous Capture
7666 	    */
7667 	sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
7668 	buffered_sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR;
7669 	online = pipe->stream->config.online;
7670 	continuous = pipe->stream->config.continuous;
7671 	need_in_frameinfo_memory =
7672 	!((sensor && (online || continuous)) || (buffered_sensor && continuous));
7673 #else
7674 	/* Construct in_frame info (only in case we have dynamic input */
7675 	need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
7676 #endif
7677 	/* the input frame can come from:
7678 	    *  a) memory: connect yuvscaler to me->in_frame
7679 	    *  b) sensor, via copy binary: connect yuvscaler to copy binary later on */
7680 	if (need_in_frameinfo_memory)
7681 	{
7682 		/* TODO: improve for different input formats. */
7683 
7684 		/*
7685 		    * "pipe->stream->config.input_config.format" represents the sensor output
7686 		    * frame format, e.g. YUV422 8-bit.
7687 		    *
7688 		    * "in_frame_format" represents the imaging pipe's input frame format, e.g.
7689 		    * Bayer-Quad RAW.
7690 		    */
7691 		int in_frame_format;
7692 
7693 		if (pipe->stream->config.input_config.format ==
7694 		    ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY) {
7695 			in_frame_format = IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8;
7696 		} else if (pipe->stream->config.input_config.format ==
7697 			    ATOMISP_INPUT_FORMAT_YUV422_8) {
7698 			/*
7699 			    * When the sensor output frame format is "ATOMISP_INPUT_FORMAT_YUV422_8",
7700 			    * the "isp_copy_var" binary is selected as the first stage in the yuvpp
7701 			    * pipe.
7702 			    *
7703 			    * For the "isp_copy_var" binary, it reads the YUV422-8 pixels from
7704 			    * the frame buffer (at DDR) to the frame-line buffer (at VMEM).
7705 			    *
7706 			    * By now, the "isp_copy_var" binary does NOT provide a separated
7707 			    * frame-line buffer to store the YUV422-8 pixels. Instead, it stores
7708 			    * the YUV422-8 pixels in the frame-line buffer which is designed to
7709 			    * store the Bayer-Quad RAW pixels.
7710 			    *
7711 			    * To direct the "isp_copy_var" binary reading from the RAW frame-line
7712 			    * buffer, its input frame format must be specified as "IA_CSS_FRAME_
7713 			    * FORMAT_RAW".
7714 			    */
7715 			in_frame_format = IA_CSS_FRAME_FORMAT_RAW;
7716 		} else {
7717 			in_frame_format = IA_CSS_FRAME_FORMAT_NV12;
7718 		}
7719 
7720 		err = init_in_frameinfo_memory_defaults(pipe,
7721 							&me->in_frame,
7722 							in_frame_format);
7723 
7724 		if (err != IA_CSS_SUCCESS) {
7725 			IA_CSS_LEAVE_ERR_PRIVATE(err);
7726 			return err;
7727 		}
7728 
7729 		in_frame = &me->in_frame;
7730 	} else
7731 	{
7732 		in_frame = NULL;
7733 	}
7734 
7735 	for (i = 0; i < num_output_stage; i++)
7736 	{
7737 		assert(i < IA_CSS_PIPE_MAX_OUTPUT_STAGE);
7738 		if (pipe->output_info[i].res.width != 0) {
7739 			err = init_out_frameinfo_defaults(pipe, &me->out_frame[i], i);
7740 			if (err != IA_CSS_SUCCESS) {
7741 				IA_CSS_LEAVE_ERR_PRIVATE(err);
7742 				return err;
7743 			}
7744 			out_frame[i] = &me->out_frame[i];
7745 		}
7746 
7747 		/* Construct vf_frame info (only in case we have VF) */
7748 		if (pipe->vf_output_info[i].res.width != 0) {
7749 			err = init_vf_frameinfo_defaults(pipe, &me->vf_frame[i], i);
7750 			if (err != IA_CSS_SUCCESS) {
7751 				IA_CSS_LEAVE_ERR_PRIVATE(err);
7752 				return err;
7753 			}
7754 			vf_frame[i] = &me->vf_frame[i];
7755 		}
7756 	}
7757 
7758 	copy_binary       = &pipe->pipe_settings.yuvpp.copy_binary;
7759 	vf_pp_binary      = pipe->pipe_settings.yuvpp.vf_pp_binary;
7760 	yuv_scaler_binary = pipe->pipe_settings.yuvpp.yuv_scaler_binary;
7761 	need_scaler = need_yuv_scaler_stage(pipe);
7762 
7763 	if (pipe->pipe_settings.yuvpp.copy_binary.info)
7764 	{
7765 		struct ia_css_frame *in_frame_local = NULL;
7766 
7767 #ifdef USE_INPUT_SYSTEM_VERSION_2401
7768 		/* After isp copy is enabled in_frame needs to be passed. */
7769 		if (!online)
7770 			in_frame_local = in_frame;
7771 #endif
7772 
7773 		if (need_scaler) {
7774 			ia_css_pipe_util_set_output_frames(bin_out_frame, 0, NULL);
7775 			ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
7776 							    bin_out_frame, in_frame_local, NULL);
7777 		} else {
7778 			ia_css_pipe_util_set_output_frames(bin_out_frame, 0, out_frame[0]);
7779 			ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
7780 							    bin_out_frame, in_frame_local, NULL);
7781 		}
7782 
7783 		err = ia_css_pipeline_create_and_add_stage(me,
7784 			&stage_desc,
7785 			&copy_stage);
7786 
7787 		if (err != IA_CSS_SUCCESS) {
7788 			IA_CSS_LEAVE_ERR_PRIVATE(err);
7789 			return err;
7790 		}
7791 
7792 		if (copy_stage) {
7793 			/* if we use yuv scaler binary, vf output should be from there */
7794 			copy_stage->args.copy_vf = !need_scaler;
7795 			/* for yuvpp pipe, it should always be enabled */
7796 			copy_stage->args.copy_output = true;
7797 			/* connect output of copy binary to input of yuv scaler */
7798 			in_frame = copy_stage->args.out_frame[0];
7799 		}
7800 	}
7801 
7802 	if (need_scaler)
7803 	{
7804 		struct ia_css_frame *tmp_out_frame = NULL;
7805 		struct ia_css_frame *tmp_vf_frame = NULL;
7806 		struct ia_css_frame *tmp_in_frame = in_frame;
7807 
7808 		for (i = 0, j = 0; i < num_stage; i++) {
7809 			assert(j < num_output_stage);
7810 			if (pipe->pipe_settings.yuvpp.is_output_stage[i]) {
7811 				tmp_out_frame = out_frame[j];
7812 				tmp_vf_frame = vf_frame[j];
7813 			} else {
7814 				tmp_out_frame = NULL;
7815 				tmp_vf_frame = NULL;
7816 			}
7817 
7818 			err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame,
7819 						    NULL,
7820 						    &yuv_scaler_binary[i],
7821 						    &yuv_scaler_stage);
7822 
7823 			if (err != IA_CSS_SUCCESS) {
7824 				IA_CSS_LEAVE_ERR_PRIVATE(err);
7825 				return err;
7826 			}
7827 			/* we use output port 1 as internal output port */
7828 			tmp_in_frame = yuv_scaler_stage->args.out_frame[1];
7829 			if (pipe->pipe_settings.yuvpp.is_output_stage[i]) {
7830 				if (tmp_vf_frame && (tmp_vf_frame->info.res.width != 0)) {
7831 					in_frame = yuv_scaler_stage->args.out_vf_frame;
7832 					err = add_vf_pp_stage(pipe, in_frame, tmp_vf_frame, &vf_pp_binary[j],
7833 								&vf_pp_stage);
7834 
7835 					if (err != IA_CSS_SUCCESS) {
7836 						IA_CSS_LEAVE_ERR_PRIVATE(err);
7837 						return err;
7838 					}
7839 				}
7840 				j++;
7841 			}
7842 		}
7843 	} else if (copy_stage)
7844 	{
7845 		if (vf_frame[0] && vf_frame[0]->info.res.width != 0) {
7846 			in_frame = copy_stage->args.out_vf_frame;
7847 			err = add_vf_pp_stage(pipe, in_frame, vf_frame[0], &vf_pp_binary[0],
7848 						&vf_pp_stage);
7849 		}
7850 		if (err != IA_CSS_SUCCESS) {
7851 			IA_CSS_LEAVE_ERR_PRIVATE(err);
7852 			return err;
7853 		}
7854 	}
7855 
7856 	ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
7857 
7858 	IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
7859 
7860 	return IA_CSS_SUCCESS;
7861 }
7862 
7863 static enum ia_css_err
7864 create_host_copy_pipeline(struct ia_css_pipe *pipe,
7865 			    unsigned int max_input_width,
7866 			    struct ia_css_frame *out_frame) {
7867 	struct ia_css_pipeline *me;
7868 	enum ia_css_err err = IA_CSS_SUCCESS;
7869 	struct ia_css_pipeline_stage_desc stage_desc;
7870 
7871 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7872 			    "create_host_copy_pipeline() enter:\n");
7873 
7874 	/* pipeline already created as part of create_host_pipeline_structure */
7875 	me = &pipe->pipeline;
7876 	ia_css_pipeline_clean(me);
7877 
7878 	/* Construct out_frame info */
7879 	out_frame->contiguous = false;
7880 	out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
7881 
7882 	if (copy_on_sp(pipe) &&
7883 	    pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8)
7884 	{
7885 		ia_css_frame_info_init(
7886 		    &out_frame->info,
7887 		    JPEG_BYTES,
7888 		    1,
7889 		    IA_CSS_FRAME_FORMAT_BINARY_8,
7890 		    0);
7891 	} else if (out_frame->info.format == IA_CSS_FRAME_FORMAT_RAW)
7892 	{
7893 		out_frame->info.raw_bit_depth =
7894 		ia_css_pipe_util_pipe_input_format_bpp(pipe);
7895 	}
7896 
7897 	me->num_stages = 1;
7898 	me->pipe_id = IA_CSS_PIPE_ID_COPY;
7899 	pipe->mode  = IA_CSS_PIPE_ID_COPY;
7900 
7901 	ia_css_pipe_get_sp_func_stage_desc(&stage_desc, out_frame,
7902 					    IA_CSS_PIPELINE_RAW_COPY, max_input_width);
7903 	err = ia_css_pipeline_create_and_add_stage(me,
7904 		&stage_desc,
7905 		NULL);
7906 
7907 	ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
7908 
7909 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7910 			    "create_host_copy_pipeline() leave:\n");
7911 
7912 	return err;
7913 }
7914 
7915 static enum ia_css_err
7916 create_host_isyscopy_capture_pipeline(struct ia_css_pipe *pipe) {
7917 	struct ia_css_pipeline *me = &pipe->pipeline;
7918 	enum ia_css_err err = IA_CSS_SUCCESS;
7919 	struct ia_css_pipeline_stage_desc stage_desc;
7920 	struct ia_css_frame *out_frame = &me->out_frame[0];
7921 	struct ia_css_pipeline_stage *out_stage = NULL;
7922 	unsigned int thread_id;
7923 	enum sh_css_queue_id queue_id;
7924 	unsigned int max_input_width = MAX_VECTORS_PER_INPUT_LINE_CONT * ISP_VEC_NELEMS;
7925 
7926 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7927 			    "create_host_isyscopy_capture_pipeline() enter:\n");
7928 	ia_css_pipeline_clean(me);
7929 
7930 	/* Construct out_frame info */
7931 	err = sh_css_pipe_get_output_frame_info(pipe, &out_frame->info, 0);
7932 	if (err != IA_CSS_SUCCESS)
7933 		return err;
7934 	out_frame->contiguous = false;
7935 	out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
7936 	ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
7937 	ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, thread_id, &queue_id);
7938 	out_frame->dynamic_queue_id = queue_id;
7939 	out_frame->buf_type = IA_CSS_BUFFER_TYPE_OUTPUT_FRAME;
7940 
7941 	me->num_stages = 1;
7942 	me->pipe_id = IA_CSS_PIPE_ID_CAPTURE;
7943 	pipe->mode  = IA_CSS_PIPE_ID_CAPTURE;
7944 	ia_css_pipe_get_sp_func_stage_desc(&stage_desc, out_frame,
7945 					    IA_CSS_PIPELINE_ISYS_COPY, max_input_width);
7946 	err = ia_css_pipeline_create_and_add_stage(me,
7947 		&stage_desc, &out_stage);
7948 	if (err != IA_CSS_SUCCESS)
7949 		return err;
7950 
7951 	ia_css_pipeline_finalize_stages(me, pipe->stream->config.continuous);
7952 
7953 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7954 			    "create_host_isyscopy_capture_pipeline() leave:\n");
7955 
7956 	return err;
7957 }
7958 
7959 static enum ia_css_err
7960 create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) {
7961 	struct ia_css_pipeline *me;
7962 	enum ia_css_err err = IA_CSS_SUCCESS;
7963 	enum ia_css_capture_mode mode;
7964 	struct ia_css_pipeline_stage *current_stage = NULL;
7965 	struct ia_css_pipeline_stage *yuv_scaler_stage = NULL;
7966 	struct ia_css_binary *copy_binary,
7967 		*primary_binary[MAX_NUM_PRIMARY_STAGES],
7968 		*vf_pp_binary,
7969 		*pre_isp_binary,
7970 		*anr_gdc_binary,
7971 		*post_isp_binary,
7972 		*yuv_scaler_binary,
7973 		*capture_pp_binary,
7974 		*capture_ldc_binary;
7975 	bool need_pp = false;
7976 	bool raw;
7977 
7978 	struct ia_css_frame *in_frame;
7979 	struct ia_css_frame *out_frame;
7980 	struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
7981 	struct ia_css_frame *vf_frame;
7982 	struct ia_css_pipeline_stage_desc stage_desc;
7983 	bool need_in_frameinfo_memory = false;
7984 #ifdef USE_INPUT_SYSTEM_VERSION_2401
7985 	bool sensor = false;
7986 	bool buffered_sensor = false;
7987 	bool online = false;
7988 	bool continuous = false;
7989 #endif
7990 	unsigned int i, num_yuv_scaler, num_primary_stage;
7991 	bool need_yuv_pp = false;
7992 	bool *is_output_stage = NULL;
7993 	bool need_ldc = false;
7994 
7995 	IA_CSS_ENTER_PRIVATE("");
7996 	assert(pipe);
7997 	assert(pipe->stream);
7998 	assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || pipe->mode == IA_CSS_PIPE_ID_COPY);
7999 
8000 	me = &pipe->pipeline;
8001 	mode = pipe->config.default_capture_config.mode;
8002 	raw = (mode == IA_CSS_CAPTURE_MODE_RAW);
8003 	ia_css_pipeline_clean(me);
8004 	ia_css_pipe_util_create_output_frames(out_frames);
8005 
8006 #ifdef USE_INPUT_SYSTEM_VERSION_2401
8007 	/* When the input system is 2401, always enable 'in_frameinfo_memory'
8008 	    * except for the following:
8009 	    * - Direct Sensor Mode Online Capture
8010 	    * - Direct Sensor Mode Online Capture
8011 	    * - Direct Sensor Mode Continuous Capture
8012 	    * - Buffered Sensor Mode Continuous Capture
8013 	    */
8014 	sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR);
8015 	buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR);
8016 	online = pipe->stream->config.online;
8017 	continuous = pipe->stream->config.continuous;
8018 	need_in_frameinfo_memory =
8019 	!((sensor && (online || continuous)) || (buffered_sensor && (online || continuous)));
8020 #else
8021 	/* Construct in_frame info (only in case we have dynamic input */
8022 	need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
8023 #endif
8024 	if (need_in_frameinfo_memory)
8025 	{
8026 		err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame,
8027 							IA_CSS_FRAME_FORMAT_RAW);
8028 		if (err != IA_CSS_SUCCESS) {
8029 			IA_CSS_LEAVE_ERR_PRIVATE(err);
8030 			return err;
8031 		}
8032 
8033 		in_frame = &me->in_frame;
8034 	} else
8035 	{
8036 		in_frame = NULL;
8037 	}
8038 
8039 	err = init_out_frameinfo_defaults(pipe, &me->out_frame[0], 0);
8040 	if (err != IA_CSS_SUCCESS)
8041 	{
8042 		IA_CSS_LEAVE_ERR_PRIVATE(err);
8043 		return err;
8044 	}
8045 	out_frame = &me->out_frame[0];
8046 
8047 	/* Construct vf_frame info (only in case we have VF) */
8048 	if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0])
8049 	{
8050 		if (mode == IA_CSS_CAPTURE_MODE_RAW || mode == IA_CSS_CAPTURE_MODE_BAYER) {
8051 			/* These modes don't support viewfinder output */
8052 			vf_frame = NULL;
8053 		} else {
8054 			init_vf_frameinfo_defaults(pipe, &me->vf_frame[0], 0);
8055 			vf_frame = &me->vf_frame[0];
8056 		}
8057 	} else
8058 	{
8059 		vf_frame = NULL;
8060 	}
8061 
8062 	copy_binary       = &pipe->pipe_settings.capture.copy_binary;
8063 	num_primary_stage = pipe->pipe_settings.capture.num_primary_stage;
8064 	if ((num_primary_stage == 0) && (mode == IA_CSS_CAPTURE_MODE_PRIMARY))
8065 	{
8066 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR);
8067 		return IA_CSS_ERR_INTERNAL_ERROR;
8068 	}
8069 	for (i = 0; i < num_primary_stage; i++)
8070 	{
8071 		primary_binary[i] = &pipe->pipe_settings.capture.primary_binary[i];
8072 	}
8073 	vf_pp_binary      = &pipe->pipe_settings.capture.vf_pp_binary;
8074 	pre_isp_binary    = &pipe->pipe_settings.capture.pre_isp_binary;
8075 	anr_gdc_binary    = &pipe->pipe_settings.capture.anr_gdc_binary;
8076 	post_isp_binary   = &pipe->pipe_settings.capture.post_isp_binary;
8077 	capture_pp_binary = &pipe->pipe_settings.capture.capture_pp_binary;
8078 	yuv_scaler_binary = pipe->pipe_settings.capture.yuv_scaler_binary;
8079 	num_yuv_scaler	  = pipe->pipe_settings.capture.num_yuv_scaler;
8080 	is_output_stage   = pipe->pipe_settings.capture.is_output_stage;
8081 	capture_ldc_binary = &pipe->pipe_settings.capture.capture_ldc_binary;
8082 
8083 	need_pp = (need_capture_pp(pipe) || pipe->output_stage) &&
8084 		    mode != IA_CSS_CAPTURE_MODE_RAW &&
8085 		    mode != IA_CSS_CAPTURE_MODE_BAYER;
8086 	need_yuv_pp = (yuv_scaler_binary && yuv_scaler_binary->info);
8087 	need_ldc = (capture_ldc_binary && capture_ldc_binary->info);
8088 
8089 	if (pipe->pipe_settings.capture.copy_binary.info)
8090 	{
8091 		if (raw) {
8092 			ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
8093 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2401)
8094 			if (!continuous) {
8095 				ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
8096 								    out_frames, in_frame, NULL);
8097 			} else {
8098 				in_frame = pipe->stream->last_pipe->continuous_frames[0];
8099 				ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
8100 								    out_frames, in_frame, NULL);
8101 			}
8102 #else
8103 			ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
8104 							    out_frames, NULL, NULL);
8105 #endif
8106 		} else {
8107 			ia_css_pipe_util_set_output_frames(out_frames, 0, in_frame);
8108 			ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
8109 							    out_frames, NULL, NULL);
8110 		}
8111 
8112 		err = ia_css_pipeline_create_and_add_stage(me,
8113 			&stage_desc,
8114 			&current_stage);
8115 		if (err != IA_CSS_SUCCESS) {
8116 			IA_CSS_LEAVE_ERR_PRIVATE(err);
8117 			return err;
8118 		}
8119 	} else if (pipe->stream->config.continuous)
8120 	{
8121 		in_frame = pipe->stream->last_pipe->continuous_frames[0];
8122 	}
8123 
8124 	if (mode == IA_CSS_CAPTURE_MODE_PRIMARY)
8125 	{
8126 		struct ia_css_frame *local_in_frame = NULL;
8127 		struct ia_css_frame *local_out_frame = NULL;
8128 
8129 		for (i = 0; i < num_primary_stage; i++) {
8130 			if (i == 0)
8131 				local_in_frame = in_frame;
8132 			else
8133 				local_in_frame = NULL;
8134 #ifndef ISP2401
8135 			if (!need_pp && (i == num_primary_stage - 1))
8136 #else
8137 			if (!need_pp && (i == num_primary_stage - 1) && !need_ldc)
8138 #endif
8139 				local_out_frame = out_frame;
8140 			else
8141 				local_out_frame = NULL;
8142 			ia_css_pipe_util_set_output_frames(out_frames, 0, local_out_frame);
8143 			/*
8144 			    * WARNING: The #if def flag has been added below as a
8145 			    * temporary solution to solve the problem of enabling the
8146 			    * view finder in a single binary in a capture flow. The
8147 			    * vf-pp stage has been removed from Skycam in the solution
8148 			    * provided. The vf-pp stage should be re-introduced when
8149 			    * required. This  * should not be considered as a clean solution.
8150 			    * Proper investigation should be done to come up with the clean
8151 			    * solution.
8152 			    * */
8153 			ia_css_pipe_get_generic_stage_desc(&stage_desc, primary_binary[i],
8154 							    out_frames, local_in_frame, NULL);
8155 			err = ia_css_pipeline_create_and_add_stage(me,
8156 				&stage_desc,
8157 				&current_stage);
8158 			if (err != IA_CSS_SUCCESS) {
8159 				IA_CSS_LEAVE_ERR_PRIVATE(err);
8160 				return err;
8161 			}
8162 		}
8163 		/* If we use copy iso primary,
8164 		    the input must be yuv iso raw */
8165 		current_stage->args.copy_vf =
8166 		    primary_binary[0]->info->sp.pipeline.mode ==
8167 		    IA_CSS_BINARY_MODE_COPY;
8168 		current_stage->args.copy_output = current_stage->args.copy_vf;
8169 	} else if (mode == IA_CSS_CAPTURE_MODE_ADVANCED ||
8170 		    mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT)
8171 	{
8172 		ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
8173 		ia_css_pipe_get_generic_stage_desc(&stage_desc, pre_isp_binary,
8174 						    out_frames, in_frame, NULL);
8175 		err = ia_css_pipeline_create_and_add_stage(me,
8176 			&stage_desc, NULL);
8177 		if (err != IA_CSS_SUCCESS) {
8178 			IA_CSS_LEAVE_ERR_PRIVATE(err);
8179 			return err;
8180 		}
8181 		ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
8182 		ia_css_pipe_get_generic_stage_desc(&stage_desc, anr_gdc_binary,
8183 						    out_frames, NULL, NULL);
8184 		err = ia_css_pipeline_create_and_add_stage(me,
8185 			&stage_desc, NULL);
8186 		if (err != IA_CSS_SUCCESS) {
8187 			IA_CSS_LEAVE_ERR_PRIVATE(err);
8188 			return err;
8189 		}
8190 
8191 		if (need_pp) {
8192 			ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
8193 			ia_css_pipe_get_generic_stage_desc(&stage_desc, post_isp_binary,
8194 							    out_frames, NULL, NULL);
8195 		} else {
8196 			ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
8197 			ia_css_pipe_get_generic_stage_desc(&stage_desc, post_isp_binary,
8198 							    out_frames, NULL, NULL);
8199 		}
8200 
8201 		err = ia_css_pipeline_create_and_add_stage(me,
8202 			&stage_desc, &current_stage);
8203 		if (err != IA_CSS_SUCCESS) {
8204 			IA_CSS_LEAVE_ERR_PRIVATE(err);
8205 			return err;
8206 		}
8207 	} else if (mode == IA_CSS_CAPTURE_MODE_BAYER)
8208 	{
8209 		ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
8210 		ia_css_pipe_get_generic_stage_desc(&stage_desc, pre_isp_binary,
8211 						    out_frames, in_frame, NULL);
8212 		err = ia_css_pipeline_create_and_add_stage(me,
8213 			&stage_desc,
8214 			NULL);
8215 		if (err != IA_CSS_SUCCESS) {
8216 			IA_CSS_LEAVE_ERR_PRIVATE(err);
8217 			return err;
8218 		}
8219 	}
8220 
8221 #ifndef ISP2401
8222 	if (need_pp && current_stage)
8223 	{
8224 		struct ia_css_frame *local_in_frame = NULL;
8225 
8226 		local_in_frame = current_stage->args.out_frame[0];
8227 
8228 		if (need_ldc) {
8229 			ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
8230 			ia_css_pipe_get_generic_stage_desc(&stage_desc, capture_ldc_binary,
8231 							    out_frames, local_in_frame, NULL);
8232 			err = ia_css_pipeline_create_and_add_stage(me,
8233 				&stage_desc,
8234 				&current_stage);
8235 			local_in_frame = current_stage->args.out_frame[0];
8236 		}
8237 		err = add_capture_pp_stage(pipe, me, local_in_frame,
8238 					    need_yuv_pp ? NULL : out_frame,
8239 #else
8240 	/* ldc and capture_pp not supported in same pipeline */
8241 	if (need_ldc && current_stage)
8242 	{
8243 		in_frame = current_stage->args.out_frame[0];
8244 		ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
8245 		ia_css_pipe_get_generic_stage_desc(&stage_desc, capture_ldc_binary,
8246 						    out_frames, in_frame, NULL);
8247 		err = ia_css_pipeline_create_and_add_stage(me,
8248 			&stage_desc,
8249 			NULL);
8250 	} else if (need_pp && current_stage)
8251 	{
8252 		in_frame = current_stage->args.out_frame[0];
8253 		err = add_capture_pp_stage(pipe, me, in_frame, need_yuv_pp ? NULL : out_frame,
8254 #endif
8255 					    capture_pp_binary,
8256 					    &current_stage);
8257 		if (err != IA_CSS_SUCCESS) {
8258 			IA_CSS_LEAVE_ERR_PRIVATE(err);
8259 			return err;
8260 		}
8261 	}
8262 
8263 	if (need_yuv_pp && current_stage)
8264 	{
8265 		struct ia_css_frame *tmp_in_frame = current_stage->args.out_frame[0];
8266 		struct ia_css_frame *tmp_out_frame = NULL;
8267 
8268 		for (i = 0; i < num_yuv_scaler; i++) {
8269 			if (is_output_stage[i] == true)
8270 				tmp_out_frame = out_frame;
8271 			else
8272 				tmp_out_frame = NULL;
8273 
8274 			err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame,
8275 						    NULL,
8276 						    &yuv_scaler_binary[i],
8277 						    &yuv_scaler_stage);
8278 			if (err != IA_CSS_SUCCESS) {
8279 				IA_CSS_LEAVE_ERR_PRIVATE(err);
8280 				return err;
8281 			}
8282 			/* we use output port 1 as internal output port */
8283 			tmp_in_frame = yuv_scaler_stage->args.out_frame[1];
8284 		}
8285 	}
8286 
8287 	/*
8288 	    * WARNING: The #if def flag has been added below as a
8289 	    * temporary solution to solve the problem of enabling the
8290 	    * view finder in a single binary in a capture flow. The vf-pp
8291 	    * stage has been removed from Skycam in the solution provided.
8292 	    * The vf-pp stage should be re-introduced when required. This
8293 	    * should not be considered as a clean solution. Proper
8294 	    * investigation should be done to come up with the clean solution.
8295 	    * */
8296 	if (mode != IA_CSS_CAPTURE_MODE_RAW && mode != IA_CSS_CAPTURE_MODE_BAYER && current_stage && vf_frame)
8297 	{
8298 		in_frame = current_stage->args.out_vf_frame;
8299 		err = add_vf_pp_stage(pipe, in_frame, vf_frame, vf_pp_binary,
8300 					&current_stage);
8301 		if (err != IA_CSS_SUCCESS) {
8302 			IA_CSS_LEAVE_ERR_PRIVATE(err);
8303 			return err;
8304 		}
8305 	}
8306 	ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
8307 
8308 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8309 			    "create_host_regular_capture_pipeline() leave:\n");
8310 
8311 	return IA_CSS_SUCCESS;
8312 }
8313 
8314 static enum ia_css_err
8315 create_host_capture_pipeline(struct ia_css_pipe *pipe) {
8316 	enum ia_css_err err = IA_CSS_SUCCESS;
8317 
8318 	IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
8319 
8320 	if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY)
8321 		err = create_host_isyscopy_capture_pipeline(pipe);
8322 	else
8323 		err = create_host_regular_capture_pipeline(pipe);
8324 	if (err != IA_CSS_SUCCESS)
8325 	{
8326 		IA_CSS_LEAVE_ERR_PRIVATE(err);
8327 		return err;
8328 	}
8329 
8330 	IA_CSS_LEAVE_ERR_PRIVATE(err);
8331 
8332 	return err;
8333 }
8334 
8335 static enum ia_css_err capture_start(
8336     struct ia_css_pipe *pipe) {
8337 	struct ia_css_pipeline *me;
8338 
8339 	enum ia_css_err err = IA_CSS_SUCCESS;
8340 	enum sh_css_pipe_config_override copy_ovrd;
8341 
8342 	IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
8343 	if (!pipe) {
8344 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
8345 		return IA_CSS_ERR_INVALID_ARGUMENTS;
8346 	}
8347 
8348 	me = &pipe->pipeline;
8349 
8350 	if ((pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW   ||
8351 		pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER) &&
8352 	    (pipe->config.mode != IA_CSS_PIPE_MODE_COPY)) {
8353 		if (copy_on_sp(pipe)) {
8354 			err = start_copy_on_sp(pipe, &me->out_frame[0]);
8355 			IA_CSS_LEAVE_ERR_PRIVATE(err);
8356 			return err;
8357 		}
8358 	}
8359 
8360 #if defined(USE_INPUT_SYSTEM_VERSION_2)
8361 	/* old isys: need to send_mipi_frames() in all pipe modes */
8362 	err = send_mipi_frames(pipe);
8363 	if (err != IA_CSS_SUCCESS) {
8364 		IA_CSS_LEAVE_ERR_PRIVATE(err);
8365 		return err;
8366 	}
8367 #elif defined(USE_INPUT_SYSTEM_VERSION_2401)
8368 	if (pipe->config.mode != IA_CSS_PIPE_MODE_COPY) {
8369 		err = send_mipi_frames(pipe);
8370 		if (err != IA_CSS_SUCCESS) {
8371 			IA_CSS_LEAVE_ERR_PRIVATE(err);
8372 			return err;
8373 		}
8374 	}
8375 
8376 #endif
8377 
8378 	{
8379 		unsigned int thread_id;
8380 
8381 		ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
8382 		copy_ovrd = 1 << thread_id;
8383 	}
8384 	start_pipe(pipe, copy_ovrd, pipe->stream->config.mode);
8385 
8386 #if !defined(HAS_NO_INPUT_SYSTEM) && !defined(USE_INPUT_SYSTEM_VERSION_2401)
8387 	/*
8388 	    * old isys: for IA_CSS_PIPE_MODE_COPY pipe, isys rx has to be configured,
8389 	    * which is currently done in start_binary(); but COPY pipe contains no binary,
8390 	    * and does not call start_binary(); so we need to configure the rx here.
8391 	    */
8392 	if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY &&
8393 	    pipe->stream->reconfigure_css_rx) {
8394 		ia_css_isys_rx_configure(&pipe->stream->csi_rx_config,
8395 					    pipe->stream->config.mode);
8396 		pipe->stream->reconfigure_css_rx = false;
8397 	}
8398 #endif
8399 
8400 	IA_CSS_LEAVE_ERR_PRIVATE(err);
8401 	return err;
8402 }
8403 
8404 static enum ia_css_err
8405 sh_css_pipe_get_output_frame_info(struct ia_css_pipe *pipe,
8406 				    struct ia_css_frame_info *info,
8407 				    unsigned int idx) {
8408 	assert(pipe);
8409 	assert(info);
8410 
8411 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8412 			    "sh_css_pipe_get_output_frame_info() enter:\n");
8413 
8414 	*info = pipe->output_info[idx];
8415 	if (copy_on_sp(pipe) &&
8416 	    pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8)
8417 	{
8418 		ia_css_frame_info_init(
8419 		    info,
8420 		    JPEG_BYTES,
8421 		    1,
8422 		    IA_CSS_FRAME_FORMAT_BINARY_8,
8423 		    0);
8424 	} else if (info->format == IA_CSS_FRAME_FORMAT_RAW ||
8425 		    info->format == IA_CSS_FRAME_FORMAT_RAW_PACKED)
8426 	{
8427 		info->raw_bit_depth =
8428 		ia_css_pipe_util_pipe_input_format_bpp(pipe);
8429 	}
8430 
8431 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8432 			    "sh_css_pipe_get_output_frame_info() leave:\n");
8433 	return IA_CSS_SUCCESS;
8434 }
8435 
8436 #if !defined(HAS_NO_INPUT_SYSTEM)
8437 void
8438 ia_css_stream_send_input_frame(const struct ia_css_stream *stream,
8439 				const unsigned short *data,
8440 				unsigned int width,
8441 				unsigned int height) {
8442 	assert(stream);
8443 
8444 	ia_css_inputfifo_send_input_frame(
8445 	    data, width, height,
8446 	    stream->config.channel_id,
8447 	    stream->config.input_config.format,
8448 	    stream->config.pixels_per_clock == 2);
8449 }
8450 
8451 void
8452 ia_css_stream_start_input_frame(const struct ia_css_stream *stream) {
8453 	assert(stream);
8454 
8455 	ia_css_inputfifo_start_frame(
8456 	    stream->config.channel_id,
8457 	    stream->config.input_config.format,
8458 	    stream->config.pixels_per_clock == 2);
8459 }
8460 
8461 void
8462 ia_css_stream_send_input_line(const struct ia_css_stream *stream,
8463 				const unsigned short *data,
8464 				unsigned int width,
8465 				const unsigned short *data2,
8466 				unsigned int width2) {
8467 	assert(stream);
8468 
8469 	ia_css_inputfifo_send_line(stream->config.channel_id,
8470 				    data, width, data2, width2);
8471 }
8472 
8473 void
8474 ia_css_stream_send_input_embedded_line(const struct ia_css_stream *stream,
8475 					enum atomisp_input_format format,
8476 					const unsigned short *data,
8477 					unsigned int width) {
8478 	assert(stream);
8479 	if (!data || width == 0)
8480 		return;
8481 	ia_css_inputfifo_send_embedded_line(stream->config.channel_id,
8482 					    format, data, width);
8483 }
8484 
8485 void
8486 ia_css_stream_end_input_frame(const struct ia_css_stream *stream) {
8487 	assert(stream);
8488 
8489 	ia_css_inputfifo_end_frame(stream->config.channel_id);
8490 }
8491 #endif
8492 
8493 static void
8494 append_firmware(struct ia_css_fw_info **l, struct ia_css_fw_info *firmware) {
8495 	IA_CSS_ENTER_PRIVATE("l = %p, firmware = %p", l, firmware);
8496 	if (!l) {
8497 		IA_CSS_ERROR("NULL fw_info");
8498 		IA_CSS_LEAVE_PRIVATE("");
8499 		return;
8500 	}
8501 	while (*l)
8502 		l = &(*l)->next;
8503 	*l = firmware;
8504 	/*firmware->next = NULL;*/ /* when multiple acc extensions are loaded, 'next' can be not NULL */
8505 	IA_CSS_LEAVE_PRIVATE("");
8506 }
8507 
8508 static void
8509 remove_firmware(struct ia_css_fw_info **l, struct ia_css_fw_info *firmware) {
8510 	assert(*l);
8511 	assert(firmware);
8512 	(void)l;
8513 	(void)firmware;
8514 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "remove_firmware() enter:\n");
8515 
8516 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "remove_firmware() leave:\n");
8517 	return; /* removing single and multiple firmware is handled in acc_unload_extension() */
8518 }
8519 
8520 static enum ia_css_err upload_isp_code(struct ia_css_fw_info *firmware) {
8521 	hrt_vaddress binary;
8522 
8523 	if (!firmware) {
8524 		IA_CSS_ERROR("NULL input parameter");
8525 		return IA_CSS_ERR_INVALID_ARGUMENTS;
8526 	}
8527 	binary = firmware->info.isp.xmem_addr;
8528 
8529 	if (!binary) {
8530 		unsigned int size = firmware->blob.size;
8531 		const unsigned char *blob;
8532 		const unsigned char *binary_name;
8533 
8534 		binary_name =
8535 		    (const unsigned char *)(IA_CSS_EXT_ISP_PROG_NAME(
8536 						firmware));
8537 		blob = binary_name +
8538 			strlen((const char *)binary_name) +
8539 			1;
8540 		binary = sh_css_load_blob(blob, size);
8541 		firmware->info.isp.xmem_addr = binary;
8542 	}
8543 
8544 	if (!binary)
8545 		return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
8546 	return IA_CSS_SUCCESS;
8547 }
8548 
8549 static enum ia_css_err
8550 acc_load_extension(struct ia_css_fw_info *firmware) {
8551 	enum ia_css_err err;
8552 	struct ia_css_fw_info *hd = firmware;
8553 
8554 	while (hd)
8555 	{
8556 		err = upload_isp_code(hd);
8557 		if (err != IA_CSS_SUCCESS)
8558 			return err;
8559 		hd = hd->next;
8560 	}
8561 
8562 	if (!firmware)
8563 		return IA_CSS_ERR_INVALID_ARGUMENTS;
8564 	firmware->loaded = true;
8565 	return IA_CSS_SUCCESS;
8566 }
8567 
8568 static void
8569 acc_unload_extension(struct ia_css_fw_info *firmware) {
8570 	struct ia_css_fw_info *hd = firmware;
8571 	struct ia_css_fw_info *hdn = NULL;
8572 
8573 	if (!firmware) /* should not happen */
8574 		return;
8575 	/* unload and remove multiple firmwares */
8576 	while (hd) {
8577 		hdn = (hd->next) ? &(*hd->next) : NULL;
8578 		if (hd->info.isp.xmem_addr) {
8579 			hmm_free(hd->info.isp.xmem_addr);
8580 			hd->info.isp.xmem_addr = mmgr_NULL;
8581 		}
8582 		hd->isp_code = NULL;
8583 		hd->next = NULL;
8584 		hd = hdn;
8585 	}
8586 
8587 	firmware->loaded = false;
8588 }
8589 
8590 /* Load firmware for extension */
8591 static enum ia_css_err
8592 ia_css_pipe_load_extension(struct ia_css_pipe *pipe,
8593 			    struct ia_css_fw_info *firmware) {
8594 	enum ia_css_err err = IA_CSS_SUCCESS;
8595 
8596 	IA_CSS_ENTER_PRIVATE("fw = %p pipe = %p", firmware, pipe);
8597 
8598 	if ((!firmware) || (!pipe))
8599 	{
8600 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
8601 		return IA_CSS_ERR_INVALID_ARGUMENTS;
8602 	}
8603 
8604 	if (firmware->info.isp.type == IA_CSS_ACC_OUTPUT)
8605 	{
8606 		if (&pipe->output_stage)
8607 			append_firmware(&pipe->output_stage, firmware);
8608 		else {
8609 			IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR);
8610 			return IA_CSS_ERR_INTERNAL_ERROR;
8611 		}
8612 	} else if (firmware->info.isp.type == IA_CSS_ACC_VIEWFINDER)
8613 	{
8614 		if (&pipe->vf_stage)
8615 			append_firmware(&pipe->vf_stage, firmware);
8616 		else {
8617 			IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR);
8618 			return IA_CSS_ERR_INTERNAL_ERROR;
8619 		}
8620 	}
8621 	err = acc_load_extension(firmware);
8622 
8623 	IA_CSS_LEAVE_ERR_PRIVATE(err);
8624 	return err;
8625 }
8626 
8627 /* Unload firmware for extension */
8628 static void
8629 ia_css_pipe_unload_extension(struct ia_css_pipe *pipe,
8630 				struct ia_css_fw_info *firmware) {
8631 	IA_CSS_ENTER_PRIVATE("fw = %p pipe = %p", firmware, pipe);
8632 
8633 	if ((!firmware) || (!pipe)) {
8634 		IA_CSS_ERROR("NULL input parameters");
8635 		IA_CSS_LEAVE_PRIVATE("");
8636 		return;
8637 	}
8638 
8639 	if (firmware->info.isp.type == IA_CSS_ACC_OUTPUT)
8640 		remove_firmware(&pipe->output_stage, firmware);
8641 	else if (firmware->info.isp.type == IA_CSS_ACC_VIEWFINDER)
8642 		remove_firmware(&pipe->vf_stage, firmware);
8643 	acc_unload_extension(firmware);
8644 
8645 	IA_CSS_LEAVE_PRIVATE("");
8646 }
8647 
8648 bool
8649 ia_css_pipeline_uses_params(struct ia_css_pipeline *me) {
8650 	struct ia_css_pipeline_stage *stage;
8651 
8652 	assert(me);
8653 
8654 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8655 			    "ia_css_pipeline_uses_params() enter: me=%p\n", me);
8656 
8657 	for (stage = me->stages; stage; stage = stage->next)
8658 		if (stage->binary_info && stage->binary_info->enable.params) {
8659 			ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8660 					    "ia_css_pipeline_uses_params() leave: return_bool=true\n");
8661 			return true;
8662 		}
8663 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8664 			    "ia_css_pipeline_uses_params() leave: return_bool=false\n");
8665 	return false;
8666 }
8667 
8668 static enum ia_css_err
8669 sh_css_pipeline_add_acc_stage(struct ia_css_pipeline *pipeline,
8670 				const void *acc_fw) {
8671 	struct ia_css_fw_info *fw = (struct ia_css_fw_info *)acc_fw;
8672 	/* In QoS case, load_extension already called, so skipping */
8673 	enum ia_css_err	err = IA_CSS_SUCCESS;
8674 
8675 	if (fw->loaded == false)
8676 		err = acc_load_extension(fw);
8677 
8678 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8679 			    "sh_css_pipeline_add_acc_stage() enter: pipeline=%p, acc_fw=%p\n",
8680 			    pipeline, acc_fw);
8681 
8682 	if (err == IA_CSS_SUCCESS)
8683 	{
8684 		struct ia_css_pipeline_stage_desc stage_desc;
8685 
8686 		ia_css_pipe_get_acc_stage_desc(&stage_desc, NULL, fw);
8687 		err = ia_css_pipeline_create_and_add_stage(pipeline,
8688 			&stage_desc,
8689 			NULL);
8690 	}
8691 
8692 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8693 			    "sh_css_pipeline_add_acc_stage() leave: return_err=%d\n", err);
8694 	return err;
8695 }
8696 
8697 /*
8698     * @brief Tag a specific frame in continuous capture.
8699     * Refer to "sh_css_internal.h" for details.
8700     */
8701 enum ia_css_err ia_css_stream_capture_frame(struct ia_css_stream *stream,
8702 	unsigned int exp_id) {
8703 	struct sh_css_tag_descr tag_descr;
8704 	u32 encoded_tag_descr;
8705 	enum ia_css_err err;
8706 
8707 	assert(stream);
8708 	IA_CSS_ENTER("exp_id=%d", exp_id);
8709 
8710 	/* Only continuous streams have a tagger */
8711 	if (exp_id == 0 || !stream->config.continuous) {
8712 		IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
8713 		return IA_CSS_ERR_INVALID_ARGUMENTS;
8714 	}
8715 
8716 	if (!sh_css_sp_is_running()) {
8717 		/* SP is not running. The queues are not valid */
8718 		IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE);
8719 		return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
8720 	}
8721 
8722 	/* Create the tag descriptor from the parameters */
8723 	sh_css_create_tag_descr(0, 0, 0, exp_id, &tag_descr);
8724 	/* Encode the tag descriptor into a 32-bit value */
8725 	encoded_tag_descr = sh_css_encode_tag_descr(&tag_descr);
8726 	/* Enqueue the encoded tag to the host2sp queue.
8727 	    * Note: The pipe and stage IDs for tag_cmd queue are hard-coded to 0
8728 	    * on both host and the SP side.
8729 	    * It is mainly because it is enough to have only one tag_cmd queue */
8730 	err = ia_css_bufq_enqueue_tag_cmd(encoded_tag_descr);
8731 
8732 	IA_CSS_LEAVE_ERR(err);
8733 	return err;
8734 }
8735 
8736 /*
8737     * @brief Configure the continuous capture.
8738     * Refer to "sh_css_internal.h" for details.
8739     */
8740 enum ia_css_err ia_css_stream_capture(
8741     struct ia_css_stream *stream,
8742     int num_captures,
8743     unsigned int skip,
8744     int offset) {
8745 	struct sh_css_tag_descr tag_descr;
8746 	unsigned int encoded_tag_descr;
8747 	enum ia_css_err return_err;
8748 
8749 	if (!stream)
8750 		return IA_CSS_ERR_INVALID_ARGUMENTS;
8751 
8752 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8753 			    "ia_css_stream_capture() enter: num_captures=%d, skip=%d, offset=%d\n",
8754 			    num_captures, skip, offset);
8755 
8756 	/* Check if the tag descriptor is valid */
8757 	if (num_captures < SH_CSS_MINIMUM_TAG_ID) {
8758 		ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8759 				    "ia_css_stream_capture() leave: return_err=%d\n",
8760 				    IA_CSS_ERR_INVALID_ARGUMENTS);
8761 		return IA_CSS_ERR_INVALID_ARGUMENTS;
8762 	}
8763 
8764 	/* Create the tag descriptor from the parameters */
8765 	sh_css_create_tag_descr(num_captures, skip, offset, 0, &tag_descr);
8766 
8767 	/* Encode the tag descriptor into a 32-bit value */
8768 	encoded_tag_descr = sh_css_encode_tag_descr(&tag_descr);
8769 
8770 	if (!sh_css_sp_is_running()) {
8771 		/* SP is not running. The queues are not valid */
8772 		ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8773 				    "ia_css_stream_capture() leaving:queues unavailable\n");
8774 		return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
8775 	}
8776 
8777 	/* Enqueue the encoded tag to the host2sp queue.
8778 	    * Note: The pipe and stage IDs for tag_cmd queue are hard-coded to 0
8779 	    * on both host and the SP side.
8780 	    * It is mainly because it is enough to have only one tag_cmd queue */
8781 	return_err = ia_css_bufq_enqueue_tag_cmd((uint32_t)encoded_tag_descr);
8782 
8783 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8784 			    "ia_css_stream_capture() leave: return_err=%d\n",
8785 			    return_err);
8786 
8787 	return return_err;
8788 }
8789 
8790 void ia_css_stream_request_flash(struct ia_css_stream *stream) {
8791 	(void)stream;
8792 
8793 	assert(stream);
8794 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8795 			    "ia_css_stream_request_flash() enter: void\n");
8796 
8797 #ifndef ISP2401
8798 	sh_css_write_host2sp_command(host2sp_cmd_start_flash);
8799 #else
8800 	if (sh_css_sp_is_running()) {
8801 		if (!sh_css_write_host2sp_command(host2sp_cmd_start_flash)) {
8802 			IA_CSS_ERROR("Call to 'sh-css_write_host2sp_command()' failed");
8803 			ia_css_debug_dump_sp_sw_debug_info();
8804 			ia_css_debug_dump_debug_info(NULL);
8805 		}
8806 	} else
8807 		IA_CSS_LOG("SP is not running!");
8808 
8809 #endif
8810 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8811 			    "ia_css_stream_request_flash() leave: return_void\n");
8812 }
8813 
8814 static void
8815 sh_css_init_host_sp_control_vars(void) {
8816 	const struct ia_css_fw_info *fw;
8817 	unsigned int HIVE_ADDR_ia_css_ispctrl_sp_isp_started;
8818 
8819 	unsigned int HIVE_ADDR_host_sp_queues_initialized;
8820 	unsigned int HIVE_ADDR_sp_sleep_mode;
8821 	unsigned int HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb;
8822 #ifndef ISP2401
8823 	unsigned int HIVE_ADDR_sp_stop_copy_preview;
8824 #endif
8825 	unsigned int HIVE_ADDR_host_sp_com;
8826 	unsigned int o = offsetof(struct host_sp_communication, host2sp_command)
8827 			    / sizeof(int);
8828 
8829 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
8830 	unsigned int i;
8831 #endif
8832 
8833 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8834 			    "sh_css_init_host_sp_control_vars() enter: void\n");
8835 
8836 	fw = &sh_css_sp_fw;
8837 	HIVE_ADDR_ia_css_ispctrl_sp_isp_started = fw->info.sp.isp_started;
8838 
8839 	HIVE_ADDR_host_sp_queues_initialized =
8840 	    fw->info.sp.host_sp_queues_initialized;
8841 	HIVE_ADDR_sp_sleep_mode = fw->info.sp.sleep_mode;
8842 	HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb = fw->info.sp.invalidate_tlb;
8843 #ifndef ISP2401
8844 	HIVE_ADDR_sp_stop_copy_preview = fw->info.sp.stop_copy_preview;
8845 #endif
8846 	HIVE_ADDR_host_sp_com = fw->info.sp.host_sp_com;
8847 
8848 	(void)HIVE_ADDR_ia_css_ispctrl_sp_isp_started; /* Suppres warnings in CRUN */
8849 
8850 	(void)HIVE_ADDR_sp_sleep_mode;
8851 	(void)HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb;
8852 #ifndef ISP2401
8853 	(void)HIVE_ADDR_sp_stop_copy_preview;
8854 #endif
8855 	(void)HIVE_ADDR_host_sp_com;
8856 
8857 	sp_dmem_store_uint32(SP0_ID,
8858 				(unsigned int)sp_address_of(ia_css_ispctrl_sp_isp_started),
8859 				(uint32_t)(0));
8860 
8861 	sp_dmem_store_uint32(SP0_ID,
8862 				(unsigned int)sp_address_of(host_sp_queues_initialized),
8863 				(uint32_t)(0));
8864 	sp_dmem_store_uint32(SP0_ID,
8865 				(unsigned int)sp_address_of(sp_sleep_mode),
8866 				(uint32_t)(0));
8867 	sp_dmem_store_uint32(SP0_ID,
8868 				(unsigned int)sp_address_of(ia_css_dmaproxy_sp_invalidate_tlb),
8869 				(uint32_t)(false));
8870 #ifndef ISP2401
8871 	sp_dmem_store_uint32(SP0_ID,
8872 				(unsigned int)sp_address_of(sp_stop_copy_preview),
8873 				my_css.stop_copy_preview ? (uint32_t)(1) : (uint32_t)(0));
8874 #endif
8875 	store_sp_array_uint(host_sp_com, o, host2sp_cmd_ready);
8876 
8877 #if !defined(HAS_NO_INPUT_SYSTEM)
8878 	for (i = 0; i < N_CSI_PORTS; i++) {
8879 		sh_css_update_host2sp_num_mipi_frames
8880 		(my_css.num_mipi_frames[i]);
8881 	}
8882 #endif
8883 
8884 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8885 			    "sh_css_init_host_sp_control_vars() leave: return_void\n");
8886 }
8887 
8888 /*
8889     * create the internal structures and fill in the configuration data
8890     */
8891 void ia_css_pipe_config_defaults(struct ia_css_pipe_config *pipe_config) {
8892 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_config_defaults()\n");
8893 	*pipe_config = DEFAULT_PIPE_CONFIG;
8894 }
8895 
8896 void
8897 ia_css_pipe_extra_config_defaults(struct ia_css_pipe_extra_config
8898 				    *extra_config) {
8899 	if (!extra_config) {
8900 		IA_CSS_ERROR("NULL input parameter");
8901 		return;
8902 	}
8903 
8904 	extra_config->enable_raw_binning = false;
8905 	extra_config->enable_yuv_ds = false;
8906 	extra_config->enable_high_speed = false;
8907 	extra_config->enable_dvs_6axis = false;
8908 	extra_config->enable_reduced_pipe = false;
8909 	extra_config->disable_vf_pp = false;
8910 	extra_config->enable_fractional_ds = false;
8911 }
8912 
8913 void ia_css_stream_config_defaults(struct ia_css_stream_config *stream_config) {
8914 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_config_defaults()\n");
8915 	assert(stream_config);
8916 	memset(stream_config, 0, sizeof(*stream_config));
8917 	stream_config->online = true;
8918 	stream_config->left_padding = -1;
8919 	stream_config->pixels_per_clock = 1;
8920 	/* temporary default value for backwards compatibility.
8921 	    * This field used to be hardcoded within CSS but this has now
8922 	    * been moved to the stream_config struct. */
8923 	stream_config->source.port.rxcount = 0x04040404;
8924 }
8925 
8926 static enum ia_css_err
8927 ia_css_acc_pipe_create(struct ia_css_pipe *pipe) {
8928 	enum ia_css_err err = IA_CSS_SUCCESS;
8929 
8930 	if (!pipe)
8931 	{
8932 		IA_CSS_ERROR("NULL input parameter");
8933 		return IA_CSS_ERR_INVALID_ARGUMENTS;
8934 	}
8935 
8936 	/* There is not meaning for num_execs = 0 semantically. Run atleast once. */
8937 	if (pipe->config.acc_num_execs == 0)
8938 		pipe->config.acc_num_execs = 1;
8939 
8940 	if (pipe->config.acc_extension)
8941 	{
8942 		err = ia_css_pipe_load_extension(pipe, pipe->config.acc_extension);
8943 	}
8944 
8945 	return err;
8946 }
8947 
8948 enum ia_css_err
8949 ia_css_pipe_create(const struct ia_css_pipe_config *config,
8950 		    struct ia_css_pipe **pipe) {
8951 #ifndef ISP2401
8952 	if (!config)
8953 #else
8954 	enum ia_css_err err = IA_CSS_SUCCESS;
8955 
8956 	IA_CSS_ENTER_PRIVATE("config = %p, pipe = %p", config, pipe);
8957 
8958 	if (!config)
8959 	{
8960 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
8961 #endif
8962 		return IA_CSS_ERR_INVALID_ARGUMENTS;
8963 #ifndef ISP2401
8964 	if (!pipe)
8965 #else
8966 }
8967 if (!pipe)
8968 {
8969 	IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
8970 #endif
8971 		return IA_CSS_ERR_INVALID_ARGUMENTS;
8972 #ifndef ISP2401
8973 	return ia_css_pipe_create_extra(config, NULL, pipe);
8974 #else
8975 }
8976 
8977 err = ia_css_pipe_create_extra(config, NULL, pipe);
8978 
8979 if (err == IA_CSS_SUCCESS)
8980 {
8981 	IA_CSS_LOG("pipe created successfully = %p", *pipe);
8982 }
8983 
8984 IA_CSS_LEAVE_ERR_PRIVATE(err);
8985 
8986 return err;
8987 #endif
8988 }
8989 
8990 enum ia_css_err
8991 ia_css_pipe_create_extra(const struct ia_css_pipe_config *config,
8992 			    const struct ia_css_pipe_extra_config *extra_config,
8993 			    struct ia_css_pipe **pipe) {
8994 	enum ia_css_err err = IA_CSS_ERR_INTERNAL_ERROR;
8995 	struct ia_css_pipe *internal_pipe = NULL;
8996 	unsigned int i;
8997 
8998 	IA_CSS_ENTER_PRIVATE("config = %p, extra_config = %p and pipe = %p", config, extra_config, pipe);
8999 
9000 	/* do not allow to create more than the maximum limit */
9001 	if (my_css.pipe_counter >= IA_CSS_PIPELINE_NUM_MAX)
9002 	{
9003 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_RESOURCE_EXHAUSTED);
9004 		return IA_CSS_ERR_INVALID_ARGUMENTS;
9005 	}
9006 
9007 	if ((!pipe) || (!config))
9008 	{
9009 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
9010 		return IA_CSS_ERR_INVALID_ARGUMENTS;
9011 	}
9012 
9013 	ia_css_debug_dump_pipe_config(config);
9014 	ia_css_debug_dump_pipe_extra_config(extra_config);
9015 
9016 	err = create_pipe(config->mode, &internal_pipe, false);
9017 	if (err != IA_CSS_SUCCESS)
9018 	{
9019 		IA_CSS_LEAVE_ERR_PRIVATE(err);
9020 		return err;
9021 	}
9022 
9023 	/* now we have a pipe structure to fill */
9024 	internal_pipe->config = *config;
9025 	if (extra_config)
9026 		internal_pipe->extra_config = *extra_config;
9027 	else
9028 		ia_css_pipe_extra_config_defaults(&internal_pipe->extra_config);
9029 
9030 	if (config->mode == IA_CSS_PIPE_MODE_ACC)
9031 	{
9032 		/* Temporary hack to migrate acceleration to CSS 2.0.
9033 		    * In the future the code for all pipe types should be
9034 		    * unified. */
9035 		*pipe = internal_pipe;
9036 		if (!internal_pipe->config.acc_extension &&
9037 		    internal_pipe->config.num_acc_stages ==
9038 		    0) { /* if no acc binary and no standalone stage */
9039 			*pipe = NULL;
9040 			IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
9041 			return IA_CSS_SUCCESS;
9042 		}
9043 		return ia_css_acc_pipe_create(internal_pipe);
9044 	}
9045 
9046 	/* Use config value when dvs_frame_delay setting equal to 2, otherwise always 1 by default */
9047 	if (internal_pipe->config.dvs_frame_delay == IA_CSS_FRAME_DELAY_2)
9048 		internal_pipe->dvs_frame_delay = 2;
9049 	else
9050 		internal_pipe->dvs_frame_delay = 1;
9051 
9052 	/* we still keep enable_raw_binning for backward compatibility, for any new
9053 	    fractional bayer downscaling, we should use bayer_ds_out_res. if both are
9054 	    specified, bayer_ds_out_res will take precedence.if none is specified, we
9055 	    set bayer_ds_out_res equal to IF output resolution(IF may do cropping on
9056 	    sensor output) or use default decimation factor 1. */
9057 	if (internal_pipe->extra_config.enable_raw_binning &&
9058 	    internal_pipe->config.bayer_ds_out_res.width)
9059 	{
9060 		/* fill some code here, if no code is needed, please remove it during integration */
9061 	}
9062 
9063 	/* YUV downscaling */
9064 	if ((internal_pipe->config.vf_pp_in_res.width ||
9065 		internal_pipe->config.capt_pp_in_res.width))
9066 	{
9067 		enum ia_css_frame_format format;
9068 
9069 		if (internal_pipe->config.vf_pp_in_res.width) {
9070 			format = IA_CSS_FRAME_FORMAT_YUV_LINE;
9071 			ia_css_frame_info_init(
9072 			    &internal_pipe->vf_yuv_ds_input_info,
9073 			    internal_pipe->config.vf_pp_in_res.width,
9074 			    internal_pipe->config.vf_pp_in_res.height,
9075 			    format, 0);
9076 		}
9077 		if (internal_pipe->config.capt_pp_in_res.width) {
9078 			format = IA_CSS_FRAME_FORMAT_YUV420;
9079 			ia_css_frame_info_init(
9080 			    &internal_pipe->out_yuv_ds_input_info,
9081 			    internal_pipe->config.capt_pp_in_res.width,
9082 			    internal_pipe->config.capt_pp_in_res.height,
9083 			    format, 0);
9084 		}
9085 	}
9086 	if (internal_pipe->config.vf_pp_in_res.width &&
9087 	    internal_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW)
9088 	{
9089 		ia_css_frame_info_init(
9090 		    &internal_pipe->vf_yuv_ds_input_info,
9091 		    internal_pipe->config.vf_pp_in_res.width,
9092 		    internal_pipe->config.vf_pp_in_res.height,
9093 		    IA_CSS_FRAME_FORMAT_YUV_LINE, 0);
9094 	}
9095 	/* handle bayer downscaling output info */
9096 	if (internal_pipe->config.bayer_ds_out_res.width)
9097 	{
9098 		ia_css_frame_info_init(
9099 		    &internal_pipe->bds_output_info,
9100 		    internal_pipe->config.bayer_ds_out_res.width,
9101 		    internal_pipe->config.bayer_ds_out_res.height,
9102 		    IA_CSS_FRAME_FORMAT_RAW, 0);
9103 	}
9104 
9105 	/* handle output info, assume always needed */
9106 	for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++)
9107 	{
9108 		if (internal_pipe->config.output_info[i].res.width) {
9109 			err = sh_css_pipe_configure_output(
9110 				    internal_pipe,
9111 				    internal_pipe->config.output_info[i].res.width,
9112 				    internal_pipe->config.output_info[i].res.height,
9113 				    internal_pipe->config.output_info[i].padded_width,
9114 				    internal_pipe->config.output_info[i].format,
9115 				    i);
9116 			if (err != IA_CSS_SUCCESS) {
9117 				IA_CSS_LEAVE_ERR_PRIVATE(err);
9118 				sh_css_free(internal_pipe);
9119 				internal_pipe = NULL;
9120 				return err;
9121 			}
9122 		}
9123 
9124 		/* handle vf output info, when configured */
9125 		internal_pipe->enable_viewfinder[i] =
9126 		    (internal_pipe->config.vf_output_info[i].res.width != 0);
9127 		if (internal_pipe->config.vf_output_info[i].res.width) {
9128 			err = sh_css_pipe_configure_viewfinder(
9129 				    internal_pipe,
9130 				    internal_pipe->config.vf_output_info[i].res.width,
9131 				    internal_pipe->config.vf_output_info[i].res.height,
9132 				    internal_pipe->config.vf_output_info[i].padded_width,
9133 				    internal_pipe->config.vf_output_info[i].format,
9134 				    i);
9135 			if (err != IA_CSS_SUCCESS) {
9136 				IA_CSS_LEAVE_ERR_PRIVATE(err);
9137 				sh_css_free(internal_pipe);
9138 				internal_pipe = NULL;
9139 				return err;
9140 			}
9141 		}
9142 	}
9143 	if (internal_pipe->config.acc_extension)
9144 	{
9145 		err = ia_css_pipe_load_extension(internal_pipe,
9146 						    internal_pipe->config.acc_extension);
9147 		if (err != IA_CSS_SUCCESS) {
9148 			IA_CSS_LEAVE_ERR_PRIVATE(err);
9149 			sh_css_free(internal_pipe);
9150 			return err;
9151 		}
9152 	}
9153 	/* set all info to zeroes first */
9154 	memset(&internal_pipe->info, 0, sizeof(internal_pipe->info));
9155 
9156 	/* all went well, return the pipe */
9157 	*pipe = internal_pipe;
9158 	IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
9159 	return IA_CSS_SUCCESS;
9160 }
9161 
9162 enum ia_css_err
9163 ia_css_pipe_get_info(const struct ia_css_pipe *pipe,
9164 			struct ia_css_pipe_info *pipe_info) {
9165 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
9166 			    "ia_css_pipe_get_info()\n");
9167 	assert(pipe_info);
9168 	if (!pipe_info)
9169 	{
9170 		ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR,
9171 				    "ia_css_pipe_get_info: pipe_info cannot be NULL\n");
9172 		return IA_CSS_ERR_INVALID_ARGUMENTS;
9173 	}
9174 	if (!pipe || !pipe->stream)
9175 	{
9176 		ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR,
9177 				    "ia_css_pipe_get_info: ia_css_stream_create needs to be called before ia_css_[stream/pipe]_get_info\n");
9178 		return IA_CSS_ERR_INVALID_ARGUMENTS;
9179 	}
9180 	/* we succeeded return the info */
9181 	*pipe_info = pipe->info;
9182 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_get_info() leave\n");
9183 	return IA_CSS_SUCCESS;
9184 }
9185 
9186 bool ia_css_pipe_has_dvs_stats(struct ia_css_pipe_info *pipe_info) {
9187 	unsigned int i;
9188 
9189 	if (pipe_info) {
9190 		for (i = 0; i < IA_CSS_DVS_STAT_NUM_OF_LEVELS; i++) {
9191 			if (pipe_info->grid_info.dvs_grid.dvs_stat_grid_info.grd_cfg[i].grd_start.enable)
9192 				return true;
9193 		}
9194 	}
9195 
9196 	return false;
9197 }
9198 
9199 enum ia_css_err
9200 ia_css_pipe_override_frame_format(struct ia_css_pipe *pipe,
9201 				    int pin_index,
9202 				    enum ia_css_frame_format new_format) {
9203 	enum ia_css_err err = IA_CSS_SUCCESS;
9204 
9205 	IA_CSS_ENTER_PRIVATE("pipe = %p, pin_index = %d, new_formats = %d", pipe, pin_index, new_format);
9206 
9207 	if (!pipe)
9208 	{
9209 		IA_CSS_ERROR("pipe is not set");
9210 		err = IA_CSS_ERR_INVALID_ARGUMENTS;
9211 		IA_CSS_LEAVE_ERR_PRIVATE(err);
9212 		return err;
9213 	}
9214 	if (0 != pin_index && 1 != pin_index)
9215 	{
9216 		IA_CSS_ERROR("pin index is not valid");
9217 		err = IA_CSS_ERR_INVALID_ARGUMENTS;
9218 		IA_CSS_LEAVE_ERR_PRIVATE(err);
9219 		return err;
9220 	}
9221 	if (new_format != IA_CSS_FRAME_FORMAT_NV12_TILEY)
9222 	{
9223 		IA_CSS_ERROR("new format is not valid");
9224 		err = IA_CSS_ERR_INVALID_ARGUMENTS;
9225 		IA_CSS_LEAVE_ERR_PRIVATE(err);
9226 		return err;
9227 	} else
9228 	{
9229 		err = ia_css_pipe_check_format(pipe, new_format);
9230 		if (err == IA_CSS_SUCCESS) {
9231 			if (pin_index == 0) {
9232 				pipe->output_info[0].format = new_format;
9233 			} else {
9234 				pipe->vf_output_info[0].format = new_format;
9235 			}
9236 		}
9237 	}
9238 	IA_CSS_LEAVE_ERR_PRIVATE(err);
9239 	return err;
9240 }
9241 
9242 #if defined(USE_INPUT_SYSTEM_VERSION_2)
9243 /* Configuration of INPUT_SYSTEM_VERSION_2401 is done on SP */
9244 static enum ia_css_err
9245 ia_css_stream_configure_rx(struct ia_css_stream *stream) {
9246 	struct ia_css_input_port *config;
9247 
9248 	assert(stream);
9249 
9250 	config = &stream->config.source.port;
9251 	/* AM: this code is not reliable, especially for 2400 */
9252 	if (config->num_lanes == 1)
9253 		stream->csi_rx_config.mode = MONO_1L_1L_0L;
9254 	else if (config->num_lanes == 2)
9255 		stream->csi_rx_config.mode = MONO_2L_1L_0L;
9256 	else if (config->num_lanes == 3)
9257 		stream->csi_rx_config.mode = MONO_3L_1L_0L;
9258 	else if (config->num_lanes == 4)
9259 		stream->csi_rx_config.mode = MONO_4L_1L_0L;
9260 	else if (config->num_lanes != 0)
9261 		return IA_CSS_ERR_INVALID_ARGUMENTS;
9262 
9263 	if (config->port > MIPI_PORT2_ID)
9264 		return IA_CSS_ERR_INVALID_ARGUMENTS;
9265 	stream->csi_rx_config.port =
9266 	ia_css_isys_port_to_mipi_port(config->port);
9267 	stream->csi_rx_config.timeout    = config->timeout;
9268 	stream->csi_rx_config.initcount  = 0;
9269 	stream->csi_rx_config.synccount  = 0x28282828;
9270 	stream->csi_rx_config.rxcount    = config->rxcount;
9271 	if (config->compression.type == IA_CSS_CSI2_COMPRESSION_TYPE_NONE)
9272 		stream->csi_rx_config.comp = MIPI_PREDICTOR_NONE;
9273 	else
9274 	{
9275 		/* not implemented yet, requires extension of the rx_cfg_t
9276 		    * struct */
9277 		return IA_CSS_ERR_INVALID_ARGUMENTS;
9278 	}
9279 	stream->csi_rx_config.is_two_ppc = (stream->config.pixels_per_clock == 2);
9280 	stream->reconfigure_css_rx = true;
9281 	return IA_CSS_SUCCESS;
9282 }
9283 #endif
9284 
9285 static struct ia_css_pipe *
9286 find_pipe(struct ia_css_pipe *pipes[],
9287 	    unsigned int num_pipes,
9288 	    enum ia_css_pipe_mode mode,
9289 	    bool copy_pipe) {
9290 	unsigned int i;
9291 
9292 	assert(pipes);
9293 	for (i = 0; i < num_pipes; i++) {
9294 		assert(pipes[i]);
9295 		if (pipes[i]->config.mode != mode)
9296 			continue;
9297 		if (copy_pipe && pipes[i]->mode != IA_CSS_PIPE_ID_COPY)
9298 			continue;
9299 		return pipes[i];
9300 	}
9301 	return NULL;
9302 }
9303 
9304 static enum ia_css_err
9305 ia_css_acc_stream_create(struct ia_css_stream *stream) {
9306 	int i;
9307 	enum ia_css_err err = IA_CSS_SUCCESS;
9308 
9309 	assert(stream);
9310 	IA_CSS_ENTER_PRIVATE("stream = %p", stream);
9311 
9312 	if (!stream)
9313 	{
9314 		IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
9315 		return IA_CSS_ERR_INVALID_ARGUMENTS;
9316 	}
9317 
9318 	for (i = 0;  i < stream->num_pipes; i++)
9319 	{
9320 		struct ia_css_pipe *pipe = stream->pipes[i];
9321 
9322 		assert(pipe);
9323 		if (!pipe) {
9324 			IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
9325 			return IA_CSS_ERR_INVALID_ARGUMENTS;
9326 		}
9327 
9328 		pipe->stream = stream;
9329 	}
9330 
9331 	/* Map SP threads before doing anything. */
9332 	err = map_sp_threads(stream, true);
9333 	if (err != IA_CSS_SUCCESS)
9334 	{
9335 		IA_CSS_LEAVE_ERR_PRIVATE(err);
9336 		return err;
9337 	}
9338 
9339 	for (i = 0;  i < stream->num_pipes; i++)
9340 	{
9341 		struct ia_css_pipe *pipe = stream->pipes[i];
9342 
9343 		assert(pipe);
9344 		ia_css_pipe_map_queue(pipe, true);
9345 	}
9346 
9347 	err = create_host_pipeline_structure(stream);
9348 	if (err != IA_CSS_SUCCESS)
9349 	{
9350 		IA_CSS_LEAVE_ERR_PRIVATE(err);
9351 		return err;
9352 	}
9353 
9354 	stream->started = false;
9355 
9356 	IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
9357 
9358 	return IA_CSS_SUCCESS;
9359 }
9360 
9361 static enum ia_css_err
9362 metadata_info_init(const struct ia_css_metadata_config *mdc,
9363 		    struct ia_css_metadata_info *md) {
9364 	/* Either both width and height should be set or neither */
9365 	if ((mdc->resolution.height > 0) ^ (mdc->resolution.width > 0))
9366 		return IA_CSS_ERR_INVALID_ARGUMENTS;
9367 
9368 	md->resolution = mdc->resolution;
9369 	/* We round up the stride to a multiple of the width
9370 	    * of the port going to DDR, this is a HW requirements (DMA). */
9371 	md->stride = CEIL_MUL(mdc->resolution.width, HIVE_ISP_DDR_WORD_BYTES);
9372 	md->size = mdc->resolution.height * md->stride;
9373 	return IA_CSS_SUCCESS;
9374 }
9375 
9376 /* ISP2401 */
9377 static enum ia_css_err check_pipe_resolutions(const struct ia_css_pipe *pipe) {
9378 	enum ia_css_err err = IA_CSS_SUCCESS;
9379 
9380 	IA_CSS_ENTER_PRIVATE("");
9381 
9382 	if (!pipe || !pipe->stream) {
9383 		IA_CSS_ERROR("null arguments");
9384 		err = IA_CSS_ERR_INTERNAL_ERROR;
9385 		goto EXIT;
9386 	}
9387 
9388 	if (ia_css_util_check_res(pipe->config.input_effective_res.width,
9389 				    pipe->config.input_effective_res.height) != IA_CSS_SUCCESS) {
9390 		IA_CSS_ERROR("effective resolution not supported");
9391 		err = IA_CSS_ERR_INVALID_ARGUMENTS;
9392 		goto EXIT;
9393 	}
9394 	if (!ia_css_util_resolution_is_zero(
9395 		pipe->stream->config.input_config.input_res)) {
9396 		if (!ia_css_util_res_leq(pipe->config.input_effective_res,
9397 					    pipe->stream->config.input_config.input_res)) {
9398 			IA_CSS_ERROR("effective resolution is larger than input resolution");
9399 			err = IA_CSS_ERR_INVALID_ARGUMENTS;
9400 			goto EXIT;
9401 		}
9402 	}
9403 	if (!ia_css_util_resolution_is_even(pipe->config.output_info[0].res)) {
9404 		IA_CSS_ERROR("output resolution must be even");
9405 		err = IA_CSS_ERR_INVALID_ARGUMENTS;
9406 		goto EXIT;
9407 	}
9408 	if (!ia_css_util_resolution_is_even(pipe->config.vf_output_info[0].res)) {
9409 		IA_CSS_ERROR("VF resolution must be even");
9410 		err = IA_CSS_ERR_INVALID_ARGUMENTS;
9411 		goto EXIT;
9412 	}
9413 EXIT:
9414 	IA_CSS_LEAVE_ERR_PRIVATE(err);
9415 	return err;
9416 }
9417 
9418 enum ia_css_err
9419 ia_css_stream_create(const struct ia_css_stream_config *stream_config,
9420 			int num_pipes,
9421 			struct ia_css_pipe *pipes[],
9422 			struct ia_css_stream **stream) {
9423 	struct ia_css_pipe *curr_pipe;
9424 	struct ia_css_stream *curr_stream = NULL;
9425 	bool spcopyonly;
9426 	bool sensor_binning_changed;
9427 	int i, j;
9428 	enum ia_css_err err = IA_CSS_ERR_INTERNAL_ERROR;
9429 	struct ia_css_metadata_info md_info;
9430 	struct ia_css_resolution effective_res;
9431 #ifdef USE_INPUT_SYSTEM_VERSION_2401
9432 	bool aspect_ratio_crop_enabled = false;
9433 #endif
9434 
9435 	IA_CSS_ENTER("num_pipes=%d", num_pipes);
9436 	ia_css_debug_dump_stream_config(stream_config, num_pipes);
9437 
9438 	/* some checks */
9439 	if (num_pipes == 0 ||
9440 	    !stream ||
9441 	    !pipes)
9442 	{
9443 		err = IA_CSS_ERR_INVALID_ARGUMENTS;
9444 		IA_CSS_LEAVE_ERR(err);
9445 		return err;
9446 	}
9447 
9448 #if defined(USE_INPUT_SYSTEM_VERSION_2)
9449 	/* We don't support metadata for JPEG stream, since they both use str2mem */
9450 	if (stream_config->input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8 &&
9451 	    stream_config->metadata_config.resolution.height > 0)
9452 	{
9453 		err = IA_CSS_ERR_INVALID_ARGUMENTS;
9454 		IA_CSS_LEAVE_ERR(err);
9455 		return err;
9456 	}
9457 #endif
9458 
9459 #ifdef USE_INPUT_SYSTEM_VERSION_2401
9460 	if (stream_config->online && stream_config->pack_raw_pixels)
9461 	{
9462 		IA_CSS_LOG("online and pack raw is invalid on input system 2401");
9463 		err = IA_CSS_ERR_INVALID_ARGUMENTS;
9464 		IA_CSS_LEAVE_ERR(err);
9465 		return err;
9466 	}
9467 #endif
9468 
9469 #if !defined(HAS_NO_INPUT_SYSTEM)
9470 	ia_css_debug_pipe_graph_dump_stream_config(stream_config);
9471 
9472 	/* check if mipi size specified */
9473 	if (stream_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
9474 #ifdef USE_INPUT_SYSTEM_VERSION_2401
9475 		if (!stream_config->online)
9476 #endif
9477 		{
9478 			unsigned int port = (unsigned int)stream_config->source.port.port;
9479 
9480 			if (port >= N_MIPI_PORT_ID) {
9481 				err = IA_CSS_ERR_INVALID_ARGUMENTS;
9482 				IA_CSS_LEAVE_ERR(err);
9483 				return err;
9484 			}
9485 
9486 			if (my_css.size_mem_words != 0) {
9487 				my_css.mipi_frame_size[port] = my_css.size_mem_words;
9488 			} else if (stream_config->mipi_buffer_config.size_mem_words != 0) {
9489 				my_css.mipi_frame_size[port] = stream_config->mipi_buffer_config.size_mem_words;
9490 			} else {
9491 				ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
9492 						    "ia_css_stream_create() exit: error, need to set mipi frame size.\n");
9493 				assert(stream_config->mipi_buffer_config.size_mem_words != 0);
9494 				err = IA_CSS_ERR_INTERNAL_ERROR;
9495 				IA_CSS_LEAVE_ERR(err);
9496 				return err;
9497 			}
9498 
9499 			if (my_css.size_mem_words != 0) {
9500 				my_css.num_mipi_frames[port] =
9501 				    2; /* Temp change: Default for backwards compatibility. */
9502 			} else if (stream_config->mipi_buffer_config.nof_mipi_buffers != 0) {
9503 				my_css.num_mipi_frames[port] =
9504 				    stream_config->mipi_buffer_config.nof_mipi_buffers;
9505 			} else {
9506 				ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
9507 						    "ia_css_stream_create() exit: error, need to set number of mipi frames.\n");
9508 				assert(stream_config->mipi_buffer_config.nof_mipi_buffers != 0);
9509 				err = IA_CSS_ERR_INTERNAL_ERROR;
9510 				IA_CSS_LEAVE_ERR(err);
9511 				return err;
9512 			}
9513 		}
9514 #endif
9515 
9516 	/* Currently we only supported metadata up to a certain size. */
9517 	err = metadata_info_init(&stream_config->metadata_config, &md_info);
9518 	if (err != IA_CSS_SUCCESS)
9519 	{
9520 		IA_CSS_LEAVE_ERR(err);
9521 		return err;
9522 	}
9523 
9524 	/* allocate the stream instance */
9525 	curr_stream = kmalloc(sizeof(struct ia_css_stream), GFP_KERNEL);
9526 	if (!curr_stream)
9527 	{
9528 		err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
9529 		IA_CSS_LEAVE_ERR(err);
9530 		return err;
9531 	}
9532 	/* default all to 0 */
9533 	memset(curr_stream, 0, sizeof(struct ia_css_stream));
9534 	curr_stream->info.metadata_info = md_info;
9535 
9536 	/* allocate pipes */
9537 	curr_stream->num_pipes = num_pipes;
9538 	curr_stream->pipes = kcalloc(num_pipes, sizeof(struct ia_css_pipe *), GFP_KERNEL);
9539 	if (!curr_stream->pipes)
9540 	{
9541 		curr_stream->num_pipes = 0;
9542 		kfree(curr_stream);
9543 		curr_stream = NULL;
9544 		err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
9545 		IA_CSS_LEAVE_ERR(err);
9546 		return err;
9547 	}
9548 	/* store pipes */
9549 	spcopyonly = (num_pipes == 1) && (pipes[0]->config.mode == IA_CSS_PIPE_MODE_COPY);
9550 	for (i = 0; i < num_pipes; i++)
9551 		curr_stream->pipes[i] = pipes[i];
9552 	curr_stream->last_pipe = curr_stream->pipes[0];
9553 	/* take over stream config */
9554 	curr_stream->config = *stream_config;
9555 
9556 #if defined(USE_INPUT_SYSTEM_VERSION_2401) && defined(CSI2P_DISABLE_ISYS2401_ONLINE_MODE)
9557 	if (stream_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR &&
9558 	    stream_config->online)
9559 		curr_stream->config.online = false;
9560 #endif
9561 
9562 #ifdef USE_INPUT_SYSTEM_VERSION_2401
9563 	if (curr_stream->config.online)
9564 	{
9565 		curr_stream->config.source.port.num_lanes =
9566 		    stream_config->source.port.num_lanes;
9567 		curr_stream->config.mode =  IA_CSS_INPUT_MODE_BUFFERED_SENSOR;
9568 	}
9569 #endif
9570 	/* in case driver doesn't configure init number of raw buffers, configure it here */
9571 	if (curr_stream->config.target_num_cont_raw_buf == 0)
9572 		curr_stream->config.target_num_cont_raw_buf = NUM_CONTINUOUS_FRAMES;
9573 	if (curr_stream->config.init_num_cont_raw_buf == 0)
9574 		curr_stream->config.init_num_cont_raw_buf = curr_stream->config.target_num_cont_raw_buf;
9575 
9576 	/* Enable locking & unlocking of buffers in RAW buffer pool */
9577 	if (curr_stream->config.ia_css_enable_raw_buffer_locking)
9578 		sh_css_sp_configure_enable_raw_pool_locking(
9579 		    curr_stream->config.lock_all);
9580 
9581 	/* copy mode specific stuff */
9582 	switch (curr_stream->config.mode)
9583 	{
9584 	case IA_CSS_INPUT_MODE_SENSOR:
9585 	case IA_CSS_INPUT_MODE_BUFFERED_SENSOR:
9586 #if defined(USE_INPUT_SYSTEM_VERSION_2)
9587 		ia_css_stream_configure_rx(curr_stream);
9588 #endif
9589 		break;
9590 	case IA_CSS_INPUT_MODE_TPG:
9591 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
9592 		IA_CSS_LOG("tpg_configuration: x_mask=%d, y_mask=%d, x_delta=%d, y_delta=%d, xy_mask=%d",
9593 			    curr_stream->config.source.tpg.x_mask,
9594 			    curr_stream->config.source.tpg.y_mask,
9595 			    curr_stream->config.source.tpg.x_delta,
9596 			    curr_stream->config.source.tpg.y_delta,
9597 			    curr_stream->config.source.tpg.xy_mask);
9598 
9599 		sh_css_sp_configure_tpg(
9600 		    curr_stream->config.source.tpg.x_mask,
9601 		    curr_stream->config.source.tpg.y_mask,
9602 		    curr_stream->config.source.tpg.x_delta,
9603 		    curr_stream->config.source.tpg.y_delta,
9604 		    curr_stream->config.source.tpg.xy_mask);
9605 #endif
9606 		break;
9607 	case IA_CSS_INPUT_MODE_PRBS:
9608 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
9609 		IA_CSS_LOG("mode prbs");
9610 		sh_css_sp_configure_prbs(curr_stream->config.source.prbs.seed);
9611 #endif
9612 		break;
9613 	case IA_CSS_INPUT_MODE_MEMORY:
9614 		IA_CSS_LOG("mode memory");
9615 		curr_stream->reconfigure_css_rx = false;
9616 		break;
9617 	default:
9618 		IA_CSS_LOG("mode sensor/default");
9619 	}
9620 
9621 #ifdef USE_INPUT_SYSTEM_VERSION_2401
9622 	err = aspect_ratio_crop_init(curr_stream,
9623 					pipes,
9624 					&aspect_ratio_crop_enabled);
9625 	if (err != IA_CSS_SUCCESS)
9626 	{
9627 		IA_CSS_LEAVE_ERR(err);
9628 		return err;
9629 	}
9630 #endif
9631 	for (i = 0; i < num_pipes; i++)
9632 	{
9633 		struct ia_css_resolution effective_res;
9634 
9635 		curr_pipe = pipes[i];
9636 		/* set current stream */
9637 		curr_pipe->stream = curr_stream;
9638 		/* take over effective info */
9639 
9640 		effective_res = curr_pipe->config.input_effective_res;
9641 		if (effective_res.height == 0 || effective_res.width == 0) {
9642 			effective_res = curr_pipe->stream->config.input_config.effective_res;
9643 
9644 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
9645 			/* The aspect ratio cropping is currently only
9646 			    * supported on the new input system. */
9647 			if (aspect_ratio_crop_check(aspect_ratio_crop_enabled, curr_pipe)) {
9648 				struct ia_css_resolution crop_res;
9649 
9650 				err = aspect_ratio_crop(curr_pipe, &crop_res);
9651 				if (err == IA_CSS_SUCCESS) {
9652 					effective_res = crop_res;
9653 				} else {
9654 					/* in case of error fallback to default
9655 					    * effective resolution from driver. */
9656 					IA_CSS_LOG("aspect_ratio_crop() failed with err(%d)", err);
9657 				}
9658 			}
9659 #endif
9660 			curr_pipe->config.input_effective_res = effective_res;
9661 		}
9662 		IA_CSS_LOG("effective_res=%dx%d",
9663 			    effective_res.width,
9664 			    effective_res.height);
9665 	}
9666 
9667 	if (atomisp_hw_is_isp2401) {
9668 		for (i = 0; i < num_pipes; i++) {
9669 			if (pipes[i]->config.mode != IA_CSS_PIPE_MODE_ACC &&
9670 			    pipes[i]->config.mode != IA_CSS_PIPE_MODE_COPY) {
9671 				err = check_pipe_resolutions(pipes[i]);
9672 				if (err != IA_CSS_SUCCESS) {
9673 					goto ERR;
9674 				}
9675 			}
9676 		}
9677 	}
9678 
9679 	err = ia_css_stream_isp_parameters_init(curr_stream);
9680 	if (err != IA_CSS_SUCCESS)
9681 		goto ERR;
9682 	IA_CSS_LOG("isp_params_configs: %p", curr_stream->isp_params_configs);
9683 
9684 	if (num_pipes == 1 && pipes[0]->config.mode == IA_CSS_PIPE_MODE_ACC)
9685 	{
9686 		*stream = curr_stream;
9687 		err = ia_css_acc_stream_create(curr_stream);
9688 		goto ERR;
9689 	}
9690 	/* sensor binning */
9691 	if (!spcopyonly)
9692 	{
9693 		sensor_binning_changed =
9694 		    sh_css_params_set_binning_factor(curr_stream,
9695 							curr_stream->config.sensor_binning_factor);
9696 	} else
9697 	{
9698 		sensor_binning_changed = false;
9699 	}
9700 
9701 	IA_CSS_LOG("sensor_binning=%d, changed=%d",
9702 		    curr_stream->config.sensor_binning_factor, sensor_binning_changed);
9703 	/* loop over pipes */
9704 	IA_CSS_LOG("num_pipes=%d", num_pipes);
9705 	curr_stream->cont_capt = false;
9706 	/* Temporary hack: we give the preview pipe a reference to the capture
9707 	    * pipe in continuous capture mode. */
9708 	if (curr_stream->config.continuous)
9709 	{
9710 		/* Search for the preview pipe and create the copy pipe */
9711 		struct ia_css_pipe *preview_pipe;
9712 		struct ia_css_pipe *video_pipe;
9713 		struct ia_css_pipe *acc_pipe;
9714 		struct ia_css_pipe *capture_pipe = NULL;
9715 		struct ia_css_pipe *copy_pipe = NULL;
9716 
9717 		if (num_pipes >= 2) {
9718 			curr_stream->cont_capt = true;
9719 			curr_stream->disable_cont_vf = curr_stream->config.disable_cont_viewfinder;
9720 
9721 			if (!atomisp_hw_is_isp2401)
9722 				curr_stream->stop_copy_preview = my_css.stop_copy_preview;
9723 		}
9724 
9725 		/* Create copy pipe here, since it may not be exposed to the driver */
9726 		preview_pipe = find_pipe(pipes, num_pipes,
9727 					    IA_CSS_PIPE_MODE_PREVIEW, false);
9728 		video_pipe = find_pipe(pipes, num_pipes,
9729 					IA_CSS_PIPE_MODE_VIDEO, false);
9730 		acc_pipe = find_pipe(pipes, num_pipes,
9731 					IA_CSS_PIPE_MODE_ACC, false);
9732 		if (acc_pipe && num_pipes == 2 && curr_stream->cont_capt == true)
9733 			curr_stream->cont_capt =
9734 			    false; /* preview + QoS case will not need cont_capt switch */
9735 		if (curr_stream->cont_capt == true) {
9736 			capture_pipe = find_pipe(pipes, num_pipes,
9737 						    IA_CSS_PIPE_MODE_CAPTURE, false);
9738 			if (!capture_pipe) {
9739 				err = IA_CSS_ERR_INTERNAL_ERROR;
9740 				goto ERR;
9741 			}
9742 		}
9743 		/* We do not support preview and video pipe at the same time */
9744 		if (preview_pipe && video_pipe) {
9745 			err = IA_CSS_ERR_INVALID_ARGUMENTS;
9746 			goto ERR;
9747 		}
9748 
9749 		if (preview_pipe && !preview_pipe->pipe_settings.preview.copy_pipe) {
9750 			err = create_pipe(IA_CSS_PIPE_MODE_CAPTURE, &copy_pipe, true);
9751 			if (err != IA_CSS_SUCCESS)
9752 				goto ERR;
9753 			ia_css_pipe_config_defaults(&copy_pipe->config);
9754 			preview_pipe->pipe_settings.preview.copy_pipe = copy_pipe;
9755 			copy_pipe->stream = curr_stream;
9756 		}
9757 		if (preview_pipe && (curr_stream->cont_capt == true)) {
9758 			preview_pipe->pipe_settings.preview.capture_pipe = capture_pipe;
9759 		}
9760 		if (video_pipe && !video_pipe->pipe_settings.video.copy_pipe) {
9761 			err = create_pipe(IA_CSS_PIPE_MODE_CAPTURE, &copy_pipe, true);
9762 			if (err != IA_CSS_SUCCESS)
9763 				goto ERR;
9764 			ia_css_pipe_config_defaults(&copy_pipe->config);
9765 			video_pipe->pipe_settings.video.copy_pipe = copy_pipe;
9766 			copy_pipe->stream = curr_stream;
9767 		}
9768 		if (video_pipe && (curr_stream->cont_capt == true)) {
9769 			video_pipe->pipe_settings.video.capture_pipe = capture_pipe;
9770 		}
9771 		if (preview_pipe && acc_pipe) {
9772 			preview_pipe->pipe_settings.preview.acc_pipe = acc_pipe;
9773 		}
9774 	}
9775 	for (i = 0; i < num_pipes; i++)
9776 	{
9777 		curr_pipe = pipes[i];
9778 		/* set current stream */
9779 		curr_pipe->stream = curr_stream;
9780 
9781 		if (!atomisp_hw_is_isp2401) {
9782 			/* take over effective info */
9783 
9784 			effective_res = curr_pipe->config.input_effective_res;
9785 			err = ia_css_util_check_res(
9786 				effective_res.width,
9787 				effective_res.height);
9788 			if (err != IA_CSS_SUCCESS)
9789 				goto ERR;
9790 		}
9791 		/* sensor binning per pipe */
9792 		if (sensor_binning_changed)
9793 			sh_css_pipe_free_shading_table(curr_pipe);
9794 	}
9795 
9796 	/* now pipes have been configured, info should be available */
9797 	for (i = 0; i < num_pipes; i++)
9798 	{
9799 		struct ia_css_pipe_info *pipe_info = NULL;
9800 
9801 		curr_pipe = pipes[i];
9802 
9803 		err = sh_css_pipe_load_binaries(curr_pipe);
9804 		if (err != IA_CSS_SUCCESS)
9805 			goto ERR;
9806 
9807 		/* handle each pipe */
9808 		pipe_info = &curr_pipe->info;
9809 		for (j = 0; j < IA_CSS_PIPE_MAX_OUTPUT_STAGE; j++) {
9810 			err = sh_css_pipe_get_output_frame_info(curr_pipe,
9811 								&pipe_info->output_info[j], j);
9812 			if (err != IA_CSS_SUCCESS)
9813 				goto ERR;
9814 		}
9815 
9816 		if (atomisp_hw_is_isp2401)
9817 			pipe_info->output_system_in_res_info = curr_pipe->config.output_system_in_res;
9818 
9819 		if (!spcopyonly) {
9820 			if (!atomisp_hw_is_isp2401)
9821 				err = sh_css_pipe_get_shading_info(curr_pipe,
9822 								    &pipe_info->shading_info, NULL);
9823 			else
9824 				err = sh_css_pipe_get_shading_info(curr_pipe,
9825 								    &pipe_info->shading_info, &curr_pipe->config);
9826 
9827 			if (err != IA_CSS_SUCCESS)
9828 				goto ERR;
9829 			err = sh_css_pipe_get_grid_info(curr_pipe,
9830 							&pipe_info->grid_info);
9831 			if (err != IA_CSS_SUCCESS)
9832 				goto ERR;
9833 			for (j = 0; j < IA_CSS_PIPE_MAX_OUTPUT_STAGE; j++) {
9834 				sh_css_pipe_get_viewfinder_frame_info(curr_pipe,
9835 									&pipe_info->vf_output_info[j], j);
9836 				if (err != IA_CSS_SUCCESS)
9837 					goto ERR;
9838 			}
9839 		}
9840 
9841 		my_css.active_pipes[ia_css_pipe_get_pipe_num(curr_pipe)] = curr_pipe;
9842 	}
9843 
9844 	curr_stream->started = false;
9845 
9846 	/* Map SP threads before doing anything. */
9847 	err = map_sp_threads(curr_stream, true);
9848 	if (err != IA_CSS_SUCCESS)
9849 	{
9850 		IA_CSS_LOG("map_sp_threads: return_err=%d", err);
9851 		goto ERR;
9852 	}
9853 
9854 	for (i = 0; i < num_pipes; i++)
9855 	{
9856 		curr_pipe = pipes[i];
9857 		ia_css_pipe_map_queue(curr_pipe, true);
9858 	}
9859 
9860 	/* Create host side pipeline objects without stages */
9861 	err = create_host_pipeline_structure(curr_stream);
9862 	if (err != IA_CSS_SUCCESS)
9863 	{
9864 		IA_CSS_LOG("create_host_pipeline_structure: return_err=%d", err);
9865 		goto ERR;
9866 	}
9867 
9868 	/* assign curr_stream */
9869 	*stream = curr_stream;
9870 
9871 ERR:
9872 	if (err == IA_CSS_SUCCESS) {
9873 		/* working mode: enter into the seed list */
9874 		if (my_css_save.mode == sh_css_mode_working) {
9875 			for (i = 0; i < MAX_ACTIVE_STREAMS; i++) {
9876 				if (!my_css_save.stream_seeds[i].stream) {
9877 					IA_CSS_LOG("entered stream into loc=%d", i);
9878 					my_css_save.stream_seeds[i].orig_stream = stream;
9879 					my_css_save.stream_seeds[i].stream = curr_stream;
9880 					my_css_save.stream_seeds[i].num_pipes = num_pipes;
9881 					my_css_save.stream_seeds[i].stream_config = *stream_config;
9882 					for (j = 0; j < num_pipes; j++) {
9883 						my_css_save.stream_seeds[i].pipe_config[j] = pipes[j]->config;
9884 						my_css_save.stream_seeds[i].pipes[j] = pipes[j];
9885 						my_css_save.stream_seeds[i].orig_pipes[j] = &pipes[j];
9886 					}
9887 					break;
9888 				}
9889 			}
9890 		} else {
9891 			ia_css_stream_destroy(curr_stream);
9892 		}
9893 	} else {
9894 		ia_css_stream_destroy(curr_stream);
9895 	}
9896 	IA_CSS_LEAVE("return_err=%d mode=%d", err, my_css_save.mode);
9897 	return err;
9898 }
9899 
9900 enum ia_css_err
9901 ia_css_stream_destroy(struct ia_css_stream *stream) {
9902 	int i;
9903 	enum ia_css_err err = IA_CSS_SUCCESS;
9904 
9905 	IA_CSS_ENTER_PRIVATE("stream = %p", stream);
9906 	if (!stream)
9907 	{
9908 		err = IA_CSS_ERR_INVALID_ARGUMENTS;
9909 		IA_CSS_LEAVE_ERR_PRIVATE(err);
9910 		return err;
9911 	}
9912 
9913 	ia_css_stream_isp_parameters_uninit(stream);
9914 
9915 	if ((stream->last_pipe) &&
9916 	    ia_css_pipeline_is_mapped(stream->last_pipe->pipe_num))
9917 	{
9918 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
9919 		bool free_mpi;
9920 
9921 		for (i = 0; i < stream->num_pipes; i++) {
9922 			struct ia_css_pipe *entry = stream->pipes[i];
9923 			unsigned int sp_thread_id;
9924 			struct sh_css_sp_pipeline_terminal *sp_pipeline_input_terminal;
9925 
9926 			assert(entry);
9927 			if (entry) {
9928 				/* get the SP thread id */
9929 				if (ia_css_pipeline_get_sp_thread_id(
9930 					ia_css_pipe_get_pipe_num(entry), &sp_thread_id) != true)
9931 					return IA_CSS_ERR_INTERNAL_ERROR;
9932 				/* get the target input terminal */
9933 				sp_pipeline_input_terminal =
9934 				&sh_css_sp_group.pipe_io[sp_thread_id].input;
9935 
9936 				for (i = 0; i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++) {
9937 					ia_css_isys_stream_h isys_stream =
9938 					&sp_pipeline_input_terminal->context.virtual_input_system_stream[i];
9939 					if (stream->config.isys_config[i].valid && isys_stream->valid)
9940 						ia_css_isys_stream_destroy(isys_stream);
9941 				}
9942 			}
9943 		}
9944 		free_mpi = stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR;
9945 		if (atomisp_hw_is_isp2401) {
9946 			free_mpi |= stream->config.mode == IA_CSS_INPUT_MODE_TPG;
9947 			free_mpi |= stream->config.mode == IA_CSS_INPUT_MODE_PRBS;
9948 		}
9949 
9950 		if (free_mpi) {
9951 			for (i = 0; i < stream->num_pipes; i++) {
9952 				struct ia_css_pipe *entry = stream->pipes[i];
9953 				/* free any mipi frames that are remaining:
9954 				    * some test stream create-destroy cycles do not generate output frames
9955 				    * and the mipi buffer is not freed in the deque function
9956 				    */
9957 				if (entry)
9958 					free_mipi_frames(entry);
9959 			}
9960 		}
9961 		stream_unregister_with_csi_rx(stream);
9962 #endif
9963 
9964 		for (i = 0; i < stream->num_pipes; i++) {
9965 			struct ia_css_pipe *curr_pipe = stream->pipes[i];
9966 
9967 			assert(curr_pipe);
9968 			ia_css_pipe_map_queue(curr_pipe, false);
9969 		}
9970 
9971 		err = map_sp_threads(stream, false);
9972 		if (err != IA_CSS_SUCCESS) {
9973 			IA_CSS_LEAVE_ERR_PRIVATE(err);
9974 			return err;
9975 		}
9976 	}
9977 
9978 	/* remove references from pipes to stream */
9979 	for (i = 0; i < stream->num_pipes; i++)
9980 	{
9981 		struct ia_css_pipe *entry = stream->pipes[i];
9982 
9983 		assert(entry);
9984 		if (entry) {
9985 			/* clear reference to stream */
9986 			entry->stream = NULL;
9987 			/* check internal copy pipe */
9988 			if (entry->mode == IA_CSS_PIPE_ID_PREVIEW &&
9989 			    entry->pipe_settings.preview.copy_pipe) {
9990 				IA_CSS_LOG("clearing stream on internal preview copy pipe");
9991 				entry->pipe_settings.preview.copy_pipe->stream = NULL;
9992 			}
9993 			if (entry->mode == IA_CSS_PIPE_ID_VIDEO &&
9994 			    entry->pipe_settings.video.copy_pipe) {
9995 				IA_CSS_LOG("clearing stream on internal video copy pipe");
9996 				entry->pipe_settings.video.copy_pipe->stream = NULL;
9997 			}
9998 			err = sh_css_pipe_unload_binaries(entry);
9999 		}
10000 	}
10001 	/* free associated memory of stream struct */
10002 	kfree(stream->pipes);
10003 	stream->pipes = NULL;
10004 	stream->num_pipes = 0;
10005 
10006 	/* working mode: take out of the seed list */
10007 	if (my_css_save.mode == sh_css_mode_working) {
10008 		for (i = 0; i < MAX_ACTIVE_STREAMS; i++) {
10009 			if (my_css_save.stream_seeds[i].stream == stream)
10010 			{
10011 				IA_CSS_LOG("took out stream %d", i);
10012 				my_css_save.stream_seeds[i].stream = NULL;
10013 				break;
10014 			}
10015 		}
10016 	}
10017 
10018 	kfree(stream);
10019 	IA_CSS_LEAVE_ERR(err);
10020 
10021 	return err;
10022 }
10023 
10024 enum ia_css_err
10025 ia_css_stream_get_info(const struct ia_css_stream *stream,
10026 			struct ia_css_stream_info *stream_info) {
10027 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_info: enter/exit\n");
10028 	assert(stream);
10029 	assert(stream_info);
10030 
10031 	*stream_info = stream->info;
10032 	return IA_CSS_SUCCESS;
10033 }
10034 
10035 /*
10036     * Rebuild a stream, including allocating structs, setting configuration and
10037     * building the required pipes.
10038     * The data is taken from the css_save struct updated upon stream creation.
10039     * The stream handle is used to identify the correct entry in the css_save struct
10040     */
10041 enum ia_css_err
10042 ia_css_stream_load(struct ia_css_stream *stream) {
10043 
10044 	if (!atomisp_hw_is_isp2401) {
10045 		int i;
10046 		enum ia_css_err err;
10047 
10048 		assert(stream);
10049 		ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,	"ia_css_stream_load() enter,\n");
10050 		for (i = 0; i < MAX_ACTIVE_STREAMS; i++)
10051 		{
10052 			if (my_css_save.stream_seeds[i].stream == stream) {
10053 				int j;
10054 
10055 				for (j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++) {
10056 					if ((err = ia_css_pipe_create(&my_css_save.stream_seeds[i].pipe_config[j],
10057 								    &my_css_save.stream_seeds[i].pipes[j])) != IA_CSS_SUCCESS) {
10058 						if (j) {
10059 							int k;
10060 
10061 							for (k = 0; k < j; k++)
10062 								ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[k]);
10063 						}
10064 						return err;
10065 					}
10066 				}
10067 				err = ia_css_stream_create(&my_css_save.stream_seeds[i].stream_config,
10068 							my_css_save.stream_seeds[i].num_pipes,
10069 							my_css_save.stream_seeds[i].pipes,
10070 							&my_css_save.stream_seeds[i].stream);
10071 				if (err != IA_CSS_SUCCESS) {
10072 					ia_css_stream_destroy(stream);
10073 					for (j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++)
10074 						ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[j]);
10075 					return err;
10076 				}
10077 				break;
10078 			}
10079 		}
10080 		ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,	"ia_css_stream_load() exit,\n");
10081 		return IA_CSS_SUCCESS;
10082 	} else {
10083 		/* TODO remove function - DEPRECATED */
10084 		(void)stream;
10085 		return IA_CSS_ERR_NOT_SUPPORTED;
10086 	}
10087 }
10088 
10089 enum ia_css_err
10090 ia_css_stream_start(struct ia_css_stream *stream) {
10091 	enum ia_css_err err = IA_CSS_SUCCESS;
10092 
10093 	IA_CSS_ENTER("stream = %p", stream);
10094 	if ((!stream) || (!stream->last_pipe))
10095 	{
10096 		IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
10097 		return IA_CSS_ERR_INVALID_ARGUMENTS;
10098 	}
10099 	IA_CSS_LOG("starting %d", stream->last_pipe->mode);
10100 
10101 	sh_css_sp_set_disable_continuous_viewfinder(stream->disable_cont_vf);
10102 
10103 	/* Create host side pipeline. */
10104 	err = create_host_pipeline(stream);
10105 	if (err != IA_CSS_SUCCESS)
10106 	{
10107 		IA_CSS_LEAVE_ERR(err);
10108 		return err;
10109 	}
10110 
10111 #if !defined(HAS_NO_INPUT_SYSTEM)
10112 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
10113 	if ((stream->config.mode == IA_CSS_INPUT_MODE_SENSOR) ||
10114 	    (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR))
10115 		stream_register_with_csi_rx(stream);
10116 #endif
10117 #endif
10118 
10119 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
10120 	/* Initialize mipi size checks */
10121 	if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
10122 	{
10123 		unsigned int idx;
10124 		unsigned int port = (unsigned int)(stream->config.source.port.port);
10125 
10126 		for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT; idx++) {
10127 			sh_css_sp_group.config.mipi_sizes_for_check[port][idx] =
10128 			sh_css_get_mipi_sizes_for_check(port, idx);
10129 		}
10130 	}
10131 #endif
10132 
10133 #if !defined(HAS_NO_INPUT_SYSTEM)
10134 	if (stream->config.mode != IA_CSS_INPUT_MODE_MEMORY)
10135 	{
10136 		err = sh_css_config_input_network(stream);
10137 		if (err != IA_CSS_SUCCESS)
10138 			return err;
10139 	}
10140 #endif /* !HAS_NO_INPUT_SYSTEM */
10141 
10142 	err = sh_css_pipe_start(stream);
10143 	IA_CSS_LEAVE_ERR(err);
10144 	return err;
10145 }
10146 
10147 enum ia_css_err
10148 ia_css_stream_stop(struct ia_css_stream *stream) {
10149 	enum ia_css_err err = IA_CSS_SUCCESS;
10150 
10151 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_stop() enter/exit\n");
10152 	assert(stream);
10153 	assert(stream->last_pipe);
10154 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_stop: stopping %d\n",
10155 			    stream->last_pipe->mode);
10156 
10157 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
10158 	/* De-initialize mipi size checks */
10159 	if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
10160 	{
10161 		unsigned int idx;
10162 		unsigned int port = (unsigned int)(stream->config.source.port.port);
10163 
10164 		for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT; idx++) {
10165 			sh_css_sp_group.config.mipi_sizes_for_check[port][idx] = 0;
10166 		}
10167 	}
10168 #endif
10169 
10170 	if (!atomisp_hw_is_isp2401) {
10171 		err = ia_css_pipeline_request_stop(&stream->last_pipe->pipeline);
10172 	} else {
10173 		err = sh_css_pipes_stop(stream);
10174 	}
10175 
10176 	if (err != IA_CSS_SUCCESS)
10177 		return err;
10178 
10179 	/* Ideally, unmapping should happen after pipeline_stop, but current
10180 	    * semantics do not allow that. */
10181 	/* err = map_sp_threads(stream, false); */
10182 
10183 	return err;
10184 }
10185 
10186 bool
10187 ia_css_stream_has_stopped(struct ia_css_stream *stream) {
10188 	bool stopped;
10189 
10190 	assert(stream);
10191 
10192 	if (!atomisp_hw_is_isp2401) {
10193 		stopped = ia_css_pipeline_has_stopped(&stream->last_pipe->pipeline);
10194 	} else {
10195 		stopped = sh_css_pipes_have_stopped(stream);
10196 	}
10197 
10198 	return stopped;
10199 }
10200 
10201 /* ISP2400 */
10202 /*
10203     * Destroy the stream and all the pipes related to it.
10204     * The stream handle is used to identify the correct entry in the css_save struct
10205     */
10206 enum ia_css_err
10207 ia_css_stream_unload(struct ia_css_stream *stream) {
10208 	int i;
10209 
10210 	assert(stream);
10211 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,	"ia_css_stream_unload() enter,\n");
10212 	/* some checks */
10213 	assert(stream);
10214 	for (i = 0; i < MAX_ACTIVE_STREAMS; i++)
10215 		if (my_css_save.stream_seeds[i].stream == stream)
10216 		{
10217 			int j;
10218 
10219 			ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
10220 					    "ia_css_stream_unload(): unloading %d (%p)\n", i,
10221 					    my_css_save.stream_seeds[i].stream);
10222 			ia_css_stream_destroy(stream);
10223 			for (j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++)
10224 				ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[j]);
10225 			ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
10226 					    "ia_css_stream_unload(): after unloading %d (%p)\n", i,
10227 					    my_css_save.stream_seeds[i].stream);
10228 			break;
10229 		}
10230 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,	"ia_css_stream_unload() exit,\n");
10231 	return IA_CSS_SUCCESS;
10232 }
10233 
10234 enum ia_css_err
10235 ia_css_temp_pipe_to_pipe_id(const struct ia_css_pipe *pipe,
10236 			    enum ia_css_pipe_id *pipe_id) {
10237 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_temp_pipe_to_pipe_id() enter/exit\n");
10238 	if (pipe)
10239 		*pipe_id = pipe->mode;
10240 	else
10241 		*pipe_id = IA_CSS_PIPE_ID_COPY;
10242 
10243 	return IA_CSS_SUCCESS;
10244 }
10245 
10246 enum atomisp_input_format
10247 ia_css_stream_get_format(const struct ia_css_stream *stream) {
10248 	return stream->config.input_config.format;
10249 }
10250 
10251 bool
10252 ia_css_stream_get_two_pixels_per_clock(const struct ia_css_stream *stream) {
10253 	return (stream->config.pixels_per_clock == 2);
10254 }
10255 
10256 struct ia_css_binary *
10257 ia_css_stream_get_shading_correction_binary(const struct ia_css_stream
10258 	*stream) {
10259 	struct ia_css_pipe *pipe;
10260 
10261 	assert(stream);
10262 
10263 	pipe = stream->pipes[0];
10264 
10265 	if (stream->num_pipes == 2) {
10266 		assert(stream->pipes[1]);
10267 		if (stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_VIDEO ||
10268 		    stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_PREVIEW)
10269 			pipe = stream->pipes[1];
10270 	}
10271 
10272 	return ia_css_pipe_get_shading_correction_binary(pipe);
10273 }
10274 
10275 struct ia_css_binary *
10276 ia_css_stream_get_dvs_binary(const struct ia_css_stream *stream) {
10277 	int i;
10278 	struct ia_css_pipe *video_pipe = NULL;
10279 
10280 	/* First we find the video pipe */
10281 	for (i = 0; i < stream->num_pipes; i++) {
10282 		struct ia_css_pipe *pipe = stream->pipes[i];
10283 
10284 		if (pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) {
10285 			video_pipe = pipe;
10286 			break;
10287 		}
10288 	}
10289 	if (video_pipe)
10290 		return &video_pipe->pipe_settings.video.video_binary;
10291 	return NULL;
10292 }
10293 
10294 struct ia_css_binary *
10295 ia_css_stream_get_3a_binary(const struct ia_css_stream *stream) {
10296 	struct ia_css_pipe *pipe;
10297 	struct ia_css_binary *s3a_binary = NULL;
10298 
10299 	assert(stream);
10300 
10301 	pipe = stream->pipes[0];
10302 
10303 	if (stream->num_pipes == 2) {
10304 		assert(stream->pipes[1]);
10305 		if (stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_VIDEO ||
10306 		    stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_PREVIEW)
10307 			pipe = stream->pipes[1];
10308 	}
10309 
10310 	s3a_binary = ia_css_pipe_get_s3a_binary(pipe);
10311 
10312 	return s3a_binary;
10313 }
10314 
10315 enum ia_css_err
10316 ia_css_stream_set_output_padded_width(struct ia_css_stream *stream,
10317 					unsigned int output_padded_width) {
10318 	struct ia_css_pipe *pipe;
10319 
10320 	assert(stream);
10321 
10322 	pipe = stream->last_pipe;
10323 
10324 	assert(pipe);
10325 
10326 	/* set the config also just in case (redundant info? why do we save config in pipe?) */
10327 	pipe->config.output_info[IA_CSS_PIPE_OUTPUT_STAGE_0].padded_width = output_padded_width;
10328 	pipe->output_info[IA_CSS_PIPE_OUTPUT_STAGE_0].padded_width = output_padded_width;
10329 
10330 	return IA_CSS_SUCCESS;
10331 }
10332 
10333 static struct ia_css_binary *
10334 ia_css_pipe_get_shading_correction_binary(const struct ia_css_pipe *pipe) {
10335 	struct ia_css_binary *binary = NULL;
10336 
10337 	assert(pipe);
10338 
10339 	switch (pipe->config.mode) {
10340 	case IA_CSS_PIPE_MODE_PREVIEW:
10341 		binary = (struct ia_css_binary *)&pipe->pipe_settings.preview.preview_binary;
10342 		break;
10343 	case IA_CSS_PIPE_MODE_VIDEO:
10344 		binary = (struct ia_css_binary *)&pipe->pipe_settings.video.video_binary;
10345 		break;
10346 	case IA_CSS_PIPE_MODE_CAPTURE:
10347 		if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
10348 			unsigned int i;
10349 
10350 			for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
10351 				if (pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.sc) {
10352 					binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.primary_binary[i];
10353 					break;
10354 				}
10355 			}
10356 		} else if (pipe->config.default_capture_config.mode ==
10357 			    IA_CSS_CAPTURE_MODE_BAYER)
10358 			binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
10359 		else if (pipe->config.default_capture_config.mode ==
10360 			    IA_CSS_CAPTURE_MODE_ADVANCED ||
10361 			    pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) {
10362 			if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_1)
10363 				binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
10364 			else if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_2_2)
10365 				binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.post_isp_binary;
10366 		}
10367 		break;
10368 	default:
10369 		break;
10370 	}
10371 
10372 	if (binary && binary->info->sp.enable.sc)
10373 		return binary;
10374 
10375 	return NULL;
10376 }
10377 
10378 static struct ia_css_binary *
10379 ia_css_pipe_get_s3a_binary(const struct ia_css_pipe *pipe) {
10380 	struct ia_css_binary *binary = NULL;
10381 
10382 	assert(pipe);
10383 
10384 	switch (pipe->config.mode) {
10385 	case IA_CSS_PIPE_MODE_PREVIEW:
10386 		binary = (struct ia_css_binary *)&pipe->pipe_settings.preview.preview_binary;
10387 		break;
10388 	case IA_CSS_PIPE_MODE_VIDEO:
10389 		binary = (struct ia_css_binary *)&pipe->pipe_settings.video.video_binary;
10390 		break;
10391 	case IA_CSS_PIPE_MODE_CAPTURE:
10392 		if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
10393 			unsigned int i;
10394 
10395 			for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
10396 				if (pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.s3a) {
10397 					binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.primary_binary[i];
10398 					break;
10399 				}
10400 			}
10401 		} else if (pipe->config.default_capture_config.mode ==
10402 			    IA_CSS_CAPTURE_MODE_BAYER)
10403 			binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
10404 		else if (pipe->config.default_capture_config.mode ==
10405 			    IA_CSS_CAPTURE_MODE_ADVANCED ||
10406 			    pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) {
10407 			if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_1)
10408 				binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
10409 			else if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_2_2)
10410 				binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.post_isp_binary;
10411 			else
10412 				assert(0);
10413 		}
10414 		break;
10415 	default:
10416 		break;
10417 	}
10418 
10419 	if (binary && !binary->info->sp.enable.s3a)
10420 		binary = NULL;
10421 
10422 	return binary;
10423 }
10424 
10425 static struct ia_css_binary *
10426 ia_css_pipe_get_sdis_binary(const struct ia_css_pipe *pipe) {
10427 	struct ia_css_binary *binary = NULL;
10428 
10429 	assert(pipe);
10430 
10431 	switch (pipe->config.mode) {
10432 	case IA_CSS_PIPE_MODE_VIDEO:
10433 		binary = (struct ia_css_binary *)&pipe->pipe_settings.video.video_binary;
10434 		break;
10435 	default:
10436 		break;
10437 	}
10438 
10439 	if (binary && !binary->info->sp.enable.dis)
10440 		binary = NULL;
10441 
10442 	return binary;
10443 }
10444 
10445 struct ia_css_pipeline *
10446 ia_css_pipe_get_pipeline(const struct ia_css_pipe *pipe) {
10447 	assert(pipe);
10448 
10449 	return (struct ia_css_pipeline *)&pipe->pipeline;
10450 }
10451 
10452 unsigned int
10453 ia_css_pipe_get_pipe_num(const struct ia_css_pipe *pipe) {
10454 	assert(pipe);
10455 
10456 	/* KW was not sure this function was not returning a value
10457 	    that was out of range; so added an assert, and, for the
10458 	    case when asserts are not enabled, clip to the largest
10459 	    value; pipe_num is unsigned so the value cannot be too small
10460 	*/
10461 	assert(pipe->pipe_num < IA_CSS_PIPELINE_NUM_MAX);
10462 
10463 	if (pipe->pipe_num >= IA_CSS_PIPELINE_NUM_MAX)
10464 		return (IA_CSS_PIPELINE_NUM_MAX - 1);
10465 
10466 	return pipe->pipe_num;
10467 }
10468 
10469 unsigned int
10470 ia_css_pipe_get_isp_pipe_version(const struct ia_css_pipe *pipe) {
10471 	assert(pipe);
10472 
10473 	return (unsigned int)pipe->config.isp_pipe_version;
10474 }
10475 
10476 #define SP_START_TIMEOUT_US 30000000
10477 
10478 enum ia_css_err
10479 ia_css_start_sp(void) {
10480 	unsigned long timeout;
10481 	enum ia_css_err err = IA_CSS_SUCCESS;
10482 
10483 	IA_CSS_ENTER("");
10484 	sh_css_sp_start_isp();
10485 
10486 	/* waiting for the SP is completely started */
10487 	timeout = SP_START_TIMEOUT_US;
10488 	while ((ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_INITIALIZED) && timeout)
10489 	{
10490 		timeout--;
10491 		hrt_sleep();
10492 	}
10493 	if (timeout == 0)
10494 	{
10495 		IA_CSS_ERROR("timeout during SP initialization");
10496 		return IA_CSS_ERR_INTERNAL_ERROR;
10497 	}
10498 
10499 	/* Workaround, in order to run two streams in parallel. See TASK 4271*/
10500 	/* TODO: Fix this. */
10501 
10502 	sh_css_init_host_sp_control_vars();
10503 
10504 	/* buffers should be initialized only when sp is started */
10505 	/* AM: At the moment it will be done only when there is no stream active. */
10506 
10507 	sh_css_setup_queues();
10508 	ia_css_bufq_dump_queue_info();
10509 
10510 	IA_CSS_LEAVE_ERR(err);
10511 	return err;
10512 }
10513 
10514 /*
10515     *	Time to wait SP for termincate. Only condition when this can happen
10516     *	is a fatal hw failure, but we must be able to detect this and emit
10517     *	a proper error trace.
10518     */
10519 #define SP_SHUTDOWN_TIMEOUT_US 200000
10520 
10521 enum ia_css_err
10522 ia_css_stop_sp(void) {
10523 	unsigned long timeout;
10524 	enum ia_css_err err = IA_CSS_SUCCESS;
10525 
10526 	IA_CSS_ENTER("void");
10527 
10528 	if (!sh_css_sp_is_running())
10529 	{
10530 		err = IA_CSS_ERR_INVALID_ARGUMENTS;
10531 		IA_CSS_LEAVE("SP already stopped : return_err=%d", err);
10532 
10533 		/* Return an error - stop SP should not have been called by driver */
10534 		return err;
10535 	}
10536 
10537 	/* For now, stop whole SP */
10538 	if (!atomisp_hw_is_isp2401) {
10539 		sh_css_write_host2sp_command(host2sp_cmd_terminate);
10540 	} else {
10541 		if (!sh_css_write_host2sp_command(host2sp_cmd_terminate))
10542 		{
10543 			IA_CSS_ERROR("Call to 'sh-css_write_host2sp_command()' failed");
10544 			ia_css_debug_dump_sp_sw_debug_info();
10545 			ia_css_debug_dump_debug_info(NULL);
10546 		}
10547 	}
10548 
10549 	sh_css_sp_set_sp_running(false);
10550 
10551 	timeout = SP_SHUTDOWN_TIMEOUT_US;
10552 	while (!ia_css_spctrl_is_idle(SP0_ID) && timeout)
10553 	{
10554 		timeout--;
10555 		hrt_sleep();
10556 	}
10557 	if ((ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_TERMINATED))
10558 		IA_CSS_WARNING("SP has not terminated (SW)");
10559 
10560 	if (timeout == 0)
10561 	{
10562 		IA_CSS_WARNING("SP is not idle");
10563 		ia_css_debug_dump_sp_sw_debug_info();
10564 	}
10565 	timeout = SP_SHUTDOWN_TIMEOUT_US;
10566 	while (!isp_ctrl_getbit(ISP0_ID, ISP_SC_REG, ISP_IDLE_BIT) && timeout)
10567 	{
10568 		timeout--;
10569 		hrt_sleep();
10570 	}
10571 	if (timeout == 0)
10572 	{
10573 		IA_CSS_WARNING("ISP is not idle");
10574 		ia_css_debug_dump_sp_sw_debug_info();
10575 	}
10576 
10577 	sh_css_hmm_buffer_record_uninit();
10578 
10579 	/* clear pending param sets from refcount */
10580 	sh_css_param_clear_param_sets();
10581 
10582 	IA_CSS_LEAVE_ERR(err);
10583 	return err;
10584 }
10585 
10586 enum ia_css_err
10587 ia_css_update_continuous_frames(struct ia_css_stream *stream) {
10588 	struct ia_css_pipe *pipe;
10589 	unsigned int i;
10590 
10591 	ia_css_debug_dtrace(
10592 	    IA_CSS_DEBUG_TRACE,
10593 	    "sh_css_update_continuous_frames() enter:\n");
10594 
10595 	if (!stream)
10596 	{
10597 		ia_css_debug_dtrace(
10598 		    IA_CSS_DEBUG_TRACE,
10599 		    "sh_css_update_continuous_frames() leave: invalid stream, return_void\n");
10600 		return IA_CSS_ERR_INVALID_ARGUMENTS;
10601 	}
10602 
10603 	pipe = stream->continuous_pipe;
10604 
10605 	for (i = stream->config.init_num_cont_raw_buf;
10606 		i < stream->config.target_num_cont_raw_buf; i++)
10607 	{
10608 		sh_css_update_host2sp_offline_frame(i,
10609 						    pipe->continuous_frames[i], pipe->cont_md_buffers[i]);
10610 	}
10611 	sh_css_update_host2sp_cont_num_raw_frames
10612 	(stream->config.target_num_cont_raw_buf, true);
10613 	ia_css_debug_dtrace(
10614 	    IA_CSS_DEBUG_TRACE,
10615 	    "sh_css_update_continuous_frames() leave: return_void\n");
10616 
10617 	return IA_CSS_SUCCESS;
10618 }
10619 
10620 void ia_css_pipe_map_queue(struct ia_css_pipe *pipe, bool map) {
10621 	unsigned int thread_id;
10622 	enum ia_css_pipe_id pipe_id;
10623 	unsigned int pipe_num;
10624 	bool need_input_queue;
10625 
10626 	IA_CSS_ENTER("");
10627 	assert(pipe);
10628 
10629 	pipe_id = pipe->mode;
10630 	pipe_num = pipe->pipe_num;
10631 
10632 	ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
10633 
10634 #if defined(HAS_NO_INPUT_SYSTEM) || defined(USE_INPUT_SYSTEM_VERSION_2401)
10635 	need_input_queue = true;
10636 #else
10637 	need_input_queue = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
10638 #endif
10639 
10640 	/* map required buffer queues to resources */
10641 	/* TODO: to be improved */
10642 	if (pipe->mode == IA_CSS_PIPE_ID_PREVIEW) {
10643 		if (need_input_queue)
10644 			ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10645 		ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10646 		ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10647 		ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
10648 #if defined SH_CSS_ENABLE_METADATA
10649 		ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10650 #endif
10651 		if (pipe->pipe_settings.preview.preview_binary.info &&
10652 		    pipe->pipe_settings.preview.preview_binary.info->sp.enable.s3a)
10653 			ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
10654 	} else if (pipe->mode == IA_CSS_PIPE_ID_CAPTURE) {
10655 		unsigned int i;
10656 
10657 		if (need_input_queue)
10658 			ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10659 		ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10660 		ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME, map);
10661 		ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10662 		ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
10663 #if defined SH_CSS_ENABLE_METADATA
10664 		ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10665 #endif
10666 		if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
10667 			for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
10668 				if (pipe->pipe_settings.capture.primary_binary[i].info &&
10669 				    pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.s3a) {
10670 					ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
10671 					break;
10672 				}
10673 			}
10674 		} else if (pipe->config.default_capture_config.mode ==
10675 			    IA_CSS_CAPTURE_MODE_ADVANCED ||
10676 			    pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT ||
10677 			    pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER) {
10678 			if (pipe->pipe_settings.capture.pre_isp_binary.info &&
10679 			    pipe->pipe_settings.capture.pre_isp_binary.info->sp.enable.s3a)
10680 				ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
10681 		}
10682 	} else if (pipe->mode == IA_CSS_PIPE_ID_VIDEO) {
10683 		if (need_input_queue)
10684 			ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10685 		ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10686 		if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0])
10687 			ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME, map);
10688 		ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10689 		ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
10690 #if defined SH_CSS_ENABLE_METADATA
10691 		ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10692 #endif
10693 		if (pipe->pipe_settings.video.video_binary.info &&
10694 		    pipe->pipe_settings.video.video_binary.info->sp.enable.s3a)
10695 			ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
10696 		if (pipe->pipe_settings.video.video_binary.info &&
10697 		    (pipe->pipe_settings.video.video_binary.info->sp.enable.dis
10698 		    ))
10699 			ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_DIS_STATISTICS, map);
10700 	} else if (pipe->mode == IA_CSS_PIPE_ID_COPY) {
10701 		if (need_input_queue)
10702 			ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10703 		if (!pipe->stream->config.continuous)
10704 			ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10705 #if defined SH_CSS_ENABLE_METADATA
10706 		ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10707 #endif
10708 	} else if (pipe->mode == IA_CSS_PIPE_ID_ACC) {
10709 		if (need_input_queue)
10710 			ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10711 		ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10712 		ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10713 		ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
10714 #if defined SH_CSS_ENABLE_METADATA
10715 		ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10716 #endif
10717 	} else if (pipe->mode == IA_CSS_PIPE_ID_YUVPP) {
10718 		unsigned int idx;
10719 
10720 		for (idx = 0; idx < IA_CSS_PIPE_MAX_OUTPUT_STAGE; idx++) {
10721 			ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx, map);
10722 			if (pipe->enable_viewfinder[idx])
10723 				ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx, map);
10724 		}
10725 		if (need_input_queue)
10726 			ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10727 		ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10728 #if defined SH_CSS_ENABLE_METADATA
10729 		ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10730 #endif
10731 	}
10732 	IA_CSS_LEAVE("");
10733 }
10734 
10735 #if CONFIG_ON_FRAME_ENQUEUE()
10736 static enum ia_css_err set_config_on_frame_enqueue(struct ia_css_frame_info
10737 	*info, struct frame_data_wrapper *frame) {
10738 	frame->config_on_frame_enqueue.padded_width = 0;
10739 
10740 	/* currently we support configuration on frame enqueue only on YUV formats */
10741 	/* on other formats the padded_width is zeroed for no configuration override */
10742 	switch (info->format) {
10743 	case IA_CSS_FRAME_FORMAT_YUV420:
10744 	case IA_CSS_FRAME_FORMAT_NV12:
10745 		if (info->padded_width > info->res.width) {
10746 			frame->config_on_frame_enqueue.padded_width = info->padded_width;
10747 		} else if ((info->padded_width < info->res.width) && (info->padded_width > 0)) {
10748 			return IA_CSS_ERR_INVALID_ARGUMENTS;
10749 		}
10750 		/* nothing to do if width == padded width or padded width is zeroed (the same) */
10751 		break;
10752 	default:
10753 		break;
10754 	}
10755 
10756 	return IA_CSS_SUCCESS;
10757 }
10758 #endif
10759 
10760 enum ia_css_err
10761 ia_css_unlock_raw_frame(struct ia_css_stream *stream, uint32_t exp_id) {
10762 	enum ia_css_err ret;
10763 
10764 	IA_CSS_ENTER("");
10765 
10766 	/* Only continuous streams have a tagger to which we can send the
10767 	    * unlock message. */
10768 	if (!stream || !stream->config.continuous)
10769 	{
10770 		IA_CSS_ERROR("invalid stream pointer");
10771 		return IA_CSS_ERR_INVALID_ARGUMENTS;
10772 	}
10773 
10774 	if (exp_id > IA_CSS_ISYS_MAX_EXPOSURE_ID ||
10775 	    exp_id < IA_CSS_ISYS_MIN_EXPOSURE_ID)
10776 	{
10777 		IA_CSS_ERROR("invalid expsure ID: %d\n", exp_id);
10778 		return IA_CSS_ERR_INVALID_ARGUMENTS;
10779 	}
10780 
10781 	/* Send the event. Since we verified that the exp_id is valid,
10782 	    * we can safely assign it to an 8-bit argument here. */
10783 	ret = ia_css_bufq_enqueue_psys_event(
10784 	    IA_CSS_PSYS_SW_EVENT_UNLOCK_RAW_BUFFER, exp_id, 0, 0);
10785 
10786 	IA_CSS_LEAVE_ERR(ret);
10787 	return ret;
10788 }
10789 
10790 /* @brief	Set the state (Enable or Disable) of the Extension stage in the
10791     *		given pipe.
10792     */
10793 enum ia_css_err
10794 ia_css_pipe_set_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle,
10795 				bool enable) {
10796 	unsigned int thread_id;
10797 	struct ia_css_pipeline_stage *stage;
10798 	enum ia_css_err err = IA_CSS_SUCCESS;
10799 
10800 	IA_CSS_ENTER("");
10801 
10802 	/* Parameter Check */
10803 	if (!pipe || !pipe->stream)
10804 	{
10805 		IA_CSS_ERROR("Invalid Pipe.");
10806 		err = IA_CSS_ERR_INVALID_ARGUMENTS;
10807 	} else if (!(pipe->config.acc_extension))
10808 	{
10809 		IA_CSS_ERROR("Invalid Pipe(No Extension Firmware)");
10810 		err = IA_CSS_ERR_INVALID_ARGUMENTS;
10811 	} else if (!sh_css_sp_is_running())
10812 	{
10813 		IA_CSS_ERROR("Leaving: queue unavailable.");
10814 		err = IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
10815 	} else
10816 	{
10817 		/* Query the threadid and stage_num for the Extension firmware*/
10818 		ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
10819 		err = ia_css_pipeline_get_stage_from_fw(&pipe->pipeline, fw_handle, &stage);
10820 		if (err == IA_CSS_SUCCESS) {
10821 			/* Set the Extension State;. TODO: Add check for stage firmware.type (QOS)*/
10822 			err = ia_css_bufq_enqueue_psys_event(
10823 			    (uint8_t)IA_CSS_PSYS_SW_EVENT_STAGE_ENABLE_DISABLE,
10824 			    (uint8_t)thread_id,
10825 			    (uint8_t)stage->stage_num,
10826 			    enable ? 1 : 0);
10827 			if (err == IA_CSS_SUCCESS) {
10828 				if (enable)
10829 					SH_CSS_QOS_STAGE_ENABLE(&sh_css_sp_group.pipe[thread_id], stage->stage_num);
10830 				else
10831 					SH_CSS_QOS_STAGE_DISABLE(&sh_css_sp_group.pipe[thread_id], stage->stage_num);
10832 			}
10833 		}
10834 	}
10835 	IA_CSS_LEAVE("err:%d handle:%u enable:%d", err, fw_handle, enable);
10836 	return err;
10837 }
10838 
10839 /*	@brief	Get the state (Enable or Disable) of the Extension stage in the
10840     *	given pipe.
10841     */
10842 enum ia_css_err
10843 ia_css_pipe_get_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle,
10844 				bool *enable) {
10845 	struct ia_css_pipeline_stage *stage;
10846 	unsigned int thread_id;
10847 	enum ia_css_err err = IA_CSS_SUCCESS;
10848 
10849 	IA_CSS_ENTER("");
10850 
10851 	/* Parameter Check */
10852 	if (!pipe || !pipe->stream)
10853 	{
10854 		IA_CSS_ERROR("Invalid Pipe.");
10855 		err = IA_CSS_ERR_INVALID_ARGUMENTS;
10856 	} else if (!(pipe->config.acc_extension))
10857 	{
10858 		IA_CSS_ERROR("Invalid Pipe (No Extension Firmware).");
10859 		err = IA_CSS_ERR_INVALID_ARGUMENTS;
10860 	} else if (!sh_css_sp_is_running())
10861 	{
10862 		IA_CSS_ERROR("Leaving: queue unavailable.");
10863 		err = IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
10864 	} else
10865 	{
10866 		/* Query the threadid and stage_num corresponding to the Extension firmware*/
10867 		ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
10868 		err = ia_css_pipeline_get_stage_from_fw(&pipe->pipeline, fw_handle, &stage);
10869 
10870 		if (err == IA_CSS_SUCCESS) {
10871 			/* Get the Extension State */
10872 			*enable = (SH_CSS_QOS_STAGE_IS_ENABLED(&sh_css_sp_group.pipe[thread_id],
10873 								stage->stage_num)) ? true : false;
10874 		}
10875 	}
10876 	IA_CSS_LEAVE("err:%d handle:%u enable:%d", err, fw_handle, *enable);
10877 	return err;
10878 }
10879 
10880 /* ISP2401 */
10881 enum ia_css_err
10882 ia_css_pipe_update_qos_ext_mapped_arg(struct ia_css_pipe *pipe,
10883 					uint32_t fw_handle,
10884 					struct ia_css_isp_param_css_segments *css_seg,
10885 					struct ia_css_isp_param_isp_segments *isp_seg) {
10886 	unsigned int HIVE_ADDR_sp_group;
10887 	static struct sh_css_sp_group sp_group;
10888 	static struct sh_css_sp_stage sp_stage;
10889 	static struct sh_css_isp_stage isp_stage;
10890 	const struct ia_css_fw_info *fw;
10891 	unsigned int thread_id;
10892 	struct ia_css_pipeline_stage *stage;
10893 	enum ia_css_err err = IA_CSS_SUCCESS;
10894 	int stage_num = 0;
10895 	enum ia_css_isp_memories mem;
10896 	bool enabled;
10897 
10898 	IA_CSS_ENTER("");
10899 
10900 	fw = &sh_css_sp_fw;
10901 
10902 	/* Parameter Check */
10903 	if (!pipe || !pipe->stream)
10904 	{
10905 		IA_CSS_ERROR("Invalid Pipe.");
10906 		err = IA_CSS_ERR_INVALID_ARGUMENTS;
10907 	} else if (!(pipe->config.acc_extension))
10908 	{
10909 		IA_CSS_ERROR("Invalid Pipe (No Extension Firmware).");
10910 		err = IA_CSS_ERR_INVALID_ARGUMENTS;
10911 	} else if (!sh_css_sp_is_running())
10912 	{
10913 		IA_CSS_ERROR("Leaving: queue unavailable.");
10914 		err = IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
10915 	} else
10916 	{
10917 		/* Query the thread_id and stage_num corresponding to the Extension firmware */
10918 		ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
10919 		err = ia_css_pipeline_get_stage_from_fw(&pipe->pipeline, fw_handle, &stage);
10920 		if (err == IA_CSS_SUCCESS) {
10921 			/* Get the Extension State */
10922 			enabled = (SH_CSS_QOS_STAGE_IS_ENABLED(&sh_css_sp_group.pipe[thread_id],
10923 								stage->stage_num)) ? true : false;
10924 			/* Update mapped arg only when extension stage is not enabled */
10925 			if (enabled) {
10926 				IA_CSS_ERROR("Leaving: cannot update when stage is enabled.");
10927 				err = IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
10928 			} else {
10929 				stage_num = stage->stage_num;
10930 
10931 				HIVE_ADDR_sp_group = fw->info.sp.group;
10932 				sp_dmem_load(SP0_ID,
10933 						(unsigned int)sp_address_of(sp_group),
10934 						&sp_group, sizeof(struct sh_css_sp_group));
10935 				mmgr_load(sp_group.pipe[thread_id].sp_stage_addr[stage_num],
10936 					    &sp_stage, sizeof(struct sh_css_sp_stage));
10937 
10938 				mmgr_load(sp_stage.isp_stage_addr,
10939 					    &isp_stage, sizeof(struct sh_css_isp_stage));
10940 
10941 				for (mem = 0; mem < N_IA_CSS_ISP_MEMORIES; mem++) {
10942 					isp_stage.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].address =
10943 					    css_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].address;
10944 					isp_stage.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].size =
10945 					    css_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].size;
10946 					isp_stage.binary_info.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].address
10947 					    =
10948 						isp_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].address;
10949 					isp_stage.binary_info.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].size
10950 					    =
10951 						isp_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].size;
10952 				}
10953 
10954 				mmgr_store(sp_stage.isp_stage_addr,
10955 					    &isp_stage, sizeof(struct sh_css_isp_stage));
10956 			}
10957 		}
10958 	}
10959 	IA_CSS_LEAVE("err:%d handle:%u", err, fw_handle);
10960 	return err;
10961 }
10962 
10963 #ifdef USE_INPUT_SYSTEM_VERSION_2401
10964 static enum ia_css_err
10965 aspect_ratio_crop_init(struct ia_css_stream *curr_stream,
10966 			struct ia_css_pipe *pipes[],
10967 			bool *do_crop_status) {
10968 	enum ia_css_err err = IA_CSS_SUCCESS;
10969 	int i;
10970 	struct ia_css_pipe *curr_pipe;
10971 	u32 pipe_mask = 0;
10972 
10973 	if ((!curr_stream) ||
10974 	    (curr_stream->num_pipes == 0) ||
10975 	    (!pipes) ||
10976 	    (!do_crop_status))
10977 	{
10978 		err = IA_CSS_ERR_INVALID_ARGUMENTS;
10979 		IA_CSS_LEAVE_ERR(err);
10980 		return err;
10981 	}
10982 
10983 	for (i = 0; i < curr_stream->num_pipes; i++)
10984 	{
10985 		curr_pipe = pipes[i];
10986 		pipe_mask |= (1 << curr_pipe->config.mode);
10987 	}
10988 
10989 	*do_crop_status =
10990 	(((pipe_mask & (1 << IA_CSS_PIPE_MODE_PREVIEW)) ||
10991 	    (pipe_mask & (1 << IA_CSS_PIPE_MODE_VIDEO))) &&
10992 	    (pipe_mask & (1 << IA_CSS_PIPE_MODE_CAPTURE)) &&
10993 	    curr_stream->config.continuous);
10994 	return IA_CSS_SUCCESS;
10995 }
10996 
10997 static bool
10998 aspect_ratio_crop_check(bool enabled, struct ia_css_pipe *curr_pipe) {
10999 	bool status = false;
11000 
11001 	if ((curr_pipe) && enabled) {
11002 		if ((curr_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) ||
11003 		    (curr_pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) ||
11004 		    (curr_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE))
11005 			status = true;
11006 	}
11007 
11008 	return status;
11009 }
11010 
11011 static enum ia_css_err
11012 aspect_ratio_crop(struct ia_css_pipe *curr_pipe,
11013 		    struct ia_css_resolution *effective_res) {
11014 	enum ia_css_err err = IA_CSS_SUCCESS;
11015 	struct ia_css_resolution crop_res;
11016 	struct ia_css_resolution *in_res = NULL;
11017 	struct ia_css_resolution *out_res = NULL;
11018 	bool use_bds_output_info = false;
11019 	bool use_vf_pp_in_res = false;
11020 	bool use_capt_pp_in_res = false;
11021 
11022 	if ((!curr_pipe) ||
11023 	    (!effective_res))
11024 	{
11025 		err = IA_CSS_ERR_INVALID_ARGUMENTS;
11026 		IA_CSS_LEAVE_ERR(err);
11027 		return err;
11028 	}
11029 
11030 	if ((curr_pipe->config.mode != IA_CSS_PIPE_MODE_PREVIEW) &&
11031 	    (curr_pipe->config.mode != IA_CSS_PIPE_MODE_VIDEO) &&
11032 	    (curr_pipe->config.mode != IA_CSS_PIPE_MODE_CAPTURE))
11033 	{
11034 		err = IA_CSS_ERR_INVALID_ARGUMENTS;
11035 		IA_CSS_LEAVE_ERR(err);
11036 		return err;
11037 	}
11038 
11039 	use_bds_output_info =
11040 	((curr_pipe->bds_output_info.res.width != 0) &&
11041 	    (curr_pipe->bds_output_info.res.height != 0));
11042 
11043 	use_vf_pp_in_res =
11044 	((curr_pipe->config.vf_pp_in_res.width != 0) &&
11045 	    (curr_pipe->config.vf_pp_in_res.height != 0));
11046 
11047 	use_capt_pp_in_res =
11048 	((curr_pipe->config.capt_pp_in_res.width != 0) &&
11049 	    (curr_pipe->config.capt_pp_in_res.height != 0));
11050 
11051 	in_res = &curr_pipe->stream->config.input_config.effective_res;
11052 	out_res = &curr_pipe->output_info[0].res;
11053 
11054 	switch (curr_pipe->config.mode)
11055 	{
11056 	case IA_CSS_PIPE_MODE_PREVIEW:
11057 		if (use_bds_output_info)
11058 			out_res = &curr_pipe->bds_output_info.res;
11059 		else if (use_vf_pp_in_res)
11060 			out_res = &curr_pipe->config.vf_pp_in_res;
11061 		break;
11062 	case IA_CSS_PIPE_MODE_VIDEO:
11063 		if (use_bds_output_info)
11064 			out_res = &curr_pipe->bds_output_info.res;
11065 		break;
11066 	case IA_CSS_PIPE_MODE_CAPTURE:
11067 		if (use_capt_pp_in_res)
11068 			out_res = &curr_pipe->config.capt_pp_in_res;
11069 		break;
11070 	case IA_CSS_PIPE_MODE_ACC:
11071 	case IA_CSS_PIPE_MODE_COPY:
11072 	case IA_CSS_PIPE_MODE_YUVPP:
11073 	default:
11074 		IA_CSS_ERROR("aspect ratio cropping invalid args: mode[%d]\n",
11075 				curr_pipe->config.mode);
11076 		assert(0);
11077 		break;
11078 	}
11079 
11080 	err = ia_css_frame_find_crop_resolution(in_res, out_res, &crop_res);
11081 	if (err == IA_CSS_SUCCESS)
11082 	{
11083 		*effective_res = crop_res;
11084 	} else
11085 	{
11086 		/* in case of error fallback to default
11087 		    * effective resolution from driver. */
11088 		IA_CSS_LOG("ia_css_frame_find_crop_resolution() failed with err(%d)", err);
11089 	}
11090 	return err;
11091 }
11092 #endif
11093 
11094 static void
11095 sh_css_hmm_buffer_record_init(void) {
11096 	int i;
11097 
11098 	for (i = 0; i < MAX_HMM_BUFFER_NUM; i++)
11099 		sh_css_hmm_buffer_record_reset(&hmm_buffer_record[i]);
11100 }
11101 
11102 static void
11103 sh_css_hmm_buffer_record_uninit(void) {
11104 	int i;
11105 	struct sh_css_hmm_buffer_record *buffer_record = NULL;
11106 
11107 	buffer_record = &hmm_buffer_record[0];
11108 	for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
11109 		if (buffer_record->in_use) {
11110 			if (buffer_record->h_vbuf)
11111 				ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &buffer_record->h_vbuf);
11112 			sh_css_hmm_buffer_record_reset(buffer_record);
11113 		}
11114 		buffer_record++;
11115 	}
11116 }
11117 
11118 static void
11119 sh_css_hmm_buffer_record_reset(struct sh_css_hmm_buffer_record *buffer_record) {
11120 	assert(buffer_record);
11121 	buffer_record->in_use = false;
11122 	buffer_record->type = IA_CSS_BUFFER_TYPE_INVALID;
11123 	buffer_record->h_vbuf = NULL;
11124 	buffer_record->kernel_ptr = 0;
11125 }
11126 
11127 static struct sh_css_hmm_buffer_record
11128 *sh_css_hmm_buffer_record_acquire(struct ia_css_rmgr_vbuf_handle *h_vbuf,
11129 				    enum ia_css_buffer_type type,
11130 				    hrt_address kernel_ptr) {
11131 	int i;
11132 	struct sh_css_hmm_buffer_record *buffer_record = NULL;
11133 	struct sh_css_hmm_buffer_record *out_buffer_record = NULL;
11134 
11135 	assert(h_vbuf);
11136 	assert((type > IA_CSS_BUFFER_TYPE_INVALID) &&
11137 		(type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE));
11138 	assert(kernel_ptr != 0);
11139 
11140 	buffer_record = &hmm_buffer_record[0];
11141 	for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
11142 		if (!buffer_record->in_use) {
11143 			buffer_record->in_use = true;
11144 			buffer_record->type = type;
11145 			buffer_record->h_vbuf = h_vbuf;
11146 			buffer_record->kernel_ptr = kernel_ptr;
11147 			out_buffer_record = buffer_record;
11148 			break;
11149 		}
11150 		buffer_record++;
11151 	}
11152 
11153 	return out_buffer_record;
11154 }
11155 
11156 static struct sh_css_hmm_buffer_record
11157 *sh_css_hmm_buffer_record_validate(hrt_vaddress ddr_buffer_addr,
11158 				    enum ia_css_buffer_type type) {
11159 	int i;
11160 	struct sh_css_hmm_buffer_record *buffer_record = NULL;
11161 	bool found_record = false;
11162 
11163 	buffer_record = &hmm_buffer_record[0];
11164 	for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
11165 		if ((buffer_record->in_use) &&
11166 		    (buffer_record->type == type) &&
11167 		    (buffer_record->h_vbuf) &&
11168 		    (buffer_record->h_vbuf->vptr == ddr_buffer_addr)) {
11169 			found_record = true;
11170 			break;
11171 		}
11172 		buffer_record++;
11173 	}
11174 
11175 	if (found_record)
11176 		return buffer_record;
11177 	else
11178 		return NULL;
11179 }
11180