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