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