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