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