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