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