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