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