1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Support for Intel Camera Imaging ISP subsystem.
4  * Copyright (c) 2010 - 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 #include "hmm.h"
17 
18 #include "ia_css_debug.h"
19 #include "sw_event_global.h"		/* encode_sw_event */
20 #include "sp.h"			/* cnd_sp_irq_enable() */
21 #include "assert_support.h"
22 #include "sh_css_sp.h"
23 #include "ia_css_pipeline.h"
24 #include "ia_css_isp_param.h"
25 #include "ia_css_bufq.h"
26 
27 #define PIPELINE_NUM_UNMAPPED                   (~0U)
28 #define PIPELINE_SP_THREAD_EMPTY_TOKEN          (0x0)
29 #define PIPELINE_SP_THREAD_RESERVED_TOKEN       (0x1)
30 
31 /*******************************************************
32 *** Static variables
33 ********************************************************/
34 static unsigned int pipeline_num_to_sp_thread_map[IA_CSS_PIPELINE_NUM_MAX];
35 static unsigned int pipeline_sp_thread_list[SH_CSS_MAX_SP_THREADS];
36 
37 /*******************************************************
38 *** Static functions
39 ********************************************************/
40 static void pipeline_init_sp_thread_map(void);
41 static void pipeline_map_num_to_sp_thread(unsigned int pipe_num);
42 static void pipeline_unmap_num_to_sp_thread(unsigned int pipe_num);
43 static void pipeline_init_defaults(
44     struct ia_css_pipeline *pipeline,
45     enum ia_css_pipe_id pipe_id,
46     unsigned int pipe_num,
47     unsigned int dvs_frame_delay);
48 
49 static void pipeline_stage_destroy(struct ia_css_pipeline_stage *stage);
50 static int pipeline_stage_create(
51     struct ia_css_pipeline_stage_desc *stage_desc,
52     struct ia_css_pipeline_stage **new_stage);
53 static void ia_css_pipeline_set_zoom_stage(struct ia_css_pipeline *pipeline);
54 static void ia_css_pipeline_configure_inout_port(struct ia_css_pipeline *me,
55 	bool continuous);
56 
57 /*******************************************************
58 *** Public functions
59 ********************************************************/
60 void ia_css_pipeline_init(void)
61 {
62 	pipeline_init_sp_thread_map();
63 }
64 
65 int ia_css_pipeline_create(
66     struct ia_css_pipeline *pipeline,
67     enum ia_css_pipe_id pipe_id,
68     unsigned int pipe_num,
69     unsigned int dvs_frame_delay)
70 {
71 	assert(pipeline);
72 	IA_CSS_ENTER_PRIVATE("pipeline = %p, pipe_id = %d, pipe_num = %d, dvs_frame_delay = %d",
73 			     pipeline, pipe_id, pipe_num, dvs_frame_delay);
74 	if (!pipeline) {
75 		IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
76 		return -EINVAL;
77 	}
78 
79 	pipeline_init_defaults(pipeline, pipe_id, pipe_num, dvs_frame_delay);
80 
81 	IA_CSS_LEAVE_ERR_PRIVATE(0);
82 	return 0;
83 }
84 
85 void ia_css_pipeline_map(unsigned int pipe_num, bool map)
86 {
87 	assert(pipe_num < IA_CSS_PIPELINE_NUM_MAX);
88 	IA_CSS_ENTER_PRIVATE("pipe_num = %d, map = %d", pipe_num, map);
89 
90 	if (pipe_num >= IA_CSS_PIPELINE_NUM_MAX) {
91 		IA_CSS_ERROR("Invalid pipe number");
92 		IA_CSS_LEAVE_PRIVATE("void");
93 		return;
94 	}
95 	if (map)
96 		pipeline_map_num_to_sp_thread(pipe_num);
97 	else
98 		pipeline_unmap_num_to_sp_thread(pipe_num);
99 	IA_CSS_LEAVE_PRIVATE("void");
100 }
101 
102 /* @brief destroy a pipeline
103  *
104  * @param[in] pipeline
105  * @return    None
106  *
107  */
108 void ia_css_pipeline_destroy(struct ia_css_pipeline *pipeline)
109 {
110 	assert(pipeline);
111 	IA_CSS_ENTER_PRIVATE("pipeline = %p", pipeline);
112 
113 	if (!pipeline) {
114 		IA_CSS_ERROR("NULL input parameter");
115 		IA_CSS_LEAVE_PRIVATE("void");
116 		return;
117 	}
118 
119 	IA_CSS_LOG("pipe_num = %d", pipeline->pipe_num);
120 
121 	/* Free the pipeline number */
122 	ia_css_pipeline_clean(pipeline);
123 
124 	IA_CSS_LEAVE_PRIVATE("void");
125 }
126 
127 /* Run a pipeline and wait till it completes. */
128 void ia_css_pipeline_start(enum ia_css_pipe_id pipe_id,
129 			   struct ia_css_pipeline *pipeline)
130 {
131 	u8 pipe_num = 0;
132 	unsigned int thread_id;
133 
134 	assert(pipeline);
135 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
136 			    "ia_css_pipeline_start() enter: pipe_id=%d, pipeline=%p\n",
137 			    pipe_id, pipeline);
138 	pipeline->pipe_id = pipe_id;
139 	sh_css_sp_init_pipeline(pipeline, pipe_id, pipe_num,
140 				false, false, false, true, SH_CSS_BDS_FACTOR_1_00,
141 				SH_CSS_PIPE_CONFIG_OVRD_NO_OVRD,
142 				IA_CSS_INPUT_MODE_MEMORY, NULL, NULL,
143 #if !defined(HAS_NO_INPUT_SYSTEM)
144 				(enum mipi_port_id)0,
145 #endif
146 				NULL, NULL);
147 
148 	ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
149 	if (!sh_css_sp_is_running()) {
150 		ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
151 				    "ia_css_pipeline_start() error,leaving\n");
152 		/* queues are invalid*/
153 		return;
154 	}
155 	ia_css_bufq_enqueue_psys_event(IA_CSS_PSYS_SW_EVENT_START_STREAM,
156 				       (uint8_t)thread_id,
157 				       0,
158 				       0);
159 
160 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
161 			    "ia_css_pipeline_start() leave: return_void\n");
162 }
163 
164 /*
165  * @brief Query the SP thread ID.
166  * Refer to "sh_css_internal.h" for details.
167  */
168 bool ia_css_pipeline_get_sp_thread_id(unsigned int key, unsigned int *val)
169 {
170 	IA_CSS_ENTER("key=%d, val=%p", key, val);
171 
172 	if ((!val) || (key >= IA_CSS_PIPELINE_NUM_MAX) || (key >= IA_CSS_PIPE_ID_NUM)) {
173 		IA_CSS_LEAVE("return value = false");
174 		return false;
175 	}
176 
177 	*val = pipeline_num_to_sp_thread_map[key];
178 
179 	if (*val == (unsigned int)PIPELINE_NUM_UNMAPPED) {
180 		IA_CSS_LOG("unmapped pipeline number");
181 		IA_CSS_LEAVE("return value = false");
182 		return false;
183 	}
184 	IA_CSS_LEAVE("return value = true");
185 	return true;
186 }
187 
188 void ia_css_pipeline_dump_thread_map_info(void)
189 {
190 	unsigned int i;
191 
192 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
193 			    "pipeline_num_to_sp_thread_map:\n");
194 	for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) {
195 		ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
196 				    "pipe_num: %u, tid: 0x%x\n", i, pipeline_num_to_sp_thread_map[i]);
197 	}
198 }
199 
200 int ia_css_pipeline_request_stop(struct ia_css_pipeline *pipeline)
201 {
202 	int err = 0;
203 	unsigned int thread_id;
204 
205 	assert(pipeline);
206 
207 	if (!pipeline)
208 		return -EINVAL;
209 
210 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
211 			    "ia_css_pipeline_request_stop() enter: pipeline=%p\n",
212 			    pipeline);
213 	pipeline->stop_requested = true;
214 
215 	/* Send stop event to the sp*/
216 	/* This needs improvement, stop on all the pipes available
217 	 * in the stream*/
218 	ia_css_pipeline_get_sp_thread_id(pipeline->pipe_num, &thread_id);
219 	if (!sh_css_sp_is_running()) {
220 		ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
221 				    "ia_css_pipeline_request_stop() leaving\n");
222 		/* queues are invalid */
223 		return -EBUSY;
224 	}
225 	ia_css_bufq_enqueue_psys_event(IA_CSS_PSYS_SW_EVENT_STOP_STREAM,
226 				       (uint8_t)thread_id,
227 				       0,
228 				       0);
229 	sh_css_sp_uninit_pipeline(pipeline->pipe_num);
230 
231 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
232 			    "ia_css_pipeline_request_stop() leave: return_err=%d\n",
233 			    err);
234 	return err;
235 }
236 
237 void ia_css_pipeline_clean(struct ia_css_pipeline *pipeline)
238 {
239 	struct ia_css_pipeline_stage *s;
240 
241 	assert(pipeline);
242 	IA_CSS_ENTER_PRIVATE("pipeline = %p", pipeline);
243 
244 	if (!pipeline) {
245 		IA_CSS_ERROR("NULL input parameter");
246 		IA_CSS_LEAVE_PRIVATE("void");
247 		return;
248 	}
249 	s = pipeline->stages;
250 
251 	while (s) {
252 		struct ia_css_pipeline_stage *next = s->next;
253 
254 		pipeline_stage_destroy(s);
255 		s = next;
256 	}
257 	pipeline_init_defaults(pipeline, pipeline->pipe_id, pipeline->pipe_num,
258 			       pipeline->dvs_frame_delay);
259 
260 	IA_CSS_LEAVE_PRIVATE("void");
261 }
262 
263 /* @brief Add a stage to pipeline.
264  *
265  * @param       pipeline      Pointer to the pipeline to be added to.
266  * @param[in]   stage_desc    The description of the stage
267  * @param[out]	stage         The successor of the stage.
268  * @return      0 or error code upon error.
269  *
270  * Add a new stage to a non-NULL pipeline.
271  * The stage consists of an ISP binary or firmware and input and
272  * output arguments.
273 */
274 int ia_css_pipeline_create_and_add_stage(
275     struct ia_css_pipeline *pipeline,
276     struct ia_css_pipeline_stage_desc *stage_desc,
277     struct ia_css_pipeline_stage **stage)
278 {
279 	struct ia_css_pipeline_stage *last, *new_stage = NULL;
280 	int err;
281 
282 	/* other arguments can be NULL */
283 	assert(pipeline);
284 	assert(stage_desc);
285 	last = pipeline->stages;
286 
287 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
288 			    "ia_css_pipeline_create_and_add_stage() enter:\n");
289 	if (!stage_desc->binary && !stage_desc->firmware
290 	    && (stage_desc->sp_func == IA_CSS_PIPELINE_NO_FUNC)) {
291 		ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
292 				    "ia_css_pipeline_create_and_add_stage() done: Invalid args\n");
293 
294 		return -EINVAL;
295 	}
296 
297 	/* Find the last stage */
298 	while (last && last->next)
299 		last = last->next;
300 
301 	/* if in_frame is not set, we use the out_frame from the previous
302 	 * stage, if no previous stage, it's an error.
303 	 */
304 	if ((stage_desc->sp_func == IA_CSS_PIPELINE_NO_FUNC)
305 	    && (!stage_desc->in_frame)
306 	    && (!stage_desc->firmware)
307 	    && (!stage_desc->binary->online)) {
308 		/* Do this only for ISP stages*/
309 		if (last && last->args.out_frame[0])
310 			stage_desc->in_frame = last->args.out_frame[0];
311 
312 		if (!stage_desc->in_frame)
313 			return -EINVAL;
314 	}
315 
316 	/* Create the new stage */
317 	err = pipeline_stage_create(stage_desc, &new_stage);
318 	if (err) {
319 		ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
320 				    "ia_css_pipeline_create_and_add_stage() done: stage_create_failed\n");
321 		return err;
322 	}
323 
324 	if (last)
325 		last->next = new_stage;
326 	else
327 		pipeline->stages = new_stage;
328 
329 	/* Output the new stage */
330 	if (stage)
331 		*stage = new_stage;
332 
333 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
334 			    "ia_css_pipeline_create_and_add_stage() done:\n");
335 	return 0;
336 }
337 
338 void ia_css_pipeline_finalize_stages(struct ia_css_pipeline *pipeline,
339 				     bool continuous)
340 {
341 	unsigned int i = 0;
342 	struct ia_css_pipeline_stage *stage;
343 
344 	assert(pipeline);
345 	for (stage = pipeline->stages; stage; stage = stage->next) {
346 		stage->stage_num = i;
347 		i++;
348 	}
349 	pipeline->num_stages = i;
350 
351 	ia_css_pipeline_set_zoom_stage(pipeline);
352 	ia_css_pipeline_configure_inout_port(pipeline, continuous);
353 }
354 
355 int ia_css_pipeline_get_stage(struct ia_css_pipeline *pipeline,
356 	int mode,
357 	struct ia_css_pipeline_stage **stage)
358 {
359 	struct ia_css_pipeline_stage *s;
360 
361 	assert(pipeline);
362 	assert(stage);
363 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
364 			    "ia_css_pipeline_get_stage() enter:\n");
365 	for (s = pipeline->stages; s; s = s->next) {
366 		if (s->mode == mode) {
367 			*stage = s;
368 			return 0;
369 		}
370 	}
371 	return -EINVAL;
372 }
373 
374 int ia_css_pipeline_get_stage_from_fw(struct ia_css_pipeline
375 	*pipeline,
376 	u32 fw_handle,
377 	struct ia_css_pipeline_stage **stage)
378 {
379 	struct ia_css_pipeline_stage *s;
380 
381 	assert(pipeline);
382 	assert(stage);
383 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "%s()\n", __func__);
384 	for (s = pipeline->stages; s; s = s->next) {
385 		if ((s->firmware) && (s->firmware->handle == fw_handle)) {
386 			*stage = s;
387 			return 0;
388 		}
389 	}
390 	return -EINVAL;
391 }
392 
393 int ia_css_pipeline_get_fw_from_stage(struct ia_css_pipeline
394 	*pipeline,
395 	u32 stage_num,
396 	uint32_t *fw_handle)
397 {
398 	struct ia_css_pipeline_stage *s;
399 
400 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "%s()\n", __func__);
401 	if ((!pipeline) || (!fw_handle))
402 		return -EINVAL;
403 
404 	for (s = pipeline->stages; s; s = s->next) {
405 		if ((s->stage_num == stage_num) && (s->firmware)) {
406 			*fw_handle = s->firmware->handle;
407 			return 0;
408 		}
409 	}
410 	return -EINVAL;
411 }
412 
413 int ia_css_pipeline_get_output_stage(
414     struct ia_css_pipeline *pipeline,
415     int mode,
416     struct ia_css_pipeline_stage **stage)
417 {
418 	struct ia_css_pipeline_stage *s;
419 
420 	assert(pipeline);
421 	assert(stage);
422 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
423 			    "ia_css_pipeline_get_output_stage() enter:\n");
424 
425 	*stage = NULL;
426 	/* First find acceleration firmware at end of pipe */
427 	for (s = pipeline->stages; s; s = s->next) {
428 		if (s->firmware && s->mode == mode &&
429 		    s->firmware->info.isp.sp.enable.output)
430 			*stage = s;
431 	}
432 	if (*stage)
433 		return 0;
434 	/* If no firmware, find binary in pipe */
435 	return ia_css_pipeline_get_stage(pipeline, mode, stage);
436 }
437 
438 bool ia_css_pipeline_has_stopped(struct ia_css_pipeline *pipeline)
439 {
440 	/* Android compilation files if made an local variable
441 	stack size on android is limited to 2k and this structure
442 	is around 2.5K, in place of static malloc can be done but
443 	if this call is made too often it will lead to fragment memory
444 	versus a fixed allocation */
445 	static struct sh_css_sp_group sp_group;
446 	unsigned int thread_id;
447 	const struct ia_css_fw_info *fw;
448 	unsigned int HIVE_ADDR_sp_group;
449 
450 	fw = &sh_css_sp_fw;
451 	HIVE_ADDR_sp_group = fw->info.sp.group;
452 
453 	ia_css_pipeline_get_sp_thread_id(pipeline->pipe_num, &thread_id);
454 	sp_dmem_load(SP0_ID,
455 		     (unsigned int)sp_address_of(sp_group),
456 		     &sp_group, sizeof(struct sh_css_sp_group));
457 	return sp_group.pipe[thread_id].num_stages == 0;
458 }
459 
460 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
461 struct sh_css_sp_pipeline_io_status *ia_css_pipeline_get_pipe_io_status(void)
462 {
463 	return(&sh_css_sp_group.pipe_io_status);
464 }
465 #endif
466 
467 bool ia_css_pipeline_is_mapped(unsigned int key)
468 {
469 	bool ret = false;
470 
471 	IA_CSS_ENTER_PRIVATE("key = %d", key);
472 
473 	if ((key >= IA_CSS_PIPELINE_NUM_MAX) || (key >= IA_CSS_PIPE_ID_NUM)) {
474 		IA_CSS_ERROR("Invalid key!!");
475 		IA_CSS_LEAVE_PRIVATE("return = %d", false);
476 		return false;
477 	}
478 
479 	ret = (bool)(pipeline_num_to_sp_thread_map[key] != (unsigned int)
480 		     PIPELINE_NUM_UNMAPPED);
481 
482 	IA_CSS_LEAVE_PRIVATE("return = %d", ret);
483 	return ret;
484 }
485 
486 /*******************************************************
487 *** Static functions
488 ********************************************************/
489 
490 /* Pipeline:
491  * To organize the several different binaries for each type of mode,
492  * we use a pipeline. A pipeline contains a number of stages, each with
493  * their own binary and frame pointers.
494  * When stages are added to a pipeline, output frames that are not passed
495  * from outside are automatically allocated.
496  * When input frames are not passed from outside, each stage will use the
497  * output frame of the previous stage as input (the full resolution output,
498  * not the viewfinder output).
499  * Pipelines must be cleaned and re-created when settings of the binaries
500  * change.
501  */
502 static void pipeline_stage_destroy(struct ia_css_pipeline_stage *stage)
503 {
504 	unsigned int i;
505 
506 	for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) {
507 		if (stage->out_frame_allocated[i]) {
508 			ia_css_frame_free(stage->args.out_frame[i]);
509 			stage->args.out_frame[i] = NULL;
510 		}
511 	}
512 	if (stage->vf_frame_allocated) {
513 		ia_css_frame_free(stage->args.out_vf_frame);
514 		stage->args.out_vf_frame = NULL;
515 	}
516 	kvfree(stage);
517 }
518 
519 static void pipeline_init_sp_thread_map(void)
520 {
521 	unsigned int i;
522 
523 	for (i = 1; i < SH_CSS_MAX_SP_THREADS; i++)
524 		pipeline_sp_thread_list[i] = PIPELINE_SP_THREAD_EMPTY_TOKEN;
525 
526 	for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++)
527 		pipeline_num_to_sp_thread_map[i] = PIPELINE_NUM_UNMAPPED;
528 }
529 
530 static void pipeline_map_num_to_sp_thread(unsigned int pipe_num)
531 {
532 	unsigned int i;
533 	bool found_sp_thread = false;
534 
535 	/* pipe is not mapped to any thread */
536 	assert(pipeline_num_to_sp_thread_map[pipe_num]
537 	       == (unsigned int)PIPELINE_NUM_UNMAPPED);
538 
539 	for (i = 0; i < SH_CSS_MAX_SP_THREADS; i++) {
540 		if (pipeline_sp_thread_list[i] ==
541 		    PIPELINE_SP_THREAD_EMPTY_TOKEN) {
542 			pipeline_sp_thread_list[i] =
543 			    PIPELINE_SP_THREAD_RESERVED_TOKEN;
544 			pipeline_num_to_sp_thread_map[pipe_num] = i;
545 			found_sp_thread = true;
546 			break;
547 		}
548 	}
549 
550 	/* Make sure a mapping is found */
551 	/* I could do:
552 		assert(i < SH_CSS_MAX_SP_THREADS);
553 
554 		But the below is more descriptive.
555 	*/
556 	assert(found_sp_thread);
557 }
558 
559 static void pipeline_unmap_num_to_sp_thread(unsigned int pipe_num)
560 {
561 	unsigned int thread_id;
562 
563 	assert(pipeline_num_to_sp_thread_map[pipe_num]
564 	       != (unsigned int)PIPELINE_NUM_UNMAPPED);
565 
566 	thread_id = pipeline_num_to_sp_thread_map[pipe_num];
567 	pipeline_num_to_sp_thread_map[pipe_num] = PIPELINE_NUM_UNMAPPED;
568 	pipeline_sp_thread_list[thread_id] = PIPELINE_SP_THREAD_EMPTY_TOKEN;
569 }
570 
571 static int pipeline_stage_create(
572     struct ia_css_pipeline_stage_desc *stage_desc,
573     struct ia_css_pipeline_stage **new_stage)
574 {
575 	int err = 0;
576 	struct ia_css_pipeline_stage *stage = NULL;
577 	struct ia_css_binary *binary;
578 	struct ia_css_frame *vf_frame;
579 	struct ia_css_frame *out_frame[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
580 	const struct ia_css_fw_info *firmware;
581 	unsigned int i;
582 
583 	/* Verify input parameters*/
584 	if (!(stage_desc->in_frame) && !(stage_desc->firmware)
585 	    && (stage_desc->binary) && !(stage_desc->binary->online)) {
586 		err = -EINVAL;
587 		goto ERR;
588 	}
589 
590 	binary = stage_desc->binary;
591 	firmware = stage_desc->firmware;
592 	vf_frame = stage_desc->vf_frame;
593 	for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) {
594 		out_frame[i] = stage_desc->out_frame[i];
595 	}
596 
597 	stage = kvzalloc(sizeof(*stage), GFP_KERNEL);
598 	if (!stage) {
599 		err = -ENOMEM;
600 		goto ERR;
601 	}
602 
603 	if (firmware) {
604 		stage->binary = NULL;
605 		stage->binary_info =
606 		    (struct ia_css_binary_info *)&firmware->info.isp;
607 	} else {
608 		stage->binary = binary;
609 		if (binary)
610 			stage->binary_info =
611 			    (struct ia_css_binary_info *)binary->info;
612 		else
613 			stage->binary_info = NULL;
614 	}
615 
616 	stage->firmware = firmware;
617 	stage->sp_func = stage_desc->sp_func;
618 	stage->max_input_width = stage_desc->max_input_width;
619 	stage->mode = stage_desc->mode;
620 	for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
621 		stage->out_frame_allocated[i] = false;
622 	stage->vf_frame_allocated = false;
623 	stage->next = NULL;
624 	sh_css_binary_args_reset(&stage->args);
625 
626 	for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) {
627 		if (!(out_frame[i]) && (binary)
628 		    && (binary->out_frame_info[i].res.width)) {
629 			err = ia_css_frame_allocate_from_info(&out_frame[i],
630 							      &binary->out_frame_info[i]);
631 			if (err)
632 				goto ERR;
633 			stage->out_frame_allocated[i] = true;
634 		}
635 	}
636 	/* VF frame is not needed in case of need_pp
637 	   However, the capture binary needs a vf frame to write to.
638 	 */
639 	if (!vf_frame) {
640 		if ((binary && binary->vf_frame_info.res.width) ||
641 		    (firmware && firmware->info.isp.sp.enable.vf_veceven)
642 		   ) {
643 			err = ia_css_frame_allocate_from_info(&vf_frame,
644 							      &binary->vf_frame_info);
645 			if (err)
646 				goto ERR;
647 			stage->vf_frame_allocated = true;
648 		}
649 	} else if (vf_frame && binary && binary->vf_frame_info.res.width
650 		   && !firmware) {
651 		/* only mark as allocated if buffer pointer available */
652 		if (vf_frame->data != mmgr_NULL)
653 			stage->vf_frame_allocated = true;
654 	}
655 
656 	stage->args.in_frame = stage_desc->in_frame;
657 	for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
658 		stage->args.out_frame[i] = out_frame[i];
659 	stage->args.out_vf_frame = vf_frame;
660 	*new_stage = stage;
661 	return err;
662 ERR:
663 	if (stage)
664 		pipeline_stage_destroy(stage);
665 	return err;
666 }
667 
668 static const struct ia_css_frame ia_css_default_frame = DEFAULT_FRAME;
669 
670 static void pipeline_init_defaults(
671     struct ia_css_pipeline *pipeline,
672     enum ia_css_pipe_id pipe_id,
673     unsigned int pipe_num,
674     unsigned int dvs_frame_delay)
675 {
676 	unsigned int i;
677 
678 	pipeline->pipe_id = pipe_id;
679 	pipeline->stages = NULL;
680 	pipeline->stop_requested = false;
681 	pipeline->current_stage = NULL;
682 
683 	memcpy(&pipeline->in_frame, &ia_css_default_frame,
684 	       sizeof(ia_css_default_frame));
685 
686 	for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
687 		memcpy(&pipeline->out_frame[i], &ia_css_default_frame,
688 		       sizeof(ia_css_default_frame));
689 		memcpy(&pipeline->vf_frame[i], &ia_css_default_frame,
690 		       sizeof(ia_css_default_frame));
691 	}
692 	pipeline->num_execs = -1;
693 	pipeline->acquire_isp_each_stage = true;
694 	pipeline->pipe_num = (uint8_t)pipe_num;
695 	pipeline->dvs_frame_delay = dvs_frame_delay;
696 }
697 
698 static void ia_css_pipeline_set_zoom_stage(struct ia_css_pipeline *pipeline)
699 {
700 	struct ia_css_pipeline_stage *stage = NULL;
701 	int err = 0;
702 
703 	assert(pipeline);
704 	if (pipeline->pipe_id == IA_CSS_PIPE_ID_PREVIEW) {
705 		/* in preview pipeline, vf_pp stage should do zoom */
706 		err = ia_css_pipeline_get_stage(pipeline, IA_CSS_BINARY_MODE_VF_PP, &stage);
707 		if (!err)
708 			stage->enable_zoom = true;
709 	} else if (pipeline->pipe_id == IA_CSS_PIPE_ID_CAPTURE) {
710 		/* in capture pipeline, capture_pp stage should do zoom */
711 		err = ia_css_pipeline_get_stage(pipeline, IA_CSS_BINARY_MODE_CAPTURE_PP,
712 						&stage);
713 		if (!err)
714 			stage->enable_zoom = true;
715 	} else if (pipeline->pipe_id == IA_CSS_PIPE_ID_VIDEO) {
716 		/* in video pipeline, video stage should do zoom */
717 		err = ia_css_pipeline_get_stage(pipeline, IA_CSS_BINARY_MODE_VIDEO, &stage);
718 		if (!err)
719 			stage->enable_zoom = true;
720 	} else if (pipeline->pipe_id == IA_CSS_PIPE_ID_YUVPP) {
721 		/* in yuvpp pipeline, first yuv_scaler stage should do zoom */
722 		err = ia_css_pipeline_get_stage(pipeline, IA_CSS_BINARY_MODE_CAPTURE_PP,
723 						&stage);
724 		if (!err)
725 			stage->enable_zoom = true;
726 	}
727 }
728 
729 static void
730 ia_css_pipeline_configure_inout_port(struct ia_css_pipeline *me,
731 				     bool continuous)
732 {
733 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
734 			    "ia_css_pipeline_configure_inout_port() enter: pipe_id(%d) continuous(%d)\n",
735 			    me->pipe_id, continuous);
736 	switch (me->pipe_id) {
737 	case IA_CSS_PIPE_ID_PREVIEW:
738 	case IA_CSS_PIPE_ID_VIDEO:
739 		SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
740 					    (uint8_t)SH_CSS_PORT_INPUT,
741 					    (uint8_t)(continuous ? SH_CSS_COPYSINK_TYPE : SH_CSS_HOST_TYPE), 1);
742 		SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
743 					    (uint8_t)SH_CSS_PORT_OUTPUT,
744 					    (uint8_t)SH_CSS_HOST_TYPE, 1);
745 		break;
746 	case IA_CSS_PIPE_ID_COPY: /*Copy pipe ports configured to "offline" mode*/
747 		SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
748 					    (uint8_t)SH_CSS_PORT_INPUT,
749 					    (uint8_t)SH_CSS_HOST_TYPE, 1);
750 		if (continuous) {
751 			SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
752 						    (uint8_t)SH_CSS_PORT_OUTPUT,
753 						    (uint8_t)SH_CSS_COPYSINK_TYPE, 1);
754 			SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
755 						    (uint8_t)SH_CSS_PORT_OUTPUT,
756 						    (uint8_t)SH_CSS_TAGGERSINK_TYPE, 1);
757 		} else {
758 			SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
759 						    (uint8_t)SH_CSS_PORT_OUTPUT,
760 						    (uint8_t)SH_CSS_HOST_TYPE, 1);
761 		}
762 		break;
763 	case IA_CSS_PIPE_ID_CAPTURE:
764 		SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
765 					    (uint8_t)SH_CSS_PORT_INPUT,
766 					    (uint8_t)(continuous ? SH_CSS_TAGGERSINK_TYPE : SH_CSS_HOST_TYPE),
767 					    1);
768 		SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
769 					    (uint8_t)SH_CSS_PORT_OUTPUT,
770 					    (uint8_t)SH_CSS_HOST_TYPE, 1);
771 		break;
772 	case IA_CSS_PIPE_ID_YUVPP:
773 		SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
774 					    (uint8_t)SH_CSS_PORT_INPUT,
775 					    (uint8_t)(SH_CSS_HOST_TYPE), 1);
776 		SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
777 					    (uint8_t)SH_CSS_PORT_OUTPUT,
778 					    (uint8_t)SH_CSS_HOST_TYPE, 1);
779 		break;
780 	case IA_CSS_PIPE_ID_ACC:
781 		SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
782 					    (uint8_t)SH_CSS_PORT_INPUT,
783 					    (uint8_t)SH_CSS_HOST_TYPE, 1);
784 		SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
785 					    (uint8_t)SH_CSS_PORT_OUTPUT,
786 					    (uint8_t)SH_CSS_HOST_TYPE, 1);
787 		break;
788 	default:
789 		break;
790 	}
791 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
792 			    "ia_css_pipeline_configure_inout_port() leave: inout_port_config(%x)\n",
793 			    me->inout_port_config);
794 }
795