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
ia_css_pipeline_get_pipe_io_status(void)457 struct sh_css_sp_pipeline_io_status *ia_css_pipeline_get_pipe_io_status(void)
458 {
459 return(&sh_css_sp_group.pipe_io_status);
460 }
461
ia_css_pipeline_is_mapped(unsigned int key)462 bool ia_css_pipeline_is_mapped(unsigned int key)
463 {
464 bool ret = false;
465
466 IA_CSS_ENTER_PRIVATE("key = %d", key);
467
468 if ((key >= IA_CSS_PIPELINE_NUM_MAX) || (key >= IA_CSS_PIPE_ID_NUM)) {
469 IA_CSS_ERROR("Invalid key!!");
470 IA_CSS_LEAVE_PRIVATE("return = %d", false);
471 return false;
472 }
473
474 ret = (bool)(pipeline_num_to_sp_thread_map[key] != (unsigned int)
475 PIPELINE_NUM_UNMAPPED);
476
477 IA_CSS_LEAVE_PRIVATE("return = %d", ret);
478 return ret;
479 }
480
481 /*******************************************************
482 *** Static functions
483 ********************************************************/
484
485 /* Pipeline:
486 * To organize the several different binaries for each type of mode,
487 * we use a pipeline. A pipeline contains a number of stages, each with
488 * their own binary and frame pointers.
489 * When stages are added to a pipeline, output frames that are not passed
490 * from outside are automatically allocated.
491 * When input frames are not passed from outside, each stage will use the
492 * output frame of the previous stage as input (the full resolution output,
493 * not the viewfinder output).
494 * Pipelines must be cleaned and re-created when settings of the binaries
495 * change.
496 */
pipeline_stage_destroy(struct ia_css_pipeline_stage * stage)497 static void pipeline_stage_destroy(struct ia_css_pipeline_stage *stage)
498 {
499 unsigned int i;
500
501 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) {
502 if (stage->out_frame_allocated[i]) {
503 ia_css_frame_free(stage->args.out_frame[i]);
504 stage->args.out_frame[i] = NULL;
505 }
506 }
507 if (stage->vf_frame_allocated) {
508 ia_css_frame_free(stage->args.out_vf_frame);
509 stage->args.out_vf_frame = NULL;
510 }
511 kvfree(stage);
512 }
513
pipeline_init_sp_thread_map(void)514 static void pipeline_init_sp_thread_map(void)
515 {
516 unsigned int i;
517
518 for (i = 1; i < SH_CSS_MAX_SP_THREADS; i++)
519 pipeline_sp_thread_list[i] = PIPELINE_SP_THREAD_EMPTY_TOKEN;
520
521 for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++)
522 pipeline_num_to_sp_thread_map[i] = PIPELINE_NUM_UNMAPPED;
523 }
524
pipeline_map_num_to_sp_thread(unsigned int pipe_num)525 static void pipeline_map_num_to_sp_thread(unsigned int pipe_num)
526 {
527 unsigned int i;
528 bool found_sp_thread = false;
529
530 /* pipe is not mapped to any thread */
531 assert(pipeline_num_to_sp_thread_map[pipe_num]
532 == (unsigned int)PIPELINE_NUM_UNMAPPED);
533
534 for (i = 0; i < SH_CSS_MAX_SP_THREADS; i++) {
535 if (pipeline_sp_thread_list[i] ==
536 PIPELINE_SP_THREAD_EMPTY_TOKEN) {
537 pipeline_sp_thread_list[i] =
538 PIPELINE_SP_THREAD_RESERVED_TOKEN;
539 pipeline_num_to_sp_thread_map[pipe_num] = i;
540 found_sp_thread = true;
541 break;
542 }
543 }
544
545 /* Make sure a mapping is found */
546 /* I could do:
547 assert(i < SH_CSS_MAX_SP_THREADS);
548
549 But the below is more descriptive.
550 */
551 assert(found_sp_thread);
552 }
553
pipeline_unmap_num_to_sp_thread(unsigned int pipe_num)554 static void pipeline_unmap_num_to_sp_thread(unsigned int pipe_num)
555 {
556 unsigned int thread_id;
557
558 assert(pipeline_num_to_sp_thread_map[pipe_num]
559 != (unsigned int)PIPELINE_NUM_UNMAPPED);
560
561 thread_id = pipeline_num_to_sp_thread_map[pipe_num];
562 pipeline_num_to_sp_thread_map[pipe_num] = PIPELINE_NUM_UNMAPPED;
563 pipeline_sp_thread_list[thread_id] = PIPELINE_SP_THREAD_EMPTY_TOKEN;
564 }
565
pipeline_stage_create(struct ia_css_pipeline_stage_desc * stage_desc,struct ia_css_pipeline_stage ** new_stage)566 static int pipeline_stage_create(
567 struct ia_css_pipeline_stage_desc *stage_desc,
568 struct ia_css_pipeline_stage **new_stage)
569 {
570 int err = 0;
571 struct ia_css_pipeline_stage *stage = NULL;
572 struct ia_css_binary *binary;
573 struct ia_css_frame *vf_frame;
574 struct ia_css_frame *out_frame[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
575 const struct ia_css_fw_info *firmware;
576 unsigned int i;
577
578 /* Verify input parameters*/
579 if (!(stage_desc->in_frame) && !(stage_desc->firmware)
580 && (stage_desc->binary) && !(stage_desc->binary->online)) {
581 err = -EINVAL;
582 goto ERR;
583 }
584
585 binary = stage_desc->binary;
586 firmware = stage_desc->firmware;
587 vf_frame = stage_desc->vf_frame;
588 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) {
589 out_frame[i] = stage_desc->out_frame[i];
590 }
591
592 stage = kvzalloc(sizeof(*stage), GFP_KERNEL);
593 if (!stage) {
594 err = -ENOMEM;
595 goto ERR;
596 }
597
598 if (firmware) {
599 stage->binary = NULL;
600 stage->binary_info =
601 (struct ia_css_binary_info *)&firmware->info.isp;
602 } else {
603 stage->binary = binary;
604 if (binary)
605 stage->binary_info =
606 (struct ia_css_binary_info *)binary->info;
607 else
608 stage->binary_info = NULL;
609 }
610
611 stage->firmware = firmware;
612 stage->sp_func = stage_desc->sp_func;
613 stage->max_input_width = stage_desc->max_input_width;
614 stage->mode = stage_desc->mode;
615 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
616 stage->out_frame_allocated[i] = false;
617 stage->vf_frame_allocated = false;
618 stage->next = NULL;
619 sh_css_binary_args_reset(&stage->args);
620
621 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) {
622 if (!(out_frame[i]) && (binary)
623 && (binary->out_frame_info[i].res.width)) {
624 err = ia_css_frame_allocate_from_info(&out_frame[i],
625 &binary->out_frame_info[i]);
626 if (err)
627 goto ERR;
628 stage->out_frame_allocated[i] = true;
629 }
630 }
631 /* VF frame is not needed in case of need_pp
632 However, the capture binary needs a vf frame to write to.
633 */
634 if (!vf_frame) {
635 if ((binary && binary->vf_frame_info.res.width) ||
636 (firmware && firmware->info.isp.sp.enable.vf_veceven)
637 ) {
638 err = ia_css_frame_allocate_from_info(&vf_frame,
639 &binary->vf_frame_info);
640 if (err)
641 goto ERR;
642 stage->vf_frame_allocated = true;
643 }
644 } else if (vf_frame && binary && binary->vf_frame_info.res.width
645 && !firmware) {
646 /* only mark as allocated if buffer pointer available */
647 if (vf_frame->data != mmgr_NULL)
648 stage->vf_frame_allocated = true;
649 }
650
651 stage->args.in_frame = stage_desc->in_frame;
652 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
653 stage->args.out_frame[i] = out_frame[i];
654 stage->args.out_vf_frame = vf_frame;
655 *new_stage = stage;
656 return err;
657 ERR:
658 if (stage)
659 pipeline_stage_destroy(stage);
660 return err;
661 }
662
663 static const struct ia_css_frame ia_css_default_frame = DEFAULT_FRAME;
664
pipeline_init_defaults(struct ia_css_pipeline * pipeline,enum ia_css_pipe_id pipe_id,unsigned int pipe_num,unsigned int dvs_frame_delay)665 static void pipeline_init_defaults(
666 struct ia_css_pipeline *pipeline,
667 enum ia_css_pipe_id pipe_id,
668 unsigned int pipe_num,
669 unsigned int dvs_frame_delay)
670 {
671 unsigned int i;
672
673 pipeline->pipe_id = pipe_id;
674 pipeline->stages = NULL;
675 pipeline->stop_requested = false;
676 pipeline->current_stage = NULL;
677
678 memcpy(&pipeline->in_frame, &ia_css_default_frame,
679 sizeof(ia_css_default_frame));
680
681 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
682 memcpy(&pipeline->out_frame[i], &ia_css_default_frame,
683 sizeof(ia_css_default_frame));
684 memcpy(&pipeline->vf_frame[i], &ia_css_default_frame,
685 sizeof(ia_css_default_frame));
686 }
687 pipeline->num_execs = -1;
688 pipeline->acquire_isp_each_stage = true;
689 pipeline->pipe_num = (uint8_t)pipe_num;
690 pipeline->dvs_frame_delay = dvs_frame_delay;
691 }
692
ia_css_pipeline_set_zoom_stage(struct ia_css_pipeline * pipeline)693 static void ia_css_pipeline_set_zoom_stage(struct ia_css_pipeline *pipeline)
694 {
695 struct ia_css_pipeline_stage *stage = NULL;
696 int err;
697
698 assert(pipeline);
699 if (pipeline->pipe_id == IA_CSS_PIPE_ID_PREVIEW) {
700 /* in preview pipeline, vf_pp stage should do zoom */
701 err = ia_css_pipeline_get_stage(pipeline, IA_CSS_BINARY_MODE_VF_PP, &stage);
702 if (!err)
703 stage->enable_zoom = true;
704 } else if (pipeline->pipe_id == IA_CSS_PIPE_ID_CAPTURE) {
705 /* in capture pipeline, capture_pp 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 } else if (pipeline->pipe_id == IA_CSS_PIPE_ID_VIDEO) {
711 /* in video pipeline, video stage should do zoom */
712 err = ia_css_pipeline_get_stage(pipeline, IA_CSS_BINARY_MODE_VIDEO, &stage);
713 if (!err)
714 stage->enable_zoom = true;
715 } else if (pipeline->pipe_id == IA_CSS_PIPE_ID_YUVPP) {
716 /* in yuvpp pipeline, first yuv_scaler stage should do zoom */
717 err = ia_css_pipeline_get_stage(pipeline, IA_CSS_BINARY_MODE_CAPTURE_PP,
718 &stage);
719 if (!err)
720 stage->enable_zoom = true;
721 }
722 }
723
724 static void
ia_css_pipeline_configure_inout_port(struct ia_css_pipeline * me,bool continuous)725 ia_css_pipeline_configure_inout_port(struct ia_css_pipeline *me,
726 bool continuous)
727 {
728 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
729 "ia_css_pipeline_configure_inout_port() enter: pipe_id(%d) continuous(%d)\n",
730 me->pipe_id, continuous);
731 switch (me->pipe_id) {
732 case IA_CSS_PIPE_ID_PREVIEW:
733 case IA_CSS_PIPE_ID_VIDEO:
734 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
735 (uint8_t)SH_CSS_PORT_INPUT,
736 (uint8_t)(continuous ? SH_CSS_COPYSINK_TYPE : SH_CSS_HOST_TYPE), 1);
737 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
738 (uint8_t)SH_CSS_PORT_OUTPUT,
739 (uint8_t)SH_CSS_HOST_TYPE, 1);
740 break;
741 case IA_CSS_PIPE_ID_COPY: /*Copy pipe ports configured to "offline" mode*/
742 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
743 (uint8_t)SH_CSS_PORT_INPUT,
744 (uint8_t)SH_CSS_HOST_TYPE, 1);
745 if (continuous) {
746 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
747 (uint8_t)SH_CSS_PORT_OUTPUT,
748 (uint8_t)SH_CSS_COPYSINK_TYPE, 1);
749 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
750 (uint8_t)SH_CSS_PORT_OUTPUT,
751 (uint8_t)SH_CSS_TAGGERSINK_TYPE, 1);
752 } else {
753 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
754 (uint8_t)SH_CSS_PORT_OUTPUT,
755 (uint8_t)SH_CSS_HOST_TYPE, 1);
756 }
757 break;
758 case IA_CSS_PIPE_ID_CAPTURE:
759 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
760 (uint8_t)SH_CSS_PORT_INPUT,
761 (uint8_t)(continuous ? SH_CSS_TAGGERSINK_TYPE : SH_CSS_HOST_TYPE),
762 1);
763 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
764 (uint8_t)SH_CSS_PORT_OUTPUT,
765 (uint8_t)SH_CSS_HOST_TYPE, 1);
766 break;
767 case IA_CSS_PIPE_ID_YUVPP:
768 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
769 (uint8_t)SH_CSS_PORT_INPUT,
770 (uint8_t)(SH_CSS_HOST_TYPE), 1);
771 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
772 (uint8_t)SH_CSS_PORT_OUTPUT,
773 (uint8_t)SH_CSS_HOST_TYPE, 1);
774 break;
775 default:
776 break;
777 }
778 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
779 "ia_css_pipeline_configure_inout_port() leave: inout_port_config(%x)\n",
780 me->inout_port_config);
781 }
782