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