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