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 
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 
ia_css_pipeline_clean(struct ia_css_pipeline * pipeline)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 */
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)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 
ia_css_pipeline_finalize_stages(struct ia_css_pipeline * pipeline,bool continuous)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 
ia_css_pipeline_get_stage(struct ia_css_pipeline * pipeline,int mode,struct ia_css_pipeline_stage ** stage)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 
ia_css_pipeline_get_stage_from_fw(struct ia_css_pipeline * pipeline,u32 fw_handle,struct ia_css_pipeline_stage ** stage)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 
ia_css_pipeline_get_fw_from_stage(struct ia_css_pipeline * pipeline,u32 stage_num,uint32_t * fw_handle)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 
ia_css_pipeline_get_output_stage(struct ia_css_pipeline * pipeline,int mode,struct ia_css_pipeline_stage ** stage)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 
ia_css_pipeline_has_stopped(struct ia_css_pipeline * pipeline)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 
ia_css_pipeline_get_pipe_io_status(void)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 
ia_css_pipeline_is_mapped(unsigned int key)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  */
pipeline_stage_destroy(struct ia_css_pipeline_stage * stage)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 
pipeline_init_sp_thread_map(void)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 
pipeline_map_num_to_sp_thread(unsigned int pipe_num)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 
pipeline_unmap_num_to_sp_thread(unsigned int pipe_num)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 
pipeline_stage_create(struct ia_css_pipeline_stage_desc * stage_desc,struct ia_css_pipeline_stage ** new_stage)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 
582 	stage = kvzalloc(sizeof(*stage), GFP_KERNEL);
583 	if (!stage) {
584 		err = -ENOMEM;
585 		goto ERR;
586 	}
587 
588 	if (firmware) {
589 		stage->binary = NULL;
590 		stage->binary_info =
591 		    (struct ia_css_binary_info *)&firmware->info.isp;
592 	} else {
593 		stage->binary = binary;
594 		if (binary)
595 			stage->binary_info =
596 			    (struct ia_css_binary_info *)binary->info;
597 		else
598 			stage->binary_info = NULL;
599 	}
600 
601 	stage->firmware = firmware;
602 	stage->sp_func = stage_desc->sp_func;
603 	stage->max_input_width = stage_desc->max_input_width;
604 	stage->mode = stage_desc->mode;
605 	for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
606 		stage->out_frame_allocated[i] = false;
607 	stage->vf_frame_allocated = false;
608 	stage->next = NULL;
609 	sh_css_binary_args_reset(&stage->args);
610 
611 	for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) {
612 		if (!(out_frame[i]) && (binary)
613 		    && (binary->out_frame_info[i].res.width)) {
614 			err = ia_css_frame_allocate_from_info(&out_frame[i],
615 							      &binary->out_frame_info[i]);
616 			if (err)
617 				goto ERR;
618 			stage->out_frame_allocated[i] = true;
619 		}
620 	}
621 	/* VF frame is not needed in case of need_pp
622 	   However, the capture binary needs a vf frame to write to.
623 	 */
624 	if (!vf_frame) {
625 		if ((binary && binary->vf_frame_info.res.width) ||
626 		    (firmware && firmware->info.isp.sp.enable.vf_veceven)
627 		   ) {
628 			err = ia_css_frame_allocate_from_info(&vf_frame,
629 							      &binary->vf_frame_info);
630 			if (err)
631 				goto ERR;
632 			stage->vf_frame_allocated = true;
633 		}
634 	} else if (vf_frame && binary && binary->vf_frame_info.res.width
635 		   && !firmware) {
636 		/* only mark as allocated if buffer pointer available */
637 		if (vf_frame->data != mmgr_NULL)
638 			stage->vf_frame_allocated = true;
639 	}
640 
641 	stage->args.in_frame = stage_desc->in_frame;
642 	for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
643 		stage->args.out_frame[i] = out_frame[i];
644 	stage->args.out_vf_frame = vf_frame;
645 	*new_stage = stage;
646 	return err;
647 ERR:
648 	if (stage)
649 		pipeline_stage_destroy(stage);
650 	return err;
651 }
652 
653 static const struct ia_css_frame ia_css_default_frame = DEFAULT_FRAME;
654 
pipeline_init_defaults(struct ia_css_pipeline * pipeline,enum ia_css_pipe_id pipe_id,unsigned int pipe_num,unsigned int dvs_frame_delay)655 static void pipeline_init_defaults(
656     struct ia_css_pipeline *pipeline,
657     enum ia_css_pipe_id pipe_id,
658     unsigned int pipe_num,
659     unsigned int dvs_frame_delay)
660 {
661 	unsigned int i;
662 
663 	pipeline->pipe_id = pipe_id;
664 	pipeline->stages = NULL;
665 	pipeline->current_stage = NULL;
666 
667 	memcpy(&pipeline->in_frame, &ia_css_default_frame,
668 	       sizeof(ia_css_default_frame));
669 
670 	for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
671 		memcpy(&pipeline->out_frame[i], &ia_css_default_frame,
672 		       sizeof(ia_css_default_frame));
673 		memcpy(&pipeline->vf_frame[i], &ia_css_default_frame,
674 		       sizeof(ia_css_default_frame));
675 	}
676 	pipeline->num_execs = -1;
677 	pipeline->acquire_isp_each_stage = true;
678 	pipeline->pipe_num = (uint8_t)pipe_num;
679 	pipeline->dvs_frame_delay = dvs_frame_delay;
680 }
681 
ia_css_pipeline_set_zoom_stage(struct ia_css_pipeline * pipeline)682 static void ia_css_pipeline_set_zoom_stage(struct ia_css_pipeline *pipeline)
683 {
684 	struct ia_css_pipeline_stage *stage = NULL;
685 	int err;
686 
687 	assert(pipeline);
688 	if (pipeline->pipe_id == IA_CSS_PIPE_ID_PREVIEW) {
689 		/* in preview pipeline, vf_pp stage should do zoom */
690 		err = ia_css_pipeline_get_stage(pipeline, IA_CSS_BINARY_MODE_VF_PP, &stage);
691 		if (!err)
692 			stage->enable_zoom = true;
693 	} else if (pipeline->pipe_id == IA_CSS_PIPE_ID_CAPTURE) {
694 		/* in capture pipeline, capture_pp stage should do zoom */
695 		err = ia_css_pipeline_get_stage(pipeline, IA_CSS_BINARY_MODE_CAPTURE_PP,
696 						&stage);
697 		if (!err)
698 			stage->enable_zoom = true;
699 	} else if (pipeline->pipe_id == IA_CSS_PIPE_ID_VIDEO) {
700 		/* in video pipeline, video stage should do zoom */
701 		err = ia_css_pipeline_get_stage(pipeline, IA_CSS_BINARY_MODE_VIDEO, &stage);
702 		if (!err)
703 			stage->enable_zoom = true;
704 	} else if (pipeline->pipe_id == IA_CSS_PIPE_ID_YUVPP) {
705 		/* in yuvpp pipeline, first yuv_scaler stage should do zoom */
706 		err = ia_css_pipeline_get_stage(pipeline, IA_CSS_BINARY_MODE_CAPTURE_PP,
707 						&stage);
708 		if (!err)
709 			stage->enable_zoom = true;
710 	}
711 }
712 
713 static void
ia_css_pipeline_configure_inout_port(struct ia_css_pipeline * me,bool continuous)714 ia_css_pipeline_configure_inout_port(struct ia_css_pipeline *me,
715 				     bool continuous)
716 {
717 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
718 			    "ia_css_pipeline_configure_inout_port() enter: pipe_id(%d) continuous(%d)\n",
719 			    me->pipe_id, continuous);
720 	switch (me->pipe_id) {
721 	case IA_CSS_PIPE_ID_PREVIEW:
722 	case IA_CSS_PIPE_ID_VIDEO:
723 		SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
724 					    (uint8_t)SH_CSS_PORT_INPUT,
725 					    (uint8_t)(continuous ? SH_CSS_COPYSINK_TYPE : SH_CSS_HOST_TYPE), 1);
726 		SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
727 					    (uint8_t)SH_CSS_PORT_OUTPUT,
728 					    (uint8_t)SH_CSS_HOST_TYPE, 1);
729 		break;
730 	case IA_CSS_PIPE_ID_COPY: /*Copy pipe ports configured to "offline" mode*/
731 		SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
732 					    (uint8_t)SH_CSS_PORT_INPUT,
733 					    (uint8_t)SH_CSS_HOST_TYPE, 1);
734 		if (continuous) {
735 			SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
736 						    (uint8_t)SH_CSS_PORT_OUTPUT,
737 						    (uint8_t)SH_CSS_COPYSINK_TYPE, 1);
738 			SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
739 						    (uint8_t)SH_CSS_PORT_OUTPUT,
740 						    (uint8_t)SH_CSS_TAGGERSINK_TYPE, 1);
741 		} else {
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 		}
746 		break;
747 	case IA_CSS_PIPE_ID_CAPTURE:
748 		SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
749 					    (uint8_t)SH_CSS_PORT_INPUT,
750 					    (uint8_t)(continuous ? SH_CSS_TAGGERSINK_TYPE : SH_CSS_HOST_TYPE),
751 					    1);
752 		SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
753 					    (uint8_t)SH_CSS_PORT_OUTPUT,
754 					    (uint8_t)SH_CSS_HOST_TYPE, 1);
755 		break;
756 	case IA_CSS_PIPE_ID_YUVPP:
757 		SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
758 					    (uint8_t)SH_CSS_PORT_INPUT,
759 					    (uint8_t)(SH_CSS_HOST_TYPE), 1);
760 		SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
761 					    (uint8_t)SH_CSS_PORT_OUTPUT,
762 					    (uint8_t)SH_CSS_HOST_TYPE, 1);
763 		break;
764 	default:
765 		break;
766 	}
767 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
768 			    "ia_css_pipeline_configure_inout_port() leave: inout_port_config(%x)\n",
769 			    me->inout_port_config);
770 }
771