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