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