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