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 
457 #if defined(ISP2401)
ia_css_pipeline_get_pipe_io_status(void)458 struct sh_css_sp_pipeline_io_status *ia_css_pipeline_get_pipe_io_status(void)
459 {
460 	return(&sh_css_sp_group.pipe_io_status);
461 }
462 #endif
463 
ia_css_pipeline_is_mapped(unsigned int key)464 bool ia_css_pipeline_is_mapped(unsigned int key)
465 {
466 	bool ret = false;
467 
468 	IA_CSS_ENTER_PRIVATE("key = %d", key);
469 
470 	if ((key >= IA_CSS_PIPELINE_NUM_MAX) || (key >= IA_CSS_PIPE_ID_NUM)) {
471 		IA_CSS_ERROR("Invalid key!!");
472 		IA_CSS_LEAVE_PRIVATE("return = %d", false);
473 		return false;
474 	}
475 
476 	ret = (bool)(pipeline_num_to_sp_thread_map[key] != (unsigned int)
477 		     PIPELINE_NUM_UNMAPPED);
478 
479 	IA_CSS_LEAVE_PRIVATE("return = %d", ret);
480 	return ret;
481 }
482 
483 /*******************************************************
484 *** Static functions
485 ********************************************************/
486 
487 /* Pipeline:
488  * To organize the several different binaries for each type of mode,
489  * we use a pipeline. A pipeline contains a number of stages, each with
490  * their own binary and frame pointers.
491  * When stages are added to a pipeline, output frames that are not passed
492  * from outside are automatically allocated.
493  * When input frames are not passed from outside, each stage will use the
494  * output frame of the previous stage as input (the full resolution output,
495  * not the viewfinder output).
496  * Pipelines must be cleaned and re-created when settings of the binaries
497  * change.
498  */
pipeline_stage_destroy(struct ia_css_pipeline_stage * stage)499 static void pipeline_stage_destroy(struct ia_css_pipeline_stage *stage)
500 {
501 	unsigned int i;
502 
503 	for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) {
504 		if (stage->out_frame_allocated[i]) {
505 			ia_css_frame_free(stage->args.out_frame[i]);
506 			stage->args.out_frame[i] = NULL;
507 		}
508 	}
509 	if (stage->vf_frame_allocated) {
510 		ia_css_frame_free(stage->args.out_vf_frame);
511 		stage->args.out_vf_frame = NULL;
512 	}
513 	kvfree(stage);
514 }
515 
pipeline_init_sp_thread_map(void)516 static void pipeline_init_sp_thread_map(void)
517 {
518 	unsigned int i;
519 
520 	for (i = 1; i < SH_CSS_MAX_SP_THREADS; i++)
521 		pipeline_sp_thread_list[i] = PIPELINE_SP_THREAD_EMPTY_TOKEN;
522 
523 	for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++)
524 		pipeline_num_to_sp_thread_map[i] = PIPELINE_NUM_UNMAPPED;
525 }
526 
pipeline_map_num_to_sp_thread(unsigned int pipe_num)527 static void pipeline_map_num_to_sp_thread(unsigned int pipe_num)
528 {
529 	unsigned int i;
530 	bool found_sp_thread = false;
531 
532 	/* pipe is not mapped to any thread */
533 	assert(pipeline_num_to_sp_thread_map[pipe_num]
534 	       == (unsigned int)PIPELINE_NUM_UNMAPPED);
535 
536 	for (i = 0; i < SH_CSS_MAX_SP_THREADS; i++) {
537 		if (pipeline_sp_thread_list[i] ==
538 		    PIPELINE_SP_THREAD_EMPTY_TOKEN) {
539 			pipeline_sp_thread_list[i] =
540 			    PIPELINE_SP_THREAD_RESERVED_TOKEN;
541 			pipeline_num_to_sp_thread_map[pipe_num] = i;
542 			found_sp_thread = true;
543 			break;
544 		}
545 	}
546 
547 	/* Make sure a mapping is found */
548 	/* I could do:
549 		assert(i < SH_CSS_MAX_SP_THREADS);
550 
551 		But the below is more descriptive.
552 	*/
553 	assert(found_sp_thread);
554 }
555 
pipeline_unmap_num_to_sp_thread(unsigned int pipe_num)556 static void pipeline_unmap_num_to_sp_thread(unsigned int pipe_num)
557 {
558 	unsigned int thread_id;
559 
560 	assert(pipeline_num_to_sp_thread_map[pipe_num]
561 	       != (unsigned int)PIPELINE_NUM_UNMAPPED);
562 
563 	thread_id = pipeline_num_to_sp_thread_map[pipe_num];
564 	pipeline_num_to_sp_thread_map[pipe_num] = PIPELINE_NUM_UNMAPPED;
565 	pipeline_sp_thread_list[thread_id] = PIPELINE_SP_THREAD_EMPTY_TOKEN;
566 }
567 
pipeline_stage_create(struct ia_css_pipeline_stage_desc * stage_desc,struct ia_css_pipeline_stage ** new_stage)568 static int pipeline_stage_create(
569     struct ia_css_pipeline_stage_desc *stage_desc,
570     struct ia_css_pipeline_stage **new_stage)
571 {
572 	int err = 0;
573 	struct ia_css_pipeline_stage *stage = NULL;
574 	struct ia_css_binary *binary;
575 	struct ia_css_frame *vf_frame;
576 	struct ia_css_frame *out_frame[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
577 	const struct ia_css_fw_info *firmware;
578 	unsigned int i;
579 
580 	/* Verify input parameters*/
581 	if (!(stage_desc->in_frame) && !(stage_desc->firmware)
582 	    && (stage_desc->binary) && !(stage_desc->binary->online)) {
583 		err = -EINVAL;
584 		goto ERR;
585 	}
586 
587 	binary = stage_desc->binary;
588 	firmware = stage_desc->firmware;
589 	vf_frame = stage_desc->vf_frame;
590 	for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) {
591 		out_frame[i] = stage_desc->out_frame[i];
592 	}
593 
594 	stage = kvzalloc(sizeof(*stage), GFP_KERNEL);
595 	if (!stage) {
596 		err = -ENOMEM;
597 		goto ERR;
598 	}
599 
600 	if (firmware) {
601 		stage->binary = NULL;
602 		stage->binary_info =
603 		    (struct ia_css_binary_info *)&firmware->info.isp;
604 	} else {
605 		stage->binary = binary;
606 		if (binary)
607 			stage->binary_info =
608 			    (struct ia_css_binary_info *)binary->info;
609 		else
610 			stage->binary_info = NULL;
611 	}
612 
613 	stage->firmware = firmware;
614 	stage->sp_func = stage_desc->sp_func;
615 	stage->max_input_width = stage_desc->max_input_width;
616 	stage->mode = stage_desc->mode;
617 	for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
618 		stage->out_frame_allocated[i] = false;
619 	stage->vf_frame_allocated = false;
620 	stage->next = NULL;
621 	sh_css_binary_args_reset(&stage->args);
622 
623 	for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) {
624 		if (!(out_frame[i]) && (binary)
625 		    && (binary->out_frame_info[i].res.width)) {
626 			err = ia_css_frame_allocate_from_info(&out_frame[i],
627 							      &binary->out_frame_info[i]);
628 			if (err)
629 				goto ERR;
630 			stage->out_frame_allocated[i] = true;
631 		}
632 	}
633 	/* VF frame is not needed in case of need_pp
634 	   However, the capture binary needs a vf frame to write to.
635 	 */
636 	if (!vf_frame) {
637 		if ((binary && binary->vf_frame_info.res.width) ||
638 		    (firmware && firmware->info.isp.sp.enable.vf_veceven)
639 		   ) {
640 			err = ia_css_frame_allocate_from_info(&vf_frame,
641 							      &binary->vf_frame_info);
642 			if (err)
643 				goto ERR;
644 			stage->vf_frame_allocated = true;
645 		}
646 	} else if (vf_frame && binary && binary->vf_frame_info.res.width
647 		   && !firmware) {
648 		/* only mark as allocated if buffer pointer available */
649 		if (vf_frame->data != mmgr_NULL)
650 			stage->vf_frame_allocated = true;
651 	}
652 
653 	stage->args.in_frame = stage_desc->in_frame;
654 	for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
655 		stage->args.out_frame[i] = out_frame[i];
656 	stage->args.out_vf_frame = vf_frame;
657 	*new_stage = stage;
658 	return err;
659 ERR:
660 	if (stage)
661 		pipeline_stage_destroy(stage);
662 	return err;
663 }
664 
665 static const struct ia_css_frame ia_css_default_frame = DEFAULT_FRAME;
666 
pipeline_init_defaults(struct ia_css_pipeline * pipeline,enum ia_css_pipe_id pipe_id,unsigned int pipe_num,unsigned int dvs_frame_delay)667 static void pipeline_init_defaults(
668     struct ia_css_pipeline *pipeline,
669     enum ia_css_pipe_id pipe_id,
670     unsigned int pipe_num,
671     unsigned int dvs_frame_delay)
672 {
673 	unsigned int i;
674 
675 	pipeline->pipe_id = pipe_id;
676 	pipeline->stages = NULL;
677 	pipeline->stop_requested = false;
678 	pipeline->current_stage = NULL;
679 
680 	memcpy(&pipeline->in_frame, &ia_css_default_frame,
681 	       sizeof(ia_css_default_frame));
682 
683 	for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
684 		memcpy(&pipeline->out_frame[i], &ia_css_default_frame,
685 		       sizeof(ia_css_default_frame));
686 		memcpy(&pipeline->vf_frame[i], &ia_css_default_frame,
687 		       sizeof(ia_css_default_frame));
688 	}
689 	pipeline->num_execs = -1;
690 	pipeline->acquire_isp_each_stage = true;
691 	pipeline->pipe_num = (uint8_t)pipe_num;
692 	pipeline->dvs_frame_delay = dvs_frame_delay;
693 }
694 
ia_css_pipeline_set_zoom_stage(struct ia_css_pipeline * pipeline)695 static void ia_css_pipeline_set_zoom_stage(struct ia_css_pipeline *pipeline)
696 {
697 	struct ia_css_pipeline_stage *stage = NULL;
698 	int err = 0;
699 
700 	assert(pipeline);
701 	if (pipeline->pipe_id == IA_CSS_PIPE_ID_PREVIEW) {
702 		/* in preview pipeline, vf_pp stage should do zoom */
703 		err = ia_css_pipeline_get_stage(pipeline, IA_CSS_BINARY_MODE_VF_PP, &stage);
704 		if (!err)
705 			stage->enable_zoom = true;
706 	} else if (pipeline->pipe_id == IA_CSS_PIPE_ID_CAPTURE) {
707 		/* in capture pipeline, capture_pp 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 	} else if (pipeline->pipe_id == IA_CSS_PIPE_ID_VIDEO) {
713 		/* in video pipeline, video stage should do zoom */
714 		err = ia_css_pipeline_get_stage(pipeline, IA_CSS_BINARY_MODE_VIDEO, &stage);
715 		if (!err)
716 			stage->enable_zoom = true;
717 	} else if (pipeline->pipe_id == IA_CSS_PIPE_ID_YUVPP) {
718 		/* in yuvpp pipeline, first yuv_scaler stage should do zoom */
719 		err = ia_css_pipeline_get_stage(pipeline, IA_CSS_BINARY_MODE_CAPTURE_PP,
720 						&stage);
721 		if (!err)
722 			stage->enable_zoom = true;
723 	}
724 }
725 
726 static void
ia_css_pipeline_configure_inout_port(struct ia_css_pipeline * me,bool continuous)727 ia_css_pipeline_configure_inout_port(struct ia_css_pipeline *me,
728 				     bool continuous)
729 {
730 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
731 			    "ia_css_pipeline_configure_inout_port() enter: pipe_id(%d) continuous(%d)\n",
732 			    me->pipe_id, continuous);
733 	switch (me->pipe_id) {
734 	case IA_CSS_PIPE_ID_PREVIEW:
735 	case IA_CSS_PIPE_ID_VIDEO:
736 		SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
737 					    (uint8_t)SH_CSS_PORT_INPUT,
738 					    (uint8_t)(continuous ? SH_CSS_COPYSINK_TYPE : SH_CSS_HOST_TYPE), 1);
739 		SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
740 					    (uint8_t)SH_CSS_PORT_OUTPUT,
741 					    (uint8_t)SH_CSS_HOST_TYPE, 1);
742 		break;
743 	case IA_CSS_PIPE_ID_COPY: /*Copy pipe ports configured to "offline" mode*/
744 		SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
745 					    (uint8_t)SH_CSS_PORT_INPUT,
746 					    (uint8_t)SH_CSS_HOST_TYPE, 1);
747 		if (continuous) {
748 			SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
749 						    (uint8_t)SH_CSS_PORT_OUTPUT,
750 						    (uint8_t)SH_CSS_COPYSINK_TYPE, 1);
751 			SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
752 						    (uint8_t)SH_CSS_PORT_OUTPUT,
753 						    (uint8_t)SH_CSS_TAGGERSINK_TYPE, 1);
754 		} else {
755 			SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
756 						    (uint8_t)SH_CSS_PORT_OUTPUT,
757 						    (uint8_t)SH_CSS_HOST_TYPE, 1);
758 		}
759 		break;
760 	case IA_CSS_PIPE_ID_CAPTURE:
761 		SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
762 					    (uint8_t)SH_CSS_PORT_INPUT,
763 					    (uint8_t)(continuous ? SH_CSS_TAGGERSINK_TYPE : SH_CSS_HOST_TYPE),
764 					    1);
765 		SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
766 					    (uint8_t)SH_CSS_PORT_OUTPUT,
767 					    (uint8_t)SH_CSS_HOST_TYPE, 1);
768 		break;
769 	case IA_CSS_PIPE_ID_YUVPP:
770 		SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
771 					    (uint8_t)SH_CSS_PORT_INPUT,
772 					    (uint8_t)(SH_CSS_HOST_TYPE), 1);
773 		SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
774 					    (uint8_t)SH_CSS_PORT_OUTPUT,
775 					    (uint8_t)SH_CSS_HOST_TYPE, 1);
776 		break;
777 	default:
778 		break;
779 	}
780 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
781 			    "ia_css_pipeline_configure_inout_port() leave: inout_port_config(%x)\n",
782 			    me->inout_port_config);
783 }
784