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 ********************************************************/
ia_css_pipeline_init(void)51 void ia_css_pipeline_init(void)
52 {
53 	pipeline_init_sp_thread_map();
54 }
55 
ia_css_pipeline_create(struct ia_css_pipeline * pipeline,enum ia_css_pipe_id pipe_id,unsigned int pipe_num,unsigned int dvs_frame_delay)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 
ia_css_pipeline_map(unsigned int pipe_num,bool map)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  */
ia_css_pipeline_destroy(struct ia_css_pipeline * pipeline)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. */
ia_css_pipeline_start(enum ia_css_pipe_id pipe_id,struct ia_css_pipeline * pipeline)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  */
ia_css_pipeline_get_sp_thread_id(unsigned int key,unsigned int * val)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 
ia_css_pipeline_dump_thread_map_info(void)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 
ia_css_pipeline_request_stop(struct ia_css_pipeline * pipeline)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 	pipeline->stop_requested = true;
202 
203 	/* Send stop event to the sp*/
204 	/* This needs improvement, stop on all the pipes available
205 	 * in the stream*/
206 	ia_css_pipeline_get_sp_thread_id(pipeline->pipe_num, &thread_id);
207 	if (!sh_css_sp_is_running()) {
208 		ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
209 				    "ia_css_pipeline_request_stop() leaving\n");
210 		/* queues are invalid */
211 		return -EBUSY;
212 	}
213 	ia_css_bufq_enqueue_psys_event(IA_CSS_PSYS_SW_EVENT_STOP_STREAM,
214 				       (uint8_t)thread_id,
215 				       0,
216 				       0);
217 	sh_css_sp_uninit_pipeline(pipeline->pipe_num);
218 
219 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
220 			    "ia_css_pipeline_request_stop() leave: return_err=%d\n",
221 			    err);
222 	return err;
223 }
224 
ia_css_pipeline_clean(struct ia_css_pipeline * pipeline)225 void ia_css_pipeline_clean(struct ia_css_pipeline *pipeline)
226 {
227 	struct ia_css_pipeline_stage *s;
228 
229 	assert(pipeline);
230 	IA_CSS_ENTER_PRIVATE("pipeline = %p", pipeline);
231 
232 	if (!pipeline) {
233 		IA_CSS_ERROR("NULL input parameter");
234 		IA_CSS_LEAVE_PRIVATE("void");
235 		return;
236 	}
237 	s = pipeline->stages;
238 
239 	while (s) {
240 		struct ia_css_pipeline_stage *next = s->next;
241 
242 		pipeline_stage_destroy(s);
243 		s = next;
244 	}
245 	pipeline_init_defaults(pipeline, pipeline->pipe_id, pipeline->pipe_num,
246 			       pipeline->dvs_frame_delay);
247 
248 	IA_CSS_LEAVE_PRIVATE("void");
249 }
250 
251 /* @brief Add a stage to pipeline.
252  *
253  * @param       pipeline      Pointer to the pipeline to be added to.
254  * @param[in]   stage_desc    The description of the stage
255  * @param[out]	stage         The successor of the stage.
256  * @return      0 or error code upon error.
257  *
258  * Add a new stage to a non-NULL pipeline.
259  * The stage consists of an ISP binary or firmware and input and
260  * output arguments.
261 */
ia_css_pipeline_create_and_add_stage(struct ia_css_pipeline * pipeline,struct ia_css_pipeline_stage_desc * stage_desc,struct ia_css_pipeline_stage ** stage)262 int ia_css_pipeline_create_and_add_stage(
263     struct ia_css_pipeline *pipeline,
264     struct ia_css_pipeline_stage_desc *stage_desc,
265     struct ia_css_pipeline_stage **stage)
266 {
267 	struct ia_css_pipeline_stage *last, *new_stage = NULL;
268 	int err;
269 
270 	/* other arguments can be NULL */
271 	assert(pipeline);
272 	assert(stage_desc);
273 	last = pipeline->stages;
274 
275 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
276 			    "ia_css_pipeline_create_and_add_stage() enter:\n");
277 	if (!stage_desc->binary && !stage_desc->firmware
278 	    && (stage_desc->sp_func == IA_CSS_PIPELINE_NO_FUNC)) {
279 		ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
280 				    "ia_css_pipeline_create_and_add_stage() done: Invalid args\n");
281 
282 		return -EINVAL;
283 	}
284 
285 	/* Find the last stage */
286 	while (last && last->next)
287 		last = last->next;
288 
289 	/* if in_frame is not set, we use the out_frame from the previous
290 	 * stage, if no previous stage, it's an error.
291 	 */
292 	if ((stage_desc->sp_func == IA_CSS_PIPELINE_NO_FUNC)
293 	    && (!stage_desc->in_frame)
294 	    && (!stage_desc->firmware)
295 	    && (!stage_desc->binary->online)) {
296 		/* Do this only for ISP stages*/
297 		if (last && last->args.out_frame[0])
298 			stage_desc->in_frame = last->args.out_frame[0];
299 
300 		if (!stage_desc->in_frame)
301 			return -EINVAL;
302 	}
303 
304 	/* Create the new stage */
305 	err = pipeline_stage_create(stage_desc, &new_stage);
306 	if (err) {
307 		ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
308 				    "ia_css_pipeline_create_and_add_stage() done: stage_create_failed\n");
309 		return err;
310 	}
311 
312 	if (last)
313 		last->next = new_stage;
314 	else
315 		pipeline->stages = new_stage;
316 
317 	/* Output the new stage */
318 	if (stage)
319 		*stage = new_stage;
320 
321 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
322 			    "ia_css_pipeline_create_and_add_stage() done:\n");
323 	return 0;
324 }
325 
ia_css_pipeline_finalize_stages(struct ia_css_pipeline * pipeline,bool continuous)326 void ia_css_pipeline_finalize_stages(struct ia_css_pipeline *pipeline,
327 				     bool continuous)
328 {
329 	unsigned int i = 0;
330 	struct ia_css_pipeline_stage *stage;
331 
332 	assert(pipeline);
333 	for (stage = pipeline->stages; stage; stage = stage->next) {
334 		stage->stage_num = i;
335 		i++;
336 	}
337 	pipeline->num_stages = i;
338 
339 	ia_css_pipeline_set_zoom_stage(pipeline);
340 	ia_css_pipeline_configure_inout_port(pipeline, continuous);
341 }
342 
ia_css_pipeline_get_stage(struct ia_css_pipeline * pipeline,int mode,struct ia_css_pipeline_stage ** stage)343 int ia_css_pipeline_get_stage(struct ia_css_pipeline *pipeline,
344 	int mode,
345 	struct ia_css_pipeline_stage **stage)
346 {
347 	struct ia_css_pipeline_stage *s;
348 
349 	assert(pipeline);
350 	assert(stage);
351 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
352 			    "ia_css_pipeline_get_stage() enter:\n");
353 	for (s = pipeline->stages; s; s = s->next) {
354 		if (s->mode == mode) {
355 			*stage = s;
356 			return 0;
357 		}
358 	}
359 	return -EINVAL;
360 }
361 
ia_css_pipeline_get_stage_from_fw(struct ia_css_pipeline * pipeline,u32 fw_handle,struct ia_css_pipeline_stage ** stage)362 int ia_css_pipeline_get_stage_from_fw(struct ia_css_pipeline
363 	*pipeline,
364 	u32 fw_handle,
365 	struct ia_css_pipeline_stage **stage)
366 {
367 	struct ia_css_pipeline_stage *s;
368 
369 	assert(pipeline);
370 	assert(stage);
371 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "%s()\n", __func__);
372 	for (s = pipeline->stages; s; s = s->next) {
373 		if ((s->firmware) && (s->firmware->handle == fw_handle)) {
374 			*stage = s;
375 			return 0;
376 		}
377 	}
378 	return -EINVAL;
379 }
380 
ia_css_pipeline_get_fw_from_stage(struct ia_css_pipeline * pipeline,u32 stage_num,uint32_t * fw_handle)381 int ia_css_pipeline_get_fw_from_stage(struct ia_css_pipeline
382 	*pipeline,
383 	u32 stage_num,
384 	uint32_t *fw_handle)
385 {
386 	struct ia_css_pipeline_stage *s;
387 
388 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "%s()\n", __func__);
389 	if ((!pipeline) || (!fw_handle))
390 		return -EINVAL;
391 
392 	for (s = pipeline->stages; s; s = s->next) {
393 		if ((s->stage_num == stage_num) && (s->firmware)) {
394 			*fw_handle = s->firmware->handle;
395 			return 0;
396 		}
397 	}
398 	return -EINVAL;
399 }
400 
ia_css_pipeline_get_output_stage(struct ia_css_pipeline * pipeline,int mode,struct ia_css_pipeline_stage ** stage)401 int ia_css_pipeline_get_output_stage(
402     struct ia_css_pipeline *pipeline,
403     int mode,
404     struct ia_css_pipeline_stage **stage)
405 {
406 	struct ia_css_pipeline_stage *s;
407 
408 	assert(pipeline);
409 	assert(stage);
410 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
411 			    "ia_css_pipeline_get_output_stage() enter:\n");
412 
413 	*stage = NULL;
414 	/* First find acceleration firmware at end of pipe */
415 	for (s = pipeline->stages; s; s = s->next) {
416 		if (s->firmware && s->mode == mode &&
417 		    s->firmware->info.isp.sp.enable.output)
418 			*stage = s;
419 	}
420 	if (*stage)
421 		return 0;
422 	/* If no firmware, find binary in pipe */
423 	return ia_css_pipeline_get_stage(pipeline, mode, stage);
424 }
425 
ia_css_pipeline_has_stopped(struct ia_css_pipeline * pipeline)426 bool ia_css_pipeline_has_stopped(struct ia_css_pipeline *pipeline)
427 {
428 	/* Android compilation files if made an local variable
429 	stack size on android is limited to 2k and this structure
430 	is around 2.5K, in place of static malloc can be done but
431 	if this call is made too often it will lead to fragment memory
432 	versus a fixed allocation */
433 	static struct sh_css_sp_group sp_group;
434 	unsigned int thread_id;
435 	const struct ia_css_fw_info *fw;
436 	unsigned int HIVE_ADDR_sp_group;
437 
438 	fw = &sh_css_sp_fw;
439 	HIVE_ADDR_sp_group = fw->info.sp.group;
440 
441 	ia_css_pipeline_get_sp_thread_id(pipeline->pipe_num, &thread_id);
442 	sp_dmem_load(SP0_ID,
443 		     (unsigned int)sp_address_of(sp_group),
444 		     &sp_group, sizeof(struct sh_css_sp_group));
445 	return sp_group.pipe[thread_id].num_stages == 0;
446 }
447 
ia_css_pipeline_get_pipe_io_status(void)448 struct sh_css_sp_pipeline_io_status *ia_css_pipeline_get_pipe_io_status(void)
449 {
450 	return(&sh_css_sp_group.pipe_io_status);
451 }
452 
ia_css_pipeline_is_mapped(unsigned int key)453 bool ia_css_pipeline_is_mapped(unsigned int key)
454 {
455 	bool ret = false;
456 
457 	IA_CSS_ENTER_PRIVATE("key = %d", key);
458 
459 	if ((key >= IA_CSS_PIPELINE_NUM_MAX) || (key >= IA_CSS_PIPE_ID_NUM)) {
460 		IA_CSS_ERROR("Invalid key!!");
461 		IA_CSS_LEAVE_PRIVATE("return = %d", false);
462 		return false;
463 	}
464 
465 	ret = (bool)(pipeline_num_to_sp_thread_map[key] != (unsigned int)
466 		     PIPELINE_NUM_UNMAPPED);
467 
468 	IA_CSS_LEAVE_PRIVATE("return = %d", ret);
469 	return ret;
470 }
471 
472 /*******************************************************
473 *** Static functions
474 ********************************************************/
475 
476 /* Pipeline:
477  * To organize the several different binaries for each type of mode,
478  * we use a pipeline. A pipeline contains a number of stages, each with
479  * their own binary and frame pointers.
480  * When stages are added to a pipeline, output frames that are not passed
481  * from outside are automatically allocated.
482  * When input frames are not passed from outside, each stage will use the
483  * output frame of the previous stage as input (the full resolution output,
484  * not the viewfinder output).
485  * Pipelines must be cleaned and re-created when settings of the binaries
486  * change.
487  */
pipeline_stage_destroy(struct ia_css_pipeline_stage * stage)488 static void pipeline_stage_destroy(struct ia_css_pipeline_stage *stage)
489 {
490 	unsigned int i;
491 
492 	for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) {
493 		if (stage->out_frame_allocated[i]) {
494 			ia_css_frame_free(stage->args.out_frame[i]);
495 			stage->args.out_frame[i] = NULL;
496 		}
497 	}
498 	if (stage->vf_frame_allocated) {
499 		ia_css_frame_free(stage->args.out_vf_frame);
500 		stage->args.out_vf_frame = NULL;
501 	}
502 	kvfree(stage);
503 }
504 
pipeline_init_sp_thread_map(void)505 static void pipeline_init_sp_thread_map(void)
506 {
507 	unsigned int i;
508 
509 	for (i = 1; i < SH_CSS_MAX_SP_THREADS; i++)
510 		pipeline_sp_thread_list[i] = PIPELINE_SP_THREAD_EMPTY_TOKEN;
511 
512 	for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++)
513 		pipeline_num_to_sp_thread_map[i] = PIPELINE_NUM_UNMAPPED;
514 }
515 
pipeline_map_num_to_sp_thread(unsigned int pipe_num)516 static void pipeline_map_num_to_sp_thread(unsigned int pipe_num)
517 {
518 	unsigned int i;
519 	bool found_sp_thread = false;
520 
521 	/* pipe is not mapped to any thread */
522 	assert(pipeline_num_to_sp_thread_map[pipe_num]
523 	       == (unsigned int)PIPELINE_NUM_UNMAPPED);
524 
525 	for (i = 0; i < SH_CSS_MAX_SP_THREADS; i++) {
526 		if (pipeline_sp_thread_list[i] ==
527 		    PIPELINE_SP_THREAD_EMPTY_TOKEN) {
528 			pipeline_sp_thread_list[i] =
529 			    PIPELINE_SP_THREAD_RESERVED_TOKEN;
530 			pipeline_num_to_sp_thread_map[pipe_num] = i;
531 			found_sp_thread = true;
532 			break;
533 		}
534 	}
535 
536 	/* Make sure a mapping is found */
537 	/* I could do:
538 		assert(i < SH_CSS_MAX_SP_THREADS);
539 
540 		But the below is more descriptive.
541 	*/
542 	assert(found_sp_thread);
543 }
544 
pipeline_unmap_num_to_sp_thread(unsigned int pipe_num)545 static void pipeline_unmap_num_to_sp_thread(unsigned int pipe_num)
546 {
547 	unsigned int thread_id;
548 
549 	assert(pipeline_num_to_sp_thread_map[pipe_num]
550 	       != (unsigned int)PIPELINE_NUM_UNMAPPED);
551 
552 	thread_id = pipeline_num_to_sp_thread_map[pipe_num];
553 	pipeline_num_to_sp_thread_map[pipe_num] = PIPELINE_NUM_UNMAPPED;
554 	pipeline_sp_thread_list[thread_id] = PIPELINE_SP_THREAD_EMPTY_TOKEN;
555 }
556 
pipeline_stage_create(struct ia_css_pipeline_stage_desc * stage_desc,struct ia_css_pipeline_stage ** new_stage)557 static int pipeline_stage_create(
558     struct ia_css_pipeline_stage_desc *stage_desc,
559     struct ia_css_pipeline_stage **new_stage)
560 {
561 	int err = 0;
562 	struct ia_css_pipeline_stage *stage = NULL;
563 	struct ia_css_binary *binary;
564 	struct ia_css_frame *vf_frame;
565 	struct ia_css_frame *out_frame[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
566 	const struct ia_css_fw_info *firmware;
567 	unsigned int i;
568 
569 	/* Verify input parameters*/
570 	if (!(stage_desc->in_frame) && !(stage_desc->firmware)
571 	    && (stage_desc->binary) && !(stage_desc->binary->online)) {
572 		err = -EINVAL;
573 		goto ERR;
574 	}
575 
576 	binary = stage_desc->binary;
577 	firmware = stage_desc->firmware;
578 	vf_frame = stage_desc->vf_frame;
579 	for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) {
580 		out_frame[i] = stage_desc->out_frame[i];
581 	}
582 
583 	stage = kvzalloc(sizeof(*stage), GFP_KERNEL);
584 	if (!stage) {
585 		err = -ENOMEM;
586 		goto ERR;
587 	}
588 
589 	if (firmware) {
590 		stage->binary = NULL;
591 		stage->binary_info =
592 		    (struct ia_css_binary_info *)&firmware->info.isp;
593 	} else {
594 		stage->binary = binary;
595 		if (binary)
596 			stage->binary_info =
597 			    (struct ia_css_binary_info *)binary->info;
598 		else
599 			stage->binary_info = NULL;
600 	}
601 
602 	stage->firmware = firmware;
603 	stage->sp_func = stage_desc->sp_func;
604 	stage->max_input_width = stage_desc->max_input_width;
605 	stage->mode = stage_desc->mode;
606 	for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
607 		stage->out_frame_allocated[i] = false;
608 	stage->vf_frame_allocated = false;
609 	stage->next = NULL;
610 	sh_css_binary_args_reset(&stage->args);
611 
612 	for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) {
613 		if (!(out_frame[i]) && (binary)
614 		    && (binary->out_frame_info[i].res.width)) {
615 			err = ia_css_frame_allocate_from_info(&out_frame[i],
616 							      &binary->out_frame_info[i]);
617 			if (err)
618 				goto ERR;
619 			stage->out_frame_allocated[i] = true;
620 		}
621 	}
622 	/* VF frame is not needed in case of need_pp
623 	   However, the capture binary needs a vf frame to write to.
624 	 */
625 	if (!vf_frame) {
626 		if ((binary && binary->vf_frame_info.res.width) ||
627 		    (firmware && firmware->info.isp.sp.enable.vf_veceven)
628 		   ) {
629 			err = ia_css_frame_allocate_from_info(&vf_frame,
630 							      &binary->vf_frame_info);
631 			if (err)
632 				goto ERR;
633 			stage->vf_frame_allocated = true;
634 		}
635 	} else if (vf_frame && binary && binary->vf_frame_info.res.width
636 		   && !firmware) {
637 		/* only mark as allocated if buffer pointer available */
638 		if (vf_frame->data != mmgr_NULL)
639 			stage->vf_frame_allocated = true;
640 	}
641 
642 	stage->args.in_frame = stage_desc->in_frame;
643 	for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
644 		stage->args.out_frame[i] = out_frame[i];
645 	stage->args.out_vf_frame = vf_frame;
646 	*new_stage = stage;
647 	return err;
648 ERR:
649 	if (stage)
650 		pipeline_stage_destroy(stage);
651 	return err;
652 }
653 
654 static const struct ia_css_frame ia_css_default_frame = DEFAULT_FRAME;
655 
pipeline_init_defaults(struct ia_css_pipeline * pipeline,enum ia_css_pipe_id pipe_id,unsigned int pipe_num,unsigned int dvs_frame_delay)656 static void pipeline_init_defaults(
657     struct ia_css_pipeline *pipeline,
658     enum ia_css_pipe_id pipe_id,
659     unsigned int pipe_num,
660     unsigned int dvs_frame_delay)
661 {
662 	unsigned int i;
663 
664 	pipeline->pipe_id = pipe_id;
665 	pipeline->stages = NULL;
666 	pipeline->stop_requested = false;
667 	pipeline->current_stage = NULL;
668 
669 	memcpy(&pipeline->in_frame, &ia_css_default_frame,
670 	       sizeof(ia_css_default_frame));
671 
672 	for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
673 		memcpy(&pipeline->out_frame[i], &ia_css_default_frame,
674 		       sizeof(ia_css_default_frame));
675 		memcpy(&pipeline->vf_frame[i], &ia_css_default_frame,
676 		       sizeof(ia_css_default_frame));
677 	}
678 	pipeline->num_execs = -1;
679 	pipeline->acquire_isp_each_stage = true;
680 	pipeline->pipe_num = (uint8_t)pipe_num;
681 	pipeline->dvs_frame_delay = dvs_frame_delay;
682 }
683 
ia_css_pipeline_set_zoom_stage(struct ia_css_pipeline * pipeline)684 static void ia_css_pipeline_set_zoom_stage(struct ia_css_pipeline *pipeline)
685 {
686 	struct ia_css_pipeline_stage *stage = NULL;
687 	int err;
688 
689 	assert(pipeline);
690 	if (pipeline->pipe_id == IA_CSS_PIPE_ID_PREVIEW) {
691 		/* in preview pipeline, vf_pp stage should do zoom */
692 		err = ia_css_pipeline_get_stage(pipeline, IA_CSS_BINARY_MODE_VF_PP, &stage);
693 		if (!err)
694 			stage->enable_zoom = true;
695 	} else if (pipeline->pipe_id == IA_CSS_PIPE_ID_CAPTURE) {
696 		/* in capture pipeline, capture_pp stage should do zoom */
697 		err = ia_css_pipeline_get_stage(pipeline, IA_CSS_BINARY_MODE_CAPTURE_PP,
698 						&stage);
699 		if (!err)
700 			stage->enable_zoom = true;
701 	} else if (pipeline->pipe_id == IA_CSS_PIPE_ID_VIDEO) {
702 		/* in video pipeline, video stage should do zoom */
703 		err = ia_css_pipeline_get_stage(pipeline, IA_CSS_BINARY_MODE_VIDEO, &stage);
704 		if (!err)
705 			stage->enable_zoom = true;
706 	} else if (pipeline->pipe_id == IA_CSS_PIPE_ID_YUVPP) {
707 		/* in yuvpp pipeline, first yuv_scaler stage should do zoom */
708 		err = ia_css_pipeline_get_stage(pipeline, IA_CSS_BINARY_MODE_CAPTURE_PP,
709 						&stage);
710 		if (!err)
711 			stage->enable_zoom = true;
712 	}
713 }
714 
715 static void
ia_css_pipeline_configure_inout_port(struct ia_css_pipeline * me,bool continuous)716 ia_css_pipeline_configure_inout_port(struct ia_css_pipeline *me,
717 				     bool continuous)
718 {
719 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
720 			    "ia_css_pipeline_configure_inout_port() enter: pipe_id(%d) continuous(%d)\n",
721 			    me->pipe_id, continuous);
722 	switch (me->pipe_id) {
723 	case IA_CSS_PIPE_ID_PREVIEW:
724 	case IA_CSS_PIPE_ID_VIDEO:
725 		SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
726 					    (uint8_t)SH_CSS_PORT_INPUT,
727 					    (uint8_t)(continuous ? SH_CSS_COPYSINK_TYPE : SH_CSS_HOST_TYPE), 1);
728 		SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
729 					    (uint8_t)SH_CSS_PORT_OUTPUT,
730 					    (uint8_t)SH_CSS_HOST_TYPE, 1);
731 		break;
732 	case IA_CSS_PIPE_ID_COPY: /*Copy pipe ports configured to "offline" mode*/
733 		SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
734 					    (uint8_t)SH_CSS_PORT_INPUT,
735 					    (uint8_t)SH_CSS_HOST_TYPE, 1);
736 		if (continuous) {
737 			SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
738 						    (uint8_t)SH_CSS_PORT_OUTPUT,
739 						    (uint8_t)SH_CSS_COPYSINK_TYPE, 1);
740 			SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
741 						    (uint8_t)SH_CSS_PORT_OUTPUT,
742 						    (uint8_t)SH_CSS_TAGGERSINK_TYPE, 1);
743 		} else {
744 			SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
745 						    (uint8_t)SH_CSS_PORT_OUTPUT,
746 						    (uint8_t)SH_CSS_HOST_TYPE, 1);
747 		}
748 		break;
749 	case IA_CSS_PIPE_ID_CAPTURE:
750 		SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
751 					    (uint8_t)SH_CSS_PORT_INPUT,
752 					    (uint8_t)(continuous ? SH_CSS_TAGGERSINK_TYPE : SH_CSS_HOST_TYPE),
753 					    1);
754 		SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
755 					    (uint8_t)SH_CSS_PORT_OUTPUT,
756 					    (uint8_t)SH_CSS_HOST_TYPE, 1);
757 		break;
758 	case IA_CSS_PIPE_ID_YUVPP:
759 		SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
760 					    (uint8_t)SH_CSS_PORT_INPUT,
761 					    (uint8_t)(SH_CSS_HOST_TYPE), 1);
762 		SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
763 					    (uint8_t)SH_CSS_PORT_OUTPUT,
764 					    (uint8_t)SH_CSS_HOST_TYPE, 1);
765 		break;
766 	default:
767 		break;
768 	}
769 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
770 			    "ia_css_pipeline_configure_inout_port() leave: inout_port_config(%x)\n",
771 			    me->inout_port_config);
772 }
773