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 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 */
ia_css_pipeline_get_sp_thread_id(unsigned int key,unsigned int * val)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
ia_css_pipeline_dump_thread_map_info(void)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
ia_css_pipeline_request_stop(struct ia_css_pipeline * pipeline)198 int ia_css_pipeline_request_stop(struct ia_css_pipeline *pipeline)
199 {
200 int err = 0;
201 unsigned int thread_id;
202
203 assert(pipeline);
204
205 if (!pipeline)
206 return -EINVAL;
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 -EBUSY;
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
ia_css_pipeline_clean(struct ia_css_pipeline * pipeline)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 0 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 */
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)272 int 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 int 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 -EINVAL;
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 -EINVAL;
312 }
313
314 /* Create the new stage */
315 err = pipeline_stage_create(stage_desc, &new_stage);
316 if (err) {
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 0;
334 }
335
ia_css_pipeline_finalize_stages(struct ia_css_pipeline * pipeline,bool continuous)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
ia_css_pipeline_get_stage(struct ia_css_pipeline * pipeline,int mode,struct ia_css_pipeline_stage ** stage)353 int 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 0;
367 }
368 }
369 return -EINVAL;
370 }
371
ia_css_pipeline_get_stage_from_fw(struct ia_css_pipeline * pipeline,u32 fw_handle,struct ia_css_pipeline_stage ** stage)372 int 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 0;
386 }
387 }
388 return -EINVAL;
389 }
390
ia_css_pipeline_get_fw_from_stage(struct ia_css_pipeline * pipeline,u32 stage_num,uint32_t * fw_handle)391 int 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 -EINVAL;
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 0;
406 }
407 }
408 return -EINVAL;
409 }
410
ia_css_pipeline_get_output_stage(struct ia_css_pipeline * pipeline,int mode,struct ia_css_pipeline_stage ** stage)411 int 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 0;
432 /* If no firmware, find binary in pipe */
433 return ia_css_pipeline_get_stage(pipeline, mode, stage);
434 }
435
ia_css_pipeline_has_stopped(struct ia_css_pipeline * pipeline)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(ISP2401)
ia_css_pipeline_get_pipe_io_status(void)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
ia_css_pipeline_is_mapped(unsigned int key)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 */
pipeline_stage_destroy(struct ia_css_pipeline_stage * stage)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 kvfree(stage);
515 }
516
pipeline_init_sp_thread_map(void)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
pipeline_map_num_to_sp_thread(unsigned int pipe_num)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
pipeline_unmap_num_to_sp_thread(unsigned int pipe_num)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
pipeline_stage_create(struct ia_css_pipeline_stage_desc * stage_desc,struct ia_css_pipeline_stage ** new_stage)569 static int pipeline_stage_create(
570 struct ia_css_pipeline_stage_desc *stage_desc,
571 struct ia_css_pipeline_stage **new_stage)
572 {
573 int err = 0;
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 = -EINVAL;
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 = kvzalloc(sizeof(*stage), GFP_KERNEL);
596 if (!stage) {
597 err = -ENOMEM;
598 goto ERR;
599 }
600
601 if (firmware) {
602 stage->binary = NULL;
603 stage->binary_info =
604 (struct ia_css_binary_info *)&firmware->info.isp;
605 } else {
606 stage->binary = binary;
607 if (binary)
608 stage->binary_info =
609 (struct ia_css_binary_info *)binary->info;
610 else
611 stage->binary_info = NULL;
612 }
613
614 stage->firmware = firmware;
615 stage->sp_func = stage_desc->sp_func;
616 stage->max_input_width = stage_desc->max_input_width;
617 stage->mode = stage_desc->mode;
618 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
619 stage->out_frame_allocated[i] = false;
620 stage->vf_frame_allocated = false;
621 stage->next = NULL;
622 sh_css_binary_args_reset(&stage->args);
623
624 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) {
625 if (!(out_frame[i]) && (binary)
626 && (binary->out_frame_info[i].res.width)) {
627 err = ia_css_frame_allocate_from_info(&out_frame[i],
628 &binary->out_frame_info[i]);
629 if (err)
630 goto ERR;
631 stage->out_frame_allocated[i] = true;
632 }
633 }
634 /* VF frame is not needed in case of need_pp
635 However, the capture binary needs a vf frame to write to.
636 */
637 if (!vf_frame) {
638 if ((binary && binary->vf_frame_info.res.width) ||
639 (firmware && firmware->info.isp.sp.enable.vf_veceven)
640 ) {
641 err = ia_css_frame_allocate_from_info(&vf_frame,
642 &binary->vf_frame_info);
643 if (err)
644 goto ERR;
645 stage->vf_frame_allocated = true;
646 }
647 } else if (vf_frame && binary && binary->vf_frame_info.res.width
648 && !firmware) {
649 /* only mark as allocated if buffer pointer available */
650 if (vf_frame->data != mmgr_NULL)
651 stage->vf_frame_allocated = true;
652 }
653
654 stage->args.in_frame = stage_desc->in_frame;
655 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
656 stage->args.out_frame[i] = out_frame[i];
657 stage->args.out_vf_frame = vf_frame;
658 *new_stage = stage;
659 return err;
660 ERR:
661 if (stage)
662 pipeline_stage_destroy(stage);
663 return err;
664 }
665
666 static const struct ia_css_frame ia_css_default_frame = DEFAULT_FRAME;
667
pipeline_init_defaults(struct ia_css_pipeline * pipeline,enum ia_css_pipe_id pipe_id,unsigned int pipe_num,unsigned int dvs_frame_delay)668 static void pipeline_init_defaults(
669 struct ia_css_pipeline *pipeline,
670 enum ia_css_pipe_id pipe_id,
671 unsigned int pipe_num,
672 unsigned int dvs_frame_delay)
673 {
674 unsigned int i;
675
676 pipeline->pipe_id = pipe_id;
677 pipeline->stages = NULL;
678 pipeline->stop_requested = false;
679 pipeline->current_stage = NULL;
680
681 memcpy(&pipeline->in_frame, &ia_css_default_frame,
682 sizeof(ia_css_default_frame));
683
684 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
685 memcpy(&pipeline->out_frame[i], &ia_css_default_frame,
686 sizeof(ia_css_default_frame));
687 memcpy(&pipeline->vf_frame[i], &ia_css_default_frame,
688 sizeof(ia_css_default_frame));
689 }
690 pipeline->num_execs = -1;
691 pipeline->acquire_isp_each_stage = true;
692 pipeline->pipe_num = (uint8_t)pipe_num;
693 pipeline->dvs_frame_delay = dvs_frame_delay;
694 }
695
ia_css_pipeline_set_zoom_stage(struct ia_css_pipeline * pipeline)696 static void ia_css_pipeline_set_zoom_stage(struct ia_css_pipeline *pipeline)
697 {
698 struct ia_css_pipeline_stage *stage = NULL;
699 int err = 0;
700
701 assert(pipeline);
702 if (pipeline->pipe_id == IA_CSS_PIPE_ID_PREVIEW) {
703 /* in preview pipeline, vf_pp stage should do zoom */
704 err = ia_css_pipeline_get_stage(pipeline, IA_CSS_BINARY_MODE_VF_PP, &stage);
705 if (!err)
706 stage->enable_zoom = true;
707 } else if (pipeline->pipe_id == IA_CSS_PIPE_ID_CAPTURE) {
708 /* in capture pipeline, capture_pp stage should do zoom */
709 err = ia_css_pipeline_get_stage(pipeline, IA_CSS_BINARY_MODE_CAPTURE_PP,
710 &stage);
711 if (!err)
712 stage->enable_zoom = true;
713 } else if (pipeline->pipe_id == IA_CSS_PIPE_ID_VIDEO) {
714 /* in video pipeline, video stage should do zoom */
715 err = ia_css_pipeline_get_stage(pipeline, IA_CSS_BINARY_MODE_VIDEO, &stage);
716 if (!err)
717 stage->enable_zoom = true;
718 } else if (pipeline->pipe_id == IA_CSS_PIPE_ID_YUVPP) {
719 /* in yuvpp pipeline, first yuv_scaler stage should do zoom */
720 err = ia_css_pipeline_get_stage(pipeline, IA_CSS_BINARY_MODE_CAPTURE_PP,
721 &stage);
722 if (!err)
723 stage->enable_zoom = true;
724 }
725 }
726
727 static void
ia_css_pipeline_configure_inout_port(struct ia_css_pipeline * me,bool continuous)728 ia_css_pipeline_configure_inout_port(struct ia_css_pipeline *me,
729 bool continuous)
730 {
731 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
732 "ia_css_pipeline_configure_inout_port() enter: pipe_id(%d) continuous(%d)\n",
733 me->pipe_id, continuous);
734 switch (me->pipe_id) {
735 case IA_CSS_PIPE_ID_PREVIEW:
736 case IA_CSS_PIPE_ID_VIDEO:
737 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
738 (uint8_t)SH_CSS_PORT_INPUT,
739 (uint8_t)(continuous ? SH_CSS_COPYSINK_TYPE : SH_CSS_HOST_TYPE), 1);
740 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
741 (uint8_t)SH_CSS_PORT_OUTPUT,
742 (uint8_t)SH_CSS_HOST_TYPE, 1);
743 break;
744 case IA_CSS_PIPE_ID_COPY: /*Copy pipe ports configured to "offline" mode*/
745 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
746 (uint8_t)SH_CSS_PORT_INPUT,
747 (uint8_t)SH_CSS_HOST_TYPE, 1);
748 if (continuous) {
749 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
750 (uint8_t)SH_CSS_PORT_OUTPUT,
751 (uint8_t)SH_CSS_COPYSINK_TYPE, 1);
752 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
753 (uint8_t)SH_CSS_PORT_OUTPUT,
754 (uint8_t)SH_CSS_TAGGERSINK_TYPE, 1);
755 } else {
756 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
757 (uint8_t)SH_CSS_PORT_OUTPUT,
758 (uint8_t)SH_CSS_HOST_TYPE, 1);
759 }
760 break;
761 case IA_CSS_PIPE_ID_CAPTURE:
762 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
763 (uint8_t)SH_CSS_PORT_INPUT,
764 (uint8_t)(continuous ? SH_CSS_TAGGERSINK_TYPE : SH_CSS_HOST_TYPE),
765 1);
766 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
767 (uint8_t)SH_CSS_PORT_OUTPUT,
768 (uint8_t)SH_CSS_HOST_TYPE, 1);
769 break;
770 case IA_CSS_PIPE_ID_YUVPP:
771 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
772 (uint8_t)SH_CSS_PORT_INPUT,
773 (uint8_t)(SH_CSS_HOST_TYPE), 1);
774 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
775 (uint8_t)SH_CSS_PORT_OUTPUT,
776 (uint8_t)SH_CSS_HOST_TYPE, 1);
777 break;
778 case IA_CSS_PIPE_ID_ACC:
779 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
780 (uint8_t)SH_CSS_PORT_INPUT,
781 (uint8_t)SH_CSS_HOST_TYPE, 1);
782 SH_CSS_PIPE_PORT_CONFIG_SET(me->inout_port_config,
783 (uint8_t)SH_CSS_PORT_OUTPUT,
784 (uint8_t)SH_CSS_HOST_TYPE, 1);
785 break;
786 default:
787 break;
788 }
789 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
790 "ia_css_pipeline_configure_inout_port() leave: inout_port_config(%x)\n",
791 me->inout_port_config);
792 }
793