media: atomisp: get rid of most checks for ISP2401 version
[linux-2.6-microblaze.git] / drivers / staging / media / atomisp / pci / runtime / pipeline / src / pipeline.c
1 /*
2  * Support for Intel Camera Imaging ISP subsystem.
3  * Copyright (c) 2010 - 2015, Intel Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  */
14
15 #include "ia_css_debug.h"
16 #include "sw_event_global.h"            /* encode_sw_event */
17 #include "sp.h"                 /* cnd_sp_irq_enable() */
18 #include "assert_support.h"
19 #include "memory_access.h"
20 #include "sh_css_sp.h"
21 #include "ia_css_pipeline.h"
22 #include "ia_css_isp_param.h"
23 #include "ia_css_bufq.h"
24
25 #define PIPELINE_NUM_UNMAPPED                   (~0U)
26 #define PIPELINE_SP_THREAD_EMPTY_TOKEN          (0x0)
27 #define PIPELINE_SP_THREAD_RESERVED_TOKEN       (0x1)
28
29 /*******************************************************
30 *** Static variables
31 ********************************************************/
32 static unsigned int pipeline_num_to_sp_thread_map[IA_CSS_PIPELINE_NUM_MAX];
33 static unsigned int pipeline_sp_thread_list[SH_CSS_MAX_SP_THREADS];
34
35 /*******************************************************
36 *** Static functions
37 ********************************************************/
38 static void pipeline_init_sp_thread_map(void);
39 static void pipeline_map_num_to_sp_thread(unsigned int pipe_num);
40 static void pipeline_unmap_num_to_sp_thread(unsigned int pipe_num);
41 static void pipeline_init_defaults(
42     struct ia_css_pipeline *pipeline,
43     enum ia_css_pipe_id pipe_id,
44     unsigned int pipe_num,
45     unsigned int dvs_frame_delay);
46
47 static void pipeline_stage_destroy(struct ia_css_pipeline_stage *stage);
48 static enum ia_css_err pipeline_stage_create(
49     struct ia_css_pipeline_stage_desc *stage_desc,
50     struct ia_css_pipeline_stage **new_stage);
51 static void ia_css_pipeline_set_zoom_stage(struct ia_css_pipeline *pipeline);
52 static void ia_css_pipeline_configure_inout_port(struct ia_css_pipeline *me,
53         bool continuous);
54
55 /*******************************************************
56 *** Public functions
57 ********************************************************/
58 void ia_css_pipeline_init(void)
59 {
60         pipeline_init_sp_thread_map();
61 }
62
63 enum ia_css_err ia_css_pipeline_create(
64     struct ia_css_pipeline *pipeline,
65     enum ia_css_pipe_id pipe_id,
66     unsigned int pipe_num,
67     unsigned int dvs_frame_delay)
68 {
69         assert(pipeline);
70         IA_CSS_ENTER_PRIVATE("pipeline = %p, pipe_id = %d, pipe_num = %d, dvs_frame_delay = %d",
71                              pipeline, pipe_id, pipe_num, dvs_frame_delay);
72         if (!pipeline) {
73                 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
74                 return IA_CSS_ERR_INVALID_ARGUMENTS;
75         }
76
77         pipeline_init_defaults(pipeline, pipe_id, pipe_num, dvs_frame_delay);
78
79         IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
80         return IA_CSS_SUCCESS;
81 }
82
83 void ia_css_pipeline_map(unsigned int pipe_num, bool map)
84 {
85         assert(pipe_num < IA_CSS_PIPELINE_NUM_MAX);
86         IA_CSS_ENTER_PRIVATE("pipe_num = %d, map = %d", pipe_num, map);
87
88         if (pipe_num >= IA_CSS_PIPELINE_NUM_MAX) {
89                 IA_CSS_ERROR("Invalid pipe number");
90                 IA_CSS_LEAVE_PRIVATE("void");
91                 return;
92         }
93         if (map)
94                 pipeline_map_num_to_sp_thread(pipe_num);
95         else
96                 pipeline_unmap_num_to_sp_thread(pipe_num);
97         IA_CSS_LEAVE_PRIVATE("void");
98 }
99
100 /* @brief destroy a pipeline
101  *
102  * @param[in] pipeline
103  * @return    None
104  *
105  */
106 void ia_css_pipeline_destroy(struct ia_css_pipeline *pipeline)
107 {
108         assert(pipeline);
109         IA_CSS_ENTER_PRIVATE("pipeline = %p", pipeline);
110
111         if (!pipeline) {
112                 IA_CSS_ERROR("NULL input parameter");
113                 IA_CSS_LEAVE_PRIVATE("void");
114                 return;
115         }
116
117         IA_CSS_LOG("pipe_num = %d", pipeline->pipe_num);
118
119         /* Free the pipeline number */
120         ia_css_pipeline_clean(pipeline);
121
122         IA_CSS_LEAVE_PRIVATE("void");
123 }
124
125 /* Run a pipeline and wait till it completes. */
126 void ia_css_pipeline_start(enum ia_css_pipe_id pipe_id,
127                            struct ia_css_pipeline *pipeline)
128 {
129         u8 pipe_num = 0;
130         unsigned int thread_id;
131
132         assert(pipeline);
133         ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
134                             "ia_css_pipeline_start() enter: pipe_id=%d, pipeline=%p\n",
135                             pipe_id, pipeline);
136         pipeline->pipe_id = pipe_id;
137         sh_css_sp_init_pipeline(pipeline, pipe_id, pipe_num,
138                                 false, false, false, true, SH_CSS_BDS_FACTOR_1_00,
139                                 SH_CSS_PIPE_CONFIG_OVRD_NO_OVRD,
140                                 IA_CSS_INPUT_MODE_MEMORY, NULL, NULL,
141 #if !defined(HAS_NO_INPUT_SYSTEM)
142                                 (enum mipi_port_id)0,
143 #endif
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  */
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
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
198 enum ia_css_err ia_css_pipeline_request_stop(struct ia_css_pipeline *pipeline)
199 {
200         enum ia_css_err err = IA_CSS_SUCCESS;
201         unsigned int thread_id;
202
203         assert(pipeline);
204
205         if (!pipeline)
206                 return IA_CSS_ERR_INVALID_ARGUMENTS;
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 IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
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
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      IA_CSS_SUCCESS 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 */
272 enum ia_css_err 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         enum ia_css_err 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 IA_CSS_ERR_INTERNAL_ERROR;
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 IA_CSS_ERR_INTERNAL_ERROR;
312         }
313
314         /* Create the new stage */
315         err = pipeline_stage_create(stage_desc, &new_stage);
316         if (err != IA_CSS_SUCCESS) {
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 IA_CSS_SUCCESS;
334 }
335
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
353 enum ia_css_err 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 IA_CSS_SUCCESS;
367                 }
368         }
369         return IA_CSS_ERR_INTERNAL_ERROR;
370 }
371
372 enum ia_css_err 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 IA_CSS_SUCCESS;
386                 }
387         }
388         return IA_CSS_ERR_INTERNAL_ERROR;
389 }
390
391 enum ia_css_err 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 IA_CSS_ERR_INVALID_ARGUMENTS;
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 IA_CSS_SUCCESS;
406                 }
407         }
408         return IA_CSS_ERR_INTERNAL_ERROR;
409 }
410
411 enum ia_css_err 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 IA_CSS_SUCCESS;
432         /* If no firmware, find binary in pipe */
433         return ia_css_pipeline_get_stage(pipeline, mode, stage);
434 }
435
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(USE_INPUT_SYSTEM_VERSION_2401)
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
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  */
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         sh_css_free(stage);
515 }
516
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
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
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
569 static enum ia_css_err pipeline_stage_create(
570     struct ia_css_pipeline_stage_desc *stage_desc,
571     struct ia_css_pipeline_stage **new_stage)
572 {
573         enum ia_css_err err = IA_CSS_SUCCESS;
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 = IA_CSS_ERR_INTERNAL_ERROR;
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 = sh_css_malloc(sizeof(*stage));
596         if (!stage) {
597                 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
598                 goto ERR;
599         }
600         memset(stage, 0, sizeof(*stage));
601
602         if (firmware) {
603                 stage->binary = NULL;
604                 stage->binary_info =
605                     (struct ia_css_binary_info *)&firmware->info.isp;
606         } else {
607                 stage->binary = binary;
608                 if (binary)
609                         stage->binary_info =
610                             (struct ia_css_binary_info *)binary->info;
611                 else
612                         stage->binary_info = NULL;
613         }
614
615         stage->firmware = firmware;
616         stage->sp_func = stage_desc->sp_func;
617         stage->max_input_width = stage_desc->max_input_width;
618         stage->mode = stage_desc->mode;
619         for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
620                 stage->out_frame_allocated[i] = false;
621         stage->vf_frame_allocated = false;
622         stage->next = NULL;
623         sh_css_binary_args_reset(&stage->args);
624
625         for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) {
626                 if (!(out_frame[i]) && (binary)
627                     && (binary->out_frame_info[i].res.width)) {
628                         err = ia_css_frame_allocate_from_info(&out_frame[i],
629                                                               &binary->out_frame_info[i]);
630                         if (err != IA_CSS_SUCCESS)
631                                 goto ERR;
632                         stage->out_frame_allocated[i] = true;
633                 }
634         }
635         /* VF frame is not needed in case of need_pp
636            However, the capture binary needs a vf frame to write to.
637          */
638         if (!vf_frame) {
639                 if ((binary && binary->vf_frame_info.res.width) ||
640                     (firmware && firmware->info.isp.sp.enable.vf_veceven)
641                    ) {
642                         err = ia_css_frame_allocate_from_info(&vf_frame,
643                                                               &binary->vf_frame_info);
644                         if (err != IA_CSS_SUCCESS)
645                                 goto ERR;
646                         stage->vf_frame_allocated = true;
647                 }
648         } else if (vf_frame && binary && binary->vf_frame_info.res.width
649                    && !firmware) {
650                 /* only mark as allocated if buffer pointer available */
651                 if (vf_frame->data != mmgr_NULL)
652                         stage->vf_frame_allocated = true;
653         }
654
655         stage->args.in_frame = stage_desc->in_frame;
656         for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
657                 stage->args.out_frame[i] = out_frame[i];
658         stage->args.out_vf_frame = vf_frame;
659         *new_stage = stage;
660         return err;
661 ERR:
662         if (stage)
663                 pipeline_stage_destroy(stage);
664         return err;
665 }
666
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         pipeline->in_frame = DEFAULT_FRAME;
680         for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
681                 pipeline->out_frame[i] = DEFAULT_FRAME;
682                 pipeline->vf_frame[i] = DEFAULT_FRAME;
683         }
684         pipeline->num_execs = -1;
685         pipeline->acquire_isp_each_stage = true;
686         pipeline->pipe_num = (uint8_t)pipe_num;
687         pipeline->dvs_frame_delay = dvs_frame_delay;
688 }
689
690 static void ia_css_pipeline_set_zoom_stage(struct ia_css_pipeline *pipeline)
691 {
692         struct ia_css_pipeline_stage *stage = NULL;
693         enum ia_css_err err = IA_CSS_SUCCESS;
694
695         assert(pipeline);
696         if (pipeline->pipe_id == IA_CSS_PIPE_ID_PREVIEW) {
697                 /* in preview pipeline, vf_pp stage should do zoom */
698                 err = ia_css_pipeline_get_stage(pipeline, IA_CSS_BINARY_MODE_VF_PP, &stage);
699                 if (err == IA_CSS_SUCCESS)
700                         stage->enable_zoom = true;
701         } else if (pipeline->pipe_id == IA_CSS_PIPE_ID_CAPTURE) {
702                 /* in capture pipeline, capture_pp stage should do zoom */
703                 err = ia_css_pipeline_get_stage(pipeline, IA_CSS_BINARY_MODE_CAPTURE_PP,
704                                                 &stage);
705                 if (err == IA_CSS_SUCCESS)
706                         stage->enable_zoom = true;
707         } else if (pipeline->pipe_id == IA_CSS_PIPE_ID_VIDEO) {
708                 /* in video pipeline, video stage should do zoom */
709                 err = ia_css_pipeline_get_stage(pipeline, IA_CSS_BINARY_MODE_VIDEO, &stage);
710                 if (err == IA_CSS_SUCCESS)
711                         stage->enable_zoom = true;
712         } else if (pipeline->pipe_id == IA_CSS_PIPE_ID_YUVPP) {
713                 /* in yuvpp pipeline, first yuv_scaler stage should do zoom */
714                 err = ia_css_pipeline_get_stage(pipeline, IA_CSS_BINARY_MODE_CAPTURE_PP,
715                                                 &stage);
716                 if (err == IA_CSS_SUCCESS)
717                         stage->enable_zoom = true;
718         }
719 }
720
721 static void
722 ia_css_pipeline_configure_inout_port(struct ia_css_pipeline *me,
723                                      bool continuous)
724 {
725         ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
726                             "ia_css_pipeline_configure_inout_port() enter: pipe_id(%d) continuous(%d)\n",
727                             me->pipe_id, continuous);
728         switch (me->pipe_id) {
729         case IA_CSS_PIPE_ID_PREVIEW:
730         case IA_CSS_PIPE_ID_VIDEO:
731                 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
732                                             (uint8_t)SH_CSS_PORT_INPUT,
733                                             (uint8_t)(continuous ? SH_CSS_COPYSINK_TYPE : SH_CSS_HOST_TYPE), 1);
734                 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
735                                             (uint8_t)SH_CSS_PORT_OUTPUT,
736                                             (uint8_t)SH_CSS_HOST_TYPE, 1);
737                 break;
738         case IA_CSS_PIPE_ID_COPY: /*Copy pipe ports configured to "offline" mode*/
739                 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
740                                             (uint8_t)SH_CSS_PORT_INPUT,
741                                             (uint8_t)SH_CSS_HOST_TYPE, 1);
742                 if (continuous) {
743                         SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
744                                                     (uint8_t)SH_CSS_PORT_OUTPUT,
745                                                     (uint8_t)SH_CSS_COPYSINK_TYPE, 1);
746                         SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
747                                                     (uint8_t)SH_CSS_PORT_OUTPUT,
748                                                     (uint8_t)SH_CSS_TAGGERSINK_TYPE, 1);
749                 } else {
750                         SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
751                                                     (uint8_t)SH_CSS_PORT_OUTPUT,
752                                                     (uint8_t)SH_CSS_HOST_TYPE, 1);
753                 }
754                 break;
755         case IA_CSS_PIPE_ID_CAPTURE:
756                 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
757                                             (uint8_t)SH_CSS_PORT_INPUT,
758                                             (uint8_t)(continuous ? SH_CSS_TAGGERSINK_TYPE : SH_CSS_HOST_TYPE),
759                                             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         case IA_CSS_PIPE_ID_YUVPP:
765                 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
766                                             (uint8_t)SH_CSS_PORT_INPUT,
767                                             (uint8_t)(SH_CSS_HOST_TYPE), 1);
768                 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
769                                             (uint8_t)SH_CSS_PORT_OUTPUT,
770                                             (uint8_t)SH_CSS_HOST_TYPE, 1);
771                 break;
772         case IA_CSS_PIPE_ID_ACC:
773                 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
774                                             (uint8_t)SH_CSS_PORT_INPUT,
775                                             (uint8_t)SH_CSS_HOST_TYPE, 1);
776                 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
777                                             (uint8_t)SH_CSS_PORT_OUTPUT,
778                                             (uint8_t)SH_CSS_HOST_TYPE, 1);
779                 break;
780         default:
781                 break;
782         }
783         ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
784                             "ia_css_pipeline_configure_inout_port() leave: inout_port_config(%x)\n",
785                             me->inout_port_config);
786 }