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