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