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