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