]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - drivers/staging/media/atomisp/pci/atomisp2/css2400/sh_css.c
Merge remote-tracking branches 'spi/fix/armada', 'spi/fix/atmel', 'spi/fix/doc',...
[mirror_ubuntu-hirsute-kernel.git] / drivers / staging / media / atomisp / pci / atomisp2 / css2400 / sh_css.c
CommitLineData
a49d2536
AC
1/*
2 * Support for Intel Camera Imaging ISP subsystem.
3 * Copyright (c) 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/*! \file */
da22013f
AC
16#include <linux/mm.h>
17#include <linux/slab.h>
18#include <linux/vmalloc.h>
19
a49d2536
AC
20#include "ia_css.h"
21#include "sh_css_hrt.h" /* only for file 2 MIPI */
22#include "ia_css_buffer.h"
23#include "ia_css_binary.h"
24#include "sh_css_internal.h"
25#include "sh_css_mipi.h"
26#include "sh_css_sp.h" /* sh_css_sp_group */
27#if !defined(HAS_NO_INPUT_SYSTEM)
28#include "ia_css_isys.h"
29#endif
30#include "ia_css_frame.h"
31#include "sh_css_defs.h"
32#include "sh_css_firmware.h"
33#include "sh_css_params.h"
34#include "sh_css_params_internal.h"
35#include "sh_css_param_shading.h"
36#include "ia_css_refcount.h"
37#include "ia_css_rmgr.h"
38#include "ia_css_debug.h"
39#include "ia_css_debug_pipe.h"
a49d2536
AC
40#include "ia_css_device_access.h"
41#include "device_access.h"
42#include "sh_css_legacy.h"
43#include "ia_css_pipeline.h"
44#include "ia_css_stream.h"
45#include "sh_css_stream_format.h"
46#include "ia_css_pipe.h"
47#include "ia_css_util.h"
48#include "ia_css_pipe_util.h"
49#include "ia_css_pipe_binarydesc.h"
50#include "ia_css_pipe_stagedesc.h"
51#ifdef USE_INPUT_SYSTEM_VERSION_2
52#include "ia_css_isys.h"
53#endif
54
55#include "memory_access.h"
56#include "tag.h"
57#include "assert_support.h"
58#include "math_support.h"
59#include "sw_event_global.h" /* Event IDs.*/
60#if !defined(HAS_NO_INPUT_FORMATTER)
61#include "ia_css_ifmtr.h"
62#endif
63#if !defined(HAS_NO_INPUT_SYSTEM)
64#include "input_system.h"
65#endif
66#include "mmu_device.h" /* mmu_set_page_table_base_index(), ... */
fc993494 67#include "ia_css_mmu_private.h" /* sh_css_mmu_set_page_table_base_index() */
a49d2536
AC
68#include "gdc_device.h" /* HRT_GDC_N */
69#include "dma.h" /* dma_set_max_burst_size() */
70#include "irq.h" /* virq */
71#include "sp.h" /* cnd_sp_irq_enable() */
72#include "isp.h" /* cnd_isp_irq_enable, ISP_VEC_NELEMS */
73#include "gp_device.h" /* gp_device_reg_store() */
74#define __INLINE_GPIO__
75#include "gpio.h"
76#include "timed_ctrl.h"
77#include "platform_support.h" /* hrt_sleep(), inline */
78#include "ia_css_inputfifo.h"
79#define WITH_PC_MONITORING 0
80
81#define SH_CSS_VIDEO_BUFFER_ALIGNMENT 0
82
83#if WITH_PC_MONITORING
84#define MULTIPLE_SAMPLES 1
85#define NOF_SAMPLES 60
86#include "linux/kthread.h"
87#include "linux/sched.h"
88#include "linux/delay.h"
89#include "sh_css_metrics.h"
90static int thread_alive;
91#endif /* WITH_PC_MONITORING */
92
93#include "ia_css_spctrl.h"
94#include "ia_css_version_data.h"
95#include "sh_css_struct.h"
96#include "ia_css_bufq.h"
97#include "ia_css_timer.h" /* clock_value_t */
98
99#include "isp/modes/interface/input_buf.isp.h"
100
a49d2536
AC
101/* Name of the sp program: should not be built-in */
102#define SP_PROG_NAME "sp"
a49d2536
AC
103/* Size of Refcount List */
104#define REFCOUNT_SIZE 1000
105
106/* for JPEG, we don't know the length of the image upfront,
107 * but since we support sensor upto 16MP, we take this as
108 * upper limit.
109 */
110#define JPEG_BYTES (16 * 1024 * 1024)
111
112#define STATS_ENABLED(stage) (stage && stage->binary && stage->binary->info && \
113 (stage->binary->info->sp.enable.s3a || stage->binary->info->sp.enable.dis))
114
115#define DEFAULT_PLANES { {0, 0, 0, 0} }
116
117struct sh_css my_css;
118
119int (*sh_css_printf) (const char *fmt, va_list args) = NULL;
120
121/* modes of work: stream_create and stream_destroy will update the save/restore data
122 only when in working mode, not suspend/resume
123*/
124enum ia_sh_css_modes {
125 sh_css_mode_none = 0,
126 sh_css_mode_working,
127 sh_css_mode_suspend,
128 sh_css_mode_resume
129};
130
131/* a stream seed, to save and restore the stream data.
132 the stream seed contains all the data required to "grow" the seed again after it was closed.
133*/
134struct sh_css_stream_seed {
135 struct ia_css_stream **orig_stream; /* pointer to restore the original handle */
136 struct ia_css_stream *stream; /* handle, used as ID too.*/
137 struct ia_css_stream_config stream_config; /* stream config struct */
138 int num_pipes;
139 struct ia_css_pipe *pipes[IA_CSS_PIPE_ID_NUM]; /* pipe handles */
140 struct ia_css_pipe **orig_pipes[IA_CSS_PIPE_ID_NUM]; /* pointer to restore original handle */
141 struct ia_css_pipe_config pipe_config[IA_CSS_PIPE_ID_NUM]; /* pipe config structs */
142};
143
144#define MAX_ACTIVE_STREAMS 5
145/* A global struct for save/restore to hold all the data that should sustain power-down:
146 MMU base, IRQ type, env for routines, binary loaded FW and the stream seeds.
147*/
148struct sh_css_save {
149 enum ia_sh_css_modes mode;
150 uint32_t mmu_base; /* the last mmu_base */
151 enum ia_css_irq_type irq_type;
152 struct sh_css_stream_seed stream_seeds[MAX_ACTIVE_STREAMS];
153 struct ia_css_fw *loaded_fw; /* fw struct previously loaded */
154 struct ia_css_env driver_env; /* driver-supplied env copy */
155};
156
157static bool my_css_save_initialized; /* if my_css_save was initialized */
158static struct sh_css_save my_css_save;
159
160/* pqiao NOTICE: this is for css internal buffer recycling when stopping pipeline,
161 this array is temporary and will be replaced by resource manager*/
162/* Taking the biggest Size for number of Elements */
163#define MAX_HMM_BUFFER_NUM \
164 (SH_CSS_MAX_NUM_QUEUES * (IA_CSS_NUM_ELEMS_SP2HOST_BUFFER_QUEUE + 2))
165
166struct sh_css_hmm_buffer_record {
167 bool in_use;
168 enum ia_css_buffer_type type;
169 struct ia_css_rmgr_vbuf_handle *h_vbuf;
170 hrt_address kernel_ptr;
171};
172
173static struct sh_css_hmm_buffer_record hmm_buffer_record[MAX_HMM_BUFFER_NUM];
174
175#define GPIO_FLASH_PIN_MASK (1 << HIVE_GPIO_STROBE_TRIGGER_PIN)
176
177static bool fw_explicitly_loaded = false;
178
d929fb4e 179/*
a49d2536
AC
180 * Local prototypes
181 */
182
183static enum ia_css_err
184allocate_delay_frames(struct ia_css_pipe *pipe);
185
186static enum ia_css_err
187sh_css_pipe_start(struct ia_css_stream *stream);
188
189#ifdef ISP2401
d929fb4e 190/*
a49d2536
AC
191 * @brief Stop all "ia_css_pipe" instances in the target
192 * "ia_css_stream" instance.
193 *
194 * @param[in] stream Point to the target "ia_css_stream" instance.
195 *
196 * @return
197 * - IA_CSS_SUCCESS, if the "stop" requests have been sucessfully sent out.
198 * - CSS error code, otherwise.
199 *
200 *
201 * NOTE
202 * This API sends the "stop" requests to the "ia_css_pipe"
203 * instances in the same "ia_css_stream" instance. It will
204 * return without waiting for all "ia_css_pipe" instatnces
205 * being stopped.
206 */
207static enum ia_css_err
208sh_css_pipes_stop(struct ia_css_stream *stream);
209
d929fb4e 210/*
a49d2536
AC
211 * @brief Check if all "ia_css_pipe" instances in the target
212 * "ia_css_stream" instance have stopped.
213 *
214 * @param[in] stream Point to the target "ia_css_stream" instance.
215 *
216 * @return
217 * - true, if all "ia_css_pipe" instances in the target "ia_css_stream"
218 * instance have ben stopped.
219 * - false, otherwise.
220 */
221static bool
222sh_css_pipes_have_stopped(struct ia_css_stream *stream);
223
224static enum ia_css_err
225ia_css_pipe_check_format(struct ia_css_pipe *pipe, enum ia_css_frame_format format);
226
227static enum ia_css_err
228check_pipe_resolutions(const struct ia_css_pipe *pipe);
229
230#endif
231
232static enum ia_css_err
233ia_css_pipe_load_extension(struct ia_css_pipe *pipe,
234 struct ia_css_fw_info *firmware);
235
236static void
237ia_css_pipe_unload_extension(struct ia_css_pipe *pipe,
238 struct ia_css_fw_info *firmware);
239static void
240ia_css_reset_defaults(struct sh_css* css);
241
242static void
243sh_css_init_host_sp_control_vars(void);
244
a49d2536
AC
245static enum ia_css_err set_num_primary_stages(unsigned int *num, enum ia_css_pipe_version version);
246
247static bool
248need_capture_pp(const struct ia_css_pipe *pipe);
249
250static bool
251need_yuv_scaler_stage(const struct ia_css_pipe *pipe);
252
253static enum ia_css_err ia_css_pipe_create_cas_scaler_desc_single_output(
254 struct ia_css_frame_info *cas_scaler_in_info,
255 struct ia_css_frame_info *cas_scaler_out_info,
256 struct ia_css_frame_info *cas_scaler_vf_info,
257 struct ia_css_cas_binary_descr *descr);
258
259static void ia_css_pipe_destroy_cas_scaler_desc(struct ia_css_cas_binary_descr *descr);
260
261static bool
262need_downscaling(const struct ia_css_resolution in_res,
263 const struct ia_css_resolution out_res);
264
265static bool need_capt_ldc(const struct ia_css_pipe *pipe);
266
267static enum ia_css_err
268sh_css_pipe_load_binaries(struct ia_css_pipe *pipe);
269
270static
271enum ia_css_err sh_css_pipe_get_viewfinder_frame_info(
272 struct ia_css_pipe *pipe,
273 struct ia_css_frame_info *info,
274 unsigned int idx);
275
276static enum ia_css_err
277sh_css_pipe_get_output_frame_info(struct ia_css_pipe *pipe,
278 struct ia_css_frame_info *info,
279 unsigned int idx);
280
281static enum ia_css_err
282capture_start(struct ia_css_pipe *pipe);
283
284static enum ia_css_err
285video_start(struct ia_css_pipe *pipe);
286
287static enum ia_css_err
288preview_start(struct ia_css_pipe *pipe);
289
290static enum ia_css_err
291yuvpp_start(struct ia_css_pipe *pipe);
292
293static bool copy_on_sp(struct ia_css_pipe *pipe);
294
295static enum ia_css_err
296init_vf_frameinfo_defaults(struct ia_css_pipe *pipe,
297 struct ia_css_frame *vf_frame, unsigned int idx);
298
299static enum ia_css_err
300init_in_frameinfo_memory_defaults(struct ia_css_pipe *pipe,
301 struct ia_css_frame *frame, enum ia_css_frame_format format);
302
303static enum ia_css_err
304init_out_frameinfo_defaults(struct ia_css_pipe *pipe,
305 struct ia_css_frame *out_frame, unsigned int idx);
306
307static enum ia_css_err
308sh_css_pipeline_add_acc_stage(struct ia_css_pipeline *pipeline,
309 const void *acc_fw);
310
311static enum ia_css_err
312alloc_continuous_frames(
313 struct ia_css_pipe *pipe, bool init_time);
314
315static void
316pipe_global_init(void);
317
318static enum ia_css_err
319pipe_generate_pipe_num(const struct ia_css_pipe *pipe, unsigned int *pipe_number);
320
321static void
322pipe_release_pipe_num(unsigned int pipe_num);
323
324static enum ia_css_err
325create_host_pipeline_structure(struct ia_css_stream *stream);
326
327static enum ia_css_err
328create_host_pipeline(struct ia_css_stream *stream);
329
330static enum ia_css_err
331create_host_preview_pipeline(struct ia_css_pipe *pipe);
332
333static enum ia_css_err
334create_host_video_pipeline(struct ia_css_pipe *pipe);
335
336static enum ia_css_err
337create_host_copy_pipeline(struct ia_css_pipe *pipe,
338 unsigned max_input_width,
339 struct ia_css_frame *out_frame);
340
341static enum ia_css_err
342create_host_isyscopy_capture_pipeline(struct ia_css_pipe *pipe);
343
344static enum ia_css_err
345create_host_capture_pipeline(struct ia_css_pipe *pipe);
346
347static enum ia_css_err
348create_host_yuvpp_pipeline(struct ia_css_pipe *pipe);
349
350static enum ia_css_err
351create_host_acc_pipeline(struct ia_css_pipe *pipe);
352
353static unsigned int
354sh_css_get_sw_interrupt_value(unsigned int irq);
355
356static struct ia_css_binary *ia_css_pipe_get_shading_correction_binary(const struct ia_css_pipe *pipe);
357
358static struct ia_css_binary *
359ia_css_pipe_get_s3a_binary(const struct ia_css_pipe *pipe);
360
361static struct ia_css_binary *
362ia_css_pipe_get_sdis_binary(const struct ia_css_pipe *pipe);
363
364static void
365sh_css_hmm_buffer_record_init(void);
366
367static void
368sh_css_hmm_buffer_record_uninit(void);
369
370static void
371sh_css_hmm_buffer_record_reset(struct sh_css_hmm_buffer_record *buffer_record);
372
a49d2536
AC
373static struct sh_css_hmm_buffer_record
374*sh_css_hmm_buffer_record_acquire(struct ia_css_rmgr_vbuf_handle *h_vbuf,
a49d2536
AC
375 enum ia_css_buffer_type type,
376 hrt_address kernel_ptr);
377
378static struct sh_css_hmm_buffer_record
379*sh_css_hmm_buffer_record_validate(hrt_vaddress ddr_buffer_addr,
380 enum ia_css_buffer_type type);
381
382void
383ia_css_get_acc_configs(
384 struct ia_css_pipe *pipe,
385 struct ia_css_isp_config *config);
386
387
388#if CONFIG_ON_FRAME_ENQUEUE()
389static enum ia_css_err set_config_on_frame_enqueue(struct ia_css_frame_info *info, struct frame_data_wrapper *frame);
390#endif
391
392#ifdef USE_INPUT_SYSTEM_VERSION_2401
393static unsigned int get_crop_lines_for_bayer_order(const struct ia_css_stream_config *config);
394static unsigned int get_crop_columns_for_bayer_order(const struct ia_css_stream_config *config);
395static void get_pipe_extra_pixel(struct ia_css_pipe *pipe,
396 unsigned int *extra_row, unsigned int *extra_column);
397#endif
398
a49d2536
AC
399#ifdef ISP2401
400#ifdef USE_INPUT_SYSTEM_VERSION_2401
401static enum ia_css_err
402aspect_ratio_crop_init(struct ia_css_stream *curr_stream,
403 struct ia_css_pipe *pipes[],
404 bool *do_crop_status);
405
406static bool
407aspect_ratio_crop_check(bool enabled, struct ia_css_pipe *curr_pipe);
408
409static enum ia_css_err
410aspect_ratio_crop(struct ia_css_pipe *curr_pipe,
411 struct ia_css_resolution *effective_res);
412#endif
413
414#endif
415static void
416sh_css_pipe_free_shading_table(struct ia_css_pipe *pipe)
417{
418 assert(pipe != NULL);
419 if (pipe == NULL) {
420 IA_CSS_ERROR("NULL input parameter");
421 return;
422 }
423
424 if (pipe->shading_table)
425 ia_css_shading_table_free(pipe->shading_table);
426 pipe->shading_table = NULL;
427}
428
429static enum ia_css_frame_format yuv420_copy_formats[] = {
430 IA_CSS_FRAME_FORMAT_NV12,
431 IA_CSS_FRAME_FORMAT_NV21,
432 IA_CSS_FRAME_FORMAT_YV12,
433 IA_CSS_FRAME_FORMAT_YUV420,
434 IA_CSS_FRAME_FORMAT_YUV420_16,
435 IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8,
436 IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8
437};
438
439static enum ia_css_frame_format yuv422_copy_formats[] = {
440 IA_CSS_FRAME_FORMAT_NV12,
441 IA_CSS_FRAME_FORMAT_NV16,
442 IA_CSS_FRAME_FORMAT_NV21,
443 IA_CSS_FRAME_FORMAT_NV61,
444 IA_CSS_FRAME_FORMAT_YV12,
445 IA_CSS_FRAME_FORMAT_YV16,
446 IA_CSS_FRAME_FORMAT_YUV420,
447 IA_CSS_FRAME_FORMAT_YUV420_16,
448 IA_CSS_FRAME_FORMAT_YUV422,
449 IA_CSS_FRAME_FORMAT_YUV422_16,
450 IA_CSS_FRAME_FORMAT_UYVY,
451 IA_CSS_FRAME_FORMAT_YUYV
452};
453
a49d2536
AC
454/* Verify whether the selected output format is can be produced
455 * by the copy binary given the stream format.
456 * */
457static enum ia_css_err
458verify_copy_out_frame_format(struct ia_css_pipe *pipe)
459{
460 enum ia_css_frame_format out_fmt = pipe->output_info[0].format;
461 unsigned int i, found = 0;
462
463 assert(pipe != NULL);
464 assert(pipe->stream != NULL);
465
466 switch (pipe->stream->config.input_config.format) {
467 case IA_CSS_STREAM_FORMAT_YUV420_8_LEGACY:
468 case IA_CSS_STREAM_FORMAT_YUV420_8:
e6cc7108 469 for (i=0; i<ARRAY_SIZE(yuv420_copy_formats) && !found; i++)
a49d2536
AC
470 found = (out_fmt == yuv420_copy_formats[i]);
471 break;
472 case IA_CSS_STREAM_FORMAT_YUV420_10:
473 case IA_CSS_STREAM_FORMAT_YUV420_16:
474 found = (out_fmt == IA_CSS_FRAME_FORMAT_YUV420_16);
475 break;
476 case IA_CSS_STREAM_FORMAT_YUV422_8:
e6cc7108 477 for (i=0; i<ARRAY_SIZE(yuv422_copy_formats) && !found; i++)
a49d2536
AC
478 found = (out_fmt == yuv422_copy_formats[i]);
479 break;
480 case IA_CSS_STREAM_FORMAT_YUV422_10:
481 case IA_CSS_STREAM_FORMAT_YUV422_16:
482 found = (out_fmt == IA_CSS_FRAME_FORMAT_YUV422_16 ||
483 out_fmt == IA_CSS_FRAME_FORMAT_YUV420_16);
484 break;
485 case IA_CSS_STREAM_FORMAT_RGB_444:
486 case IA_CSS_STREAM_FORMAT_RGB_555:
487 case IA_CSS_STREAM_FORMAT_RGB_565:
488 found = (out_fmt == IA_CSS_FRAME_FORMAT_RGBA888 ||
489 out_fmt == IA_CSS_FRAME_FORMAT_RGB565);
490 break;
491 case IA_CSS_STREAM_FORMAT_RGB_666:
492 case IA_CSS_STREAM_FORMAT_RGB_888:
493 found = (out_fmt == IA_CSS_FRAME_FORMAT_RGBA888 ||
494 out_fmt == IA_CSS_FRAME_FORMAT_YUV420);
495 break;
496 case IA_CSS_STREAM_FORMAT_RAW_6:
497 case IA_CSS_STREAM_FORMAT_RAW_7:
498 case IA_CSS_STREAM_FORMAT_RAW_8:
499 case IA_CSS_STREAM_FORMAT_RAW_10:
500 case IA_CSS_STREAM_FORMAT_RAW_12:
501 case IA_CSS_STREAM_FORMAT_RAW_14:
502 case IA_CSS_STREAM_FORMAT_RAW_16:
503 found = (out_fmt == IA_CSS_FRAME_FORMAT_RAW) ||
504 (out_fmt == IA_CSS_FRAME_FORMAT_RAW_PACKED);
505 break;
506 case IA_CSS_STREAM_FORMAT_BINARY_8:
507 found = (out_fmt == IA_CSS_FRAME_FORMAT_BINARY_8);
508 break;
509 default:
510 break;
511 }
512 if (!found)
513 return IA_CSS_ERR_INVALID_ARGUMENTS;
514 return IA_CSS_SUCCESS;
515}
516
517unsigned int
518ia_css_stream_input_format_bits_per_pixel(struct ia_css_stream *stream)
519{
520 int bpp = 0;
521
522 if (stream != NULL)
523 bpp = ia_css_util_input_format_bpp(stream->config.input_config.format,
524 stream->config.pixels_per_clock == 2);
525
526 return bpp;
527}
528
529#if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
530static enum ia_css_err
531sh_css_config_input_network(struct ia_css_stream *stream)
532{
533 unsigned int fmt_type;
534 struct ia_css_pipe *pipe = stream->last_pipe;
535 struct ia_css_binary *binary = NULL;
536 enum ia_css_err err = IA_CSS_SUCCESS;
537
538 assert(stream != NULL);
539 assert(pipe != NULL);
540
541 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
542 "sh_css_config_input_network() enter:\n");
543
544 if (pipe->pipeline.stages)
545 binary = pipe->pipeline.stages->binary;
546
547 err = ia_css_isys_convert_stream_format_to_mipi_format(
548 stream->config.input_config.format,
549 stream->csi_rx_config.comp,
550 &fmt_type);
551 if (err != IA_CSS_SUCCESS)
552 return err;
553 sh_css_sp_program_input_circuit(fmt_type,
554 stream->config.channel_id,
555 stream->config.mode);
556
557 if ((binary && (binary->online || stream->config.continuous)) ||
558 pipe->config.mode == IA_CSS_PIPE_MODE_COPY) {
559 err = ia_css_ifmtr_configure(&stream->config,
560 binary);
561 if (err != IA_CSS_SUCCESS)
562 return err;
563 }
564
565 if (stream->config.mode == IA_CSS_INPUT_MODE_TPG ||
566 stream->config.mode == IA_CSS_INPUT_MODE_PRBS) {
567 unsigned int hblank_cycles = 100,
568 vblank_lines = 6,
569 width,
570 height,
571 vblank_cycles;
572 width = (stream->config.input_config.input_res.width) / (1 + (stream->config.pixels_per_clock == 2));
573 height = stream->config.input_config.input_res.height;
574 vblank_cycles = vblank_lines * (width + hblank_cycles);
575 sh_css_sp_configure_sync_gen(width, height, hblank_cycles,
576 vblank_cycles);
577#if defined(IS_ISP_2400_SYSTEM)
578 if (pipe->stream->config.mode == IA_CSS_INPUT_MODE_TPG) {
579 /* TODO: move define to proper file in tools */
580 #define GP_ISEL_TPG_MODE 0x90058
581 ia_css_device_store_uint32(GP_ISEL_TPG_MODE, 0);
582 }
583#endif
584 }
585 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
586 "sh_css_config_input_network() leave:\n");
587 return IA_CSS_SUCCESS;
588}
589#elif !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2401)
590static unsigned int csi2_protocol_calculate_max_subpixels_per_line(
591 enum ia_css_stream_format format,
592 unsigned int pixels_per_line)
593{
594 unsigned int rval;
595
596 switch (format) {
597 case IA_CSS_STREAM_FORMAT_YUV420_8_LEGACY:
598 /*
599 * The frame format layout is shown below.
600 *
601 * Line 0: UYY0 UYY0 ... UYY0
602 * Line 1: VYY0 VYY0 ... VYY0
603 * Line 2: UYY0 UYY0 ... UYY0
604 * Line 3: VYY0 VYY0 ... VYY0
605 * ...
606 * Line (n-2): UYY0 UYY0 ... UYY0
607 * Line (n-1): VYY0 VYY0 ... VYY0
608 *
609 * In this frame format, the even-line is
610 * as wide as the odd-line.
611 * The 0 is introduced by the input system
612 * (mipi backend).
613 */
614 rval = pixels_per_line * 2;
615 break;
616 case IA_CSS_STREAM_FORMAT_YUV420_8:
617 case IA_CSS_STREAM_FORMAT_YUV420_10:
618 case IA_CSS_STREAM_FORMAT_YUV420_16:
619 /*
620 * The frame format layout is shown below.
621 *
622 * Line 0: YYYY YYYY ... YYYY
623 * Line 1: UYVY UYVY ... UYVY UYVY
624 * Line 2: YYYY YYYY ... YYYY
625 * Line 3: UYVY UYVY ... UYVY UYVY
626 * ...
627 * Line (n-2): YYYY YYYY ... YYYY
628 * Line (n-1): UYVY UYVY ... UYVY UYVY
629 *
630 * In this frame format, the odd-line is twice
631 * wider than the even-line.
632 */
633 rval = pixels_per_line * 2;
634 break;
635 case IA_CSS_STREAM_FORMAT_YUV422_8:
636 case IA_CSS_STREAM_FORMAT_YUV422_10:
637 case IA_CSS_STREAM_FORMAT_YUV422_16:
638 /*
639 * The frame format layout is shown below.
640 *
641 * Line 0: UYVY UYVY ... UYVY
642 * Line 1: UYVY UYVY ... UYVY
643 * Line 2: UYVY UYVY ... UYVY
644 * Line 3: UYVY UYVY ... UYVY
645 * ...
646 * Line (n-2): UYVY UYVY ... UYVY
647 * Line (n-1): UYVY UYVY ... UYVY
648 *
649 * In this frame format, the even-line is
650 * as wide as the odd-line.
651 */
652 rval = pixels_per_line * 2;
653 break;
654 case IA_CSS_STREAM_FORMAT_RGB_444:
655 case IA_CSS_STREAM_FORMAT_RGB_555:
656 case IA_CSS_STREAM_FORMAT_RGB_565:
657 case IA_CSS_STREAM_FORMAT_RGB_666:
658 case IA_CSS_STREAM_FORMAT_RGB_888:
659 /*
660 * The frame format layout is shown below.
661 *
662 * Line 0: ABGR ABGR ... ABGR
663 * Line 1: ABGR ABGR ... ABGR
664 * Line 2: ABGR ABGR ... ABGR
665 * Line 3: ABGR ABGR ... ABGR
666 * ...
667 * Line (n-2): ABGR ABGR ... ABGR
668 * Line (n-1): ABGR ABGR ... ABGR
669 *
670 * In this frame format, the even-line is
671 * as wide as the odd-line.
672 */
673 rval = pixels_per_line * 4;
674 break;
675 case IA_CSS_STREAM_FORMAT_RAW_6:
676 case IA_CSS_STREAM_FORMAT_RAW_7:
677 case IA_CSS_STREAM_FORMAT_RAW_8:
678 case IA_CSS_STREAM_FORMAT_RAW_10:
679 case IA_CSS_STREAM_FORMAT_RAW_12:
680 case IA_CSS_STREAM_FORMAT_RAW_14:
681 case IA_CSS_STREAM_FORMAT_RAW_16:
682 case IA_CSS_STREAM_FORMAT_BINARY_8:
683 case IA_CSS_STREAM_FORMAT_USER_DEF1:
684 case IA_CSS_STREAM_FORMAT_USER_DEF2:
685 case IA_CSS_STREAM_FORMAT_USER_DEF3:
686 case IA_CSS_STREAM_FORMAT_USER_DEF4:
687 case IA_CSS_STREAM_FORMAT_USER_DEF5:
688 case IA_CSS_STREAM_FORMAT_USER_DEF6:
689 case IA_CSS_STREAM_FORMAT_USER_DEF7:
690 case IA_CSS_STREAM_FORMAT_USER_DEF8:
691 /*
692 * The frame format layout is shown below.
693 *
694 * Line 0: Pixel Pixel ... Pixel
695 * Line 1: Pixel Pixel ... Pixel
696 * Line 2: Pixel Pixel ... Pixel
697 * Line 3: Pixel Pixel ... Pixel
698 * ...
699 * Line (n-2): Pixel Pixel ... Pixel
700 * Line (n-1): Pixel Pixel ... Pixel
701 *
702 * In this frame format, the even-line is
703 * as wide as the odd-line.
704 */
705 rval = pixels_per_line;
706 break;
707 default:
708 rval = 0;
709 break;
710 }
711
712 return rval;
713}
714
715static bool sh_css_translate_stream_cfg_to_input_system_input_port_id(
716 struct ia_css_stream_config *stream_cfg,
717 ia_css_isys_descr_t *isys_stream_descr)
718{
719 bool rc;
720
721 rc = true;
722 switch (stream_cfg->mode) {
723 case IA_CSS_INPUT_MODE_TPG:
724
725 if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID0) {
726 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT0_ID;
727 } else if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID1) {
728 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT1_ID;
729 } else if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID2) {
730 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT2_ID;
731 }
732
733 break;
734 case IA_CSS_INPUT_MODE_PRBS:
735
736 if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID0) {
737 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT0_ID;
738 } else if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID1) {
739 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT1_ID;
740 } else if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID2) {
741 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT2_ID;
742 }
743
744 break;
745 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR:
746
747 if (stream_cfg->source.port.port == IA_CSS_CSI2_PORT0) {
748 isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT0_ID;
749 } else if (stream_cfg->source.port.port == IA_CSS_CSI2_PORT1) {
750 isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT1_ID;
751 } else if (stream_cfg->source.port.port == IA_CSS_CSI2_PORT2) {
752 isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT2_ID;
753 }
754
755 break;
756 default:
757 rc = false;
758 break;
759 }
760
761 return rc;
762}
763
764static bool sh_css_translate_stream_cfg_to_input_system_input_port_type(
765 struct ia_css_stream_config *stream_cfg,
766 ia_css_isys_descr_t *isys_stream_descr)
767{
768 bool rc;
769
770 rc = true;
771 switch (stream_cfg->mode) {
772 case IA_CSS_INPUT_MODE_TPG:
773
774 isys_stream_descr->mode = INPUT_SYSTEM_SOURCE_TYPE_TPG;
775
776 break;
777 case IA_CSS_INPUT_MODE_PRBS:
778
779 isys_stream_descr->mode = INPUT_SYSTEM_SOURCE_TYPE_PRBS;
780
781 break;
782 case IA_CSS_INPUT_MODE_SENSOR:
783 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR:
784
785 isys_stream_descr->mode = INPUT_SYSTEM_SOURCE_TYPE_SENSOR;
786 break;
787
788 default:
789 rc = false;
790 break;
791 }
792
793 return rc;
794}
795
796static bool sh_css_translate_stream_cfg_to_input_system_input_port_attr(
797 struct ia_css_stream_config *stream_cfg,
798 ia_css_isys_descr_t *isys_stream_descr,
799 int isys_stream_idx)
800{
801 bool rc;
802
803 rc = true;
804 switch (stream_cfg->mode) {
805 case IA_CSS_INPUT_MODE_TPG:
806 if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_RAMP) {
807 isys_stream_descr->tpg_port_attr.mode = PIXELGEN_TPG_MODE_RAMP;
808 } else if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_CHECKERBOARD) {
809 isys_stream_descr->tpg_port_attr.mode = PIXELGEN_TPG_MODE_CHBO;
810 } else if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_MONO) {
811 isys_stream_descr->tpg_port_attr.mode = PIXELGEN_TPG_MODE_MONO;
812 } else {
813 rc = false;
814 }
815
816 /*
817 * TODO
818 * - Make "color_cfg" as part of "ia_css_tpg_config".
819 */
820 isys_stream_descr->tpg_port_attr.color_cfg.R1 = 51;
821 isys_stream_descr->tpg_port_attr.color_cfg.G1 = 102;
822 isys_stream_descr->tpg_port_attr.color_cfg.B1 = 255;
823 isys_stream_descr->tpg_port_attr.color_cfg.R2 = 0;
824 isys_stream_descr->tpg_port_attr.color_cfg.G2 = 100;
825 isys_stream_descr->tpg_port_attr.color_cfg.B2 = 160;
826
827 isys_stream_descr->tpg_port_attr.mask_cfg.h_mask = stream_cfg->source.tpg.x_mask;
828 isys_stream_descr->tpg_port_attr.mask_cfg.v_mask = stream_cfg->source.tpg.y_mask;
829 isys_stream_descr->tpg_port_attr.mask_cfg.hv_mask = stream_cfg->source.tpg.xy_mask;
830
831 isys_stream_descr->tpg_port_attr.delta_cfg.h_delta = stream_cfg->source.tpg.x_delta;
832 isys_stream_descr->tpg_port_attr.delta_cfg.v_delta = stream_cfg->source.tpg.y_delta;
833
834 /*
835 * TODO
836 * - Make "sync_gen_cfg" as part of "ia_css_tpg_config".
837 */
838 isys_stream_descr->tpg_port_attr.sync_gen_cfg.hblank_cycles = 100;
839 isys_stream_descr->tpg_port_attr.sync_gen_cfg.vblank_cycles = 100;
840 isys_stream_descr->tpg_port_attr.sync_gen_cfg.pixels_per_clock = stream_cfg->pixels_per_clock;
841 isys_stream_descr->tpg_port_attr.sync_gen_cfg.nr_of_frames = (uint32_t) ~(0x0);
842 isys_stream_descr->tpg_port_attr.sync_gen_cfg.pixels_per_line = stream_cfg->isys_config[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX].input_res.width;
843 isys_stream_descr->tpg_port_attr.sync_gen_cfg.lines_per_frame = stream_cfg->isys_config[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX].input_res.height;
844
845 break;
846 case IA_CSS_INPUT_MODE_PRBS:
847
848 isys_stream_descr->prbs_port_attr.seed0 = stream_cfg->source.prbs.seed;
849 isys_stream_descr->prbs_port_attr.seed1 = stream_cfg->source.prbs.seed1;
850
851 /*
852 * TODO
853 * - Make "sync_gen_cfg" as part of "ia_css_prbs_config".
854 */
855 isys_stream_descr->prbs_port_attr.sync_gen_cfg.hblank_cycles = 100;
856 isys_stream_descr->prbs_port_attr.sync_gen_cfg.vblank_cycles = 100;
857 isys_stream_descr->prbs_port_attr.sync_gen_cfg.pixels_per_clock = stream_cfg->pixels_per_clock;
858 isys_stream_descr->prbs_port_attr.sync_gen_cfg.nr_of_frames = (uint32_t) ~(0x0);
859 isys_stream_descr->prbs_port_attr.sync_gen_cfg.pixels_per_line = stream_cfg->isys_config[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX].input_res.width;
860 isys_stream_descr->prbs_port_attr.sync_gen_cfg.lines_per_frame = stream_cfg->isys_config[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX].input_res.height;
861
862 break;
863 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR:
864 {
865 enum ia_css_err err;
866 unsigned int fmt_type;
867
868 err = ia_css_isys_convert_stream_format_to_mipi_format(
869 stream_cfg->isys_config[isys_stream_idx].format,
870 MIPI_PREDICTOR_NONE,
871 &fmt_type);
872 if (err != IA_CSS_SUCCESS)
873 rc = false;
874
875 isys_stream_descr->csi_port_attr.active_lanes = stream_cfg->source.port.num_lanes;
876 isys_stream_descr->csi_port_attr.fmt_type = fmt_type;
877 isys_stream_descr->csi_port_attr.ch_id = stream_cfg->channel_id;
878#ifdef USE_INPUT_SYSTEM_VERSION_2401
879 isys_stream_descr->online = stream_cfg->online;
880#endif
881 err |= ia_css_isys_convert_compressed_format(
882 &stream_cfg->source.port.compression,
883 isys_stream_descr);
884 if (err != IA_CSS_SUCCESS)
885 rc = false;
886
887 /* metadata */
888 isys_stream_descr->metadata.enable = false;
889 if (stream_cfg->metadata_config.resolution.height > 0) {
890 err = ia_css_isys_convert_stream_format_to_mipi_format(
891 stream_cfg->metadata_config.data_type,
892 MIPI_PREDICTOR_NONE,
893 &fmt_type);
894 if (err != IA_CSS_SUCCESS)
895 rc = false;
896 isys_stream_descr->metadata.fmt_type = fmt_type;
897 isys_stream_descr->metadata.bits_per_pixel =
898 ia_css_util_input_format_bpp(stream_cfg->metadata_config.data_type, true);
899 isys_stream_descr->metadata.pixels_per_line = stream_cfg->metadata_config.resolution.width;
900 isys_stream_descr->metadata.lines_per_frame = stream_cfg->metadata_config.resolution.height;
901#ifdef USE_INPUT_SYSTEM_VERSION_2401
902 /* For new input system, number of str2mmio requests must be even.
903 * So we round up number of metadata lines to be even. */
904 if (isys_stream_descr->metadata.lines_per_frame > 0)
905 isys_stream_descr->metadata.lines_per_frame +=
906 (isys_stream_descr->metadata.lines_per_frame & 1);
907#endif
908 isys_stream_descr->metadata.align_req_in_bytes =
909 ia_css_csi2_calculate_input_system_alignment(stream_cfg->metadata_config.data_type);
910 isys_stream_descr->metadata.enable = true;
911 }
912
913 break;
914 }
915 default:
916 rc = false;
917 break;
918 }
919
920 return rc;
921}
922
923static bool sh_css_translate_stream_cfg_to_input_system_input_port_resolution(
924 struct ia_css_stream_config *stream_cfg,
925 ia_css_isys_descr_t *isys_stream_descr,
926 int isys_stream_idx)
927{
928 unsigned int bits_per_subpixel;
929 unsigned int max_subpixels_per_line;
930 unsigned int lines_per_frame;
931 unsigned int align_req_in_bytes;
932 enum ia_css_stream_format fmt_type;
933
934 fmt_type = stream_cfg->isys_config[isys_stream_idx].format;
935 if ((stream_cfg->mode == IA_CSS_INPUT_MODE_SENSOR ||
936 stream_cfg->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) &&
937 stream_cfg->source.port.compression.type != IA_CSS_CSI2_COMPRESSION_TYPE_NONE) {
938
939 if (stream_cfg->source.port.compression.uncompressed_bits_per_pixel ==
940 UNCOMPRESSED_BITS_PER_PIXEL_10) {
941 fmt_type = IA_CSS_STREAM_FORMAT_RAW_10;
942 }
943 else if (stream_cfg->source.port.compression.uncompressed_bits_per_pixel ==
944 UNCOMPRESSED_BITS_PER_PIXEL_12) {
945 fmt_type = IA_CSS_STREAM_FORMAT_RAW_12;
946 }
947 else
948 return false;
949 }
950
951 bits_per_subpixel =
952 sh_css_stream_format_2_bits_per_subpixel(fmt_type);
953 if (bits_per_subpixel == 0)
954 return false;
955
956 max_subpixels_per_line =
957 csi2_protocol_calculate_max_subpixels_per_line(fmt_type,
958 stream_cfg->isys_config[isys_stream_idx].input_res.width);
959 if (max_subpixels_per_line == 0)
960 return false;
961
962 lines_per_frame = stream_cfg->isys_config[isys_stream_idx].input_res.height;
963 if (lines_per_frame == 0)
964 return false;
965
966 align_req_in_bytes = ia_css_csi2_calculate_input_system_alignment(fmt_type);
967
968 /* HW needs subpixel info for their settings */
969 isys_stream_descr->input_port_resolution.bits_per_pixel = bits_per_subpixel;
970 isys_stream_descr->input_port_resolution.pixels_per_line = max_subpixels_per_line;
971 isys_stream_descr->input_port_resolution.lines_per_frame = lines_per_frame;
972 isys_stream_descr->input_port_resolution.align_req_in_bytes = align_req_in_bytes;
973
974 return true;
975}
976
977static bool sh_css_translate_stream_cfg_to_isys_stream_descr(
978 struct ia_css_stream_config *stream_cfg,
979 bool early_polling,
980 ia_css_isys_descr_t *isys_stream_descr,
981 int isys_stream_idx)
982{
983 bool rc;
984
985 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
986 "sh_css_translate_stream_cfg_to_isys_stream_descr() enter:\n");
987 rc = sh_css_translate_stream_cfg_to_input_system_input_port_id(stream_cfg, isys_stream_descr);
988 rc &= sh_css_translate_stream_cfg_to_input_system_input_port_type(stream_cfg, isys_stream_descr);
989 rc &= sh_css_translate_stream_cfg_to_input_system_input_port_attr(stream_cfg, isys_stream_descr, isys_stream_idx);
990 rc &= sh_css_translate_stream_cfg_to_input_system_input_port_resolution(stream_cfg, isys_stream_descr, isys_stream_idx);
991
992 isys_stream_descr->raw_packed = stream_cfg->pack_raw_pixels;
993 isys_stream_descr->linked_isys_stream_id = (int8_t) stream_cfg->isys_config[isys_stream_idx].linked_isys_stream_id;
994 /*
995 * Early polling is required for timestamp accuracy in certain case.
996 * The ISYS HW polling is started on
997 * ia_css_isys_stream_capture_indication() instead of
998 * ia_css_pipeline_sp_wait_for_isys_stream_N() as isp processing of
999 * capture takes longer than getting an ISYS frame
1000 *
1001 * Only 2401 relevant ??
1002 */
1003 isys_stream_descr->polling_mode
1004 = early_polling ? INPUT_SYSTEM_POLL_ON_CAPTURE_REQUEST
1005 : INPUT_SYSTEM_POLL_ON_WAIT_FOR_FRAME;
1006 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
1007 "sh_css_translate_stream_cfg_to_isys_stream_descr() leave:\n");
1008
1009 return rc;
1010}
1011
1012static bool sh_css_translate_binary_info_to_input_system_output_port_attr(
1013 struct ia_css_binary *binary,
1014 ia_css_isys_descr_t *isys_stream_descr)
1015{
1016 if (!binary)
1017 return false;
1018
1019 isys_stream_descr->output_port_attr.left_padding = binary->left_padding;
1020 isys_stream_descr->output_port_attr.max_isp_input_width = binary->info->sp.input.max_width;
1021
1022 return true;
1023}
1024
1025static enum ia_css_err
1026sh_css_config_input_network(struct ia_css_stream *stream)
1027{
1028 bool rc;
1029 ia_css_isys_descr_t isys_stream_descr;
1030 unsigned int sp_thread_id;
1031 struct sh_css_sp_pipeline_terminal *sp_pipeline_input_terminal;
1032 struct ia_css_pipe *pipe = NULL;
1033 struct ia_css_binary *binary = NULL;
1034 int i;
1035 uint32_t isys_stream_id;
1036 bool early_polling = false;
1037
1038 assert(stream != NULL);
1039 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
1040 "sh_css_config_input_network() enter 0x%p:\n", stream);
1041
1042 if (stream->config.continuous == true) {
1043 if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE) {
1044 pipe = stream->last_pipe;
1045 } else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_YUVPP) {
1046 pipe = stream->last_pipe;
1047 } else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) {
1048 pipe = stream->last_pipe->pipe_settings.preview.copy_pipe;
1049 } else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) {
1050 pipe = stream->last_pipe->pipe_settings.video.copy_pipe;
1051 }
1052 } else {
1053 pipe = stream->last_pipe;
1054 if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE) {
1055 /*
1056 * We need to poll the ISYS HW in capture_indication itself
1057 * for "non-continous" capture usecase for getting accurate
1058 * isys frame capture timestamps.
1059 * This is because the capturepipe propcessing takes longer
1060 * to execute than the input system frame capture.
1061 * 2401 specific
1062 */
1063 early_polling = true;
1064 }
1065 }
1066
1067 assert(pipe != NULL);
1068 if (pipe == NULL)
1069 return IA_CSS_ERR_INTERNAL_ERROR;
1070
1071 if (pipe->pipeline.stages != NULL)
1072 if (pipe->pipeline.stages->binary != NULL)
1073 binary = pipe->pipeline.stages->binary;
1074
1075
1076
1077 if (binary) {
1078 /* this was being done in ifmtr in 2400.
1079 * online and cont bypass the init_in_frameinfo_memory_defaults
1080 * so need to do it here
1081 */
1082 ia_css_get_crop_offsets(pipe, &binary->in_frame_info);
1083 }
1084
1085 /* get the SP thread id */
1086 rc = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &sp_thread_id);
1087 if (rc != true)
1088 return IA_CSS_ERR_INTERNAL_ERROR;
1089 /* get the target input terminal */
1090 sp_pipeline_input_terminal = &(sh_css_sp_group.pipe_io[sp_thread_id].input);
1091
1092 for (i = 0; i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++) {
1093 /* initialization */
1094 memset((void*)(&isys_stream_descr), 0, sizeof(ia_css_isys_descr_t));
1095 sp_pipeline_input_terminal->context.virtual_input_system_stream[i].valid = 0;
1096 sp_pipeline_input_terminal->ctrl.virtual_input_system_stream_cfg[i].valid = 0;
1097
1098 if (!stream->config.isys_config[i].valid)
1099 continue;
1100
1101 /* translate the stream configuration to the Input System (2401) configuration */
1102 rc = sh_css_translate_stream_cfg_to_isys_stream_descr(
1103 &(stream->config),
1104 early_polling,
1105 &(isys_stream_descr), i);
1106
1107 if (stream->config.online) {
1108 rc &= sh_css_translate_binary_info_to_input_system_output_port_attr(
1109 binary,
1110 &(isys_stream_descr));
1111 }
1112
1113 if (rc != true)
1114 return IA_CSS_ERR_INTERNAL_ERROR;
1115
1116 isys_stream_id = ia_css_isys_generate_stream_id(sp_thread_id, i);
1117
1118 /* create the virtual Input System (2401) */
1119 rc = ia_css_isys_stream_create(
1120 &(isys_stream_descr),
1121 &(sp_pipeline_input_terminal->context.virtual_input_system_stream[i]),
1122 isys_stream_id);
1123 if (rc != true)
1124 return IA_CSS_ERR_INTERNAL_ERROR;
1125
1126 /* calculate the configuration of the virtual Input System (2401) */
1127 rc = ia_css_isys_stream_calculate_cfg(
1128 &(sp_pipeline_input_terminal->context.virtual_input_system_stream[i]),
1129 &(isys_stream_descr),
1130 &(sp_pipeline_input_terminal->ctrl.virtual_input_system_stream_cfg[i]));
1131 if (rc != true) {
1132 ia_css_isys_stream_destroy(&(sp_pipeline_input_terminal->context.virtual_input_system_stream[i]));
1133 return IA_CSS_ERR_INTERNAL_ERROR;
1134 }
1135 }
1136
1137 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
1138 "sh_css_config_input_network() leave:\n");
1139
1140 return IA_CSS_SUCCESS;
1141}
1142
1143static inline struct ia_css_pipe *stream_get_last_pipe(
1144 struct ia_css_stream *stream)
1145{
1146 struct ia_css_pipe *last_pipe = NULL;
1147 if (stream != NULL)
1148 last_pipe = stream->last_pipe;
1149
1150 return last_pipe;
1151}
1152
1153static inline struct ia_css_pipe *stream_get_copy_pipe(
1154 struct ia_css_stream *stream)
1155{
1156 struct ia_css_pipe *copy_pipe = NULL;
1157 struct ia_css_pipe *last_pipe = NULL;
1158 enum ia_css_pipe_id pipe_id;
1159
1160 last_pipe = stream_get_last_pipe(stream);
1161
1162 if ((stream != NULL) &&
1163 (last_pipe != NULL) &&
1164 (stream->config.continuous)) {
1165
1166 pipe_id = last_pipe->mode;
1167 switch (pipe_id) {
1168 case IA_CSS_PIPE_ID_PREVIEW:
1169 copy_pipe = last_pipe->pipe_settings.preview.copy_pipe;
1170 break;
1171 case IA_CSS_PIPE_ID_VIDEO:
1172 copy_pipe = last_pipe->pipe_settings.video.copy_pipe;
1173 break;
1174 default:
1175 copy_pipe = NULL;
1176 break;
1177 }
1178 }
1179
1180 return copy_pipe;
1181}
1182
1183static inline struct ia_css_pipe *stream_get_target_pipe(
1184 struct ia_css_stream *stream)
1185{
1186 struct ia_css_pipe *target_pipe;
1187
1188 /* get the pipe that consumes the stream */
1189 if (stream->config.continuous) {
1190 target_pipe = stream_get_copy_pipe(stream);
1191 } else {
1192 target_pipe = stream_get_last_pipe(stream);
1193 }
1194
1195 return target_pipe;
1196}
1197
1198static enum ia_css_err stream_csi_rx_helper(
1199 struct ia_css_stream *stream,
1200 enum ia_css_err (*func)(enum ia_css_csi2_port, uint32_t))
1201{
1202 enum ia_css_err retval = IA_CSS_ERR_INTERNAL_ERROR;
1203 uint32_t sp_thread_id, stream_id;
1204 bool rc;
1205 struct ia_css_pipe *target_pipe = NULL;
1206
1207 if ((stream == NULL) || (stream->config.mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR))
1208 goto exit;
1209
1210 target_pipe = stream_get_target_pipe(stream);
1211
1212 if (target_pipe == NULL)
1213 goto exit;
1214
1215 rc = ia_css_pipeline_get_sp_thread_id(
1216 ia_css_pipe_get_pipe_num(target_pipe),
1217 &sp_thread_id);
1218
1219 if (!rc)
1220 goto exit;
1221
1222 /* (un)register all valid "virtual isys streams" within the ia_css_stream */
1223 stream_id = 0;
1224 do {
1225 if (stream->config.isys_config[stream_id].valid) {
1226 uint32_t isys_stream_id = ia_css_isys_generate_stream_id(sp_thread_id, stream_id);
1227 retval = func(stream->config.source.port.port, isys_stream_id);
1228 }
1229 stream_id++;
1230 } while ((retval == IA_CSS_SUCCESS) &&
1231 (stream_id < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH));
1232
1233exit:
1234 return retval;
1235}
1236
1237static inline enum ia_css_err stream_register_with_csi_rx(
1238 struct ia_css_stream *stream)
1239{
1240 return stream_csi_rx_helper(stream, ia_css_isys_csi_rx_register_stream);
1241}
1242
1243static inline enum ia_css_err stream_unregister_with_csi_rx(
1244 struct ia_css_stream *stream)
1245{
1246 return stream_csi_rx_helper(stream, ia_css_isys_csi_rx_unregister_stream);
1247}
1248#endif
1249
1250#if WITH_PC_MONITORING
1251static struct task_struct *my_kthread; /* Handle for the monitoring thread */
1252static int sh_binary_running; /* Enable sampling in the thread */
1253
1254static void print_pc_histo(char *core_name, struct sh_css_pc_histogram *hist)
1255{
1256 unsigned i;
1257 unsigned cnt_run = 0;
1258 unsigned cnt_stall = 0;
1259
1260 if (hist == NULL)
1261 return;
1262
1263 sh_css_print("%s histogram length = %d\n", core_name, hist->length);
1264 sh_css_print("%s PC\trun\tstall\n", core_name);
1265
1266 for (i = 0; i < hist->length; i++) {
1267 if ((hist->run[i] == 0) && (hist->run[i] == hist->stall[i]))
1268 continue;
1269 sh_css_print("%s %d\t%d\t%d\n",
1270 core_name, i, hist->run[i], hist->stall[i]);
1271 cnt_run += hist->run[i];
1272 cnt_stall += hist->stall[i];
1273 }
1274
1275 sh_css_print(" Statistics for %s, cnt_run = %d, cnt_stall = %d, "
1276 "hist->length = %d\n",
1277 core_name, cnt_run, cnt_stall, hist->length);
1278}
1279
1280static void print_pc_histogram(void)
1281{
1282 struct ia_css_binary_metrics *metrics;
1283
1284 for (metrics = sh_css_metrics.binary_metrics;
1285 metrics;
1286 metrics = metrics->next) {
1287 if (metrics->mode == IA_CSS_BINARY_MODE_PREVIEW ||
1288 metrics->mode == IA_CSS_BINARY_MODE_VF_PP) {
1289 sh_css_print("pc_histogram for binary %d is SKIPPED\n",
1290 metrics->id);
1291 continue;
1292 }
1293
1294 sh_css_print(" pc_histogram for binary %d\n", metrics->id);
1295 print_pc_histo(" ISP", &metrics->isp_histogram);
1296 print_pc_histo(" SP", &metrics->sp_histogram);
1297 sh_css_print("print_pc_histogram() done for binay->id = %d, "
1298 "done.\n", metrics->id);
1299 }
1300
1301 sh_css_print("PC_MONITORING:print_pc_histogram() -- DONE\n");
1302}
1303
1304static int pc_monitoring(void *data)
1305{
1306 int i = 0;
1307
1308 (void)data;
1309 while (true) {
1310 if (sh_binary_running) {
1311 sh_css_metrics_sample_pcs();
1312#if MULTIPLE_SAMPLES
1313 for (i = 0; i < NOF_SAMPLES; i++)
1314 sh_css_metrics_sample_pcs();
1315#endif
1316 }
1317 usleep_range(10, 50);
1318 }
1319 return 0;
1320}
1321
1322static void spying_thread_create(void)
1323{
1324 my_kthread = kthread_run(pc_monitoring, NULL, "sh_pc_monitor");
1325 sh_css_metrics_enable_pc_histogram(1);
1326}
1327
1328static void input_frame_info(struct ia_css_frame_info frame_info)
1329{
1330 sh_css_print("SH_CSS:input_frame_info() -- frame->info.res.width = %d, "
1331 "frame->info.res.height = %d, format = %d\n",
1332 frame_info.res.width, frame_info.res.height, frame_info.format);
1333}
1334#endif /* WITH_PC_MONITORING */
1335
1336static void
1337start_binary(struct ia_css_pipe *pipe,
1338 struct ia_css_binary *binary)
1339{
1340 struct ia_css_stream *stream;
1341
1342 assert(pipe != NULL);
1343 /* Acceleration uses firmware, the binary thus can be NULL */
1344 /* assert(binary != NULL); */
1345
1346 (void)binary;
1347
1348#if !defined(HAS_NO_INPUT_SYSTEM)
1349 stream = pipe->stream;
1350#else
1351 (void)pipe;
1352 (void)stream;
1353#endif
1354
1355 if (binary)
1356 sh_css_metrics_start_binary(&binary->metrics);
1357
1358#if WITH_PC_MONITORING
1359 sh_css_print("PC_MONITORING: %s() -- binary id = %d , "
1360 "enable_dvs_envelope = %d\n",
1361 __func__, binary->info->sp.id,
1362 binary->info->sp.enable.dvs_envelope);
1363 input_frame_info(binary->in_frame_info);
1364
1365 if (binary && binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_VIDEO)
1366 sh_binary_running = true;
1367#endif
1368
1369#if !defined(HAS_NO_INPUT_SYSTEM) && !defined(USE_INPUT_SYSTEM_VERSION_2401)
1370 if (stream->reconfigure_css_rx) {
1371 ia_css_isys_rx_configure(&pipe->stream->csi_rx_config,
1372 pipe->stream->config.mode);
1373 stream->reconfigure_css_rx = false;
1374 }
1375#endif
1376}
1377
1378/* start the copy function on the SP */
1379static enum ia_css_err
1380start_copy_on_sp(struct ia_css_pipe *pipe,
1381 struct ia_css_frame *out_frame)
1382{
1383
1384 (void)out_frame;
1385 assert(pipe != NULL);
1386 assert(pipe->stream != NULL);
1387
1388 if ((pipe == NULL) || (pipe->stream == NULL))
1389 return IA_CSS_ERR_INVALID_ARGUMENTS;
1390
1391#if !defined(HAS_NO_INPUT_SYSTEM) && !defined(USE_INPUT_SYSTEM_VERSION_2401)
1392 if (pipe->stream->reconfigure_css_rx)
1393 ia_css_isys_rx_disable();
1394#endif
1395
1396 if (pipe->stream->config.input_config.format != IA_CSS_STREAM_FORMAT_BINARY_8)
1397 return IA_CSS_ERR_INTERNAL_ERROR;
1398 sh_css_sp_start_binary_copy(ia_css_pipe_get_pipe_num(pipe), out_frame, pipe->stream->config.pixels_per_clock == 2);
1399
1400#if !defined(HAS_NO_INPUT_SYSTEM) && !defined(USE_INPUT_SYSTEM_VERSION_2401)
1401 if (pipe->stream->reconfigure_css_rx) {
1402 ia_css_isys_rx_configure(&pipe->stream->csi_rx_config, pipe->stream->config.mode);
1403 pipe->stream->reconfigure_css_rx = false;
1404 }
1405#endif
1406
1407 return IA_CSS_SUCCESS;
1408}
1409
1410void sh_css_binary_args_reset(struct sh_css_binary_args *args)
1411{
1412 unsigned int i;
1413
1414#ifndef ISP2401
1415 for (i = 0; i < NUM_VIDEO_TNR_FRAMES; i++)
1416#else
1417 for (i = 0; i < NUM_TNR_FRAMES; i++)
1418#endif
1419 args->tnr_frames[i] = NULL;
1420 for (i = 0; i < MAX_NUM_VIDEO_DELAY_FRAMES; i++)
1421 args->delay_frames[i] = NULL;
1422 args->in_frame = NULL;
1423 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
1424 args->out_frame[i] = NULL;
1425 args->out_vf_frame = NULL;
1426 args->copy_vf = false;
1427 args->copy_output = true;
1428 args->vf_downscale_log2 = 0;
1429}
1430
1431static void start_pipe(
1432 struct ia_css_pipe *me,
1433 enum sh_css_pipe_config_override copy_ovrd,
1434 enum ia_css_input_mode input_mode)
1435{
1436#if defined(HAS_NO_INPUT_SYSTEM)
1437 (void)input_mode;
1438#endif
1439
1440 IA_CSS_ENTER_PRIVATE("me = %p, copy_ovrd = %d, input_mode = %d",
1441 me, copy_ovrd, input_mode);
1442
1443 assert(me != NULL); /* all callers are in this file and call with non null argument */
1444
1445 sh_css_sp_init_pipeline(&me->pipeline,
1446 me->mode,
1447 (uint8_t)ia_css_pipe_get_pipe_num(me),
1448 me->config.default_capture_config.enable_xnr != 0,
1449 me->stream->config.pixels_per_clock == 2,
1450 me->stream->config.continuous,
1451 false,
1452 me->required_bds_factor,
1453 copy_ovrd,
1454 input_mode,
1455 &me->stream->config.metadata_config,
a49d2536 1456 &me->stream->info.metadata_info
a49d2536 1457#if !defined(HAS_NO_INPUT_SYSTEM)
94e23b61 1458 ,(input_mode==IA_CSS_INPUT_MODE_MEMORY) ?
a49d2536 1459 (mipi_port_ID_t)0 :
a49d2536 1460 me->stream->config.source.port.port
a49d2536 1461#endif
94e23b61
AC
1462#ifdef ISP2401
1463 ,&me->config.internal_frame_origin_bqs_on_sctbl,
1464 me->stream->isp_params_configs
a49d2536 1465#endif
94e23b61 1466 );
a49d2536
AC
1467
1468 if (me->config.mode != IA_CSS_PIPE_MODE_COPY) {
1469 struct ia_css_pipeline_stage *stage;
1470 stage = me->pipeline.stages;
1471 if (stage) {
1472 me->pipeline.current_stage = stage;
1473 start_binary(me, stage->binary);
1474 }
1475 }
1476 IA_CSS_LEAVE_PRIVATE("void");
1477}
1478
1479void
1480sh_css_invalidate_shading_tables(struct ia_css_stream *stream)
1481{
1482 int i;
1483 assert(stream != NULL);
1484
1485 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1486 "sh_css_invalidate_shading_tables() enter:\n");
1487
1488 for (i=0; i<stream->num_pipes; i++) {
1489 assert(stream->pipes[i] != NULL);
1490 sh_css_pipe_free_shading_table(stream->pipes[i]);
1491 }
1492
1493 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1494 "sh_css_invalidate_shading_tables() leave: return_void\n");
1495}
1496
1497#ifndef ISP2401
1498static void
1499enable_interrupts(enum ia_css_irq_type irq_type)
1500{
1501#ifdef USE_INPUT_SYSTEM_VERSION_2
1502 mipi_port_ID_t port;
1503#endif
1504 bool enable_pulse = irq_type != IA_CSS_IRQ_TYPE_EDGE;
1505 IA_CSS_ENTER_PRIVATE("");
1506 /* Enable IRQ on the SP which signals that SP goes to idle
1507 * (aka ready state) */
1508 cnd_sp_irq_enable(SP0_ID, true);
1509 /* Set the IRQ device 0 to either level or pulse */
1510 irq_enable_pulse(IRQ0_ID, enable_pulse);
1511
1512 cnd_virq_enable_channel(virq_sp, true);
1513
1514 /* Enable SW interrupt 0, this is used to signal ISYS events */
1515 cnd_virq_enable_channel(
1516 (virq_id_t)(IRQ_SW_CHANNEL0_ID + IRQ_SW_CHANNEL_OFFSET),
1517 true);
1518 /* Enable SW interrupt 1, this is used to signal PSYS events */
1519 cnd_virq_enable_channel(
1520 (virq_id_t)(IRQ_SW_CHANNEL1_ID + IRQ_SW_CHANNEL_OFFSET),
1521 true);
1522#if !defined(HAS_IRQ_MAP_VERSION_2)
1523 /* IRQ_SW_CHANNEL2_ID does not exist on 240x systems */
1524 cnd_virq_enable_channel(
1525 (virq_id_t)(IRQ_SW_CHANNEL2_ID + IRQ_SW_CHANNEL_OFFSET),
1526 true);
1527 virq_clear_all();
1528#endif
1529
1530#ifdef USE_INPUT_SYSTEM_VERSION_2
1531 for (port = 0; port < N_MIPI_PORT_ID; port++)
1532 ia_css_isys_rx_enable_all_interrupts(port);
1533#endif
1534
a49d2536
AC
1535 IA_CSS_LEAVE_PRIVATE("");
1536}
1537
1538#endif
a49d2536 1539
a49d2536
AC
1540static bool sh_css_setup_spctrl_config(const struct ia_css_fw_info *fw,
1541 const char * program,
1542 ia_css_spctrl_cfg *spctrl_cfg)
1543{
1544 if((fw == NULL)||(spctrl_cfg == NULL))
1545 return false;
1546 spctrl_cfg->sp_entry = 0;
1547 spctrl_cfg->program_name = (char *)(program);
1548
a49d2536
AC
1549 spctrl_cfg->ddr_data_offset = fw->blob.data_source;
1550 spctrl_cfg->dmem_data_addr = fw->blob.data_target;
1551 spctrl_cfg->dmem_bss_addr = fw->blob.bss_target;
1552 spctrl_cfg->data_size = fw->blob.data_size ;
1553 spctrl_cfg->bss_size = fw->blob.bss_size;
1554
1555 spctrl_cfg->spctrl_config_dmem_addr = fw->info.sp.init_dmem_data;
1556 spctrl_cfg->spctrl_state_dmem_addr = fw->info.sp.sw_state;
1557
1558 spctrl_cfg->code_size = fw->blob.size;
1559 spctrl_cfg->code = fw->blob.code;
1560 spctrl_cfg->sp_entry = fw->info.sp.sp_entry; /* entry function ptr on SP */
f16595ae 1561
a49d2536
AC
1562 return true;
1563}
1564void
1565ia_css_unload_firmware(void)
1566{
1567 if (sh_css_num_binaries)
1568 {
1569 /* we have already loaded before so get rid of the old stuff */
1570 ia_css_binary_uninit();
1571 sh_css_unload_firmware();
1572 }
1573 fw_explicitly_loaded = false;
1574}
1575
1576static void
1577ia_css_reset_defaults(struct sh_css* css)
1578{
1579 struct sh_css default_css;
1580
1581 /* Reset everything to zero */
1582 memset(&default_css, 0, sizeof(default_css));
1583
1584 /* Initialize the non zero values*/
1585 default_css.check_system_idle = true;
1586 default_css.num_cont_raw_frames = NUM_CONTINUOUS_FRAMES;
1587
1588 /* All should be 0: but memset does it already.
1589 * default_css.num_mipi_frames[N_CSI_PORTS] = 0;
1590 */
1591
1592 default_css.irq_type = IA_CSS_IRQ_TYPE_EDGE;
1593
1594 /*Set the defaults to the output */
1595 *css = default_css;
1596}
1597
1598bool
1599ia_css_check_firmware_version(const struct ia_css_fw *fw)
1600{
1601 bool retval = false;
1602
1603 if (fw != NULL) {
1604 retval = sh_css_check_firmware_version(fw->data);
1605 }
1606 return retval;
1607}
1608
1609enum ia_css_err
1610ia_css_load_firmware(const struct ia_css_env *env,
1611 const struct ia_css_fw *fw)
1612{
1613 enum ia_css_err err;
1614
1615 if (env == NULL)
1616 return IA_CSS_ERR_INVALID_ARGUMENTS;
1617 if (fw == NULL)
1618 return IA_CSS_ERR_INVALID_ARGUMENTS;
1619
1620 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_load_firmware() enter\n");
1621
a49d2536 1622 /* make sure we initialize my_css */
da22013f 1623 if (my_css.flush != env->cpu_mem_env.flush) {
a49d2536 1624 ia_css_reset_defaults(&my_css);
a49d2536
AC
1625 my_css.flush = env->cpu_mem_env.flush;
1626 }
1627
1628 ia_css_unload_firmware(); /* in case we are called twice */
1629 err = sh_css_load_firmware(fw->data, fw->bytes);
1630 if (err == IA_CSS_SUCCESS) {
1631 err = ia_css_binary_init_infos();
1632 if (err == IA_CSS_SUCCESS)
1633 fw_explicitly_loaded = true;
1634 }
1635
1636 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_load_firmware() leave \n");
1637 return err;
1638}
1639
1640enum ia_css_err
1641ia_css_init(const struct ia_css_env *env,
1642 const struct ia_css_fw *fw,
1643 uint32_t mmu_l1_base,
1644 enum ia_css_irq_type irq_type)
1645{
1646 enum ia_css_err err;
1647 ia_css_spctrl_cfg spctrl_cfg;
a49d2536 1648
a49d2536
AC
1649 void (*flush_func)(struct ia_css_acc_fw *fw);
1650 hrt_data select, enable;
1651
d929fb4e 1652 /*
a49d2536
AC
1653 * The C99 standard does not specify the exact object representation of structs;
1654 * the representation is compiler dependent.
1655 *
1656 * The structs that are communicated between host and SP/ISP should have the
1657 * exact same object representation. The compiler that is used to compile the
1658 * firmware is hivecc.
1659 *
1660 * To check if a different compiler, used to compile a host application, uses
1661 * another object representation, macros are defined specifying the size of
1662 * the structs as expected by the firmware.
1663 *
1664 * A host application shall verify that a sizeof( ) of the struct is equal to
1665 * the SIZE_OF_XXX macro of the corresponding struct. If they are not
1666 * equal, functionality will break.
1667 */
1668 /* Check struct sh_css_ddr_address_map */
1669 COMPILATION_ERROR_IF( sizeof(struct sh_css_ddr_address_map) != SIZE_OF_SH_CSS_DDR_ADDRESS_MAP_STRUCT );
1670 /* Check struct host_sp_queues */
1671 COMPILATION_ERROR_IF( sizeof(struct host_sp_queues) != SIZE_OF_HOST_SP_QUEUES_STRUCT );
1672 COMPILATION_ERROR_IF( sizeof(struct ia_css_circbuf_desc_s) != SIZE_OF_IA_CSS_CIRCBUF_DESC_S_STRUCT );
1673 COMPILATION_ERROR_IF( sizeof(struct ia_css_circbuf_elem_s) != SIZE_OF_IA_CSS_CIRCBUF_ELEM_S_STRUCT );
1674
1675 /* Check struct host_sp_communication */
1676 COMPILATION_ERROR_IF( sizeof(struct host_sp_communication) != SIZE_OF_HOST_SP_COMMUNICATION_STRUCT );
1677 COMPILATION_ERROR_IF( sizeof(struct sh_css_event_irq_mask) != SIZE_OF_SH_CSS_EVENT_IRQ_MASK_STRUCT );
1678
1679 /* Check struct sh_css_hmm_buffer */
1680 COMPILATION_ERROR_IF( sizeof(struct sh_css_hmm_buffer) != SIZE_OF_SH_CSS_HMM_BUFFER_STRUCT );
1681 COMPILATION_ERROR_IF( sizeof(struct ia_css_isp_3a_statistics) != SIZE_OF_IA_CSS_ISP_3A_STATISTICS_STRUCT );
1682 COMPILATION_ERROR_IF( sizeof(struct ia_css_isp_dvs_statistics) != SIZE_OF_IA_CSS_ISP_DVS_STATISTICS_STRUCT );
1683 COMPILATION_ERROR_IF( sizeof(struct ia_css_metadata) != SIZE_OF_IA_CSS_METADATA_STRUCT );
1684
1685 /* Check struct ia_css_init_dmem_cfg */
1686 COMPILATION_ERROR_IF( sizeof(struct ia_css_sp_init_dmem_cfg) != SIZE_OF_IA_CSS_SP_INIT_DMEM_CFG_STRUCT );
1687
1688 if (fw == NULL && !fw_explicitly_loaded)
1689 return IA_CSS_ERR_INVALID_ARGUMENTS;
1690 if (env == NULL)
1691 return IA_CSS_ERR_INVALID_ARGUMENTS;
1692
1693 sh_css_printf = env->print_env.debug_print;
1694
1695 IA_CSS_ENTER("void");
1696
a49d2536
AC
1697 flush_func = env->cpu_mem_env.flush;
1698
1699 pipe_global_init();
1700 ia_css_pipeline_init();
1701 ia_css_queue_map_init();
1702
1703 ia_css_device_access_init(&env->hw_access_env);
a49d2536
AC
1704
1705 select = gpio_reg_load(GPIO0_ID, _gpio_block_reg_do_select)
1706 & (~GPIO_FLASH_PIN_MASK);
1707 enable = gpio_reg_load(GPIO0_ID, _gpio_block_reg_do_e)
1708 | GPIO_FLASH_PIN_MASK;
1709 sh_css_mmu_set_page_table_base_index(mmu_l1_base);
1710#ifndef ISP2401
1711 my_css_save.mmu_base = mmu_l1_base;
1712#else
1713 ia_css_save_mmu_base_addr(mmu_l1_base);
1714#endif
1715
a49d2536
AC
1716 ia_css_reset_defaults(&my_css);
1717
1718 my_css_save.driver_env = *env;
a49d2536
AC
1719 my_css.flush = flush_func;
1720
1721 err = ia_css_rmgr_init();
1722 if (err != IA_CSS_SUCCESS) {
1723 IA_CSS_LEAVE_ERR(err);
1724 return err;
1725 }
1726
1727#ifndef ISP2401
1728 IA_CSS_LOG("init: %d", my_css_save_initialized);
1729#else
1730 ia_css_save_restore_data_init();
1731#endif
1732
1733#ifndef ISP2401
1734 if (!my_css_save_initialized)
1735 {
1736 my_css_save_initialized = true;
1737 my_css_save.mode = sh_css_mode_working;
1738 memset(my_css_save.stream_seeds, 0, sizeof(struct sh_css_stream_seed) * MAX_ACTIVE_STREAMS);
1739 IA_CSS_LOG("init: %d mode=%d", my_css_save_initialized, my_css_save.mode);
1740 }
1741#endif
1742 mipi_init();
1743
1744#ifndef ISP2401
1745 /* In case this has been programmed already, update internal
1746 data structure ... DEPRECATED */
1747 my_css.page_table_base_index = mmu_get_page_table_base_index(MMU0_ID);
1748
1749#endif
1750 my_css.irq_type = irq_type;
1751#ifndef ISP2401
1752 my_css_save.irq_type = irq_type;
1753#else
1754 ia_css_save_irq_type(irq_type);
1755#endif
1756 enable_interrupts(my_css.irq_type);
1757
1758 /* configure GPIO to output mode */
1759 gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_select, select);
1760 gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_e, enable);
1761 gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_0, 0);
1762
1763 err = ia_css_refcount_init(REFCOUNT_SIZE);
1764 if (err != IA_CSS_SUCCESS) {
1765 IA_CSS_LEAVE_ERR(err);
1766 return err;
1767 }
1768 err = sh_css_params_init();
1769 if (err != IA_CSS_SUCCESS) {
1770 IA_CSS_LEAVE_ERR(err);
1771 return err;
1772 }
1773 if (fw)
1774 {
1775 ia_css_unload_firmware(); /* in case we already had firmware loaded */
1776 err = sh_css_load_firmware(fw->data, fw->bytes);
1777 if (err != IA_CSS_SUCCESS) {
1778 IA_CSS_LEAVE_ERR(err);
1779 return err;
1780 }
1781 err = ia_css_binary_init_infos();
1782 if (err != IA_CSS_SUCCESS) {
1783 IA_CSS_LEAVE_ERR(err);
1784 return err;
1785 }
1786 fw_explicitly_loaded = false;
1787#ifndef ISP2401
1788 my_css_save.loaded_fw = (struct ia_css_fw *)fw;
1789#endif
1790 }
1791 if(!sh_css_setup_spctrl_config(&sh_css_sp_fw,SP_PROG_NAME,&spctrl_cfg))
1792 return IA_CSS_ERR_INTERNAL_ERROR;
1793
1794 err = ia_css_spctrl_load_fw(SP0_ID, &spctrl_cfg);
1795 if (err != IA_CSS_SUCCESS) {
1796 IA_CSS_LEAVE_ERR(err);
1797 return err;
1798 }
a49d2536 1799
a49d2536
AC
1800#if WITH_PC_MONITORING
1801 if (!thread_alive) {
1802 thread_alive++;
1803 sh_css_print("PC_MONITORING: %s() -- create thread DISABLED\n",
1804 __func__);
1805 spying_thread_create();
1806 }
1807#endif
1808 if (!sh_css_hrt_system_is_idle()) {
1809 IA_CSS_LEAVE_ERR(IA_CSS_ERR_SYSTEM_NOT_IDLE);
1810 return IA_CSS_ERR_SYSTEM_NOT_IDLE;
1811 }
1812 /* can be called here, queuing works, but:
1813 - when sp is started later, it will wipe queued items
1814 so for now we leave it for later and make sure
1815 updates are not called to frequently.
1816 sh_css_init_buffer_queues();
1817 */
1818
1819#if defined(HAS_INPUT_SYSTEM_VERSION_2) && defined(HAS_INPUT_SYSTEM_VERSION_2401)
1820#if defined(USE_INPUT_SYSTEM_VERSION_2)
1821 gp_device_reg_store(GP_DEVICE0_ID, _REG_GP_SWITCH_ISYS2401_ADDR, 0);
1822#elif defined (USE_INPUT_SYSTEM_VERSION_2401)
1823 gp_device_reg_store(GP_DEVICE0_ID, _REG_GP_SWITCH_ISYS2401_ADDR, 1);
1824#endif
1825#endif
1826
1827#if !defined(HAS_NO_INPUT_SYSTEM)
1828 dma_set_max_burst_size(DMA0_ID, HIVE_DMA_BUS_DDR_CONN,
1829 ISP_DMA_MAX_BURST_LENGTH);
1830
1831 if(ia_css_isys_init() != INPUT_SYSTEM_ERR_NO_ERROR)
1832 err = IA_CSS_ERR_INVALID_ARGUMENTS;
1833#endif
1834
1835 sh_css_params_map_and_store_default_gdc_lut();
1836
1837 IA_CSS_LEAVE_ERR(err);
1838 return err;
1839}
1840
1841enum ia_css_err ia_css_suspend(void)
1842{
1843 int i;
1844 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_suspend() enter\n");
1845 my_css_save.mode = sh_css_mode_suspend;
1846 for(i=0;i<MAX_ACTIVE_STREAMS;i++)
1847 if (my_css_save.stream_seeds[i].stream != NULL)
1848 {
1849 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "==*> unloading seed %d (%p)\n", i, my_css_save.stream_seeds[i].stream);
1850 ia_css_stream_unload(my_css_save.stream_seeds[i].stream);
1851 }
1852 my_css_save.mode = sh_css_mode_working;
1853 ia_css_stop_sp();
1854 ia_css_uninit();
1855 for(i=0;i<MAX_ACTIVE_STREAMS;i++)
1856 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "==*> after 1: seed %d (%p)\n", i, my_css_save.stream_seeds[i].stream);
1857 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_suspend() leave\n");
0d82b57c 1858 return IA_CSS_SUCCESS;
a49d2536
AC
1859}
1860
1861enum ia_css_err
1862ia_css_resume(void)
1863{
1864 int i, j;
1865 enum ia_css_err err;
1866 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_resume() enter: void\n");
1867
1868 err = ia_css_init(&(my_css_save.driver_env), my_css_save.loaded_fw, my_css_save.mmu_base, my_css_save.irq_type);
1869 if (err != IA_CSS_SUCCESS)
0d82b57c 1870 return err;
a49d2536
AC
1871 err = ia_css_start_sp();
1872 if (err != IA_CSS_SUCCESS)
0d82b57c 1873 return err;
a49d2536
AC
1874 my_css_save.mode = sh_css_mode_resume;
1875 for(i=0;i<MAX_ACTIVE_STREAMS;i++)
1876 {
1877 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "==*> seed stream %p\n", my_css_save.stream_seeds[i].stream);
1878 if (my_css_save.stream_seeds[i].stream != NULL)
1879 {
1880 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "==*> loading seed %d\n", i);
1881 err = ia_css_stream_load(my_css_save.stream_seeds[i].stream);
1882 if (err != IA_CSS_SUCCESS)
1883 {
1884 if (i)
1885 for(j=0;j<i;j++)
1886 ia_css_stream_unload(my_css_save.stream_seeds[j].stream);
0d82b57c 1887 return err;
a49d2536
AC
1888 }
1889 err = ia_css_stream_start(my_css_save.stream_seeds[i].stream);
1890 if (err != IA_CSS_SUCCESS)
1891 {
1892 for(j=0;j<=i;j++)
1893 {
1894 ia_css_stream_stop(my_css_save.stream_seeds[j].stream);
1895 ia_css_stream_unload(my_css_save.stream_seeds[j].stream);
1896 }
0d82b57c 1897 return err;
a49d2536
AC
1898 }
1899 *my_css_save.stream_seeds[i].orig_stream = my_css_save.stream_seeds[i].stream;
1900 for(j=0;j<my_css_save.stream_seeds[i].num_pipes;j++)
1901 *(my_css_save.stream_seeds[i].orig_pipes[j]) = my_css_save.stream_seeds[i].pipes[j];
1902 }
1903 }
1904 my_css_save.mode = sh_css_mode_working;
1905 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_resume() leave: return_void\n");
0d82b57c 1906 return IA_CSS_SUCCESS;
a49d2536
AC
1907}
1908
1909enum ia_css_err
1910ia_css_enable_isys_event_queue(bool enable)
1911{
1912 if (sh_css_sp_is_running())
1913 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
1914 sh_css_sp_enable_isys_event_queue(enable);
1915 return IA_CSS_SUCCESS;
1916}
1917
83fceac0 1918void *sh_css_malloc(size_t size)
a49d2536 1919{
158aeefc 1920 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_malloc() enter: size=%zu\n",size);
da22013f
AC
1921 /* FIXME: This first test can probably go away */
1922 if (size == 0)
1923 return NULL;
1924 if (size > PAGE_SIZE)
1925 return vmalloc(size);
1926 return kmalloc(size, GFP_KERNEL);
a49d2536
AC
1927}
1928
83fceac0 1929void *sh_css_calloc(size_t N, size_t size)
a49d2536 1930{
da22013f
AC
1931 void *p;
1932
158aeefc 1933 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_calloc() enter: N=%zu, size=%zu\n",N,size);
da22013f
AC
1934
1935 /* FIXME: this test can probably go away */
1936 if (size > 0) {
1937 p = sh_css_malloc(N*size);
1938 if (p)
1939 memset(p, 0, size);
bfc13351 1940 return p;
da22013f 1941 }
a49d2536
AC
1942 return NULL;
1943}
1944
83fceac0 1945void sh_css_free(void *ptr)
a49d2536 1946{
da22013f
AC
1947 if (is_vmalloc_addr(ptr))
1948 vfree(ptr);
1949 else
1950 kfree(ptr);
a49d2536
AC
1951}
1952
1953/* For Acceleration API: Flush FW (shared buffer pointer) arguments */
1954void
1955sh_css_flush(struct ia_css_acc_fw *fw)
1956{
1957 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_flush() enter:\n");
1958 if ((fw != NULL) && (my_css.flush != NULL))
1959 my_css.flush(fw);
1960}
1961
1962/* Mapping sp threads. Currently, this is done when a stream is created and
1963 * pipelines are ready to be converted to sp pipelines. Be careful if you are
1964 * doing it from stream_create since we could run out of sp threads due to
1965 * allocation on inactive pipelines. */
1966static enum ia_css_err
1967map_sp_threads(struct ia_css_stream *stream, bool map)
1968{
1969 struct ia_css_pipe *main_pipe = NULL;
1970 struct ia_css_pipe *copy_pipe = NULL;
1971 struct ia_css_pipe *capture_pipe = NULL;
1972 struct ia_css_pipe *acc_pipe = NULL;
1973 enum ia_css_err err = IA_CSS_SUCCESS;
1974 enum ia_css_pipe_id pipe_id;
1975
1976 assert(stream != NULL);
158aeefc
JP
1977 IA_CSS_ENTER_PRIVATE("stream = %p, map = %s",
1978 stream, map ? "true" : "false");
a49d2536
AC
1979
1980 if (stream == NULL) {
1981 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
1982 return IA_CSS_ERR_INVALID_ARGUMENTS;
1983 }
1984
1985 main_pipe = stream->last_pipe;
1986 pipe_id = main_pipe->mode;
1987
1988 ia_css_pipeline_map(main_pipe->pipe_num, map);
1989
1990 switch (pipe_id) {
1991 case IA_CSS_PIPE_ID_PREVIEW:
1992 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
1993 capture_pipe = main_pipe->pipe_settings.preview.capture_pipe;
1994 acc_pipe = main_pipe->pipe_settings.preview.acc_pipe;
1995 break;
1996
1997 case IA_CSS_PIPE_ID_VIDEO:
1998 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
1999 capture_pipe = main_pipe->pipe_settings.video.capture_pipe;
2000 break;
2001
2002 case IA_CSS_PIPE_ID_CAPTURE:
2003 case IA_CSS_PIPE_ID_ACC:
2004 default:
2005 break;
2006 }
2007
2008 if (acc_pipe) {
2009 ia_css_pipeline_map(acc_pipe->pipe_num, map);
2010 }
2011
2012 if(capture_pipe) {
2013 ia_css_pipeline_map(capture_pipe->pipe_num, map);
2014 }
2015
2016 /* Firmware expects copy pipe to be the last pipe mapped. (if needed) */
2017 if(copy_pipe) {
2018 ia_css_pipeline_map(copy_pipe->pipe_num, map);
2019 }
2020 /* DH regular multi pipe - not continuous mode: map the next pipes too */
2021 if (!stream->config.continuous) {
2022 int i;
2023 for (i = 1; i < stream->num_pipes; i++)
2024 ia_css_pipeline_map(stream->pipes[i]->pipe_num, map);
2025 }
2026
2027 IA_CSS_LEAVE_ERR_PRIVATE(err);
2028 return err;
2029}
2030
2031/* creates a host pipeline skeleton for all pipes in a stream. Called during
2032 * stream_create. */
2033static enum ia_css_err
2034create_host_pipeline_structure(struct ia_css_stream *stream)
2035{
2036 struct ia_css_pipe *copy_pipe = NULL, *capture_pipe = NULL;
2037 struct ia_css_pipe *acc_pipe = NULL;
2038 enum ia_css_pipe_id pipe_id;
2039 struct ia_css_pipe *main_pipe = NULL;
2040 enum ia_css_err err = IA_CSS_SUCCESS;
2041 unsigned int copy_pipe_delay = 0,
2042 capture_pipe_delay = 0;
2043
2044 assert(stream != NULL);
2045 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
2046
2047 if (stream == NULL) {
2048 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
2049 return IA_CSS_ERR_INVALID_ARGUMENTS;
2050 }
2051
2052 main_pipe = stream->last_pipe;
2053 assert(main_pipe != NULL);
2054 if (main_pipe == NULL) {
2055 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
2056 return IA_CSS_ERR_INVALID_ARGUMENTS;
2057 }
2058
2059 pipe_id = main_pipe->mode;
2060
2061 switch (pipe_id) {
2062 case IA_CSS_PIPE_ID_PREVIEW:
2063 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
2064 copy_pipe_delay = main_pipe->dvs_frame_delay;
2065 capture_pipe = main_pipe->pipe_settings.preview.capture_pipe;
2066 capture_pipe_delay = IA_CSS_FRAME_DELAY_0;
2067 acc_pipe = main_pipe->pipe_settings.preview.acc_pipe;
2068 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode, main_pipe->pipe_num, main_pipe->dvs_frame_delay);
2069 break;
2070
2071 case IA_CSS_PIPE_ID_VIDEO:
2072 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
2073 copy_pipe_delay = main_pipe->dvs_frame_delay;
2074 capture_pipe = main_pipe->pipe_settings.video.capture_pipe;
2075 capture_pipe_delay = IA_CSS_FRAME_DELAY_0;
2076 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode, main_pipe->pipe_num, main_pipe->dvs_frame_delay);
2077 break;
2078
2079 case IA_CSS_PIPE_ID_CAPTURE:
2080 capture_pipe = main_pipe;
2081 capture_pipe_delay = main_pipe->dvs_frame_delay;
2082 break;
2083
2084 case IA_CSS_PIPE_ID_YUVPP:
2085 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode,
2086 main_pipe->pipe_num, main_pipe->dvs_frame_delay);
2087 break;
2088
2089 case IA_CSS_PIPE_ID_ACC:
2090 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode, main_pipe->pipe_num, main_pipe->dvs_frame_delay);
2091 break;
2092
2093 default:
2094 err = IA_CSS_ERR_INVALID_ARGUMENTS;
2095 }
2096
2097 if ((IA_CSS_SUCCESS == err) && copy_pipe) {
2098 err = ia_css_pipeline_create(&copy_pipe->pipeline,
2099 copy_pipe->mode,
2100 copy_pipe->pipe_num,
2101 copy_pipe_delay);
2102 }
2103
2104 if ((IA_CSS_SUCCESS == err) && capture_pipe) {
2105 err = ia_css_pipeline_create(&capture_pipe->pipeline,
2106 capture_pipe->mode,
2107 capture_pipe->pipe_num,
2108 capture_pipe_delay);
2109 }
2110
2111 if ((IA_CSS_SUCCESS == err) && acc_pipe) {
2112 err = ia_css_pipeline_create(&acc_pipe->pipeline, acc_pipe->mode, acc_pipe->pipe_num, main_pipe->dvs_frame_delay);
2113 }
2114
2115 /* DH regular multi pipe - not continuous mode: create the next pipelines too */
2116 if (!stream->config.continuous) {
2117 int i;
2118 for (i = 1; i < stream->num_pipes && IA_CSS_SUCCESS == err; i++) {
2119 main_pipe = stream->pipes[i];
2120 err = ia_css_pipeline_create(&main_pipe->pipeline,
2121 main_pipe->mode,
2122 main_pipe->pipe_num,
2123 main_pipe->dvs_frame_delay);
2124 }
2125 }
2126
2127 IA_CSS_LEAVE_ERR_PRIVATE(err);
2128 return err;
2129}
2130
2131/* creates a host pipeline for all pipes in a stream. Called during
2132 * stream_start. */
2133static enum ia_css_err
2134create_host_pipeline(struct ia_css_stream *stream)
2135{
2136 struct ia_css_pipe *copy_pipe = NULL, *capture_pipe = NULL;
2137 struct ia_css_pipe *acc_pipe = NULL;
2138 enum ia_css_pipe_id pipe_id;
2139 struct ia_css_pipe *main_pipe = NULL;
2140 enum ia_css_err err = IA_CSS_SUCCESS;
2141 unsigned max_input_width = 0;
2142
2143 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
2144 if (stream == NULL) {
2145 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
2146 return IA_CSS_ERR_INVALID_ARGUMENTS;
2147 }
2148
2149 main_pipe = stream->last_pipe;
2150 pipe_id = main_pipe->mode;
2151
2152 /* No continuous frame allocation for capture pipe. It uses the
2153 * "main" pipe's frames. */
2154 if ((pipe_id == IA_CSS_PIPE_ID_PREVIEW) ||
2155 (pipe_id == IA_CSS_PIPE_ID_VIDEO)) {
2156 /* About pipe_id == IA_CSS_PIPE_ID_PREVIEW && stream->config.mode != IA_CSS_INPUT_MODE_MEMORY:
2157 * The original condition pipe_id == IA_CSS_PIPE_ID_PREVIEW is too strong. E.g. in SkyCam (with memory
2158 * based input frames) there is no continuous mode and thus no need for allocated continuous frames
2159 * This is not only for SkyCam but for all preview cases that use DDR based input frames. For this
2160 * reason the stream->config.mode != IA_CSS_INPUT_MODE_MEMORY has beed added.
2161 */
2162 if (stream->config.continuous ||
2163 (pipe_id == IA_CSS_PIPE_ID_PREVIEW && stream->config.mode != IA_CSS_INPUT_MODE_MEMORY)) {
2164 err = alloc_continuous_frames(main_pipe, true);
2165 if (err != IA_CSS_SUCCESS)
2166 goto ERR;
2167 }
2168
a49d2536
AC
2169 }
2170
2171#if defined(USE_INPUT_SYSTEM_VERSION_2)
2172 /* old isys: need to allocate_mipi_frames() even in IA_CSS_PIPE_MODE_COPY */
2173 if (pipe_id != IA_CSS_PIPE_ID_ACC) {
2174 err = allocate_mipi_frames(main_pipe, &stream->info);
2175 if (err != IA_CSS_SUCCESS)
2176 goto ERR;
2177 }
2178#elif defined(USE_INPUT_SYSTEM_VERSION_2401)
2179 if ((pipe_id != IA_CSS_PIPE_ID_ACC) &&
2180 (main_pipe->config.mode != IA_CSS_PIPE_MODE_COPY)) {
2181 err = allocate_mipi_frames(main_pipe, &stream->info);
2182 if (err != IA_CSS_SUCCESS)
2183 goto ERR;
2184 }
2185#endif
2186
2187 switch (pipe_id) {
2188 case IA_CSS_PIPE_ID_PREVIEW:
2189 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
2190 capture_pipe = main_pipe->pipe_settings.preview.capture_pipe;
2191 acc_pipe = main_pipe->pipe_settings.preview.acc_pipe;
2192 max_input_width =
2193 main_pipe->pipe_settings.preview.preview_binary.info->sp.input.max_width;
2194
2195 err = create_host_preview_pipeline(main_pipe);
2196 if (err != IA_CSS_SUCCESS)
2197 goto ERR;
2198
2199 break;
2200
2201 case IA_CSS_PIPE_ID_VIDEO:
2202 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
2203 capture_pipe = main_pipe->pipe_settings.video.capture_pipe;
2204 max_input_width =
2205 main_pipe->pipe_settings.video.video_binary.info->sp.input.max_width;
2206
2207 err = create_host_video_pipeline(main_pipe);
2208 if (err != IA_CSS_SUCCESS)
2209 goto ERR;
2210
2211 break;
2212
2213 case IA_CSS_PIPE_ID_CAPTURE:
2214 capture_pipe = main_pipe;
2215
2216 break;
2217
2218 case IA_CSS_PIPE_ID_YUVPP:
2219 err = create_host_yuvpp_pipeline(main_pipe);
2220 if (err != IA_CSS_SUCCESS)
2221 goto ERR;
2222
2223 break;
2224
2225 case IA_CSS_PIPE_ID_ACC:
2226 err = create_host_acc_pipeline(main_pipe);
2227 if (err != IA_CSS_SUCCESS)
2228 goto ERR;
2229
2230 break;
2231 default:
2232 err = IA_CSS_ERR_INVALID_ARGUMENTS;
2233 }
2234 if (err != IA_CSS_SUCCESS)
2235 goto ERR;
2236
2237 if(copy_pipe) {
2238 err = create_host_copy_pipeline(copy_pipe, max_input_width,
2239 main_pipe->continuous_frames[0]);
2240 if (err != IA_CSS_SUCCESS)
2241 goto ERR;
2242 }
2243
2244 if(capture_pipe) {
2245 err = create_host_capture_pipeline(capture_pipe);
2246 if (err != IA_CSS_SUCCESS)
2247 goto ERR;
2248 }
2249
2250 if (acc_pipe) {
2251 err = create_host_acc_pipeline(acc_pipe);
2252 if (err != IA_CSS_SUCCESS)
2253 goto ERR;
2254 }
2255
2256 /* DH regular multi pipe - not continuous mode: create the next pipelines too */
2257 if (!stream->config.continuous) {
2258 int i;
2259 for (i = 1; i < stream->num_pipes && IA_CSS_SUCCESS == err; i++) {
2260 switch (stream->pipes[i]->mode) {
2261 case IA_CSS_PIPE_ID_PREVIEW:
2262 err = create_host_preview_pipeline(stream->pipes[i]);
2263 break;
2264 case IA_CSS_PIPE_ID_VIDEO:
2265 err = create_host_video_pipeline(stream->pipes[i]);
2266 break;
2267 case IA_CSS_PIPE_ID_CAPTURE:
2268 err = create_host_capture_pipeline(stream->pipes[i]);
2269 break;
2270 case IA_CSS_PIPE_ID_YUVPP:
2271 err = create_host_yuvpp_pipeline(stream->pipes[i]);
2272 break;
2273 case IA_CSS_PIPE_ID_ACC:
2274 err = create_host_acc_pipeline(stream->pipes[i]);
2275 break;
2276 default:
2277 err = IA_CSS_ERR_INVALID_ARGUMENTS;
2278 }
2279 if (err != IA_CSS_SUCCESS)
2280 goto ERR;
2281 }
2282 }
2283
2284ERR:
2285 IA_CSS_LEAVE_ERR_PRIVATE(err);
2286 return err;
2287}
2288
2289static enum ia_css_err
2290init_pipe_defaults(enum ia_css_pipe_mode mode,
2291 struct ia_css_pipe *pipe,
2292 bool copy_pipe)
2293{
2294 static struct ia_css_pipe default_pipe = IA_CSS_DEFAULT_PIPE;
2295 static struct ia_css_preview_settings prev = IA_CSS_DEFAULT_PREVIEW_SETTINGS;
2296 static struct ia_css_capture_settings capt = IA_CSS_DEFAULT_CAPTURE_SETTINGS;
2297 static struct ia_css_video_settings video = IA_CSS_DEFAULT_VIDEO_SETTINGS;
2298 static struct ia_css_yuvpp_settings yuvpp = IA_CSS_DEFAULT_YUVPP_SETTINGS;
2299
2300 if (pipe == NULL) {
2301 IA_CSS_ERROR("NULL pipe parameter");
2302 return IA_CSS_ERR_INVALID_ARGUMENTS;
2303 }
2304
2305 /* Initialize pipe to pre-defined defaults */
2306 *pipe = default_pipe;
2307
2308 /* TODO: JB should not be needed, but temporary backward reference */
2309 switch (mode) {
2310 case IA_CSS_PIPE_MODE_PREVIEW:
2311 pipe->mode = IA_CSS_PIPE_ID_PREVIEW;
2312 pipe->pipe_settings.preview = prev;
2313 break;
2314 case IA_CSS_PIPE_MODE_CAPTURE:
2315 if (copy_pipe) {
2316 pipe->mode = IA_CSS_PIPE_ID_COPY;
2317 } else {
2318 pipe->mode = IA_CSS_PIPE_ID_CAPTURE;
2319 }
2320 pipe->pipe_settings.capture = capt;
2321 break;
2322 case IA_CSS_PIPE_MODE_VIDEO:
2323 pipe->mode = IA_CSS_PIPE_ID_VIDEO;
2324 pipe->pipe_settings.video = video;
2325 break;
2326 case IA_CSS_PIPE_MODE_ACC:
2327 pipe->mode = IA_CSS_PIPE_ID_ACC;
2328 break;
2329 case IA_CSS_PIPE_MODE_COPY:
2330 pipe->mode = IA_CSS_PIPE_ID_CAPTURE;
2331 break;
2332 case IA_CSS_PIPE_MODE_YUVPP:
2333 pipe->mode = IA_CSS_PIPE_ID_YUVPP;
2334 pipe->pipe_settings.yuvpp = yuvpp;
2335 break;
2336 default:
2337 return IA_CSS_ERR_INVALID_ARGUMENTS;
2338 }
2339
2340 return IA_CSS_SUCCESS;
2341}
2342
2343static void
2344pipe_global_init(void)
2345{
2346 uint8_t i;
2347
2348 my_css.pipe_counter = 0;
2349 for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) {
2350 my_css.all_pipes[i] = NULL;
2351 }
2352}
2353
2354static enum ia_css_err
2355pipe_generate_pipe_num(const struct ia_css_pipe *pipe, unsigned int *pipe_number)
2356{
2357 const uint8_t INVALID_PIPE_NUM = (uint8_t)~(0);
2358 uint8_t pipe_num = INVALID_PIPE_NUM;
2359 uint8_t i;
2360
2361 if (pipe == NULL) {
2362 IA_CSS_ERROR("NULL pipe parameter");
2363 return IA_CSS_ERR_INVALID_ARGUMENTS;
2364 }
2365
2366 /* Assign a new pipe_num .... search for empty place */
2367 for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) {
2368 if (my_css.all_pipes[i] == NULL) {
2369 /*position is reserved */
2370 my_css.all_pipes[i] = (struct ia_css_pipe *)pipe;
2371 pipe_num = i;
2372 break;
2373 }
2374 }
2375 if (pipe_num == INVALID_PIPE_NUM) {
2376 /* Max number of pipes already allocated */
2377 IA_CSS_ERROR("Max number of pipes already created");
2378 return IA_CSS_ERR_RESOURCE_EXHAUSTED;
2379 }
2380
2381 my_css.pipe_counter++;
2382
2383 IA_CSS_LOG("pipe_num (%d)", pipe_num);
2384
2385 *pipe_number = pipe_num;
2386 return IA_CSS_SUCCESS;
2387}
2388
2389static void
2390pipe_release_pipe_num(unsigned int pipe_num)
2391{
2392 my_css.all_pipes[pipe_num] = NULL;
2393 my_css.pipe_counter--;
2394 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2395 "pipe_release_pipe_num (%d)\n", pipe_num);
2396}
2397
2398static enum ia_css_err
2399create_pipe(enum ia_css_pipe_mode mode,
2400 struct ia_css_pipe **pipe,
2401 bool copy_pipe)
2402{
2403 enum ia_css_err err = IA_CSS_SUCCESS;
2404 struct ia_css_pipe *me;
2405
2406 if (pipe == NULL) {
2407 IA_CSS_ERROR("NULL pipe parameter");
2408 return IA_CSS_ERR_INVALID_ARGUMENTS;
2409 }
2410
94853b65 2411 me = kmalloc(sizeof(*me), GFP_KERNEL);
a49d2536
AC
2412 if (!me)
2413 return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
2414
2415 err = init_pipe_defaults(mode, me, copy_pipe);
2416 if (err != IA_CSS_SUCCESS) {
94853b65 2417 kfree(me);
a49d2536
AC
2418 return err;
2419 }
2420
2421 err = pipe_generate_pipe_num(me, &(me->pipe_num));
2422 if (err != IA_CSS_SUCCESS) {
94853b65 2423 kfree(me);
a49d2536
AC
2424 return err;
2425 }
2426
2427 *pipe = me;
2428 return IA_CSS_SUCCESS;
2429}
2430
2431struct ia_css_pipe *
2432find_pipe_by_num(uint32_t pipe_num)
2433{
2434 unsigned int i;
2435 for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++){
2436 if (my_css.all_pipes[i] &&
2437 ia_css_pipe_get_pipe_num(my_css.all_pipes[i]) == pipe_num) {
2438 return my_css.all_pipes[i];
2439 }
2440 }
2441 return NULL;
2442}
2443
2444static void sh_css_pipe_free_acc_binaries (
2445 struct ia_css_pipe *pipe)
2446{
2447 struct ia_css_pipeline *pipeline;
2448 struct ia_css_pipeline_stage *stage;
2449
2450 assert(pipe != NULL);
2451 if (pipe == NULL) {
2452 IA_CSS_ERROR("NULL input pointer");
2453 return;
2454 }
2455 pipeline = &pipe->pipeline;
2456
2457 /* loop through the stages and unload them */
2458 for (stage = pipeline->stages; stage; stage = stage->next) {
2459 struct ia_css_fw_info *firmware = (struct ia_css_fw_info *)
2460 stage->firmware;
2461 if (firmware)
2462 ia_css_pipe_unload_extension(pipe, firmware);
2463 }
2464}
2465
2466enum ia_css_err
2467ia_css_pipe_destroy(struct ia_css_pipe *pipe)
2468{
2469 enum ia_css_err err = IA_CSS_SUCCESS;
2470 IA_CSS_ENTER("pipe = %p", pipe);
2471
2472 if (pipe == NULL) {
2473 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
2474 return IA_CSS_ERR_INVALID_ARGUMENTS;
2475 }
2476
2477 if (pipe->stream != NULL) {
2478 IA_CSS_LOG("ia_css_stream_destroy not called!");
2479 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
2480 return IA_CSS_ERR_INVALID_ARGUMENTS;
2481 }
2482
2483 switch (pipe->config.mode) {
2484 case IA_CSS_PIPE_MODE_PREVIEW:
2485 /* need to take into account that this function is also called
2486 on the internal copy pipe */
2487 if (pipe->mode == IA_CSS_PIPE_ID_PREVIEW) {
2488 ia_css_frame_free_multiple(NUM_CONTINUOUS_FRAMES,
2489 pipe->continuous_frames);
2490 ia_css_metadata_free_multiple(NUM_CONTINUOUS_FRAMES,
2491 pipe->cont_md_buffers);
2492 if (pipe->pipe_settings.preview.copy_pipe) {
2493 err = ia_css_pipe_destroy(pipe->pipe_settings.preview.copy_pipe);
2494 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_destroy(): "
2495 "destroyed internal copy pipe err=%d\n", err);
2496 }
2497 }
2498 break;
2499 case IA_CSS_PIPE_MODE_VIDEO:
2500 if (pipe->mode == IA_CSS_PIPE_ID_VIDEO) {
2501 ia_css_frame_free_multiple(NUM_CONTINUOUS_FRAMES,
2502 pipe->continuous_frames);
2503 ia_css_metadata_free_multiple(NUM_CONTINUOUS_FRAMES,
2504 pipe->cont_md_buffers);
2505 if (pipe->pipe_settings.video.copy_pipe) {
2506 err = ia_css_pipe_destroy(pipe->pipe_settings.video.copy_pipe);
2507 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_destroy(): "
2508 "destroyed internal copy pipe err=%d\n", err);
2509 }
2510 }
2511#ifndef ISP2401
2512 ia_css_frame_free_multiple(NUM_VIDEO_TNR_FRAMES, pipe->pipe_settings.video.tnr_frames);
2513#else
2514 ia_css_frame_free_multiple(NUM_TNR_FRAMES, pipe->pipe_settings.video.tnr_frames);
2515#endif
2516 ia_css_frame_free_multiple(MAX_NUM_VIDEO_DELAY_FRAMES, pipe->pipe_settings.video.delay_frames);
2517 break;
2518 case IA_CSS_PIPE_MODE_CAPTURE:
2519 ia_css_frame_free_multiple(MAX_NUM_VIDEO_DELAY_FRAMES, pipe->pipe_settings.capture.delay_frames);
2520 break;
2521 case IA_CSS_PIPE_MODE_ACC:
2522 sh_css_pipe_free_acc_binaries(pipe);
2523 break;
2524 case IA_CSS_PIPE_MODE_COPY:
2525 break;
2526 case IA_CSS_PIPE_MODE_YUVPP:
2527 break;
2528 }
2529
a49d2536
AC
2530 sh_css_params_free_gdc_lut(pipe->scaler_pp_lut);
2531 pipe->scaler_pp_lut = mmgr_NULL;
a49d2536
AC
2532
2533 my_css.active_pipes[ia_css_pipe_get_pipe_num(pipe)] = NULL;
2534 sh_css_pipe_free_shading_table(pipe);
2535
2536 ia_css_pipeline_destroy(&pipe->pipeline);
2537 pipe_release_pipe_num(ia_css_pipe_get_pipe_num(pipe));
2538
2539 /* Temporarily, not every sh_css_pipe has an acc_extension. */
2540 if (pipe->config.acc_extension) {
2541 ia_css_pipe_unload_extension(pipe, pipe->config.acc_extension);
2542 }
94853b65 2543 kfree(pipe);
a49d2536
AC
2544 IA_CSS_LEAVE("err = %d", err);
2545 return err;
2546}
2547
2548void
2549ia_css_uninit(void)
2550{
2551 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_uninit() enter: void\n");
2552#if WITH_PC_MONITORING
2553 sh_css_print("PC_MONITORING: %s() -- started\n", __func__);
2554 print_pc_histogram();
2555#endif
2556
2557 sh_css_params_free_default_gdc_lut();
2558
2559
2560 /* TODO: JB: implement decent check and handling of freeing mipi frames */
2561 //assert(ref_count_mipi_allocation == 0); //mipi frames are not freed
2562 /* cleanup generic data */
2563 sh_css_params_uninit();
2564 ia_css_refcount_uninit();
2565
2566 ia_css_rmgr_uninit();
2567
2568#if !defined(HAS_NO_INPUT_FORMATTER)
2569 /* needed for reprogramming the inputformatter after power cycle of css */
2570 ifmtr_set_if_blocking_mode_reset = true;
2571#endif
2572
2573 if (fw_explicitly_loaded == false) {
2574 ia_css_unload_firmware();
2575 }
2576 ia_css_spctrl_unload_fw(SP0_ID);
2577 sh_css_sp_set_sp_running(false);
a49d2536
AC
2578#if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
2579 /* check and free any remaining mipi frames */
2580 free_mipi_frames(NULL);
2581#endif
2582
2583 sh_css_sp_reset_global_vars();
2584
2585#if !defined(HAS_NO_INPUT_SYSTEM)
2586 ia_css_isys_uninit();
2587#endif
2588
2589 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_uninit() leave: return_void\n");
2590}
2591
a49d2536
AC
2592#if defined(HAS_IRQ_MAP_VERSION_2)
2593enum ia_css_err ia_css_irq_translate(
2594 unsigned int *irq_infos)
2595{
2596 virq_id_t irq;
2597 enum hrt_isp_css_irq_status status = hrt_isp_css_irq_status_more_irqs;
2598 unsigned int infos = 0;
2599
2600/* irq_infos can be NULL, but that would make the function useless */
2601/* assert(irq_infos != NULL); */
2602 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_irq_translate() enter: irq_infos=%p\n",irq_infos);
2603
2604 while (status == hrt_isp_css_irq_status_more_irqs) {
2605 status = virq_get_channel_id(&irq);
2606 if (status == hrt_isp_css_irq_status_error)
2607 return IA_CSS_ERR_INTERNAL_ERROR;
2608
2609#if WITH_PC_MONITORING
2610 sh_css_print("PC_MONITORING: %s() irq = %d, "
2611 "sh_binary_running set to 0\n", __func__, irq);
2612 sh_binary_running = 0 ;
2613#endif
2614
2615 switch (irq) {
2616 case virq_sp:
2617 /* When SP goes to idle, info is available in the
2618 * event queue. */
2619 infos |= IA_CSS_IRQ_INFO_EVENTS_READY;
2620 break;
2621 case virq_isp:
a49d2536
AC
2622 break;
2623#if !defined(HAS_NO_INPUT_SYSTEM)
2624 case virq_isys_sof:
2625 infos |= IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF;
2626 break;
2627 case virq_isys_eof:
2628 infos |= IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF;
2629 break;
2630 case virq_isys_csi:
2631 infos |= IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR;
2632 break;
2633#endif
2634#if !defined(HAS_NO_INPUT_FORMATTER)
2635 case virq_ifmt0_id:
2636 infos |= IA_CSS_IRQ_INFO_IF_ERROR;
2637 break;
2638#endif
2639 case virq_dma:
2640 infos |= IA_CSS_IRQ_INFO_DMA_ERROR;
2641 break;
2642 case virq_sw_pin_0:
2643 infos |= sh_css_get_sw_interrupt_value(0);
2644 break;
2645 case virq_sw_pin_1:
2646 infos |= sh_css_get_sw_interrupt_value(1);
2647 /* pqiao TODO: also assumption here */
2648 break;
2649 default:
2650 break;
2651 }
2652 }
2653
2654 if (irq_infos)
2655 *irq_infos = infos;
2656
2657 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_irq_translate() "
158aeefc 2658 "leave: irq_infos=%u\n", infos);
a49d2536
AC
2659
2660 return IA_CSS_SUCCESS;
2661}
2662
2663enum ia_css_err ia_css_irq_enable(
2664 enum ia_css_irq_info info,
2665 bool enable)
2666{
2667 virq_id_t irq = N_virq_id;
2668 IA_CSS_ENTER("info=%d, enable=%d", info, enable);
2669
2670 switch (info) {
2671#if !defined(HAS_NO_INPUT_FORMATTER)
2672 case IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF:
2673 irq = virq_isys_sof;
2674 break;
2675 case IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF:
2676 irq = virq_isys_eof;
2677 break;
2678 case IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR:
2679 irq = virq_isys_csi;
2680 break;
2681#endif
2682#if !defined(HAS_NO_INPUT_FORMATTER)
2683 case IA_CSS_IRQ_INFO_IF_ERROR:
2684 irq = virq_ifmt0_id;
2685 break;
2686#endif
2687 case IA_CSS_IRQ_INFO_DMA_ERROR:
2688 irq = virq_dma;
2689 break;
2690 case IA_CSS_IRQ_INFO_SW_0:
2691 irq = virq_sw_pin_0;
2692 break;
2693 case IA_CSS_IRQ_INFO_SW_1:
2694 irq = virq_sw_pin_1;
2695 break;
2696 default:
2697 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
2698 return IA_CSS_ERR_INVALID_ARGUMENTS;
2699 }
2700
2701 cnd_virq_enable_channel(irq, enable);
2702
2703 IA_CSS_LEAVE_ERR(IA_CSS_SUCCESS);
2704 return IA_CSS_SUCCESS;
2705}
2706
2707#else
2708#error "sh_css.c: IRQ MAP must be one of \
2709 {IRQ_MAP_VERSION_2}"
2710#endif
2711
2712static unsigned int
2713sh_css_get_sw_interrupt_value(unsigned int irq)
2714{
2715 unsigned int irq_value;
2716 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_get_sw_interrupt_value() enter: irq=%d\n",irq);
2717 irq_value = sh_css_sp_get_sw_interrupt_value(irq);
2718 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_get_sw_interrupt_value() leave: irq_value=%d\n",irq_value);
2719 return irq_value;
2720}
2721
2722/* configure and load the copy binary, the next binary is used to
2723 determine whether the copy binary needs to do left padding. */
2724static enum ia_css_err load_copy_binary(
2725 struct ia_css_pipe *pipe,
2726 struct ia_css_binary *copy_binary,
2727 struct ia_css_binary *next_binary)
2728{
2729 struct ia_css_frame_info copy_out_info, copy_in_info, copy_vf_info;
2730 unsigned int left_padding;
2731 enum ia_css_err err;
2732 struct ia_css_binary_descr copy_descr;
2733
2734 /* next_binary can be NULL */
2735 assert(pipe != NULL);
2736 assert(copy_binary != NULL);
2737 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2738 "load_copy_binary() enter:\n");
2739
2740 if (next_binary != NULL) {
2741 copy_out_info = next_binary->in_frame_info;
2742 left_padding = next_binary->left_padding;
2743 } else {
2744 copy_out_info = pipe->output_info[0];
2745 copy_vf_info = pipe->vf_output_info[0];
2746 ia_css_frame_info_set_format(&copy_vf_info, IA_CSS_FRAME_FORMAT_YUV_LINE);
2747 left_padding = 0;
2748 }
2749
2750 ia_css_pipe_get_copy_binarydesc(pipe, &copy_descr,
2751 &copy_in_info, &copy_out_info, (next_binary != NULL) ? NULL : NULL/*TODO: &copy_vf_info*/);
2752 err = ia_css_binary_find(&copy_descr, copy_binary);
2753 if (err != IA_CSS_SUCCESS)
2754 return err;
2755 copy_binary->left_padding = left_padding;
2756 return IA_CSS_SUCCESS;
2757}
2758
2759static enum ia_css_err
2760alloc_continuous_frames(
2761 struct ia_css_pipe *pipe, bool init_time)
2762{
2763 enum ia_css_err err = IA_CSS_SUCCESS;
2764 struct ia_css_frame_info ref_info;
2765 enum ia_css_pipe_id pipe_id;
2766 bool continuous;
2767 unsigned int i, idx;
2768 unsigned int num_frames;
2769 struct ia_css_pipe *capture_pipe = NULL;
2770
2771 IA_CSS_ENTER_PRIVATE("pipe = %p, init_time = %d", pipe, init_time);
2772
2773 if ((pipe == NULL) || (pipe->stream == NULL)) {
2774 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
2775 return IA_CSS_ERR_INVALID_ARGUMENTS;
2776 }
2777
2778 pipe_id = pipe->mode;
2779 continuous = pipe->stream->config.continuous;
2780
2781 if (continuous) {
2782 if (init_time) {
2783 num_frames = pipe->stream->config.init_num_cont_raw_buf;
2784 pipe->stream->continuous_pipe = pipe;
2785 } else
2786 num_frames = pipe->stream->config.target_num_cont_raw_buf;
2787 } else {
2788 num_frames = NUM_ONLINE_INIT_CONTINUOUS_FRAMES;
2789 }
2790
2791 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) {
2792 ref_info = pipe->pipe_settings.preview.preview_binary.in_frame_info;
2793 } else if (pipe_id == IA_CSS_PIPE_ID_VIDEO) {
2794 ref_info = pipe->pipe_settings.video.video_binary.in_frame_info;
2795 }
2796 else {
2797 /* should not happen */
2798 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR);
2799 return IA_CSS_ERR_INTERNAL_ERROR;
2800 }
2801
2802#if defined(USE_INPUT_SYSTEM_VERSION_2401)
2803 /* For CSI2+, the continuous frame will hold the full input frame */
2804 ref_info.res.width = pipe->stream->config.input_config.input_res.width;
2805 ref_info.res.height = pipe->stream->config.input_config.input_res.height;
2806
2807 /* Ensure padded width is aligned for 2401 */
2808 ref_info.padded_width = CEIL_MUL(ref_info.res.width, 2 * ISP_VEC_NELEMS);
2809#endif
2810
2811#if !defined(HAS_NO_PACKED_RAW_PIXELS)
2812 if (pipe->stream->config.pack_raw_pixels) {
2813 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2814 "alloc_continuous_frames() IA_CSS_FRAME_FORMAT_RAW_PACKED\n");
2815 ref_info.format = IA_CSS_FRAME_FORMAT_RAW_PACKED;
2816 } else
2817#endif
2818 {
2819 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2820 "alloc_continuous_frames() IA_CSS_FRAME_FORMAT_RAW\n");
2821 ref_info.format = IA_CSS_FRAME_FORMAT_RAW;
2822 }
2823
2824 /* Write format back to binary */
2825 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) {
2826 pipe->pipe_settings.preview.preview_binary.in_frame_info.format = ref_info.format;
2827 capture_pipe = pipe->pipe_settings.preview.capture_pipe;
2828 } else if (pipe_id == IA_CSS_PIPE_ID_VIDEO) {
2829 pipe->pipe_settings.video.video_binary.in_frame_info.format = ref_info.format;
2830 capture_pipe = pipe->pipe_settings.video.capture_pipe;
2831 } else {
2832 /* should not happen */
2833 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR);
2834 return IA_CSS_ERR_INTERNAL_ERROR;
2835 }
2836
2837 if (init_time)
2838 idx = 0;
2839 else
2840 idx = pipe->stream->config.init_num_cont_raw_buf;
2841
2842 for (i = idx; i < NUM_CONTINUOUS_FRAMES; i++) {
2843 /* free previous frame */
2844 if (pipe->continuous_frames[i]) {
2845 ia_css_frame_free(pipe->continuous_frames[i]);
2846 pipe->continuous_frames[i] = NULL;
2847 }
2848 /* free previous metadata buffer */
2849 ia_css_metadata_free(pipe->cont_md_buffers[i]);
2850 pipe->cont_md_buffers[i] = NULL;
2851
2852 /* check if new frame needed */
2853 if (i < num_frames) {
2854 /* allocate new frame */
2855 err = ia_css_frame_allocate_from_info(
2856 &pipe->continuous_frames[i],
2857 &ref_info);
2858 if (err != IA_CSS_SUCCESS) {
2859 IA_CSS_LEAVE_ERR_PRIVATE(err);
2860 return err;
2861 }
2862 /* allocate metadata buffer */
2863 pipe->cont_md_buffers[i] = ia_css_metadata_allocate(
2864 &pipe->stream->info.metadata_info);
2865 }
2866 }
2867 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
2868 return IA_CSS_SUCCESS;
2869}
2870
2871enum ia_css_err
2872ia_css_alloc_continuous_frame_remain(struct ia_css_stream *stream)
2873{
2874 if (stream == NULL)
2875 return IA_CSS_ERR_INVALID_ARGUMENTS;
2876 return alloc_continuous_frames(stream->continuous_pipe, false);
2877}
2878
2879static enum ia_css_err
2880load_preview_binaries(struct ia_css_pipe *pipe)
2881{
2882 struct ia_css_frame_info prev_in_info,
2883 prev_bds_out_info,
2884 prev_out_info,
2885 prev_vf_info;
2886 struct ia_css_binary_descr preview_descr;
2887 bool online;
2888 enum ia_css_err err = IA_CSS_SUCCESS;
2889 bool continuous, need_vf_pp = false;
2890 bool need_isp_copy_binary = false;
2891#ifdef USE_INPUT_SYSTEM_VERSION_2401
2892 bool sensor = false;
2893#endif
2894 /* preview only have 1 output pin now */
2895 struct ia_css_frame_info *pipe_out_info = &pipe->output_info[0];
a49d2536
AC
2896 struct ia_css_preview_settings *mycs = &pipe->pipe_settings.preview;
2897
a49d2536
AC
2898 IA_CSS_ENTER_PRIVATE("");
2899 assert(pipe != NULL);
2900 assert(pipe->stream != NULL);
2901 assert(pipe->mode == IA_CSS_PIPE_ID_PREVIEW);
2902
2903 online = pipe->stream->config.online;
2904 continuous = pipe->stream->config.continuous;
2905#ifdef USE_INPUT_SYSTEM_VERSION_2401
2906 sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
2907#endif
2908
a49d2536 2909 if (mycs->preview_binary.info)
a49d2536
AC
2910 return IA_CSS_SUCCESS;
2911
2912 err = ia_css_util_check_input(&pipe->stream->config, false, false);
2913 if (err != IA_CSS_SUCCESS)
2914 return err;
2915 err = ia_css_frame_check_info(pipe_out_info);
2916 if (err != IA_CSS_SUCCESS)
2917 return err;
2918
2919 /* Note: the current selection of vf_pp binary and
2920 * parameterization of the preview binary contains a few pieces
2921 * of hardcoded knowledge. This needs to be cleaned up such that
2922 * the binary selection becomes more generic.
2923 * The vf_pp binary is needed if one or more of the following features
2924 * are required:
2925 * 1. YUV downscaling.
2926 * 2. Digital zoom.
2927 * 3. An output format that is not supported by the preview binary.
2928 * In practice this means something other than yuv_line or nv12.
2929 * The decision if the vf_pp binary is needed for YUV downscaling is
2930 * made after the preview binary selection, since some preview binaries
2931 * can perform the requested YUV downscaling.
2932 * */
2933 need_vf_pp = pipe->config.enable_dz;
2934 need_vf_pp |= pipe_out_info->format != IA_CSS_FRAME_FORMAT_YUV_LINE &&
2935 !(pipe_out_info->format == IA_CSS_FRAME_FORMAT_NV12 ||
2936 pipe_out_info->format == IA_CSS_FRAME_FORMAT_NV12_16 ||
2937 pipe_out_info->format == IA_CSS_FRAME_FORMAT_NV12_TILEY);
2938
2939 /* Preview step 1 */
2940 if (pipe->vf_yuv_ds_input_info.res.width)
2941 prev_vf_info = pipe->vf_yuv_ds_input_info;
2942 else
2943 prev_vf_info = *pipe_out_info;
2944 /* If vf_pp is needed, then preview must output yuv_line.
2945 * The exception is when vf_pp is manually disabled, that is only
2946 * used in combination with a pipeline extension that requires
2947 * yuv_line as input.
2948 * */
2949 if (need_vf_pp)
2950 ia_css_frame_info_set_format(&prev_vf_info,
2951 IA_CSS_FRAME_FORMAT_YUV_LINE);
2952
2953 err = ia_css_pipe_get_preview_binarydesc(
2954 pipe,
2955 &preview_descr,
2956 &prev_in_info,
2957 &prev_bds_out_info,
2958 &prev_out_info,
2959 &prev_vf_info);
2960 if (err != IA_CSS_SUCCESS)
2961 return err;
b1c056e0 2962 err = ia_css_binary_find(&preview_descr, &mycs->preview_binary);
a49d2536
AC
2963 if (err != IA_CSS_SUCCESS)
2964 return err;
2965
2966#ifdef ISP2401
2967 /* The delay latency determines the number of invalid frames after
2968 * a stream is started. */
2969 pipe->num_invalid_frames = pipe->dvs_frame_delay;
2970 pipe->info.num_invalid_frames = pipe->num_invalid_frames;
2971
2972 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2973 "load_preview_binaries() num_invalid_frames=%d dvs_frame_delay=%d\n",
2974 pipe->num_invalid_frames, pipe->dvs_frame_delay);
2975
2976#endif
2977 /* The vf_pp binary is needed when (further) YUV downscaling is required */
a49d2536
AC
2978 need_vf_pp |= mycs->preview_binary.out_frame_info[0].res.width != pipe_out_info->res.width;
2979 need_vf_pp |= mycs->preview_binary.out_frame_info[0].res.height != pipe_out_info->res.height;
a49d2536
AC
2980
2981 /* When vf_pp is needed, then the output format of the selected
2982 * preview binary must be yuv_line. If this is not the case,
2983 * then the preview binary selection is done again.
2984 */
2985 if (need_vf_pp &&
a49d2536 2986 (mycs->preview_binary.out_frame_info[0].format != IA_CSS_FRAME_FORMAT_YUV_LINE)) {
a49d2536
AC
2987
2988 /* Preview step 2 */
2989 if (pipe->vf_yuv_ds_input_info.res.width)
2990 prev_vf_info = pipe->vf_yuv_ds_input_info;
2991 else
2992 prev_vf_info = *pipe_out_info;
2993
2994 ia_css_frame_info_set_format(&prev_vf_info,
2995 IA_CSS_FRAME_FORMAT_YUV_LINE);
2996
2997 err = ia_css_pipe_get_preview_binarydesc(
2998 pipe,
2999 &preview_descr,
3000 &prev_in_info,
3001 &prev_bds_out_info,
3002 &prev_out_info,
3003 &prev_vf_info);
3004 if (err != IA_CSS_SUCCESS)
3005 return err;
3006 err = ia_css_binary_find(&preview_descr,
a49d2536 3007 &mycs->preview_binary);
a49d2536
AC
3008 if (err != IA_CSS_SUCCESS)
3009 return err;
3010 }
3011
3012 if (need_vf_pp) {
3013 struct ia_css_binary_descr vf_pp_descr;
3014
3015 /* Viewfinder post-processing */
3016 ia_css_pipe_get_vfpp_binarydesc(pipe, &vf_pp_descr,
a49d2536 3017 &mycs->preview_binary.out_frame_info[0],
a49d2536
AC
3018 pipe_out_info);
3019 err = ia_css_binary_find(&vf_pp_descr,
a49d2536 3020 &mycs->vf_pp_binary);
a49d2536
AC
3021 if (err != IA_CSS_SUCCESS)
3022 return err;
3023 }
3024
3025#ifdef USE_INPUT_SYSTEM_VERSION_2401
3026 /* When the input system is 2401, only the Direct Sensor Mode
3027 * Offline Preview uses the ISP copy binary.
3028 */
3029 need_isp_copy_binary = !online && sensor;
3030#else
3031#ifndef ISP2401
3032 need_isp_copy_binary = !online && !continuous;
3033#else
3034 /* About pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY:
3035 * This is typical the case with SkyCam (which has no input system) but it also applies to all cases
3036 * where the driver chooses for memory based input frames. In these cases, a copy binary (which typical
3037 * copies sensor data to DDR) does not have much use.
3038 */
3039 need_isp_copy_binary = !online && !continuous && !(pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY);
3040#endif
3041#endif
3042
3043 /* Copy */
3044 if (need_isp_copy_binary) {
3045 err = load_copy_binary(pipe,
a49d2536
AC
3046 &mycs->copy_binary,
3047 &mycs->preview_binary);
a49d2536
AC
3048 if (err != IA_CSS_SUCCESS)
3049 return err;
3050 }
3051
3052 if (pipe->shading_table) {
3053 ia_css_shading_table_free(pipe->shading_table);
3054 pipe->shading_table = NULL;
3055 }
3056
3057 return IA_CSS_SUCCESS;
3058}
3059
3060static void
3061ia_css_binary_unload(struct ia_css_binary *binary)
3062{
3063 ia_css_binary_destroy_isp_parameters(binary);
3064}
3065
3066static enum ia_css_err
3067unload_preview_binaries(struct ia_css_pipe *pipe)
3068{
3069 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3070
3071 if ((pipe == NULL) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) {
3072 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
3073 return IA_CSS_ERR_INVALID_ARGUMENTS;
3074 }
3075 ia_css_binary_unload(&pipe->pipe_settings.preview.copy_binary);
3076 ia_css_binary_unload(&pipe->pipe_settings.preview.preview_binary);
3077 ia_css_binary_unload(&pipe->pipe_settings.preview.vf_pp_binary);
3078
3079 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
3080 return IA_CSS_SUCCESS;
3081}
3082
3083static const struct ia_css_fw_info *last_output_firmware(
3084 const struct ia_css_fw_info *fw)
3085{
3086 const struct ia_css_fw_info *last_fw = NULL;
3087/* fw can be NULL */
3088 IA_CSS_ENTER_LEAVE_PRIVATE("");
3089
3090 for (; fw; fw = fw->next) {
3091 const struct ia_css_fw_info *info = fw;
3092 if (info->info.isp.sp.enable.output)
3093 last_fw = fw;
3094 }
3095 return last_fw;
3096}
3097
3098static enum ia_css_err add_firmwares(
3099 struct ia_css_pipeline *me,
3100 struct ia_css_binary *binary,
3101 const struct ia_css_fw_info *fw,
3102 const struct ia_css_fw_info *last_fw,
3103 unsigned int binary_mode,
3104 struct ia_css_frame *in_frame,
3105 struct ia_css_frame *out_frame,
3106 struct ia_css_frame *vf_frame,
3107 struct ia_css_pipeline_stage **my_stage,
3108 struct ia_css_pipeline_stage **vf_stage)
3109{
3110 enum ia_css_err err = IA_CSS_SUCCESS;
3111 struct ia_css_pipeline_stage *extra_stage = NULL;
3112 struct ia_css_pipeline_stage_desc stage_desc;
3113
3114/* all args can be NULL ??? */
3115 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3116 "add_firmwares() enter:\n");
3117
3118 for (; fw; fw = fw->next) {
3119 struct ia_css_frame *out[IA_CSS_BINARY_MAX_OUTPUT_PORTS] = {NULL};
3120 struct ia_css_frame *in = NULL;
3121 struct ia_css_frame *vf = NULL;
3122 if ((fw == last_fw) && (fw->info.isp.sp.enable.out_frame != 0)) {
3123 out[0] = out_frame;
3124 }
3125 if (fw->info.isp.sp.enable.in_frame != 0) {
3126 in = in_frame;
3127 }
3128 if (fw->info.isp.sp.enable.out_frame != 0) {
3129 vf = vf_frame;
3130 }
3131 ia_css_pipe_get_firmwares_stage_desc(&stage_desc, binary,
3132 out, in, vf, fw, binary_mode);
3133 err = ia_css_pipeline_create_and_add_stage(me,
3134 &stage_desc,
3135 &extra_stage);
3136 if (err != IA_CSS_SUCCESS)
3137 return err;
3138 if (fw->info.isp.sp.enable.output != 0)
3139 in_frame = extra_stage->args.out_frame[0];
3140 if (my_stage && !*my_stage && extra_stage)
3141 *my_stage = extra_stage;
3142 if (vf_stage && !*vf_stage && extra_stage &&
3143 fw->info.isp.sp.enable.vf_veceven)
3144 *vf_stage = extra_stage;
3145 }
3146 return err;
3147}
3148
3149static enum ia_css_err add_vf_pp_stage(
3150 struct ia_css_pipe *pipe,
3151 struct ia_css_frame *in_frame,
3152 struct ia_css_frame *out_frame,
3153 struct ia_css_binary *vf_pp_binary,
3154 struct ia_css_pipeline_stage **vf_pp_stage)
3155{
3156
3157 struct ia_css_pipeline *me = NULL;
3158 const struct ia_css_fw_info *last_fw = NULL;
3159 enum ia_css_err err = IA_CSS_SUCCESS;
3160 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3161 struct ia_css_pipeline_stage_desc stage_desc;
3162
3163/* out_frame can be NULL ??? */
3164
3165 if (pipe == NULL)
3166 return IA_CSS_ERR_INVALID_ARGUMENTS;
3167 if (in_frame == NULL)
3168 return IA_CSS_ERR_INVALID_ARGUMENTS;
3169 if (vf_pp_binary == NULL)
3170 return IA_CSS_ERR_INVALID_ARGUMENTS;
3171 if (vf_pp_stage == NULL)
3172 return IA_CSS_ERR_INVALID_ARGUMENTS;
3173
3174 ia_css_pipe_util_create_output_frames(out_frames);
3175 me = &pipe->pipeline;
3176
3177 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3178 "add_vf_pp_stage() enter:\n");
3179
3180 *vf_pp_stage = NULL;
3181
3182 last_fw = last_output_firmware(pipe->vf_stage);
3183 if (!pipe->extra_config.disable_vf_pp) {
3184 if (last_fw) {
3185 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3186 ia_css_pipe_get_generic_stage_desc(&stage_desc, vf_pp_binary,
3187 out_frames, in_frame, NULL);
3188 } else{
3189 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
3190 ia_css_pipe_get_generic_stage_desc(&stage_desc, vf_pp_binary,
3191 out_frames, in_frame, NULL);
3192 }
3193 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc, vf_pp_stage);
3194 if (err != IA_CSS_SUCCESS)
3195 return err;
3196 in_frame = (*vf_pp_stage)->args.out_frame[0];
3197 }
3198 err = add_firmwares(me, vf_pp_binary, pipe->vf_stage, last_fw,
3199 IA_CSS_BINARY_MODE_VF_PP,
3200 in_frame, out_frame, NULL,
3201 vf_pp_stage, NULL);
3202 return err;
3203}
3204
3205static enum ia_css_err add_yuv_scaler_stage(
3206 struct ia_css_pipe *pipe,
3207 struct ia_css_pipeline *me,
3208 struct ia_css_frame *in_frame,
3209 struct ia_css_frame *out_frame,
3210 struct ia_css_frame *internal_out_frame,
3211 struct ia_css_binary *yuv_scaler_binary,
3212 struct ia_css_pipeline_stage **pre_vf_pp_stage)
3213{
3214 const struct ia_css_fw_info *last_fw;
3215 enum ia_css_err err = IA_CSS_SUCCESS;
3216 struct ia_css_frame *vf_frame = NULL;
3217 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3218 struct ia_css_pipeline_stage_desc stage_desc;
3219
3220 /* out_frame can be NULL ??? */
3221 assert(in_frame != NULL);
3222 assert(pipe != NULL);
3223 assert(me != NULL);
3224 assert(yuv_scaler_binary != NULL);
3225 assert(pre_vf_pp_stage != NULL);
3226 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3227 "add_yuv_scaler_stage() enter:\n");
3228
3229 *pre_vf_pp_stage = NULL;
3230 ia_css_pipe_util_create_output_frames(out_frames);
3231
3232 last_fw = last_output_firmware(pipe->output_stage);
3233
3234 if(last_fw) {
3235 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3236 ia_css_pipe_get_generic_stage_desc(&stage_desc,
3237 yuv_scaler_binary, out_frames, in_frame, vf_frame);
3238 } else {
3239 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
3240 ia_css_pipe_util_set_output_frames(out_frames, 1, internal_out_frame);
3241 ia_css_pipe_get_generic_stage_desc(&stage_desc,
3242 yuv_scaler_binary, out_frames, in_frame, vf_frame);
3243 }
3244 err = ia_css_pipeline_create_and_add_stage(me,
3245 &stage_desc,
3246 pre_vf_pp_stage);
3247 if (err != IA_CSS_SUCCESS)
3248 return err;
3249 in_frame = (*pre_vf_pp_stage)->args.out_frame[0];
3250
3251 err = add_firmwares(me, yuv_scaler_binary, pipe->output_stage, last_fw,
3252 IA_CSS_BINARY_MODE_CAPTURE_PP,
3253 in_frame, out_frame, vf_frame,
3254 NULL, pre_vf_pp_stage);
3255 /* If a firmware produce vf_pp output, we set that as vf_pp input */
3256 (*pre_vf_pp_stage)->args.vf_downscale_log2 = yuv_scaler_binary->vf_downscale_log2;
3257
3258 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3259 "add_yuv_scaler_stage() leave:\n");
3260 return err;
3261}
3262
3263static enum ia_css_err add_capture_pp_stage(
3264 struct ia_css_pipe *pipe,
3265 struct ia_css_pipeline *me,
3266 struct ia_css_frame *in_frame,
3267 struct ia_css_frame *out_frame,
3268 struct ia_css_binary *capture_pp_binary,
3269 struct ia_css_pipeline_stage **capture_pp_stage)
3270{
3271 const struct ia_css_fw_info *last_fw = NULL;
3272 enum ia_css_err err = IA_CSS_SUCCESS;
3273 struct ia_css_frame *vf_frame = NULL;
3274 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3275 struct ia_css_pipeline_stage_desc stage_desc;
3276
3277 /* out_frame can be NULL ??? */
3278 assert(in_frame != NULL);
3279 assert(pipe != NULL);
3280 assert(me != NULL);
3281 assert(capture_pp_binary != NULL);
3282 assert(capture_pp_stage != NULL);
3283 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3284 "add_capture_pp_stage() enter:\n");
3285
3286 *capture_pp_stage = NULL;
3287 ia_css_pipe_util_create_output_frames(out_frames);
3288
3289 last_fw = last_output_firmware(pipe->output_stage);
3290 err = ia_css_frame_allocate_from_info(&vf_frame,
3291 &capture_pp_binary->vf_frame_info);
3292 if (err != IA_CSS_SUCCESS)
3293 return err;
3294 if(last_fw) {
3295 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3296 ia_css_pipe_get_generic_stage_desc(&stage_desc,
3297 capture_pp_binary, out_frames, NULL, vf_frame);
3298 } else {
3299 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
3300 ia_css_pipe_get_generic_stage_desc(&stage_desc,
3301 capture_pp_binary, out_frames, NULL, vf_frame);
3302 }
3303 err = ia_css_pipeline_create_and_add_stage(me,
3304 &stage_desc,
3305 capture_pp_stage);
3306 if (err != IA_CSS_SUCCESS)
3307 return err;
3308 err = add_firmwares(me, capture_pp_binary, pipe->output_stage, last_fw,
3309 IA_CSS_BINARY_MODE_CAPTURE_PP,
3310 in_frame, out_frame, vf_frame,
3311 NULL, capture_pp_stage);
3312 /* If a firmware produce vf_pp output, we set that as vf_pp input */
3313 if (*capture_pp_stage) {
3314 (*capture_pp_stage)->args.vf_downscale_log2 =
3315 capture_pp_binary->vf_downscale_log2;
3316 }
3317 return err;
3318}
3319
3320static void sh_css_setup_queues(void)
3321{
3322 const struct ia_css_fw_info *fw;
3323 unsigned int HIVE_ADDR_host_sp_queues_initialized;
3324
3325 sh_css_hmm_buffer_record_init();
3326
3327 sh_css_event_init_irq_mask();
3328
3329 fw = &sh_css_sp_fw;
3330 HIVE_ADDR_host_sp_queues_initialized =
3331 fw->info.sp.host_sp_queues_initialized;
3332
3333 ia_css_bufq_init();
3334
3335 /* set "host_sp_queues_initialized" to "true" */
3336 sp_dmem_store_uint32(SP0_ID,
3337 (unsigned int)sp_address_of(host_sp_queues_initialized),
3338 (uint32_t)(1));
3339 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_setup_queues() leave:\n");
3340}
3341
3342static enum ia_css_err
3343init_vf_frameinfo_defaults(struct ia_css_pipe *pipe,
3344 struct ia_css_frame *vf_frame, unsigned int idx)
3345{
3346 enum ia_css_err err = IA_CSS_SUCCESS;
3347 unsigned int thread_id;
3348 enum sh_css_queue_id queue_id;
3349
3350 assert(vf_frame != NULL);
3351
3352 sh_css_pipe_get_viewfinder_frame_info(pipe, &vf_frame->info, idx);
3353 vf_frame->contiguous = false;
3354 vf_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
3355 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
3356 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx, thread_id, &queue_id);
3357 vf_frame->dynamic_queue_id = queue_id;
3358 vf_frame->buf_type = IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx;
3359
3360 err = ia_css_frame_init_planes(vf_frame);
3361 return err;
3362}
3363
3364#ifdef USE_INPUT_SYSTEM_VERSION_2401
3365static unsigned int
3366get_crop_lines_for_bayer_order (
3367 const struct ia_css_stream_config *config)
3368{
3369 assert(config != NULL);
3370 if ((IA_CSS_BAYER_ORDER_BGGR == config->input_config.bayer_order)
3371 || (IA_CSS_BAYER_ORDER_GBRG == config->input_config.bayer_order))
3372 return 1;
3373
3374 return 0;
3375}
3376
3377static unsigned int
3378get_crop_columns_for_bayer_order (
3379 const struct ia_css_stream_config *config)
3380{
3381 assert(config != NULL);
3382 if ((IA_CSS_BAYER_ORDER_RGGB == config->input_config.bayer_order)
3383 || (IA_CSS_BAYER_ORDER_GBRG == config->input_config.bayer_order))
3384 return 1;
3385
3386 return 0;
3387}
3388
3389/* This function is to get the sum of all extra pixels in addition to the effective
3390 * input, it includes dvs envelop and filter run-in */
3391static void get_pipe_extra_pixel(struct ia_css_pipe *pipe,
3392 unsigned int *extra_row, unsigned int *extra_column)
3393{
3394 enum ia_css_pipe_id pipe_id = pipe->mode;
3395 unsigned int left_cropping = 0, top_cropping = 0;
3396 unsigned int i;
3397 struct ia_css_resolution dvs_env = pipe->config.dvs_envelope;
3398
3399 /* The dvs envelope info may not be correctly sent down via pipe config
3400 * The check is made and the correct value is populated in the binary info
3401 * Use this value when computing crop, else excess lines may get trimmed
3402 */
3403 switch (pipe_id) {
3404 case IA_CSS_PIPE_ID_PREVIEW:
3405 if (pipe->pipe_settings.preview.preview_binary.info) {
3406 left_cropping = pipe->pipe_settings.preview.preview_binary.info->sp.pipeline.left_cropping;
3407 top_cropping = pipe->pipe_settings.preview.preview_binary.info->sp.pipeline.top_cropping;
3408 }
3409 dvs_env = pipe->pipe_settings.preview.preview_binary.dvs_envelope;
3410 break;
3411 case IA_CSS_PIPE_ID_VIDEO:
3412 if (pipe->pipe_settings.video.video_binary.info) {
3413 left_cropping = pipe->pipe_settings.video.video_binary.info->sp.pipeline.left_cropping;
3414 top_cropping = pipe->pipe_settings.video.video_binary.info->sp.pipeline.top_cropping;
3415 }
3416 dvs_env = pipe->pipe_settings.video.video_binary.dvs_envelope;
3417 break;
3418 case IA_CSS_PIPE_ID_CAPTURE:
3419 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
3420 if (pipe->pipe_settings.capture.primary_binary[i].info) {
3421 left_cropping += pipe->pipe_settings.capture.primary_binary[i].info->sp.pipeline.left_cropping;
3422 top_cropping += pipe->pipe_settings.capture.primary_binary[i].info->sp.pipeline.top_cropping;
3423 }
3424 dvs_env.width += pipe->pipe_settings.capture.primary_binary[i].dvs_envelope.width;
3425 dvs_env.height += pipe->pipe_settings.capture.primary_binary[i].dvs_envelope.height;
3426 }
3427 break;
3428 default:
3429 break;
3430 }
3431
3432 *extra_row = top_cropping + dvs_env.height;
3433 *extra_column = left_cropping + dvs_env.width;
3434}
3435
3436void
3437ia_css_get_crop_offsets (
3438 struct ia_css_pipe *pipe,
3439 struct ia_css_frame_info *in_frame)
3440{
3441 unsigned int row = 0;
3442 unsigned int column = 0;
3443 struct ia_css_resolution *input_res;
3444 struct ia_css_resolution *effective_res;
3445 unsigned int extra_row = 0, extra_col = 0;
3446 unsigned int min_reqd_height, min_reqd_width;
3447
3448 assert(pipe != NULL);
3449 assert(pipe->stream != NULL);
3450 assert(in_frame != NULL);
3451
3452 IA_CSS_ENTER_PRIVATE("pipe = %p effective_wd = %u effective_ht = %u",
3453 pipe, pipe->config.input_effective_res.width,
3454 pipe->config.input_effective_res.height);
3455
3456 input_res = &pipe->stream->config.input_config.input_res;
3457#ifndef ISP2401
3458 effective_res = &pipe->stream->config.input_config.effective_res;
3459#else
3460 effective_res = &pipe->config.input_effective_res;
3461#endif
3462
3463 get_pipe_extra_pixel(pipe, &extra_row, &extra_col);
3464
3465 in_frame->raw_bayer_order = pipe->stream->config.input_config.bayer_order;
3466
3467 min_reqd_height = effective_res->height + extra_row;
3468 min_reqd_width = effective_res->width + extra_col;
3469
3470 if (input_res->height > min_reqd_height) {
3471 row = (input_res->height - min_reqd_height) / 2;
3472 row &= ~0x1;
3473 }
3474 if (input_res->width > min_reqd_width) {
3475 column = (input_res->width - min_reqd_width) / 2;
3476 column &= ~0x1;
3477 }
3478
3479 /*
3480 * TODO:
3481 * 1. Require the special support for RAW10 packed mode.
3482 * 2. Require the special support for the online use cases.
3483 */
3484
3485 /* ISP expects GRBG bayer order, we skip one line and/or one row
3486 * to correct in case the input bayer order is different.
3487 */
3488 column += get_crop_columns_for_bayer_order(&pipe->stream->config);
3489 row += get_crop_lines_for_bayer_order(&pipe->stream->config);
3490
3491 in_frame->crop_info.start_column = column;
3492 in_frame->crop_info.start_line = row;
3493
3494 IA_CSS_LEAVE_PRIVATE("void start_col: %u start_row: %u", column, row);
3495
3496 return;
3497}
3498#endif
3499
3500static enum ia_css_err
3501init_in_frameinfo_memory_defaults(struct ia_css_pipe *pipe,
3502 struct ia_css_frame *frame, enum ia_css_frame_format format)
3503{
3504 struct ia_css_frame *in_frame;
3505 enum ia_css_err err = IA_CSS_SUCCESS;
3506 unsigned int thread_id;
3507 enum sh_css_queue_id queue_id;
3508
3509 assert(frame != NULL);
3510 in_frame = frame;
3511
3512 in_frame->info.format = format;
3513
3514#ifdef USE_INPUT_SYSTEM_VERSION_2401
3515 if (format == IA_CSS_FRAME_FORMAT_RAW)
3516 in_frame->info.format = (pipe->stream->config.pack_raw_pixels) ?
3517 IA_CSS_FRAME_FORMAT_RAW_PACKED : IA_CSS_FRAME_FORMAT_RAW;
3518#endif
3519
3520
3521 in_frame->info.res.width = pipe->stream->config.input_config.input_res.width;
3522 in_frame->info.res.height = pipe->stream->config.input_config.input_res.height;
3523 in_frame->info.raw_bit_depth =
3524 ia_css_pipe_util_pipe_input_format_bpp(pipe);
3525 ia_css_frame_info_set_width(&in_frame->info, pipe->stream->config.input_config.input_res.width, 0);
3526 in_frame->contiguous = false;
3527 in_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
3528 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
3529 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_INPUT_FRAME, thread_id, &queue_id);
3530 in_frame->dynamic_queue_id = queue_id;
3531 in_frame->buf_type = IA_CSS_BUFFER_TYPE_INPUT_FRAME;
3532#ifdef USE_INPUT_SYSTEM_VERSION_2401
3533 ia_css_get_crop_offsets(pipe, &in_frame->info);
3534#endif
3535 err = ia_css_frame_init_planes(in_frame);
3536
3537 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3538 "init_in_frameinfo_memory_defaults() bayer_order = %d:\n", in_frame->info.raw_bayer_order);
3539
3540 return err;
3541}
3542
3543static enum ia_css_err
3544init_out_frameinfo_defaults(struct ia_css_pipe *pipe,
3545 struct ia_css_frame *out_frame, unsigned int idx)
3546{
3547 enum ia_css_err err = IA_CSS_SUCCESS;
3548 unsigned int thread_id;
3549 enum sh_css_queue_id queue_id;
3550
3551 assert(out_frame != NULL);
3552
3553 sh_css_pipe_get_output_frame_info(pipe, &out_frame->info, idx);
3554 out_frame->contiguous = false;
3555 out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
3556 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
3557 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx, thread_id, &queue_id);
3558 out_frame->dynamic_queue_id = queue_id;
3559 out_frame->buf_type = IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx;
3560 err = ia_css_frame_init_planes(out_frame);
3561
3562 return err;
3563}
3564
3565/* Create stages for video pipe */
3566static enum ia_css_err create_host_video_pipeline(struct ia_css_pipe *pipe)
3567{
3568 struct ia_css_pipeline_stage_desc stage_desc;
3569 struct ia_css_binary *copy_binary, *video_binary,
3570 *yuv_scaler_binary, *vf_pp_binary;
3571 struct ia_css_pipeline_stage *copy_stage = NULL;
3572 struct ia_css_pipeline_stage *video_stage = NULL;
3573 struct ia_css_pipeline_stage *yuv_scaler_stage = NULL;
3574 struct ia_css_pipeline_stage *vf_pp_stage = NULL;
3575 struct ia_css_pipeline *me;
3576 struct ia_css_frame *in_frame = NULL;
3577 struct ia_css_frame *out_frame;
3578 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3579 struct ia_css_frame *vf_frame = NULL;
3580 enum ia_css_err err = IA_CSS_SUCCESS;
3581 bool need_copy = false;
3582 bool need_vf_pp = false;
3583 bool need_yuv_pp = false;
3584 unsigned num_output_pins;
3585 bool need_in_frameinfo_memory = false;
3586
3587 unsigned int i, num_yuv_scaler;
3588 bool *is_output_stage = NULL;
3589
3590 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3591 if ((pipe == NULL) || (pipe->stream == NULL) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) {
3592 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
3593 return IA_CSS_ERR_INVALID_ARGUMENTS;
3594 }
3595 ia_css_pipe_util_create_output_frames(out_frames);
3596 out_frame = &pipe->out_frame_struct;
3597
3598 /* pipeline already created as part of create_host_pipeline_structure */
3599 me = &pipe->pipeline;
3600 ia_css_pipeline_clean(me);
3601
3602 me->dvs_frame_delay = pipe->dvs_frame_delay;
3603
3604#ifdef USE_INPUT_SYSTEM_VERSION_2401
3605 /* When the input system is 2401, always enable 'in_frameinfo_memory'
3606 * except for the following: online or continuous
3607 */
3608 need_in_frameinfo_memory = !(pipe->stream->config.online || pipe->stream->config.continuous);
3609#else
3610 /* Construct in_frame info (only in case we have dynamic input */
3611 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
3612#endif
3613
3614 /* Construct in_frame info (only in case we have dynamic input */
3615 if (need_in_frameinfo_memory) {
3616 in_frame = &pipe->in_frame_struct;
3617 err = init_in_frameinfo_memory_defaults(pipe, in_frame, IA_CSS_FRAME_FORMAT_RAW);
3618 if (err != IA_CSS_SUCCESS)
3619 goto ERR;
3620 }
3621
3622 out_frame->data = 0;
3623 err = init_out_frameinfo_defaults(pipe, out_frame, 0);
3624 if (err != IA_CSS_SUCCESS)
3625 goto ERR;
3626
3627 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
3628 vf_frame = &pipe->vf_frame_struct;
3629 vf_frame->data = 0;
3630 err = init_vf_frameinfo_defaults(pipe, vf_frame, 0);
3631 if (err != IA_CSS_SUCCESS)
3632 goto ERR;
3633 }
3634
3635 copy_binary = &pipe->pipe_settings.video.copy_binary;
3636 video_binary = &pipe->pipe_settings.video.video_binary;
3637 vf_pp_binary = &pipe->pipe_settings.video.vf_pp_binary;
3638 num_output_pins = video_binary->info->num_output_pins;
3639
3640 yuv_scaler_binary = pipe->pipe_settings.video.yuv_scaler_binary;
3641 num_yuv_scaler = pipe->pipe_settings.video.num_yuv_scaler;
3642 is_output_stage = pipe->pipe_settings.video.is_output_stage;
3643
3644 need_copy = (copy_binary != NULL && copy_binary->info != NULL);
3645 need_vf_pp = (vf_pp_binary != NULL && vf_pp_binary->info != NULL);
3646 need_yuv_pp = (yuv_scaler_binary != NULL && yuv_scaler_binary->info != NULL);
3647
3648 if (need_copy) {
3649 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3650 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
3651 out_frames, NULL, NULL);
3652 err = ia_css_pipeline_create_and_add_stage(me,
3653 &stage_desc,
3654 &copy_stage);
3655 if (err != IA_CSS_SUCCESS)
3656 goto ERR;
3657 in_frame = me->stages->args.out_frame[0];
3658 } else if (pipe->stream->config.continuous) {
3659#ifdef USE_INPUT_SYSTEM_VERSION_2401
3660 /* When continous is enabled, configure in_frame with the
3661 * last pipe, which is the copy pipe.
3662 */
3663 in_frame = pipe->stream->last_pipe->continuous_frames[0];
3664#else
3665 in_frame = pipe->continuous_frames[0];
3666#endif
3667 }
3668
3669 ia_css_pipe_util_set_output_frames(out_frames, 0, need_yuv_pp ? NULL : out_frame);
3670
3671 /* when the video binary supports a second output pin,
3672 it can directly produce the vf_frame. */
3673 if(need_vf_pp) {
3674 ia_css_pipe_get_generic_stage_desc(&stage_desc, video_binary,
3675 out_frames, in_frame, NULL);
3676 } else {
3677 ia_css_pipe_get_generic_stage_desc(&stage_desc, video_binary,
3678 out_frames, in_frame, vf_frame);
3679 }
3680 err = ia_css_pipeline_create_and_add_stage(me,
3681 &stage_desc,
3682 &video_stage);
3683 if (err != IA_CSS_SUCCESS)
3684 goto ERR;
3685
3686 /* If we use copy iso video, the input must be yuv iso raw */
3687 if(video_stage) {
3688 video_stage->args.copy_vf =
3689 video_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY;
3690 video_stage->args.copy_output = video_stage->args.copy_vf;
3691 }
3692
3693 /* when the video binary supports only 1 output pin, vf_pp is needed to
3694 produce the vf_frame.*/
3695 if (need_vf_pp && video_stage) {
3696 in_frame = video_stage->args.out_vf_frame;
3697 err = add_vf_pp_stage(pipe, in_frame, vf_frame, vf_pp_binary,
3698 &vf_pp_stage);
3699 if (err != IA_CSS_SUCCESS)
3700 goto ERR;
3701 }
3702 if (video_stage) {
3703 int frm;
3704#ifndef ISP2401
3705 for (frm = 0; frm < NUM_VIDEO_TNR_FRAMES; frm++) {
3706#else
3707 for (frm = 0; frm < NUM_TNR_FRAMES; frm++) {
3708#endif
3709 video_stage->args.tnr_frames[frm] =
3710 pipe->pipe_settings.video.tnr_frames[frm];
3711 }
3712 for (frm = 0; frm < MAX_NUM_VIDEO_DELAY_FRAMES; frm++) {
3713 video_stage->args.delay_frames[frm] =
3714 pipe->pipe_settings.video.delay_frames[frm];
3715 }
3716 }
3717
3718 /* Append Extension on Video out, if enabled */
3719 if (!need_vf_pp && video_stage && pipe->config.acc_extension &&
3720 (pipe->config.acc_extension->info.isp.type == IA_CSS_ACC_OUTPUT))
3721 {
3722 struct ia_css_frame *out = NULL;
3723 struct ia_css_frame *in = NULL;
3724
3725 if ((pipe->config.acc_extension->info.isp.sp.enable.output) &&
3726 (pipe->config.acc_extension->info.isp.sp.enable.in_frame) &&
3727 (pipe->config.acc_extension->info.isp.sp.enable.out_frame)) {
3728
3729 /* In/Out Frame mapping to support output frame extension.*/
3730 out = video_stage->args.out_frame[0];
3731 err = ia_css_frame_allocate_from_info(&in, &(pipe->output_info[0]));
3732 if (err != IA_CSS_SUCCESS)
3733 goto ERR;
3734 video_stage->args.out_frame[0] = in;
3735 }
3736
3737 err = add_firmwares( me, video_binary, pipe->output_stage,
3738 last_output_firmware(pipe->output_stage),
3739 IA_CSS_BINARY_MODE_VIDEO,
3740 in, out, NULL, &video_stage, NULL);
3741 if (err != IA_CSS_SUCCESS)
3742 goto ERR;
3743 }
3744
3745 if (need_yuv_pp && video_stage) {
3746 struct ia_css_frame *tmp_in_frame = video_stage->args.out_frame[0];
3747 struct ia_css_frame *tmp_out_frame = NULL;
3748
3749 for (i = 0; i < num_yuv_scaler; i++) {
3750 if (is_output_stage[i] == true) {
3751 tmp_out_frame = out_frame;
3752 } else {
3753 tmp_out_frame = NULL;
3754 }
3755 err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame,
3756 NULL,
3757 &yuv_scaler_binary[i],
3758 &yuv_scaler_stage);
3759
3760 if (err != IA_CSS_SUCCESS) {
3761 IA_CSS_LEAVE_ERR_PRIVATE(err);
3762 return err;
3763 }
3764 /* we use output port 1 as internal output port */
3765 if (yuv_scaler_stage)
3766 tmp_in_frame = yuv_scaler_stage->args.out_frame[1];
3767 }
3768 }
3769
3770 pipe->pipeline.acquire_isp_each_stage = false;
3771 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
3772
3773ERR:
3774 IA_CSS_LEAVE_ERR_PRIVATE(err);
3775 return err;
3776}
3777
3778static enum ia_css_err
3779create_host_acc_pipeline(struct ia_css_pipe *pipe)
3780{
3781 enum ia_css_err err = IA_CSS_SUCCESS;
b5eb7ac1 3782 const struct ia_css_fw_info *fw;
a49d2536
AC
3783 unsigned int i;
3784
3785 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3786 if ((pipe == NULL) || (pipe->stream == NULL)) {
3787 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
3788 return IA_CSS_ERR_INVALID_ARGUMENTS;
3789 }
3790
3791 pipe->pipeline.num_execs = pipe->config.acc_num_execs;
3792 /* Reset pipe_qos_config to default disable all QOS extension stages */
3793 if (pipe->config.acc_extension)
3794 pipe->pipeline.pipe_qos_config = 0;
3795
b5eb7ac1 3796 fw = pipe->vf_stage;
a49d2536
AC
3797 for (i = 0; fw; fw = fw->next){
3798 err = sh_css_pipeline_add_acc_stage(&pipe->pipeline, fw);
3799 if (err != IA_CSS_SUCCESS)
3800 goto ERR;
3801 }
a49d2536
AC
3802
3803 for (i=0; i<pipe->config.num_acc_stages; i++) {
3804 struct ia_css_fw_info *fw = pipe->config.acc_stages[i];
3805 err = sh_css_pipeline_add_acc_stage(&pipe->pipeline, fw);
3806 if (err != IA_CSS_SUCCESS)
3807 goto ERR;
3808 }
3809
3810 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
3811
3812ERR:
3813 IA_CSS_LEAVE_ERR_PRIVATE(err);
3814 return err;
3815}
3816
3817/* Create stages for preview */
3818static enum ia_css_err
3819create_host_preview_pipeline(struct ia_css_pipe *pipe)
3820{
3821 struct ia_css_pipeline_stage *copy_stage = NULL;
3822 struct ia_css_pipeline_stage *preview_stage = NULL;
3823 struct ia_css_pipeline_stage *vf_pp_stage = NULL;
3824 struct ia_css_pipeline_stage_desc stage_desc;
3825 struct ia_css_pipeline *me = NULL;
3826 struct ia_css_binary *copy_binary, *preview_binary, *vf_pp_binary = NULL;
3827 struct ia_css_frame *in_frame = NULL;
3828 enum ia_css_err err = IA_CSS_SUCCESS;
3829 struct ia_css_frame *out_frame;
3830 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3831 bool need_in_frameinfo_memory = false;
3832#ifdef USE_INPUT_SYSTEM_VERSION_2401
3833 bool sensor = false;
3834 bool buffered_sensor = false;
3835 bool online = false;
3836 bool continuous = false;
3837#endif
3838
3839 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3840 if ((pipe == NULL) || (pipe->stream == NULL) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) {
3841 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
3842 return IA_CSS_ERR_INVALID_ARGUMENTS;
3843 }
3844
3845
3846 ia_css_pipe_util_create_output_frames(out_frames);
3847 /* pipeline already created as part of create_host_pipeline_structure */
3848 me = &pipe->pipeline;
3849 ia_css_pipeline_clean(me);
3850
3851#ifdef USE_INPUT_SYSTEM_VERSION_2401
3852 /* When the input system is 2401, always enable 'in_frameinfo_memory'
3853 * except for the following:
3854 * - Direct Sensor Mode Online Preview
3855 * - Buffered Sensor Mode Online Preview
3856 * - Direct Sensor Mode Continuous Preview
3857 * - Buffered Sensor Mode Continous Preview
3858 */
3859 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR);
3860 buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR);
3861 online = pipe->stream->config.online;
3862 continuous = pipe->stream->config.continuous;
3863 need_in_frameinfo_memory =
3864 !((sensor && (online || continuous)) || (buffered_sensor && (online || continuous)));
3865#else
3866 /* Construct in_frame info (only in case we have dynamic input */
3867 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
3868#endif
3869 if (need_in_frameinfo_memory) {
3870 err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame, IA_CSS_FRAME_FORMAT_RAW);
3871 if (err != IA_CSS_SUCCESS)
3872 goto ERR;
3873
3874 in_frame = &me->in_frame;
3875 } else {
3876 in_frame = NULL;
3877 }
3878
3879 err = init_out_frameinfo_defaults(pipe, &me->out_frame[0], 0);
3880 if (err != IA_CSS_SUCCESS)
3881 goto ERR;
3882 out_frame = &me->out_frame[0];
3883
3884 copy_binary = &pipe->pipe_settings.preview.copy_binary;
3885 preview_binary = &pipe->pipe_settings.preview.preview_binary;
3886 if (pipe->pipe_settings.preview.vf_pp_binary.info)
3887 vf_pp_binary = &pipe->pipe_settings.preview.vf_pp_binary;
3888
3889 if (pipe->pipe_settings.preview.copy_binary.info) {
3890 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3891 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
3892 out_frames, NULL, NULL);
3893 err = ia_css_pipeline_create_and_add_stage(me,
3894 &stage_desc,
3895 &copy_stage);
3896 if (err != IA_CSS_SUCCESS)
3897 goto ERR;
3898 in_frame = me->stages->args.out_frame[0];
3899#ifndef ISP2401
3900 } else {
3901#else
3902 } else if (pipe->stream->config.continuous) {
3903#endif
3904#ifdef USE_INPUT_SYSTEM_VERSION_2401
3905 /* When continuous is enabled, configure in_frame with the
3906 * last pipe, which is the copy pipe.
3907 */
3908 if (continuous || !online){
3909 in_frame = pipe->stream->last_pipe->continuous_frames[0];
3910 }
3911#else
3912 in_frame = pipe->continuous_frames[0];
3913#endif
3914 }
3915
3916 if (vf_pp_binary) {
3917 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3918 ia_css_pipe_get_generic_stage_desc(&stage_desc, preview_binary,
3919 out_frames, in_frame, NULL);
3920 } else {
3921 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
3922 ia_css_pipe_get_generic_stage_desc(&stage_desc, preview_binary,
3923 out_frames, in_frame, NULL);
3924 }
3925 err = ia_css_pipeline_create_and_add_stage(me,
3926 &stage_desc,
3927 &preview_stage);
3928 if (err != IA_CSS_SUCCESS)
3929 goto ERR;
3930 /* If we use copy iso preview, the input must be yuv iso raw */
3931 preview_stage->args.copy_vf =
3932 preview_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY;
3933 preview_stage->args.copy_output = !preview_stage->args.copy_vf;
3934 if (preview_stage->args.copy_vf && !preview_stage->args.out_vf_frame) {
3935 /* in case of copy, use the vf frame as output frame */
3936 preview_stage->args.out_vf_frame =
3937 preview_stage->args.out_frame[0];
3938 }
3939 if (vf_pp_binary) {
3940 if (preview_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY)
3941 in_frame = preview_stage->args.out_vf_frame;
3942 else
3943 in_frame = preview_stage->args.out_frame[0];
3944 err = add_vf_pp_stage(pipe, in_frame, out_frame, vf_pp_binary,
3945 &vf_pp_stage);
3946 if (err != IA_CSS_SUCCESS)
3947 goto ERR;
3948 }
3949
3950 pipe->pipeline.acquire_isp_each_stage = false;
3951 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
3952
3953ERR:
3954 IA_CSS_LEAVE_ERR_PRIVATE(err);
3955 return err;
3956}
3957
3958static void send_raw_frames(struct ia_css_pipe *pipe)
3959{
3960 if (pipe->stream->config.continuous) {
3961 unsigned int i;
3962
3963 sh_css_update_host2sp_cont_num_raw_frames
3964 (pipe->stream->config.init_num_cont_raw_buf, true);
3965 sh_css_update_host2sp_cont_num_raw_frames
3966 (pipe->stream->config.target_num_cont_raw_buf, false);
3967
3968 /* Hand-over all the SP-internal buffers */
3969 for (i = 0; i < pipe->stream->config.init_num_cont_raw_buf; i++) {
3970 sh_css_update_host2sp_offline_frame(i,
3971 pipe->continuous_frames[i], pipe->cont_md_buffers[i]);
3972 }
3973 }
3974
3975 return;
3976}
3977
3978static enum ia_css_err
3979preview_start(struct ia_css_pipe *pipe)
3980{
3981 struct ia_css_pipeline *me ;
3982 struct ia_css_binary *copy_binary, *preview_binary, *vf_pp_binary = NULL;
3983 enum ia_css_err err = IA_CSS_SUCCESS;
3984 struct ia_css_pipe *copy_pipe, *capture_pipe;
3985 struct ia_css_pipe *acc_pipe;
3986 enum sh_css_pipe_config_override copy_ovrd;
3987 enum ia_css_input_mode preview_pipe_input_mode;
3988
3989 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3990 if ((pipe == NULL) || (pipe->stream == NULL) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) {
3991 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
3992 return IA_CSS_ERR_INVALID_ARGUMENTS;
3993 }
3994
3995 me = &pipe->pipeline;
3996
3997 preview_pipe_input_mode = pipe->stream->config.mode;
3998
3999 copy_pipe = pipe->pipe_settings.preview.copy_pipe;
4000 capture_pipe = pipe->pipe_settings.preview.capture_pipe;
4001 acc_pipe = pipe->pipe_settings.preview.acc_pipe;
4002
4003 copy_binary = &pipe->pipe_settings.preview.copy_binary;
4004 preview_binary = &pipe->pipe_settings.preview.preview_binary;
4005 if (pipe->pipe_settings.preview.vf_pp_binary.info)
4006 vf_pp_binary = &pipe->pipe_settings.preview.vf_pp_binary;
4007
4008 sh_css_metrics_start_frame();
4009
4010#if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
4011 /* multi stream video needs mipi buffers */
4012 err = send_mipi_frames(pipe);
4013 if (err != IA_CSS_SUCCESS)
4014 goto ERR;
4015#endif
4016 send_raw_frames(pipe);
4017
4018 {
4019 unsigned int thread_id;
4020
4021 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
4022 copy_ovrd = 1 << thread_id;
4023
4024 if (pipe->stream->cont_capt) {
4025 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe), &thread_id);
4026 copy_ovrd |= 1 << thread_id;
4027 }
4028 }
4029
4030 /* Construct and load the copy pipe */
4031 if (pipe->stream->config.continuous) {
4032 sh_css_sp_init_pipeline(&copy_pipe->pipeline,
4033 IA_CSS_PIPE_ID_COPY,
4034 (uint8_t)ia_css_pipe_get_pipe_num(copy_pipe),
4035 false,
4036 pipe->stream->config.pixels_per_clock == 2, false,
4037 false, pipe->required_bds_factor,
4038 copy_ovrd,
4039 pipe->stream->config.mode,
4040 &pipe->stream->config.metadata_config,
4041#ifndef ISP2401
4042 &pipe->stream->info.metadata_info
4043#else
4044 &pipe->stream->info.metadata_info,
4045#endif
4046#if !defined(HAS_NO_INPUT_SYSTEM)
4047#ifndef ISP2401
4048 , pipe->stream->config.source.port.port
4049#else
4050 pipe->stream->config.source.port.port,
4051#endif
4052#endif
4053#ifndef ISP2401
4054 );
4055#else
4056 &pipe->config.internal_frame_origin_bqs_on_sctbl,
4057 pipe->stream->isp_params_configs);
4058#endif
4059
4060 /* make the preview pipe start with mem mode input, copy handles
4061 the actual mode */
4062 preview_pipe_input_mode = IA_CSS_INPUT_MODE_MEMORY;
4063 }
4064
4065 /* Construct and load the capture pipe */
4066 if (pipe->stream->cont_capt) {
4067 sh_css_sp_init_pipeline(&capture_pipe->pipeline,
4068 IA_CSS_PIPE_ID_CAPTURE,
4069 (uint8_t)ia_css_pipe_get_pipe_num(capture_pipe),
4070 capture_pipe->config.default_capture_config.enable_xnr != 0,
4071 capture_pipe->stream->config.pixels_per_clock == 2,
4072 true, /* continuous */
4073 false, /* offline */
4074 capture_pipe->required_bds_factor,
4075 0,
4076 IA_CSS_INPUT_MODE_MEMORY,
4077 &pipe->stream->config.metadata_config,
4078#ifndef ISP2401
4079 &pipe->stream->info.metadata_info
4080#else
4081 &pipe->stream->info.metadata_info,
4082#endif
4083#if !defined(HAS_NO_INPUT_SYSTEM)
4084#ifndef ISP2401
4085 , (mipi_port_ID_t)0
4086#else
4087 (mipi_port_ID_t)0,
4088#endif
4089#endif
4090#ifndef ISP2401
4091 );
4092#else
4093 &capture_pipe->config.internal_frame_origin_bqs_on_sctbl,
4094 capture_pipe->stream->isp_params_configs);
4095#endif
4096 }
4097
4098 if (acc_pipe) {
4099 sh_css_sp_init_pipeline(&acc_pipe->pipeline,
4100 IA_CSS_PIPE_ID_ACC,
4101 (uint8_t) ia_css_pipe_get_pipe_num(acc_pipe),
4102 false,
4103 pipe->stream->config.pixels_per_clock == 2,
4104 false, /* continuous */
4105 false, /* offline */
4106 pipe->required_bds_factor,
4107 0,
4108 IA_CSS_INPUT_MODE_MEMORY,
4109 NULL,
4110#ifndef ISP2401
4111 NULL
4112#else
4113 NULL,
4114#endif
4115#if !defined(HAS_NO_INPUT_SYSTEM)
4116#ifndef ISP2401
4117 , (mipi_port_ID_t) 0
4118#else
4119 (mipi_port_ID_t) 0,
4120#endif
4121#endif
4122#ifndef ISP2401
4123 );
4124#else
4125 &pipe->config.internal_frame_origin_bqs_on_sctbl,
4126 pipe->stream->isp_params_configs);
4127#endif
4128 }
4129
4130 start_pipe(pipe, copy_ovrd, preview_pipe_input_mode);
4131
4132#if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
4133ERR:
4134#endif
4135 IA_CSS_LEAVE_ERR_PRIVATE(err);
4136 return err;
4137}
4138
4139enum ia_css_err
4140ia_css_pipe_enqueue_buffer(struct ia_css_pipe *pipe,
4141 const struct ia_css_buffer *buffer)
4142{
4143 enum ia_css_err return_err = IA_CSS_SUCCESS;
4144 unsigned int thread_id;
4145 enum sh_css_queue_id queue_id;
4146 struct ia_css_pipeline *pipeline;
4147 struct ia_css_pipeline_stage *stage;
4148 struct ia_css_rmgr_vbuf_handle p_vbuf;
4149 struct ia_css_rmgr_vbuf_handle *h_vbuf;
4150 struct sh_css_hmm_buffer ddr_buffer;
4151 enum ia_css_buffer_type buf_type;
4152 enum ia_css_pipe_id pipe_id;
4153 bool ret_err;
4154
4155 IA_CSS_ENTER("pipe=%p, buffer=%p", pipe, buffer);
4156
4157 if ((pipe == NULL) || (buffer == NULL)) {
4158 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4159 return IA_CSS_ERR_INVALID_ARGUMENTS;
4160 }
4161
4162 buf_type = buffer->type;
4163 /* following code will be enabled when IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME
4164 is removed */
4165#if 0
4166 if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) {
4167 bool found_pipe = false;
4168 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
4169 if ((buffer->data.frame->info.res.width == pipe->output_info[i].res.width) &&
4170 (buffer->data.frame->info.res.height == pipe->output_info[i].res.height)) {
4171 buf_type += i;
4172 found_pipe = true;
4173 break;
4174 }
4175 }
4176 if (!found_pipe)
4177 return IA_CSS_ERR_INVALID_ARGUMENTS;
4178 }
4179 if (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME) {
4180 bool found_pipe = false;
4181 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
4182 if ((buffer->data.frame->info.res.width == pipe->vf_output_info[i].res.width) &&
4183 (buffer->data.frame->info.res.height == pipe->vf_output_info[i].res.height)) {
4184 buf_type += i;
4185 found_pipe = true;
4186 break;
4187 }
4188 }
4189 if (!found_pipe)
4190 return IA_CSS_ERR_INVALID_ARGUMENTS;
4191 }
4192#endif
4193 pipe_id = pipe->mode;
4194
4195 IA_CSS_LOG("pipe_id=%d, buf_type=%d", pipe_id, buf_type);
4196
4197
4198 assert(pipe_id < IA_CSS_PIPE_ID_NUM);
4199 assert(buf_type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE);
4200 if ((buf_type == IA_CSS_BUFFER_TYPE_INVALID) ||
4201 (buf_type >= IA_CSS_NUM_DYNAMIC_BUFFER_TYPE) ||
4202 (pipe_id >= IA_CSS_PIPE_ID_NUM)) {
4203 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR);
4204 return IA_CSS_ERR_INTERNAL_ERROR;
4205 }
4206
4207 ret_err = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
4208 if (!ret_err) {
4209 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4210 return IA_CSS_ERR_INVALID_ARGUMENTS;
4211 }
4212
4213 ret_err = ia_css_query_internal_queue_id(buf_type, thread_id, &queue_id);
4214 if (!ret_err) {
4215 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4216 return IA_CSS_ERR_INVALID_ARGUMENTS;
4217 }
4218
4219 if ((queue_id <= SH_CSS_INVALID_QUEUE_ID) || (queue_id >= SH_CSS_MAX_NUM_QUEUES)) {
4220 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4221 return IA_CSS_ERR_INVALID_ARGUMENTS;
4222 }
4223
4224 if (!sh_css_sp_is_running()) {
4225 IA_CSS_LOG("SP is not running!");
4226 IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE);
4227 /* SP is not running. The queues are not valid */
4228 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4229 }
4230
4231
4232 pipeline = &pipe->pipeline;
4233
4234 assert(pipeline != NULL ||
4235 pipe_id == IA_CSS_PIPE_ID_COPY ||
4236 pipe_id == IA_CSS_PIPE_ID_ACC);
4237
4238 assert(sizeof(NULL) <= sizeof(ddr_buffer.kernel_ptr));
4239 ddr_buffer.kernel_ptr = HOST_ADDRESS(NULL);
4240 ddr_buffer.cookie_ptr = buffer->driver_cookie;
4241 ddr_buffer.timing_data = buffer->timing_data;
4242
4243 if (buf_type == IA_CSS_BUFFER_TYPE_3A_STATISTICS) {
4244 if (buffer->data.stats_3a == NULL) {
4245 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4246 return IA_CSS_ERR_INVALID_ARGUMENTS;
4247 }
4248 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.stats_3a);
4249 ddr_buffer.payload.s3a = *buffer->data.stats_3a;
4250 } else if (buf_type == IA_CSS_BUFFER_TYPE_DIS_STATISTICS) {
4251 if (buffer->data.stats_dvs == NULL) {
4252 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4253 return IA_CSS_ERR_INVALID_ARGUMENTS;
4254 }
4255 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.stats_dvs);
4256 ddr_buffer.payload.dis = *buffer->data.stats_dvs;
4257 } else if (buf_type == IA_CSS_BUFFER_TYPE_METADATA) {
4258 if (buffer->data.metadata == NULL) {
4259 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4260 return IA_CSS_ERR_INVALID_ARGUMENTS;
4261 }
4262 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.metadata);
4263 ddr_buffer.payload.metadata = *buffer->data.metadata;
4264 } else if ((buf_type == IA_CSS_BUFFER_TYPE_INPUT_FRAME)
4265 || (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
4266 || (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME)
4267 || (buf_type == IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME)
4268 || (buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME)) {
4269 if (buffer->data.frame == NULL) {
4270 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4271 return IA_CSS_ERR_INVALID_ARGUMENTS;
4272 }
4273 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.frame);
4274 ddr_buffer.payload.frame.frame_data = buffer->data.frame->data;
4275 ddr_buffer.payload.frame.flashed = 0;
4276
4277 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
4278 "ia_css_pipe_enqueue_buffer() buf_type=%d, data(DDR address)=0x%x\n",
4279 buf_type, buffer->data.frame->data);
4280
4281
4282#if CONFIG_ON_FRAME_ENQUEUE()
4283 return_err = set_config_on_frame_enqueue(
4284 &buffer->data.frame->info,
4285 &ddr_buffer.payload.frame);
4286 if (IA_CSS_SUCCESS != return_err) {
4287 IA_CSS_LEAVE_ERR(return_err);
4288 return return_err;
4289 }
4290#endif
4291 }
4292
4293 /* start of test for using rmgr for acq/rel memory */
4294 p_vbuf.vptr = 0;
4295 p_vbuf.count = 0;
4296 p_vbuf.size = sizeof(struct sh_css_hmm_buffer);
4297 h_vbuf = &p_vbuf;
4298 /* TODO: change next to correct pool for optimization */
4299 ia_css_rmgr_acq_vbuf(hmm_buffer_pool, &h_vbuf);
4300
4301 assert(h_vbuf != NULL);
4302 assert(h_vbuf->vptr != 0x0);
4303
4304 if ((h_vbuf == NULL) || (h_vbuf->vptr == 0x0)) {
4305 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR);
4306 return IA_CSS_ERR_INTERNAL_ERROR;
4307 }
4308
4309 mmgr_store(h_vbuf->vptr,
4310 (void *)(&ddr_buffer),
4311 sizeof(struct sh_css_hmm_buffer));
4312 if ((buf_type == IA_CSS_BUFFER_TYPE_3A_STATISTICS)
4313 || (buf_type == IA_CSS_BUFFER_TYPE_DIS_STATISTICS)
4314 || (buf_type == IA_CSS_BUFFER_TYPE_LACE_STATISTICS)) {
4315 if (pipeline == NULL) {
4316 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &h_vbuf);
4317 IA_CSS_LOG("pipeline is empty!");
4318 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR);
4319 return IA_CSS_ERR_INTERNAL_ERROR;
4320 }
4321
4322 for (stage = pipeline->stages; stage; stage = stage->next) {
4323 /* The SP will read the params
4324 after it got empty 3a and dis */
4325 if (STATS_ENABLED(stage)) {
4326 /* there is a stage that needs it */
4327 return_err = ia_css_bufq_enqueue_buffer(thread_id,
4328 queue_id,
4329 (uint32_t)h_vbuf->vptr);
4330 }
4331 }
4332 } else if ((buf_type == IA_CSS_BUFFER_TYPE_INPUT_FRAME)
b5eb7ac1
MCC
4333 || (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
4334 || (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME)
4335 || (buf_type == IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME)
4336 || (buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME)
4337 || (buf_type == IA_CSS_BUFFER_TYPE_METADATA)) {
4338
4339 return_err = ia_css_bufq_enqueue_buffer(thread_id,
a49d2536
AC
4340 queue_id,
4341 (uint32_t)h_vbuf->vptr);
4342#if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS)
4343 if ((return_err == IA_CSS_SUCCESS) && (IA_CSS_BUFFER_TYPE_OUTPUT_FRAME == buf_type)) {
4344 IA_CSS_LOG("pfp: enqueued OF %d to q %d thread %d",
4345 ddr_buffer.payload.frame.frame_data,
4346 queue_id, thread_id);
4347 }
4348#endif
4349
4350 }
4351
4352 if (return_err == IA_CSS_SUCCESS) {
0ef9e6e5
AC
4353 if (sh_css_hmm_buffer_record_acquire(
4354 h_vbuf, buf_type,
4355 HOST_ADDRESS(ddr_buffer.kernel_ptr))) {
158aeefc 4356 IA_CSS_LOG("send vbuf=%p", h_vbuf);
a49d2536
AC
4357 } else {
4358 return_err = IA_CSS_ERR_INTERNAL_ERROR;
4359 IA_CSS_ERROR("hmm_buffer_record[]: no available slots\n");
4360 }
4361 }
4362
4363 /*
4364 * Tell the SP which queues are not empty,
4365 * by sending the software event.
4366 */
4367 if (return_err == IA_CSS_SUCCESS) {
4368 if (!sh_css_sp_is_running()) {
4369 /* SP is not running. The queues are not valid */
4370 IA_CSS_LOG("SP is not running!");
4371 IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE);
4372 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4373 }
4374 return_err = ia_css_bufq_enqueue_psys_event(
4375 IA_CSS_PSYS_SW_EVENT_BUFFER_ENQUEUED,
4376 (uint8_t)thread_id,
4377 queue_id,
4378 0);
4379 } else {
4380 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &h_vbuf);
4381 IA_CSS_ERROR("buffer not enqueued");
4382 }
4383
4384 IA_CSS_LEAVE("return value = %d", return_err);
4385
4386 return return_err;
4387}
4388
4389/*
4390 * TODO: Free up the hmm memory space.
4391 */
4392enum ia_css_err
4393ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe,
4394 struct ia_css_buffer *buffer)
4395{
4396 enum ia_css_err return_err;
4397 enum sh_css_queue_id queue_id;
4398 hrt_vaddress ddr_buffer_addr = (hrt_vaddress)0;
4399 struct sh_css_hmm_buffer ddr_buffer;
4400 enum ia_css_buffer_type buf_type;
4401 enum ia_css_pipe_id pipe_id;
4402 unsigned int thread_id;
4403 hrt_address kernel_ptr = 0;
4404 bool ret_err;
4405
4406 IA_CSS_ENTER("pipe=%p, buffer=%p", pipe, buffer);
4407
4408 if ((pipe == NULL) || (buffer == NULL)) {
4409 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4410 return IA_CSS_ERR_INVALID_ARGUMENTS;
4411 }
4412
4413 pipe_id = pipe->mode;
4414
4415 buf_type = buffer->type;
4416
4417 IA_CSS_LOG("pipe_id=%d, buf_type=%d", pipe_id, buf_type);
4418
4419 ddr_buffer.kernel_ptr = 0;
4420
4421 ret_err = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
4422 if (!ret_err) {
4423 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4424 return IA_CSS_ERR_INVALID_ARGUMENTS;
4425 }
4426
4427 ret_err = ia_css_query_internal_queue_id(buf_type, thread_id, &queue_id);
4428 if (!ret_err) {
4429 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4430 return IA_CSS_ERR_INVALID_ARGUMENTS;
4431 }
4432
4433 if ((queue_id <= SH_CSS_INVALID_QUEUE_ID) || (queue_id >= SH_CSS_MAX_NUM_QUEUES)) {
4434 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4435 return IA_CSS_ERR_INVALID_ARGUMENTS;
4436 }
4437
4438 if (!sh_css_sp_is_running()) {
4439 IA_CSS_LOG("SP is not running!");
4440 IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE);
4441 /* SP is not running. The queues are not valid */
4442 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4443 }
4444
4445 return_err = ia_css_bufq_dequeue_buffer(queue_id,
4446 (uint32_t *)&ddr_buffer_addr);
4447
4448 if (return_err == IA_CSS_SUCCESS) {
4449 struct ia_css_frame *frame;
4450 struct sh_css_hmm_buffer_record *hmm_buffer_record = NULL;
4451
4452 IA_CSS_LOG("receive vbuf=%x", (int)ddr_buffer_addr);
4453
4454 /* Validate the ddr_buffer_addr and buf_type */
4455 hmm_buffer_record = sh_css_hmm_buffer_record_validate(
4456 ddr_buffer_addr, buf_type);
4457 if (hmm_buffer_record != NULL) {
4458 /* valid hmm_buffer_record found. Save the kernel_ptr
4459 * for validation after performing mmgr_load. The
4460 * vbuf handle and buffer_record can be released.
4461 */
4462 kernel_ptr = hmm_buffer_record->kernel_ptr;
4463 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &hmm_buffer_record->h_vbuf);
4464 sh_css_hmm_buffer_record_reset(hmm_buffer_record);
4465 } else {
158aeefc 4466 IA_CSS_ERROR("hmm_buffer_record not found (0x%u) buf_type(%d)",
a49d2536
AC
4467 ddr_buffer_addr, buf_type);
4468 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR);
4469 return IA_CSS_ERR_INTERNAL_ERROR;
4470 }
4471
4472 mmgr_load(ddr_buffer_addr,
4473 &ddr_buffer,
4474 sizeof(struct sh_css_hmm_buffer));
4475
4476 /* if the kernel_ptr is 0 or an invalid, return an error.
4477 * do not access the buffer via the kernal_ptr.
4478 */
4479 if ((ddr_buffer.kernel_ptr == 0) ||
4480 (kernel_ptr != HOST_ADDRESS(ddr_buffer.kernel_ptr))) {
4481 IA_CSS_ERROR("kernel_ptr invalid");
158aeefc
JP
4482 IA_CSS_ERROR("expected: (0x%llx)", (u64)kernel_ptr);
4483 IA_CSS_ERROR("actual: (0x%llx)", (u64)HOST_ADDRESS(ddr_buffer.kernel_ptr));
a49d2536
AC
4484 IA_CSS_ERROR("buf_type: %d\n", buf_type);
4485 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR);
4486 return IA_CSS_ERR_INTERNAL_ERROR;
4487 }
4488
4489 if (ddr_buffer.kernel_ptr != 0) {
4490 /* buffer->exp_id : all instances to be removed later once the driver change
4491 * is completed. See patch #5758 for reference */
4492 buffer->exp_id = 0;
4493 buffer->driver_cookie = ddr_buffer.cookie_ptr;
4494 buffer->timing_data = ddr_buffer.timing_data;
4495
4496 if ((buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) ||
4497 (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME)) {
4498 buffer->isys_eof_clock_tick.ticks = ddr_buffer.isys_eof_clock_tick;
4499 }
4500
4501 switch (buf_type) {
4502 case IA_CSS_BUFFER_TYPE_INPUT_FRAME:
4503 case IA_CSS_BUFFER_TYPE_OUTPUT_FRAME:
4504 case IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME:
4505 if ((pipe) && (pipe->stop_requested == true))
4506 {
4507
4508#if defined(USE_INPUT_SYSTEM_VERSION_2)
4509 /* free mipi frames only for old input system
4510 * for 2401 it is done in ia_css_stream_destroy call
4511 */
4512 return_err = free_mipi_frames(pipe);
4513 if (return_err != IA_CSS_SUCCESS) {
4514 IA_CSS_LOG("free_mipi_frames() failed");
4515 IA_CSS_LEAVE_ERR(return_err);
4516 return return_err;
4517 }
4518#endif
4519 pipe->stop_requested = false;
4520 }
4521 case IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME:
4522 case IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME:
4523 frame = (struct ia_css_frame*)HOST_ADDRESS(ddr_buffer.kernel_ptr);
4524 buffer->data.frame = frame;
4525 buffer->exp_id = ddr_buffer.payload.frame.exp_id;
4526 frame->exp_id = ddr_buffer.payload.frame.exp_id;
4527 frame->isp_config_id = ddr_buffer.payload.frame.isp_parameters_id;
4528 if (ddr_buffer.payload.frame.flashed == 1)
4529 frame->flash_state =
4530 IA_CSS_FRAME_FLASH_STATE_PARTIAL;
4531 if (ddr_buffer.payload.frame.flashed == 2)
4532 frame->flash_state =
4533 IA_CSS_FRAME_FLASH_STATE_FULL;
4534 frame->valid = pipe->num_invalid_frames == 0;
4535 if (!frame->valid)
4536 pipe->num_invalid_frames--;
4537
4538 if (frame->info.format == IA_CSS_FRAME_FORMAT_BINARY_8) {
4539#ifdef USE_INPUT_SYSTEM_VERSION_2401
4540 frame->planes.binary.size = frame->data_bytes;
4541#else
4542 frame->planes.binary.size =
4543 sh_css_sp_get_binary_copy_size();
4544#endif
4545 }
4546#if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS)
4547 if (IA_CSS_BUFFER_TYPE_OUTPUT_FRAME == buf_type) {
4548 IA_CSS_LOG("pfp: dequeued OF %d with config id %d thread %d",
4549 frame->data, frame->isp_config_id, thread_id);
4550 }
4551#endif
4552
4553 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
4554 "ia_css_pipe_dequeue_buffer() buf_type=%d, data(DDR address)=0x%x\n",
4555 buf_type, buffer->data.frame->data);
4556
4557 break;
4558 case IA_CSS_BUFFER_TYPE_3A_STATISTICS:
4559 buffer->data.stats_3a =
4560 (struct ia_css_isp_3a_statistics*)HOST_ADDRESS(ddr_buffer.kernel_ptr);
4561 buffer->exp_id = ddr_buffer.payload.s3a.exp_id;
4562 buffer->data.stats_3a->exp_id = ddr_buffer.payload.s3a.exp_id;
4563 buffer->data.stats_3a->isp_config_id = ddr_buffer.payload.s3a.isp_config_id;
4564 break;
4565 case IA_CSS_BUFFER_TYPE_DIS_STATISTICS:
4566 buffer->data.stats_dvs =
4567 (struct ia_css_isp_dvs_statistics*)
4568 HOST_ADDRESS(ddr_buffer.kernel_ptr);
4569 buffer->exp_id = ddr_buffer.payload.dis.exp_id;
4570 buffer->data.stats_dvs->exp_id = ddr_buffer.payload.dis.exp_id;
4571 break;
4572 case IA_CSS_BUFFER_TYPE_LACE_STATISTICS:
4573 break;
4574 case IA_CSS_BUFFER_TYPE_METADATA:
4575 buffer->data.metadata =
4576 (struct ia_css_metadata*)HOST_ADDRESS(ddr_buffer.kernel_ptr);
4577 buffer->exp_id = ddr_buffer.payload.metadata.exp_id;
4578 buffer->data.metadata->exp_id = ddr_buffer.payload.metadata.exp_id;
4579 break;
4580 default:
4581 return_err = IA_CSS_ERR_INTERNAL_ERROR;
4582 break;
4583 }
4584 }
4585 }
4586
4587 /*
4588 * Tell the SP which queues are not full,
4589 * by sending the software event.
4590 */
4591 if (return_err == IA_CSS_SUCCESS){
4592 if (!sh_css_sp_is_running()) {
4593 IA_CSS_LOG("SP is not running!");
4594 IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE);
4595 /* SP is not running. The queues are not valid */
4596 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4597 }
4598 ia_css_bufq_enqueue_psys_event(
4599 IA_CSS_PSYS_SW_EVENT_BUFFER_DEQUEUED,
4600 0,
4601 queue_id,
4602 0);
4603 }
4604 IA_CSS_LEAVE("buffer=%p", buffer);
4605
4606 return return_err;
4607}
4608
4609/*
4610 * Cannot Move this to event module as it is of ia_css_event_type which is declared in ia_css.h
4611 * TODO: modify and move it if possible.
4612 *
4613 * !!!IMPORTANT!!! KEEP THE FOLLOWING IN SYNC:
4614 * 1) "enum ia_css_event_type" (ia_css_event_public.h)
4615 * 2) "enum sh_css_sp_event_type" (sh_css_internal.h)
4616 * 3) "enum ia_css_event_type event_id_2_event_mask" (event_handler.sp.c)
4617 * 4) "enum ia_css_event_type convert_event_sp_to_host_domain" (sh_css.c)
4618 */
4619static enum ia_css_event_type convert_event_sp_to_host_domain[] = {
d929fb4e
MCC
4620 IA_CSS_EVENT_TYPE_OUTPUT_FRAME_DONE, /** Output frame ready. */
4621 IA_CSS_EVENT_TYPE_SECOND_OUTPUT_FRAME_DONE, /** Second output frame ready. */
4622 IA_CSS_EVENT_TYPE_VF_OUTPUT_FRAME_DONE, /** Viewfinder Output frame ready. */
4623 IA_CSS_EVENT_TYPE_SECOND_VF_OUTPUT_FRAME_DONE, /** Second viewfinder Output frame ready. */
4624 IA_CSS_EVENT_TYPE_3A_STATISTICS_DONE, /** Indication that 3A statistics are available. */
4625 IA_CSS_EVENT_TYPE_DIS_STATISTICS_DONE, /** Indication that DIS statistics are available. */
4626 IA_CSS_EVENT_TYPE_PIPELINE_DONE, /** Pipeline Done event, sent after last pipeline stage. */
4627 IA_CSS_EVENT_TYPE_FRAME_TAGGED, /** Frame tagged. */
4628 IA_CSS_EVENT_TYPE_INPUT_FRAME_DONE, /** Input frame ready. */
4629 IA_CSS_EVENT_TYPE_METADATA_DONE, /** Metadata ready. */
4630 IA_CSS_EVENT_TYPE_LACE_STATISTICS_DONE, /** Indication that LACE statistics are available. */
4631 IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE, /** Extension stage executed. */
4632 IA_CSS_EVENT_TYPE_TIMER, /** Timing measurement data. */
4633 IA_CSS_EVENT_TYPE_PORT_EOF, /** End Of Frame event, sent when in buffered sensor mode. */
4634 IA_CSS_EVENT_TYPE_FW_WARNING, /** Performance warning encountered by FW */
4635 IA_CSS_EVENT_TYPE_FW_ASSERT, /** Assertion hit by FW */
4636 0, /* error if sp passes SH_CSS_SP_EVENT_NR_OF_TYPES as a valid event. */
a49d2536
AC
4637};
4638
4639enum ia_css_err
4640ia_css_dequeue_event(struct ia_css_event *event)
4641{
4642 return ia_css_dequeue_psys_event(event);
4643}
4644
4645enum ia_css_err
4646ia_css_dequeue_psys_event(struct ia_css_event *event)
4647{
4648 enum ia_css_pipe_id pipe_id = 0;
4649 uint8_t payload[4] = {0,0,0,0};
4650 enum ia_css_err ret_err;
4651
4652 /*TODO:
4653 * a) use generic decoding function , same as the one used by sp.
4654 * b) group decode and dequeue into eventQueue module
4655 *
4656 * We skip the IA_CSS_ENTER logging call
4657 * to avoid flooding the logs when the host application
4658 * uses polling. */
4659 if (event == NULL)
4660 return IA_CSS_ERR_INVALID_ARGUMENTS;
4661
4662 if (!sh_css_sp_is_running()) {
4663 /* SP is not running. The queues are not valid */
4664 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4665 }
4666
4667 /* dequeue the event (if any) from the psys event queue */
4668 ret_err = ia_css_bufq_dequeue_psys_event(payload);
4669 if (ret_err != IA_CSS_SUCCESS)
4670 return ret_err;
4671
4672 IA_CSS_LOG("event dequeued from psys event queue");
4673
4674 /* Tell the SP that we dequeued an event from the event queue. */
4675 ia_css_bufq_enqueue_psys_event(
4676 IA_CSS_PSYS_SW_EVENT_EVENT_DEQUEUED, 0, 0, 0);
4677
4678 /* Events are decoded into 4 bytes of payload, the first byte
4679 * contains the sp event type. This is converted to a host enum.
4680 * TODO: can this enum conversion be eliminated */
4681 event->type = convert_event_sp_to_host_domain[payload[0]];
4682 /* Some sane default values since not all events use all fields. */
4683 event->pipe = NULL;
4684 event->port = IA_CSS_CSI2_PORT0;
4685 event->exp_id = 0;
4686 event->fw_warning = IA_CSS_FW_WARNING_NONE;
4687 event->fw_handle = 0;
4688 event->timer_data = 0;
4689 event->timer_code = 0;
4690 event->timer_subcode = 0;
4691
4692 if (event->type == IA_CSS_EVENT_TYPE_TIMER) {
4693 /* timer event ??? get the 2nd event and decode the data into the event struct */
4694 uint32_t tmp_data;
4695 /* 1st event: LSB 16-bit timer data and code */
4696 event->timer_data = ((payload[1] & 0xFF) | ((payload[3] & 0xFF) << 8));
4697 event->timer_code = payload[2];
4698 payload[0] = payload[1] = payload[2] = payload[3] = 0;
4699 ret_err = ia_css_bufq_dequeue_psys_event(payload);
4700 if (ret_err != IA_CSS_SUCCESS) {
4701 /* no 2nd event ??? an error */
4702 /* Putting IA_CSS_ERROR is resulting in failures in
4703 * Merrifield smoke testing */
4704 IA_CSS_WARNING("Timer: Error de-queuing the 2nd TIMER event!!!\n");
4705 return ret_err;
4706 }
4707 ia_css_bufq_enqueue_psys_event(
4708 IA_CSS_PSYS_SW_EVENT_EVENT_DEQUEUED, 0, 0, 0);
4709 event->type = convert_event_sp_to_host_domain[payload[0]];
4710 /* It's a timer */
4711 if (event->type == IA_CSS_EVENT_TYPE_TIMER) {
4712 /* 2nd event data: MSB 16-bit timer and subcode */
4713 tmp_data = ((payload[1] & 0xFF) | ((payload[3] & 0xFF) << 8));
4714 event->timer_data |= (tmp_data << 16);
4715 event->timer_subcode = payload[2];
4716 }
4717 /* It's a non timer event. So clear first half of the timer event data.
4718 * If the second part of the TIMER event is not recieved, we discard
4719 * the first half of the timer data and process the non timer event without
4720 * affecting the flow. So the non timer event falls through
4721 * the code. */
4722 else {
4723 event->timer_data = 0;
4724 event->timer_code = 0;
4725 event->timer_subcode = 0;
4726 IA_CSS_ERROR("Missing 2nd timer event. Timer event discarded");
4727 }
4728 }
4729 if (event->type == IA_CSS_EVENT_TYPE_PORT_EOF) {
4730 event->port = (enum ia_css_csi2_port)payload[1];
4731 event->exp_id = payload[3];
4732 } else if (event->type == IA_CSS_EVENT_TYPE_FW_WARNING) {
4733 event->fw_warning = (enum ia_css_fw_warning)payload[1];
4734 /* exp_id is only available in these warning types */
4735 if (event->fw_warning == IA_CSS_FW_WARNING_EXP_ID_LOCKED ||
4736 event->fw_warning == IA_CSS_FW_WARNING_TAG_EXP_ID_FAILED)
4737 event->exp_id = payload[3];
4738 } else if (event->type == IA_CSS_EVENT_TYPE_FW_ASSERT) {
4739 event->fw_assert_module_id = payload[1]; /* module */
4740 event->fw_assert_line_no = (payload[2] << 8) + payload[3];
4741 /* payload[2] is line_no>>8, payload[3] is line_no&0xff */
4742 } else if (event->type != IA_CSS_EVENT_TYPE_TIMER) {
4743 /* pipe related events.
4744 * payload[1] contains the pipe_num,
4745 * payload[2] contains the pipe_id. These are different. */
4746 event->pipe = find_pipe_by_num(payload[1]);
4747 pipe_id = (enum ia_css_pipe_id)payload[2];
4748 /* Check to see if pipe still exists */
4749 if (!event->pipe)
4750 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4751
4752 if (event->type == IA_CSS_EVENT_TYPE_FRAME_TAGGED) {
4753 /* find the capture pipe that goes with this */
4754 int i, n;
4755 n = event->pipe->stream->num_pipes;
4756 for (i = 0; i < n; i++) {
4757 struct ia_css_pipe *p =
4758 event->pipe->stream->pipes[i];
4759 if (p->config.mode == IA_CSS_PIPE_MODE_CAPTURE) {
4760 event->pipe = p;
4761 break;
4762 }
4763 }
4764 event->exp_id = payload[3];
4765 }
4766 if (event->type == IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE) {
4767 /* payload[3] contains the acc fw handle. */
4768 uint32_t stage_num = (uint32_t)payload[3];
4769 ret_err = ia_css_pipeline_get_fw_from_stage(
4770 &(event->pipe->pipeline),
4771 stage_num,
4772 &(event->fw_handle));
4773 if (ret_err != IA_CSS_SUCCESS) {
4774 IA_CSS_ERROR("Invalid stage num received for ACC event. stage_num:%u",
4775 stage_num);
4776 return ret_err;
4777 }
4778 }
4779 }
4780
4781 if (event->pipe)
4782 IA_CSS_LEAVE("event_id=%d, pipe_id=%d", event->type, pipe_id);
4783 else
4784 IA_CSS_LEAVE("event_id=%d", event->type);
4785
4786 return IA_CSS_SUCCESS;
4787}
4788
4789enum ia_css_err
4790ia_css_dequeue_isys_event(struct ia_css_event *event)
4791{
4792 uint8_t payload[4] = {0, 0, 0, 0};
4793 enum ia_css_err err = IA_CSS_SUCCESS;
4794
4795 /* We skip the IA_CSS_ENTER logging call
4796 * to avoid flooding the logs when the host application
4797 * uses polling. */
4798 if (event == NULL)
4799 return IA_CSS_ERR_INVALID_ARGUMENTS;
4800
4801 if (!sh_css_sp_is_running()) {
4802 /* SP is not running. The queues are not valid */
4803 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4804 }
4805
4806 err = ia_css_bufq_dequeue_isys_event(payload);
4807 if (err != IA_CSS_SUCCESS)
4808 return err;
4809
4810 IA_CSS_LOG("event dequeued from isys event queue");
4811
4812 /* Update SP state to indicate that element was dequeued. */
4813 ia_css_bufq_enqueue_isys_event(IA_CSS_ISYS_SW_EVENT_EVENT_DEQUEUED);
4814
4815 /* Fill return struct with appropriate info */
4816 event->type = IA_CSS_EVENT_TYPE_PORT_EOF;
4817 /* EOF events are associated with a CSI port, not with a pipe */
4818 event->pipe = NULL;
4819 event->port = payload[1];
4820 event->exp_id = payload[3];
4821
4822 IA_CSS_LEAVE_ERR(err);
4823 return err;
4824}
4825
4826static void
4827acc_start(struct ia_css_pipe *pipe)
4828{
4829 assert(pipe != NULL);
4830 assert(pipe->stream != NULL);
4831
4832 start_pipe(pipe, SH_CSS_PIPE_CONFIG_OVRD_NO_OVRD,
4833 pipe->stream->config.mode);
4834}
4835
4836static enum ia_css_err
4837sh_css_pipe_start(struct ia_css_stream *stream)
4838{
4839 enum ia_css_err err = IA_CSS_SUCCESS;
4840
4841 struct ia_css_pipe *pipe;
4842 enum ia_css_pipe_id pipe_id;
4843 unsigned int thread_id;
4844
4845 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
4846
4847 if (stream == NULL) {
4848 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4849 return IA_CSS_ERR_INVALID_ARGUMENTS;
4850 }
4851 pipe = stream->last_pipe;
4852 if (pipe == NULL) {
4853 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4854 return IA_CSS_ERR_INVALID_ARGUMENTS;
4855 }
4856
4857 pipe_id = pipe->mode;
4858
4859 if(stream->started == true) {
4860 IA_CSS_WARNING("Cannot start stream that is already started");
4861 IA_CSS_LEAVE_ERR(err);
4862 return err;
4863 }
4864
4865 pipe->stop_requested = false;
4866
4867 switch (pipe_id) {
4868 case IA_CSS_PIPE_ID_PREVIEW:
4869 err = preview_start(pipe);
4870 break;
4871 case IA_CSS_PIPE_ID_VIDEO:
4872 err = video_start(pipe);
4873 break;
4874 case IA_CSS_PIPE_ID_CAPTURE:
4875 err = capture_start(pipe);
4876 break;
4877 case IA_CSS_PIPE_ID_YUVPP:
4878 err = yuvpp_start(pipe);
4879 break;
4880 case IA_CSS_PIPE_ID_ACC:
4881 acc_start(pipe);
4882 break;
4883 default:
4884 err = IA_CSS_ERR_INVALID_ARGUMENTS;
4885 }
4886 /* DH regular multi pipe - not continuous mode: start the next pipes too */
4887 if (!stream->config.continuous) {
4888 int i;
4889 for (i = 1; i < stream->num_pipes && IA_CSS_SUCCESS == err ; i++) {
4890 switch (stream->pipes[i]->mode) {
4891 case IA_CSS_PIPE_ID_PREVIEW:
4892 stream->pipes[i]->stop_requested = false;
4893 err = preview_start(stream->pipes[i]);
4894 break;
4895 case IA_CSS_PIPE_ID_VIDEO:
4896 stream->pipes[i]->stop_requested = false;
4897 err = video_start(stream->pipes[i]);
4898 break;
4899 case IA_CSS_PIPE_ID_CAPTURE:
4900 stream->pipes[i]->stop_requested = false;
4901 err = capture_start(stream->pipes[i]);
4902 break;
4903 case IA_CSS_PIPE_ID_YUVPP:
4904 stream->pipes[i]->stop_requested = false;
4905 err = yuvpp_start(stream->pipes[i]);
4906 break;
4907 case IA_CSS_PIPE_ID_ACC:
4908 stream->pipes[i]->stop_requested = false;
4909 acc_start(stream->pipes[i]);
4910 break;
4911 default:
4912 err = IA_CSS_ERR_INVALID_ARGUMENTS;
4913 }
4914 }
4915 }
4916 if (err != IA_CSS_SUCCESS) {
4917 IA_CSS_LEAVE_ERR_PRIVATE(err);
4918 return err;
4919 }
4920
4921 /* Force ISP parameter calculation after a mode change
4922 * Acceleration API examples pass NULL for stream but they
4923 * don't use ISP parameters anyway. So this should be okay.
4924 * The SP binary (jpeg) copy does not use any parameters.
4925 */
4926 if (!copy_on_sp(pipe)) {
4927 sh_css_invalidate_params(stream);
4928 err = sh_css_param_update_isp_params(pipe,
4929 stream->isp_params_configs, true, NULL);
4930 if (err != IA_CSS_SUCCESS) {
4931 IA_CSS_LEAVE_ERR_PRIVATE(err);
4932 return err;
4933 }
4934 }
4935
4936 ia_css_debug_pipe_graph_dump_epilogue();
4937
4938 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
4939
4940 if (!sh_css_sp_is_running()) {
4941 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE);
4942 /* SP is not running. The queues are not valid */
4943 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4944 }
4945 ia_css_bufq_enqueue_psys_event(IA_CSS_PSYS_SW_EVENT_START_STREAM,
4946 (uint8_t)thread_id, 0, 0);
4947
4948 /* DH regular multi pipe - not continuous mode: enqueue event to the next pipes too */
4949 if (!stream->config.continuous) {
4950 int i;
4951 for (i = 1; i < stream->num_pipes; i++) {
4952 ia_css_pipeline_get_sp_thread_id(
4953 ia_css_pipe_get_pipe_num(stream->pipes[i]),
4954 &thread_id);
4955 ia_css_bufq_enqueue_psys_event(
4956 IA_CSS_PSYS_SW_EVENT_START_STREAM,
4957 (uint8_t)thread_id, 0, 0);
4958 }
4959 }
4960
4961 /* in case of continuous capture mode, we also start capture thread and copy thread*/
4962 if (pipe->stream->config.continuous) {
4963 struct ia_css_pipe *copy_pipe = NULL;
4964
4965 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
4966 copy_pipe = pipe->pipe_settings.preview.copy_pipe;
4967 else if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
4968 copy_pipe = pipe->pipe_settings.video.copy_pipe;
4969
4970 if (copy_pipe == NULL) {
4971 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR);
4972 return IA_CSS_ERR_INTERNAL_ERROR;
4973 }
4974 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(copy_pipe), &thread_id);
4975 /* by the time we reach here q is initialized and handle is available.*/
4976 ia_css_bufq_enqueue_psys_event(
4977 IA_CSS_PSYS_SW_EVENT_START_STREAM,
4978 (uint8_t)thread_id, 0, 0);
4979 }
4980 if (pipe->stream->cont_capt) {
4981 struct ia_css_pipe *capture_pipe = NULL;
4982 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
4983 capture_pipe = pipe->pipe_settings.preview.capture_pipe;
4984 else if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
4985 capture_pipe = pipe->pipe_settings.video.capture_pipe;
4986
4987 if (capture_pipe == NULL) {
4988 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR);
4989 return IA_CSS_ERR_INTERNAL_ERROR;
4990 }
4991 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe), &thread_id);
4992 /* by the time we reach here q is initialized and handle is available.*/
4993 ia_css_bufq_enqueue_psys_event(
4994 IA_CSS_PSYS_SW_EVENT_START_STREAM,
4995 (uint8_t)thread_id, 0, 0);
4996 }
4997
4998 /* in case of PREVIEW mode, check whether QOS acc_pipe is available, then start the qos pipe */
4999 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) {
5000 struct ia_css_pipe *acc_pipe = NULL;
5001 acc_pipe = pipe->pipe_settings.preview.acc_pipe;
5002
5003 if (acc_pipe){
5004 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(acc_pipe), &thread_id);
5005 /* by the time we reach here q is initialized and handle is available.*/
5006 ia_css_bufq_enqueue_psys_event(
5007 IA_CSS_PSYS_SW_EVENT_START_STREAM,
5008 (uint8_t) thread_id, 0, 0);
5009 }
5010 }
5011
5012 stream->started = true;
5013
5014 IA_CSS_LEAVE_ERR_PRIVATE(err);
5015 return err;
5016}
5017
5018#ifndef ISP2401
5019void
5020sh_css_enable_cont_capt(bool enable, bool stop_copy_preview)
5021{
5022 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5023 "sh_css_enable_cont_capt() enter: enable=%d\n", enable);
5024//my_css.cont_capt = enable;
5025 my_css.stop_copy_preview = stop_copy_preview;
5026}
5027
5028bool
5029sh_css_continuous_is_enabled(uint8_t pipe_num)
5030#else
d929fb4e 5031/*
a49d2536
AC
5032 * @brief Stop all "ia_css_pipe" instances in the target
5033 * "ia_css_stream" instance.
5034 *
5035 * Refer to "Local prototypes" for more info.
5036 */
5037static enum ia_css_err
5038sh_css_pipes_stop(struct ia_css_stream *stream)
5039#endif
5040{
5041#ifndef ISP2401
5042 struct ia_css_pipe *pipe;
5043 bool continuous;
5044#else
5045 enum ia_css_err err = IA_CSS_SUCCESS;
5046 struct ia_css_pipe *main_pipe;
5047 enum ia_css_pipe_id main_pipe_id;
5048 int i;
5049#endif
5050
5051#ifndef ISP2401
5052 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_continuous_is_enabled() enter: pipe_num=%d\n", pipe_num);
5053#else
5054 assert(stream != NULL);
5055 if (stream == NULL) {
5056 IA_CSS_LOG("stream does NOT exist!");
5057 err = IA_CSS_ERR_INTERNAL_ERROR;
5058 goto ERR;
5059 }
5060#endif
5061
5062#ifndef ISP2401
5063 pipe = find_pipe_by_num(pipe_num);
5064 continuous = pipe && pipe->stream->config.continuous;
5065 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5066 "sh_css_continuous_is_enabled() leave: enable=%d\n",
5067 continuous);
5068 return continuous;
5069}
5070#else
5071 main_pipe = stream->last_pipe;
5072 assert(main_pipe != NULL);
5073 if (main_pipe == NULL) {
5074 IA_CSS_LOG("main_pipe does NOT exist!");
5075 err = IA_CSS_ERR_INTERNAL_ERROR;
5076 goto ERR;
5077 }
5078#endif
5079
5080#ifndef ISP2401
5081enum ia_css_err
5082ia_css_stream_get_max_buffer_depth(struct ia_css_stream *stream, int *buffer_depth)
5083{
5084 if (buffer_depth == NULL)
5085 return IA_CSS_ERR_INVALID_ARGUMENTS;
5086 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_max_buffer_depth() enter: void\n");
5087 (void)stream;
5088 *buffer_depth = NUM_CONTINUOUS_FRAMES;
5089 return IA_CSS_SUCCESS;
5090}
5091#else
5092 main_pipe_id = main_pipe->mode;
5093 IA_CSS_ENTER_PRIVATE("main_pipe_id=%d", main_pipe_id);
5094#endif
5095
5096#ifndef ISP2401
5097enum ia_css_err
5098ia_css_stream_set_buffer_depth(struct ia_css_stream *stream, int buffer_depth)
5099{
5100 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_set_buffer_depth() enter: num_frames=%d\n",buffer_depth);
5101 (void)stream;
5102 if (buffer_depth > NUM_CONTINUOUS_FRAMES || buffer_depth < 1)
5103 return IA_CSS_ERR_INVALID_ARGUMENTS;
5104 /* ok, value allowed */
5105 stream->config.target_num_cont_raw_buf = buffer_depth;
5106 /* TODO: check what to regarding initialization */
5107 return IA_CSS_SUCCESS;
5108}
5109#else
d929fb4e 5110 /*
a49d2536
AC
5111 * Stop all "ia_css_pipe" instances in this target
5112 * "ia_css_stream" instance.
5113 */
5114 for (i = 0; i < stream->num_pipes; i++) {
5115 /* send the "stop" request to the "ia_css_pipe" instance */
5116 IA_CSS_LOG("Send the stop-request to the pipe: pipe_id=%d",
5117 stream->pipes[i]->pipeline.pipe_id);
5118 err = ia_css_pipeline_request_stop(&stream->pipes[i]->pipeline);
5119#endif
5120
5121#ifndef ISP2401
5122enum ia_css_err
5123ia_css_stream_get_buffer_depth(struct ia_css_stream *stream, int *buffer_depth)
5124{
5125 if (buffer_depth == NULL)
5126 return IA_CSS_ERR_INVALID_ARGUMENTS;
5127 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_buffer_depth() enter: void\n");
5128#else
5129 /*
5130 * Exit this loop if "ia_css_pipeline_request_stop()"
5131 * returns the error code.
5132 *
5133 * The error code would be generated in the following
5134 * two cases:
5135 * (1) The Scalar Processor has already been stopped.
5136 * (2) The "Host->SP" event queue is full.
5137 *
5138 * As the convention of using CSS API 2.0/2.1, such CSS
5139 * error code would be propogated from the CSS-internal
5140 * API returned value to the CSS API returned value. Then
5141 * the CSS driver should capture these error code and
5142 * handle it in the driver exception handling mechanism.
5143 */
5144 if (err != IA_CSS_SUCCESS) {
5145 goto ERR;
5146 }
5147 }
5148
d929fb4e 5149 /*
a49d2536
AC
5150 * In the CSS firmware use scenario "Continuous Preview"
5151 * as well as "Continuous Video", the "ia_css_pipe" instance
5152 * "Copy Pipe" is activated. This "Copy Pipe" is private to
5153 * the CSS firmware so that it is not listed in the target
5154 * "ia_css_stream" instance.
5155 *
5156 * We need to stop this "Copy Pipe", as well.
5157 */
5158 if (main_pipe->stream->config.continuous) {
5159 struct ia_css_pipe *copy_pipe = NULL;
5160
5161 /* get the reference to "Copy Pipe" */
5162 if (main_pipe_id == IA_CSS_PIPE_ID_PREVIEW)
5163 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
5164 else if (main_pipe_id == IA_CSS_PIPE_ID_VIDEO)
5165 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
5166
5167 /* return the error code if "Copy Pipe" does NOT exist */
5168 assert(copy_pipe != NULL);
5169 if (copy_pipe == NULL) {
5170 IA_CSS_LOG("Copy Pipe does NOT exist!");
5171 err = IA_CSS_ERR_INTERNAL_ERROR;
5172 goto ERR;
5173 }
5174
5175 /* send the "stop" request to "Copy Pipe" */
5176 IA_CSS_LOG("Send the stop-request to the pipe: pipe_id=%d",
5177 copy_pipe->pipeline.pipe_id);
5178 err = ia_css_pipeline_request_stop(&copy_pipe->pipeline);
5179 }
5180
5181ERR:
5182 IA_CSS_LEAVE_ERR_PRIVATE(err);
5183 return err;
5184}
5185
d929fb4e 5186/*
a49d2536
AC
5187 * @brief Check if all "ia_css_pipe" instances in the target
5188 * "ia_css_stream" instance have stopped.
5189 *
5190 * Refer to "Local prototypes" for more info.
5191 */
5192static bool
5193sh_css_pipes_have_stopped(struct ia_css_stream *stream)
5194{
5195 bool rval = true;
5196
5197 struct ia_css_pipe *main_pipe;
5198 enum ia_css_pipe_id main_pipe_id;
5199
5200 int i;
5201
5202 assert(stream != NULL);
5203 if (stream == NULL) {
5204 IA_CSS_LOG("stream does NOT exist!");
5205 rval = false;
5206 goto RET;
5207 }
5208
5209 main_pipe = stream->last_pipe;
5210 assert(main_pipe != NULL);
5211
5212 if (main_pipe == NULL) {
5213 IA_CSS_LOG("main_pipe does NOT exist!");
5214 rval = false;
5215 goto RET;
5216 }
5217
5218 main_pipe_id = main_pipe->mode;
5219 IA_CSS_ENTER_PRIVATE("main_pipe_id=%d", main_pipe_id);
5220
d929fb4e 5221 /*
a49d2536
AC
5222 * Check if every "ia_css_pipe" instance in this target
5223 * "ia_css_stream" instance has stopped.
5224 */
5225 for (i = 0; i < stream->num_pipes; i++) {
5226 rval = rval && ia_css_pipeline_has_stopped(&stream->pipes[i]->pipeline);
5227 IA_CSS_LOG("Pipe has stopped: pipe_id=%d, stopped=%d",
5228 stream->pipes[i]->pipeline.pipe_id,
5229 rval);
5230 }
5231
d929fb4e 5232 /*
a49d2536
AC
5233 * In the CSS firmware use scenario "Continuous Preview"
5234 * as well as "Continuous Video", the "ia_css_pipe" instance
5235 * "Copy Pipe" is activated. This "Copy Pipe" is private to
5236 * the CSS firmware so that it is not listed in the target
5237 * "ia_css_stream" instance.
5238 *
5239 * We need to check if this "Copy Pipe" has stopped, as well.
5240 */
5241 if (main_pipe->stream->config.continuous) {
5242 struct ia_css_pipe *copy_pipe = NULL;
5243
5244 /* get the reference to "Copy Pipe" */
5245 if (main_pipe_id == IA_CSS_PIPE_ID_PREVIEW)
5246 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
5247 else if (main_pipe_id == IA_CSS_PIPE_ID_VIDEO)
5248 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
5249
5250 /* return if "Copy Pipe" does NOT exist */
5251 assert(copy_pipe != NULL);
5252 if (copy_pipe == NULL) {
5253 IA_CSS_LOG("Copy Pipe does NOT exist!");
5254
5255 rval = false;
5256 goto RET;
5257 }
5258
5259 /* check if "Copy Pipe" has stopped or not */
5260 rval = rval && ia_css_pipeline_has_stopped(&copy_pipe->pipeline);
5261 IA_CSS_LOG("Pipe has stopped: pipe_id=%d, stopped=%d",
5262 copy_pipe->pipeline.pipe_id,
5263 rval);
5264 }
5265
5266RET:
5267 IA_CSS_LEAVE_PRIVATE("rval=%d", rval);
5268 return rval;
5269}
5270
5271bool
5272sh_css_continuous_is_enabled(uint8_t pipe_num)
5273{
5274 struct ia_css_pipe *pipe;
5275 bool continuous;
5276
5277 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_continuous_is_enabled() enter: pipe_num=%d\n", pipe_num);
5278
5279 pipe = find_pipe_by_num(pipe_num);
5280 continuous = pipe && pipe->stream->config.continuous;
5281 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5282 "sh_css_continuous_is_enabled() leave: enable=%d\n",
5283 continuous);
5284 return continuous;
5285}
5286
5287enum ia_css_err
5288ia_css_stream_get_max_buffer_depth(struct ia_css_stream *stream, int *buffer_depth)
5289{
5290 if (buffer_depth == NULL)
5291 return IA_CSS_ERR_INVALID_ARGUMENTS;
5292 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_max_buffer_depth() enter: void\n");
5293 (void)stream;
5294 *buffer_depth = NUM_CONTINUOUS_FRAMES;
5295 return IA_CSS_SUCCESS;
5296}
5297
5298enum ia_css_err
5299ia_css_stream_set_buffer_depth(struct ia_css_stream *stream, int buffer_depth)
5300{
5301 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_set_buffer_depth() enter: num_frames=%d\n",buffer_depth);
5302 (void)stream;
5303 if (buffer_depth > NUM_CONTINUOUS_FRAMES || buffer_depth < 1)
5304 return IA_CSS_ERR_INVALID_ARGUMENTS;
5305 /* ok, value allowed */
5306 stream->config.target_num_cont_raw_buf = buffer_depth;
5307 /* TODO: check what to regarding initialization */
5308 return IA_CSS_SUCCESS;
5309}
5310
5311enum ia_css_err
5312ia_css_stream_get_buffer_depth(struct ia_css_stream *stream, int *buffer_depth)
5313{
5314 if (buffer_depth == NULL)
5315 return IA_CSS_ERR_INVALID_ARGUMENTS;
5316 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_buffer_depth() enter: void\n");
5317#endif
5318 (void)stream;
5319 *buffer_depth = stream->config.target_num_cont_raw_buf;
5320 return IA_CSS_SUCCESS;
5321}
5322
5323#if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
5324unsigned int
5325sh_css_get_mipi_sizes_for_check(const unsigned int port, const unsigned int idx)
5326{
5327 OP___assert(port < N_CSI_PORTS);
5328 OP___assert(idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT);
5329 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "sh_css_get_mipi_sizes_for_check(port %d, idx %d): %d\n",
5330 port, idx, my_css.mipi_sizes_for_check[port][idx]);
5331 return my_css.mipi_sizes_for_check[port][idx];
5332}
5333#endif
5334
5335static enum ia_css_err sh_css_pipe_configure_output(
5336 struct ia_css_pipe *pipe,
5337 unsigned int width,
5338 unsigned int height,
5339 unsigned int padded_width,
5340 enum ia_css_frame_format format,
5341 unsigned int idx)
5342{
5343 enum ia_css_err err = IA_CSS_SUCCESS;
5344
5345 IA_CSS_ENTER_PRIVATE("pipe = %p, width = %d, height = %d, paddaed width = %d, format = %d, idx = %d",
5346 pipe, width, height, padded_width, format, idx);
5347 if (pipe == NULL) {
5348 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
5349 return IA_CSS_ERR_INVALID_ARGUMENTS;
5350 }
5351
5352 err = ia_css_util_check_res(width, height);
5353 if (err != IA_CSS_SUCCESS) {
5354 IA_CSS_LEAVE_ERR_PRIVATE(err);
5355 return err;
5356 }
5357 if (pipe->output_info[idx].res.width != width ||
5358 pipe->output_info[idx].res.height != height ||
5359 pipe->output_info[idx].format != format)
5360 {
5361 ia_css_frame_info_init(
5362 &pipe->output_info[idx],
5363 width,
5364 height,
5365 format,
5366 padded_width);
5367 }
5368 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
5369 return IA_CSS_SUCCESS;
5370}
5371
5372static enum ia_css_err
5373sh_css_pipe_get_shading_info(struct ia_css_pipe *pipe,
5374#ifndef ISP2401
5375 struct ia_css_shading_info *info)
5376#else
5377 struct ia_css_shading_info *shading_info,
5378 struct ia_css_pipe_config *pipe_config)
5379#endif
5380{
5381 enum ia_css_err err = IA_CSS_SUCCESS;
5382 struct ia_css_binary *binary = NULL;
5383
5384 assert(pipe != NULL);
5385#ifndef ISP2401
5386 assert(info != NULL);
5387#else
5388 assert(shading_info != NULL);
5389 assert(pipe_config != NULL);
5390#endif
5391 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
5392 "sh_css_pipe_get_shading_info() enter:\n");
5393
5394 binary = ia_css_pipe_get_shading_correction_binary(pipe);
5395
5396 if (binary) {
5397 err = ia_css_binary_get_shading_info(binary,
5398 IA_CSS_SHADING_CORRECTION_TYPE_1,
5399 pipe->required_bds_factor,
5400 (const struct ia_css_stream_config *)&pipe->stream->config,
5401#ifndef ISP2401
5402 info);
5403#else
5404 shading_info, pipe_config);
5405#endif
5406 /* Other function calls can be added here when other shading correction types will be added
5407 * in the future.
5408 */
5409 } else {
5410 /* When the pipe does not have a binary which has the shading
5411 * correction, this function does not need to fill the shading
5412 * information. It is not a error case, and then
5413 * this function should return IA_CSS_SUCCESS.
5414 */
5415#ifndef ISP2401
5416 memset(info, 0, sizeof(*info));
5417#else
5418 memset(shading_info, 0, sizeof(*shading_info));
5419#endif
5420 }
5421 return err;
5422}
5423
5424static enum ia_css_err
5425sh_css_pipe_get_grid_info(struct ia_css_pipe *pipe,
5426 struct ia_css_grid_info *info)
5427{
5428 enum ia_css_err err = IA_CSS_SUCCESS;
5429 struct ia_css_binary *binary = NULL;
5430
5431 assert(pipe != NULL);
5432 assert(info != NULL);
5433
5434 IA_CSS_ENTER_PRIVATE("");
5435
5436 binary = ia_css_pipe_get_s3a_binary(pipe);
5437
5438 if (binary) {
5439 err = ia_css_binary_3a_grid_info(binary, info, pipe);
5440 if (err != IA_CSS_SUCCESS)
5441 goto ERR;
5442 } else
5443 memset(&info->s3a_grid, 0, sizeof(info->s3a_grid));
5444
5445 binary = ia_css_pipe_get_sdis_binary(pipe);
5446
5447 if (binary) {
5448 ia_css_binary_dvs_grid_info(binary, info, pipe);
5449 ia_css_binary_dvs_stat_grid_info(binary, info, pipe);
5450 } else {
5451 memset(&info->dvs_grid.dvs_grid_info, 0,
5452 sizeof(info->dvs_grid.dvs_grid_info));
5453 memset(&info->dvs_grid.dvs_stat_grid_info, 0,
5454 sizeof(info->dvs_grid.dvs_stat_grid_info));
5455 }
5456
5457 if (binary != NULL) {
5458 /* copy pipe does not have ISP binary*/
5459 info->isp_in_width = binary->internal_frame_info.res.width;
5460 info->isp_in_height = binary->internal_frame_info.res.height;
5461 }
5462
5463#if defined(HAS_VAMEM_VERSION_2)
5464 info->vamem_type = IA_CSS_VAMEM_TYPE_2;
5465#elif defined(HAS_VAMEM_VERSION_1)
5466 info->vamem_type = IA_CSS_VAMEM_TYPE_1;
5467#else
5468#error "Unknown VAMEM version"
5469#endif
5470
5471ERR:
5472 IA_CSS_LEAVE_ERR_PRIVATE(err);
5473 return err;
5474}
5475
5476#ifdef ISP2401
d929fb4e 5477/*
a49d2536
AC
5478 * @brief Check if a format is supported by the pipe.
5479 *
5480 */
5481static enum ia_css_err
5482ia_css_pipe_check_format(struct ia_css_pipe *pipe, enum ia_css_frame_format format)
5483{
5484 const enum ia_css_frame_format *supported_formats;
5485 int number_of_formats;
5486 int found = 0;
5487 int i;
5488
5489 IA_CSS_ENTER_PRIVATE("");
5490
5491 if (NULL == pipe || NULL == pipe->pipe_settings.video.video_binary.info) {
5492 IA_CSS_ERROR("Pipe or binary info is not set");
5493 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
5494 return IA_CSS_ERR_INVALID_ARGUMENTS;
5495 }
5496
5497 supported_formats = pipe->pipe_settings.video.video_binary.info->output_formats;
5498 number_of_formats = sizeof(pipe->pipe_settings.video.video_binary.info->output_formats)/sizeof(enum ia_css_frame_format);
5499
5500 for (i = 0; i < number_of_formats && !found; i++) {
5501 if (supported_formats[i] == format) {
5502 found = 1;
5503 break;
5504 }
5505 }
5506 if (!found) {
5507 IA_CSS_ERROR("Requested format is not supported by binary");
5508 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
5509 return IA_CSS_ERR_INVALID_ARGUMENTS;
5510 } else {
5511 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
5512 return IA_CSS_SUCCESS;
5513 }
5514}
5515#endif
5516
5517static enum ia_css_err load_video_binaries(struct ia_css_pipe *pipe)
5518{
5519 struct ia_css_frame_info video_in_info, tnr_info,
5520 *video_vf_info, video_bds_out_info, *pipe_out_info, *pipe_vf_out_info;
5521 bool online;
5522 enum ia_css_err err = IA_CSS_SUCCESS;
5523 bool continuous = pipe->stream->config.continuous;
5524 unsigned int i;
5525 unsigned num_output_pins;
5526 struct ia_css_frame_info video_bin_out_info;
5527 bool need_scaler = false;
5528 bool vf_res_different_than_output = false;
5529 bool need_vf_pp = false;
5530 int vf_ds_log2;
5531 struct ia_css_video_settings *mycs = &pipe->pipe_settings.video;
5532
5533 IA_CSS_ENTER_PRIVATE("");
5534 assert(pipe != NULL);
5535 assert(pipe->mode == IA_CSS_PIPE_ID_VIDEO);
5536 /* we only test the video_binary because offline video doesn't need a
5537 * vf_pp binary and online does not (always use) the copy_binary.
5538 * All are always reset at the same time anyway.
5539 */
5540 if (mycs->video_binary.info)
5541 return IA_CSS_SUCCESS;
5542
5543 online = pipe->stream->config.online;
5544 pipe_out_info = &pipe->output_info[0];
5545 pipe_vf_out_info = &pipe->vf_output_info[0];
5546
5547 assert(pipe_out_info != NULL);
5548
5549 /*
5550 * There is no explicit input format requirement for raw or yuv
5551 * What matters is that there is a binary that supports the stream format.
5552 * This is checked in the binary_find(), so no need to check it here
5553 */
5554 err = ia_css_util_check_input(&pipe->stream->config, false, false);
5555 if (err != IA_CSS_SUCCESS)
5556 return err;
5557 /* cannot have online video and input_mode memory */
5558 if (online && pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY)
5559 return IA_CSS_ERR_INVALID_ARGUMENTS;
5560 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
5561 err = ia_css_util_check_vf_out_info(pipe_out_info,
5562 pipe_vf_out_info);
5563 if (err != IA_CSS_SUCCESS)
5564 return err;
5565 } else {
5566 err = ia_css_frame_check_info(pipe_out_info);
5567 if (err != IA_CSS_SUCCESS)
5568 return err;
5569 }
5570
5571 if (pipe->out_yuv_ds_input_info.res.width)
5572 video_bin_out_info = pipe->out_yuv_ds_input_info;
5573 else
5574 video_bin_out_info = *pipe_out_info;
5575
5576 /* Video */
5577 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]){
5578 video_vf_info = pipe_vf_out_info;
5579 vf_res_different_than_output = (video_vf_info->res.width != video_bin_out_info.res.width) ||
5580 (video_vf_info->res.height != video_bin_out_info.res.height);
5581 }
5582 else {
5583 video_vf_info = NULL;
5584 }
5585
5586 need_scaler = need_downscaling(video_bin_out_info.res, pipe_out_info->res);
5587
5588 /* we build up the pipeline starting at the end */
5589 /* YUV post-processing if needed */
5590 if (need_scaler) {
5591 struct ia_css_cas_binary_descr cas_scaler_descr
5592 = IA_CSS_DEFAULT_CAS_BINARY_DESCR;
5593
5594 /* NV12 is the common format that is supported by both */
5595 /* yuv_scaler and the video_xx_isp2_min binaries. */
5596 video_bin_out_info.format = IA_CSS_FRAME_FORMAT_NV12;
5597
5598 err = ia_css_pipe_create_cas_scaler_desc_single_output(
5599 &video_bin_out_info,
5600 pipe_out_info,
5601 NULL,
5602 &cas_scaler_descr);
5603 if (err != IA_CSS_SUCCESS)
5604 return err;
5605 mycs->num_yuv_scaler = cas_scaler_descr.num_stage;
94853b65
AC
5606 mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage *
5607 sizeof(struct ia_css_binary), GFP_KERNEL);
bbae6156 5608 if (!mycs->yuv_scaler_binary) {
a49d2536
AC
5609 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
5610 return err;
5611 }
94853b65
AC
5612 mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage
5613 * sizeof(bool), GFP_KERNEL);
bbae6156 5614 if (!mycs->is_output_stage) {
a49d2536
AC
5615 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
5616 return err;
5617 }
5618 for (i = 0; i < cas_scaler_descr.num_stage; i++) {
5619 struct ia_css_binary_descr yuv_scaler_descr;
5620 mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i];
5621 ia_css_pipe_get_yuvscaler_binarydesc(pipe,
5622 &yuv_scaler_descr, &cas_scaler_descr.in_info[i],
5623 &cas_scaler_descr.out_info[i],
5624 &cas_scaler_descr.internal_out_info[i],
5625 &cas_scaler_descr.vf_info[i]);
5626 err = ia_css_binary_find(&yuv_scaler_descr,
5627 &mycs->yuv_scaler_binary[i]);
5628 if (err != IA_CSS_SUCCESS) {
94853b65 5629 kfree(mycs->is_output_stage);
a49d2536
AC
5630 mycs->is_output_stage = NULL;
5631 return err;
5632 }
5633 }
5634 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
5635 }
5636
5637
5638 {
5639 struct ia_css_binary_descr video_descr;
5640 enum ia_css_frame_format vf_info_format;
5641
5642 err = ia_css_pipe_get_video_binarydesc(pipe,
5643 &video_descr, &video_in_info, &video_bds_out_info, &video_bin_out_info, video_vf_info,
5644 pipe->stream->config.left_padding);
5645 if (err != IA_CSS_SUCCESS)
5646 return err;
5647
5648 /* In the case where video_vf_info is not NULL, this allows
5649 * us to find a potential video library with desired vf format.
5650 * If success, no vf_pp binary is needed.
5651 * If failed, we will look up video binary with YUV_LINE vf format
5652 */
5653 err = ia_css_binary_find(&video_descr,
5654 &mycs->video_binary);
5655
5656 if (err != IA_CSS_SUCCESS) {
5657 if (video_vf_info) {
5658 /* This will do another video binary lookup later for YUV_LINE format*/
5659 need_vf_pp = true;
5660 } else
5661 return err;
5662 } else if (video_vf_info) {
5663 /* The first video binary lookup is successful, but we may
5664 * still need vf_pp binary based on additiona check */
5665 num_output_pins = mycs->video_binary.info->num_output_pins;
5666 vf_ds_log2 = mycs->video_binary.vf_downscale_log2;
5667
5668 /* If the binary has dual output pins, we need vf_pp if the resolution
5669 * is different. */
5670 need_vf_pp |= ((num_output_pins == 2) && vf_res_different_than_output);
5671
5672 /* If the binary has single output pin, we need vf_pp if additional
5673 * scaling is needed for vf */
5674 need_vf_pp |= ((num_output_pins == 1) &&
5675 ((video_vf_info->res.width << vf_ds_log2 != pipe_out_info->res.width) ||
5676 (video_vf_info->res.height << vf_ds_log2 != pipe_out_info->res.height)));
5677 }
5678
5679 if (need_vf_pp) {
5680 /* save the current vf_info format for restoration later */
5681 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5682 "load_video_binaries() need_vf_pp; find video binary with YUV_LINE again\n");
5683
5684 vf_info_format = video_vf_info->format;
5685
5686 if (!pipe->config.enable_vfpp_bci)
5687 ia_css_frame_info_set_format(video_vf_info,
5688 IA_CSS_FRAME_FORMAT_YUV_LINE);
5689
5690 ia_css_binary_destroy_isp_parameters(&mycs->video_binary);
5691
5692 err = ia_css_binary_find(&video_descr,
5693 &mycs->video_binary);
5694
5695 /* restore original vf_info format */
5696 ia_css_frame_info_set_format(video_vf_info,
5697 vf_info_format);
5698 if (err != IA_CSS_SUCCESS)
5699 return err;
5700 }
5701 }
5702
5703 /* If a video binary does not use a ref_frame, we set the frame delay
5704 * to 0. This is the case for the 1-stage low-power video binary. */
5705 if (!mycs->video_binary.info->sp.enable.ref_frame)
5706 pipe->dvs_frame_delay = 0;
5707
5708 /* The delay latency determines the number of invalid frames after
5709 * a stream is started. */
5710 pipe->num_invalid_frames = pipe->dvs_frame_delay;
5711 pipe->info.num_invalid_frames = pipe->num_invalid_frames;
5712
5713 /* Viewfinder frames also decrement num_invalid_frames. If the pipe
5714 * outputs a viewfinder output, then we need double the number of
5715 * invalid frames */
5716 if (video_vf_info)
5717 pipe->num_invalid_frames *= 2;
5718
5719 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5720 "load_video_binaries() num_invalid_frames=%d dvs_frame_delay=%d\n",
5721 pipe->num_invalid_frames, pipe->dvs_frame_delay);
5722
5723/* pqiao TODO: temp hack for PO, should be removed after offline YUVPP is enabled */
5724#if !defined(USE_INPUT_SYSTEM_VERSION_2401)
5725 /* Copy */
5726 if (!online && !continuous) {
5727 /* TODO: what exactly needs doing, prepend the copy binary to
5728 * video base this only on !online?
5729 */
5730 err = load_copy_binary(pipe,
5731 &mycs->copy_binary,
5732 &mycs->video_binary);
5733 if (err != IA_CSS_SUCCESS)
5734 return err;
5735 }
5736#else
5737 (void)continuous;
5738#endif
5739
5740#if !defined(HAS_OUTPUT_SYSTEM)
5741 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] && need_vf_pp) {
5742 struct ia_css_binary_descr vf_pp_descr;
5743
5744 if (mycs->video_binary.vf_frame_info.format
5745 == IA_CSS_FRAME_FORMAT_YUV_LINE) {
5746 ia_css_pipe_get_vfpp_binarydesc(pipe, &vf_pp_descr,
5747 &mycs->video_binary.vf_frame_info,
5748 pipe_vf_out_info);
5749 } else {
5750 /* output from main binary is not yuv line. currently this is
5751 * possible only when bci is enabled on vfpp output */
5752 assert(pipe->config.enable_vfpp_bci == true);
5753 ia_css_pipe_get_yuvscaler_binarydesc(pipe, &vf_pp_descr,
5754 &mycs->video_binary.vf_frame_info,
5755 pipe_vf_out_info, NULL, NULL);
5756 }
5757
5758 err = ia_css_binary_find(&vf_pp_descr,
5759 &mycs->vf_pp_binary);
5760 if (err != IA_CSS_SUCCESS)
5761 return err;
5762 }
5763#endif
5764
5765 err = allocate_delay_frames(pipe);
5766
5767 if (err != IA_CSS_SUCCESS)
5768 return err;
5769
5770 if (mycs->video_binary.info->sp.enable.block_output) {
5771#ifdef ISP2401
5772 unsigned int tnr_width;
5773 unsigned int tnr_height;
5774#endif
5775 tnr_info = mycs->video_binary.out_frame_info[0];
5776#ifdef ISP2401
5777
5778 /* Select resolution for TNR. If
5779 * output_system_in_resolution(GDC_out_resolution) is
5780 * being used, then select that as it will also be in resolution for
5781 * TNR. At present, it only make sense for Skycam */
5782 if (pipe->config.output_system_in_res.width && pipe->config.output_system_in_res.height) {
5783 tnr_width = pipe->config.output_system_in_res.width;
5784 tnr_height = pipe->config.output_system_in_res.height;
5785 } else {
5786 tnr_width = tnr_info.res.width;
5787 tnr_height = tnr_info.res.height;
5788 }
5789
5790 /* Make tnr reference buffers output block width(in pix) align */
5791 tnr_info.res.width =
5792 CEIL_MUL(tnr_width,
5793 (mycs->video_binary.info->sp.block.block_width * ISP_NWAY));
5794 tnr_info.padded_width = tnr_info.res.width;
5795
5796#endif
5797 /* Make tnr reference buffers output block height align */
a49d2536 5798#ifndef ISP2401
b5eb7ac1 5799 tnr_info.res.height =
a49d2536 5800 CEIL_MUL(tnr_info.res.height,
b5eb7ac1 5801 mycs->video_binary.info->sp.block.output_block_height);
a49d2536 5802#else
b5eb7ac1 5803 tnr_info.res.height =
a49d2536 5804 CEIL_MUL(tnr_height,
b5eb7ac1 5805 mycs->video_binary.info->sp.block.output_block_height);
a49d2536 5806#endif
a49d2536
AC
5807 } else {
5808 tnr_info = mycs->video_binary.internal_frame_info;
5809 }
5810 tnr_info.format = IA_CSS_FRAME_FORMAT_YUV_LINE;
5811 tnr_info.raw_bit_depth = SH_CSS_TNR_BIT_DEPTH;
5812
5813#ifndef ISP2401
5814 for (i = 0; i < NUM_VIDEO_TNR_FRAMES; i++) {
5815#else
5816 for (i = 0; i < NUM_TNR_FRAMES; i++) {
5817#endif
5818 if (mycs->tnr_frames[i]) {
5819 ia_css_frame_free(mycs->tnr_frames[i]);
5820 mycs->tnr_frames[i] = NULL;
5821 }
5822 err = ia_css_frame_allocate_from_info(
5823 &mycs->tnr_frames[i],
5824 &tnr_info);
a49d2536
AC
5825 if (err != IA_CSS_SUCCESS)
5826 return err;
5827 }
5828 IA_CSS_LEAVE_PRIVATE("");
5829 return IA_CSS_SUCCESS;
5830}
5831
5832static enum ia_css_err
5833unload_video_binaries(struct ia_css_pipe *pipe)
5834{
5835 unsigned int i;
5836 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
5837
5838 if ((pipe == NULL) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) {
5839 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
5840 return IA_CSS_ERR_INVALID_ARGUMENTS;
5841 }
5842 ia_css_binary_unload(&pipe->pipe_settings.video.copy_binary);
5843 ia_css_binary_unload(&pipe->pipe_settings.video.video_binary);
5844 ia_css_binary_unload(&pipe->pipe_settings.video.vf_pp_binary);
5845#ifndef ISP2401
5846 ia_css_binary_unload(&pipe->pipe_settings.video.vf_pp_binary);
5847#endif
5848
5849 for (i = 0; i < pipe->pipe_settings.video.num_yuv_scaler; i++)
5850 ia_css_binary_unload(&pipe->pipe_settings.video.yuv_scaler_binary[i]);
5851
94853b65 5852 kfree(pipe->pipe_settings.video.is_output_stage);
a49d2536 5853 pipe->pipe_settings.video.is_output_stage = NULL;
94853b65 5854 kfree(pipe->pipe_settings.video.yuv_scaler_binary);
a49d2536
AC
5855 pipe->pipe_settings.video.yuv_scaler_binary = NULL;
5856
5857 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
5858 return IA_CSS_SUCCESS;
5859}
5860
5861static enum ia_css_err video_start(struct ia_css_pipe *pipe)
5862{
5863 struct ia_css_binary *copy_binary;
5864 enum ia_css_err err = IA_CSS_SUCCESS;
5865 struct ia_css_pipe *copy_pipe, *capture_pipe;
5866 enum sh_css_pipe_config_override copy_ovrd;
5867 enum ia_css_input_mode video_pipe_input_mode;
5868
5869
5870 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
5871 if ((pipe == NULL) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) {
5872 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
5873 return IA_CSS_ERR_INVALID_ARGUMENTS;
5874 }
5875
5876 video_pipe_input_mode = pipe->stream->config.mode;
5877
5878 copy_pipe = pipe->pipe_settings.video.copy_pipe;
5879 capture_pipe = pipe->pipe_settings.video.capture_pipe;
5880
5881 copy_binary = &pipe->pipe_settings.video.copy_binary;
5882
5883 sh_css_metrics_start_frame();
5884
5885 /* multi stream video needs mipi buffers */
5886
5887#if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
5888 err = send_mipi_frames(pipe);
5889 if (err != IA_CSS_SUCCESS)
5890 return err;
5891#endif
5892
5893 send_raw_frames(pipe);
5894 {
5895 unsigned int thread_id;
5896
5897 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
5898 copy_ovrd = 1 << thread_id;
5899
5900 if (pipe->stream->cont_capt) {
5901 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe), &thread_id);
5902 copy_ovrd |= 1 << thread_id;
5903 }
5904 }
5905
5906 /* Construct and load the copy pipe */
5907 if (pipe->stream->config.continuous) {
5908 sh_css_sp_init_pipeline(&copy_pipe->pipeline,
5909 IA_CSS_PIPE_ID_COPY,
5910 (uint8_t)ia_css_pipe_get_pipe_num(copy_pipe),
5911 false,
5912 pipe->stream->config.pixels_per_clock == 2, false,
5913 false, pipe->required_bds_factor,
5914 copy_ovrd,
5915 pipe->stream->config.mode,
5916 &pipe->stream->config.metadata_config,
5917#ifndef ISP2401
5918 &pipe->stream->info.metadata_info
5919#else
5920 &pipe->stream->info.metadata_info,
5921#endif
5922#if !defined(HAS_NO_INPUT_SYSTEM)
5923#ifndef ISP2401
5924 , pipe->stream->config.source.port.port
5925#else
5926 pipe->stream->config.source.port.port,
5927#endif
5928#endif
5929#ifndef ISP2401
5930 );
5931#else
5932 &copy_pipe->config.internal_frame_origin_bqs_on_sctbl,
5933 copy_pipe->stream->isp_params_configs);
5934#endif
5935
5936 /* make the video pipe start with mem mode input, copy handles
5937 the actual mode */
5938 video_pipe_input_mode = IA_CSS_INPUT_MODE_MEMORY;
5939 }
5940
5941 /* Construct and load the capture pipe */
5942 if (pipe->stream->cont_capt) {
5943 sh_css_sp_init_pipeline(&capture_pipe->pipeline,
5944 IA_CSS_PIPE_ID_CAPTURE,
5945 (uint8_t)ia_css_pipe_get_pipe_num(capture_pipe),
5946 capture_pipe->config.default_capture_config.enable_xnr != 0,
5947 capture_pipe->stream->config.pixels_per_clock == 2,
5948 true, /* continuous */
5949 false, /* offline */
5950 capture_pipe->required_bds_factor,
5951 0,
5952 IA_CSS_INPUT_MODE_MEMORY,
5953 &pipe->stream->config.metadata_config,
5954#ifndef ISP2401
5955 &pipe->stream->info.metadata_info
5956#else
5957 &pipe->stream->info.metadata_info,
5958#endif
5959#if !defined(HAS_NO_INPUT_SYSTEM)
5960#ifndef ISP2401
5961 , (mipi_port_ID_t)0
5962#else
5963 (mipi_port_ID_t)0,
5964#endif
5965#endif
5966#ifndef ISP2401
5967 );
5968#else
5969 &capture_pipe->config.internal_frame_origin_bqs_on_sctbl,
5970 capture_pipe->stream->isp_params_configs);
5971#endif
5972 }
5973
5974 start_pipe(pipe, copy_ovrd, video_pipe_input_mode);
5975
5976 IA_CSS_LEAVE_ERR_PRIVATE(err);
5977 return err;
5978}
5979
5980static
5981enum ia_css_err sh_css_pipe_get_viewfinder_frame_info(
5982 struct ia_css_pipe *pipe,
5983 struct ia_css_frame_info *info,
5984 unsigned int idx)
5985{
5986 assert(pipe != NULL);
5987 assert(info != NULL);
5988
5989/* We could print the pointer as input arg, and the values as output */
5990 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "sh_css_pipe_get_viewfinder_frame_info() enter: void\n");
5991
5992 if ( pipe->mode == IA_CSS_PIPE_ID_CAPTURE &&
5993 (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW ||
5994 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER))
5995 return IA_CSS_ERR_MODE_HAS_NO_VIEWFINDER;
5996 /* offline video does not generate viewfinder output */
5997 *info = pipe->vf_output_info[idx];
5998
5999 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
6000 "sh_css_pipe_get_viewfinder_frame_info() leave: \
6001 info.res.width=%d, info.res.height=%d, \
6002 info.padded_width=%d, info.format=%d, \
6003 info.raw_bit_depth=%d, info.raw_bayer_order=%d\n",
6004 info->res.width,info->res.height,
6005 info->padded_width,info->format,
6006 info->raw_bit_depth,info->raw_bayer_order);
6007
6008 return IA_CSS_SUCCESS;
6009}
6010
6011static enum ia_css_err
6012sh_css_pipe_configure_viewfinder(struct ia_css_pipe *pipe, unsigned int width,
6013 unsigned int height, unsigned int min_width,
6014 enum ia_css_frame_format format,
6015 unsigned int idx)
6016{
6017 enum ia_css_err err = IA_CSS_SUCCESS;
6018
6019 IA_CSS_ENTER_PRIVATE("pipe = %p, width = %d, height = %d, min_width = %d, format = %d, idx = %d\n",
6020 pipe, width, height, min_width, format, idx);
6021
6022 if (pipe == NULL) {
6023 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
6024 return IA_CSS_ERR_INVALID_ARGUMENTS;
6025 }
6026
6027
6028 err = ia_css_util_check_res(width, height);
6029 if (err != IA_CSS_SUCCESS) {
b5eb7ac1 6030 IA_CSS_LEAVE_ERR_PRIVATE(err);
a49d2536
AC
6031 return err;
6032 }
6033 if (pipe->vf_output_info[idx].res.width != width ||
6034 pipe->vf_output_info[idx].res.height != height ||
6035 pipe->vf_output_info[idx].format != format) {
6036 ia_css_frame_info_init(&pipe->vf_output_info[idx], width, height,
6037 format, min_width);
6038 }
6039 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
6040 return IA_CSS_SUCCESS;
6041}
6042
6043static enum ia_css_err load_copy_binaries(struct ia_css_pipe *pipe)
6044{
6045 enum ia_css_err err = IA_CSS_SUCCESS;
6046
6047 assert(pipe != NULL);
6048 IA_CSS_ENTER_PRIVATE("");
6049
6050 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || pipe->mode == IA_CSS_PIPE_ID_COPY);
6051 if (pipe->pipe_settings.capture.copy_binary.info)
6052 return IA_CSS_SUCCESS;
6053
6054 err = ia_css_frame_check_info(&pipe->output_info[0]);
6055 if (err != IA_CSS_SUCCESS)
6056 goto ERR;
6057
6058 err = verify_copy_out_frame_format(pipe);
6059 if (err != IA_CSS_SUCCESS)
6060 goto ERR;
6061
6062 err = load_copy_binary(pipe,
6063 &pipe->pipe_settings.capture.copy_binary,
6064 NULL);
6065
6066ERR:
6067 IA_CSS_LEAVE_ERR_PRIVATE(err);
6068 return err;
6069}
6070
6071static bool need_capture_pp(
6072 const struct ia_css_pipe *pipe)
6073{
6074 const struct ia_css_frame_info *out_info = &pipe->output_info[0];
6075 IA_CSS_ENTER_LEAVE_PRIVATE("");
6076 assert(pipe != NULL);
6077 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE);
6078#ifdef ISP2401
6079
6080 /* ldc and capture_pp are not supported in the same pipeline */
6081 if (need_capt_ldc(pipe) == true)
6082 return false;
6083#endif
6084 /* determine whether we need to use the capture_pp binary.
6085 * This is needed for:
6086 * 1. XNR or
6087 * 2. Digital Zoom or
6088 * 3. YUV downscaling
6089 */
6090 if (pipe->out_yuv_ds_input_info.res.width &&
6091 ((pipe->out_yuv_ds_input_info.res.width != out_info->res.width) ||
6092 (pipe->out_yuv_ds_input_info.res.height != out_info->res.height)))
6093 return true;
6094
6095 if (pipe->config.default_capture_config.enable_xnr != 0)
6096 return true;
6097
6098 if ((pipe->stream->isp_params_configs->dz_config.dx < HRT_GDC_N) ||
6099 (pipe->stream->isp_params_configs->dz_config.dy < HRT_GDC_N) ||
6100 pipe->config.enable_dz)
6101 return true;
6102
6103 return false;
6104}
6105
6106static bool need_capt_ldc(
6107 const struct ia_css_pipe *pipe)
6108{
6109 IA_CSS_ENTER_LEAVE_PRIVATE("");
6110 assert(pipe != NULL);
6111 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE);
6112 return (pipe->extra_config.enable_dvs_6axis) ? true:false;
6113}
6114
6115static enum ia_css_err set_num_primary_stages(unsigned int *num, enum ia_css_pipe_version version)
6116{
6117 enum ia_css_err err = IA_CSS_SUCCESS;
6118
6119 if (num == NULL)
6120 return IA_CSS_ERR_INVALID_ARGUMENTS;
6121
6122 switch (version) {
6123 case IA_CSS_PIPE_VERSION_2_6_1:
6124 *num = NUM_PRIMARY_HQ_STAGES;
6125 break;
6126 case IA_CSS_PIPE_VERSION_2_2:
6127 case IA_CSS_PIPE_VERSION_1:
6128 *num = NUM_PRIMARY_STAGES;
6129 break;
6130 default:
6131 err = IA_CSS_ERR_INVALID_ARGUMENTS;
6132 break;
6133 }
6134
6135 return err;
6136}
6137
6138static enum ia_css_err load_primary_binaries(
6139 struct ia_css_pipe *pipe)
6140{
6141 bool online = false;
6142 bool memory = false;
6143 bool continuous = false;
6144 bool need_pp = false;
6145 bool need_isp_copy_binary = false;
6146 bool need_ldc = false;
6147#ifdef USE_INPUT_SYSTEM_VERSION_2401
6148 bool sensor = false;
6149#endif
6150 struct ia_css_frame_info prim_in_info,
6151 prim_out_info,
6152 capt_pp_out_info, vf_info,
6153 *vf_pp_in_info, *pipe_out_info,
6154#ifndef ISP2401
6155 *pipe_vf_out_info, *capt_pp_in_info,
6156 capt_ldc_out_info;
6157#else
6158 *pipe_vf_out_info;
a49d2536
AC
6159#endif
6160 enum ia_css_err err = IA_CSS_SUCCESS;
6161 struct ia_css_capture_settings *mycs;
6162 unsigned int i;
6163 bool need_extra_yuv_scaler = false;
6164
6165 IA_CSS_ENTER_PRIVATE("");
6166 assert(pipe != NULL);
6167 assert(pipe->stream != NULL);
6168 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || pipe->mode == IA_CSS_PIPE_ID_COPY);
6169
6170 online = pipe->stream->config.online;
6171 memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
6172 continuous = pipe->stream->config.continuous;
6173#ifdef USE_INPUT_SYSTEM_VERSION_2401
6174 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR);
6175#endif
6176
6177 mycs = &pipe->pipe_settings.capture;
6178 pipe_out_info = &pipe->output_info[0];
6179 pipe_vf_out_info = &pipe->vf_output_info[0];
6180
6181 if (mycs->primary_binary[0].info)
6182 return IA_CSS_SUCCESS;
6183
6184 err = set_num_primary_stages(&mycs->num_primary_stage, pipe->config.isp_pipe_version);
6185 if (err != IA_CSS_SUCCESS) {
6186 IA_CSS_LEAVE_ERR_PRIVATE(err);
6187 return err;
6188 }
6189
6190 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
6191 err = ia_css_util_check_vf_out_info(pipe_out_info, pipe_vf_out_info);
6192 if (err != IA_CSS_SUCCESS) {
6193 IA_CSS_LEAVE_ERR_PRIVATE(err);
6194 return err;
6195 }
6196 }
6197 else{
6198 err = ia_css_frame_check_info(pipe_out_info);
6199 if (err != IA_CSS_SUCCESS) {
6200 IA_CSS_LEAVE_ERR_PRIVATE(err);
6201 return err;
6202 }
6203 }
6204 need_pp = need_capture_pp(pipe);
6205
6206 /* we use the vf output info to get the primary/capture_pp binary
6207 configured for vf_veceven. It will select the closest downscaling
6208 factor. */
6209 vf_info = *pipe_vf_out_info;
6210
6211/*
6212 * WARNING: The #if def flag has been added below as a
6213 * temporary solution to solve the problem of enabling the
6214 * view finder in a single binary in a capture flow. The
6215 * vf-pp stage has been removed for Skycam in the solution
6216 * provided. The vf-pp stage should be re-introduced when
6217 * required. This should not be considered as a clean solution.
6218 * Proper investigation should be done to come up with the clean
6219 * solution.
6220 * */
6221 ia_css_frame_info_set_format(&vf_info, IA_CSS_FRAME_FORMAT_YUV_LINE);
6222
6223 /* TODO: All this yuv_scaler and capturepp calculation logic
6224 * can be shared later. Capture_pp is also a yuv_scale binary
6225 * with extra XNR funcionality. Therefore, it can be made as the
6226 * first step of the cascade. */
6227 capt_pp_out_info = pipe->out_yuv_ds_input_info;
6228 capt_pp_out_info.format = IA_CSS_FRAME_FORMAT_YUV420;
6229 capt_pp_out_info.res.width /= MAX_PREFERRED_YUV_DS_PER_STEP;
6230 capt_pp_out_info.res.height /= MAX_PREFERRED_YUV_DS_PER_STEP;
6231 ia_css_frame_info_set_width(&capt_pp_out_info, capt_pp_out_info.res.width, 0);
6232
6233/*
6234 * WARNING: The #if def flag has been added below as a
6235 * temporary solution to solve the problem of enabling the
6236 * view finder in a single binary in a capture flow. The
6237 * vf-pp stage has been removed for Skycam in the solution
6238 * provided. The vf-pp stage should be re-introduced when
6239 * required. This should not be considered as a clean solution.
6240 * Proper investigation should be done to come up with the clean
6241 * solution.
6242 * */
6243 need_extra_yuv_scaler = need_downscaling(capt_pp_out_info.res,
6244 pipe_out_info->res);
6245
6246 if (need_extra_yuv_scaler) {
6247 struct ia_css_cas_binary_descr cas_scaler_descr
6248 = IA_CSS_DEFAULT_CAS_BINARY_DESCR;
6249 err = ia_css_pipe_create_cas_scaler_desc_single_output(
6250 &capt_pp_out_info,
6251 pipe_out_info,
6252 NULL,
6253 &cas_scaler_descr);
6254 if (err != IA_CSS_SUCCESS) {
6255 IA_CSS_LEAVE_ERR_PRIVATE(err);
6256 return err;
6257 }
6258 mycs->num_yuv_scaler = cas_scaler_descr.num_stage;
94853b65
AC
6259 mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage *
6260 sizeof(struct ia_css_binary), GFP_KERNEL);
bbae6156 6261 if (!mycs->yuv_scaler_binary) {
a49d2536
AC
6262 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
6263 IA_CSS_LEAVE_ERR_PRIVATE(err);
6264 return err;
6265 }
94853b65
AC
6266 mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage *
6267 sizeof(bool), GFP_KERNEL);
bbae6156 6268 if (!mycs->is_output_stage) {
a49d2536
AC
6269 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
6270 IA_CSS_LEAVE_ERR_PRIVATE(err);
6271 return err;
6272 }
6273 for (i = 0; i < cas_scaler_descr.num_stage; i++) {
6274 struct ia_css_binary_descr yuv_scaler_descr;
6275 mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i];
6276 ia_css_pipe_get_yuvscaler_binarydesc(pipe,
6277 &yuv_scaler_descr, &cas_scaler_descr.in_info[i],
6278 &cas_scaler_descr.out_info[i],
6279 &cas_scaler_descr.internal_out_info[i],
6280 &cas_scaler_descr.vf_info[i]);
a49d2536
AC
6281 err = ia_css_binary_find(&yuv_scaler_descr,
6282 &mycs->yuv_scaler_binary[i]);
6283 if (err != IA_CSS_SUCCESS) {
6284 IA_CSS_LEAVE_ERR_PRIVATE(err);
6285 return err;
6286 }
6287 }
6288 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
6289
6290 } else {
6291 capt_pp_out_info = pipe->output_info[0];
6292 }
6293
6294 /* TODO Do we disable ldc for skycam */
6295 need_ldc = need_capt_ldc(pipe);
6296#ifdef ISP2401
6297 /* ldc and capt_pp are not supported in the same pipeline */
6298 if (need_ldc) {
6299 struct ia_css_binary_descr capt_ldc_descr;
6300 ia_css_pipe_get_ldc_binarydesc(pipe,
6301 &capt_ldc_descr, &prim_out_info,
6302 &capt_pp_out_info);
6303#endif
6304
6305#ifdef ISP2401
6306 err = ia_css_binary_find(&capt_ldc_descr,
6307 &mycs->capture_ldc_binary);
6308 if (err != IA_CSS_SUCCESS) {
6309 IA_CSS_LEAVE_ERR_PRIVATE(err);
6310 return err;
6311 }
6312 } else if (need_pp) {
6313#endif
6314 /* we build up the pipeline starting at the end */
6315 /* Capture post-processing */
6316#ifndef ISP2401
6317 if (need_pp) {
6318#endif
6319 struct ia_css_binary_descr capture_pp_descr;
6320#ifndef ISP2401
6321 capt_pp_in_info = need_ldc ? &capt_ldc_out_info : &prim_out_info;
6322#endif
6323
6324 ia_css_pipe_get_capturepp_binarydesc(pipe,
6325#ifndef ISP2401
6326 &capture_pp_descr, capt_pp_in_info,
6327#else
6328 &capture_pp_descr, &prim_out_info,
6329#endif
6330 &capt_pp_out_info, &vf_info);
a49d2536
AC
6331 err = ia_css_binary_find(&capture_pp_descr,
6332 &mycs->capture_pp_binary);
6333 if (err != IA_CSS_SUCCESS) {
6334 IA_CSS_LEAVE_ERR_PRIVATE(err);
6335 return err;
6336 }
6337#ifndef ISP2401
6338
6339 if(need_ldc) {
6340 struct ia_css_binary_descr capt_ldc_descr;
6341 ia_css_pipe_get_ldc_binarydesc(pipe,
6342 &capt_ldc_descr, &prim_out_info,
6343 &capt_ldc_out_info);
6344
6345 err = ia_css_binary_find(&capt_ldc_descr,
6346 &mycs->capture_ldc_binary);
6347 if (err != IA_CSS_SUCCESS) {
6348 IA_CSS_LEAVE_ERR_PRIVATE(err);
6349 return err;
6350 }
6351 }
6352#endif
6353 } else {
6354 prim_out_info = *pipe_out_info;
6355 }
6356
6357 /* Primary */
6358 {
6359 struct ia_css_binary_descr prim_descr[MAX_NUM_PRIMARY_STAGES];
6360
6361 for (i = 0; i < mycs->num_primary_stage; i++) {
6362 struct ia_css_frame_info *local_vf_info = NULL;
6363 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] && (i == mycs->num_primary_stage - 1))
6364 local_vf_info = &vf_info;
6365 ia_css_pipe_get_primary_binarydesc(pipe, &prim_descr[i], &prim_in_info, &prim_out_info, local_vf_info, i);
a49d2536
AC
6366 err = ia_css_binary_find(&prim_descr[i], &mycs->primary_binary[i]);
6367 if (err != IA_CSS_SUCCESS) {
6368 IA_CSS_LEAVE_ERR_PRIVATE(err);
6369 return err;
6370 }
6371 }
6372 }
6373
6374 /* Viewfinder post-processing */
6375 if (need_pp) {
6376 vf_pp_in_info =
6377 &mycs->capture_pp_binary.vf_frame_info;
6378 } else {
6379 vf_pp_in_info =
6380 &mycs->primary_binary[mycs->num_primary_stage - 1].vf_frame_info;
6381 }
6382
6383/*
6384 * WARNING: The #if def flag has been added below as a
6385 * temporary solution to solve the problem of enabling the
6386 * view finder in a single binary in a capture flow. The
6387 * vf-pp stage has been removed for Skycam in the solution
6388 * provided. The vf-pp stage should be re-introduced when
6389 * required. Thisshould not be considered as a clean solution.
6390 * Proper * investigation should be done to come up with the clean
6391 * solution.
6392 * */
6393 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0])
6394 {
6395 struct ia_css_binary_descr vf_pp_descr;
6396
6397 ia_css_pipe_get_vfpp_binarydesc(pipe,
6398 &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info);
a49d2536
AC
6399 err = ia_css_binary_find(&vf_pp_descr, &mycs->vf_pp_binary);
6400 if (err != IA_CSS_SUCCESS) {
6401 IA_CSS_LEAVE_ERR_PRIVATE(err);
6402 return err;
6403 }
6404 }
6405 err = allocate_delay_frames(pipe);
6406
6407 if (err != IA_CSS_SUCCESS)
6408 return err;
6409
6410#ifdef USE_INPUT_SYSTEM_VERSION_2401
6411 /* When the input system is 2401, only the Direct Sensor Mode
6412 * Offline Capture uses the ISP copy binary.
6413 */
6414 need_isp_copy_binary = !online && sensor;
6415#else
6416 need_isp_copy_binary = !online && !continuous && !memory;
6417#endif
6418
6419 /* ISP Copy */
6420 if (need_isp_copy_binary) {
6421 err = load_copy_binary(pipe,
6422 &mycs->copy_binary,
6423 &mycs->primary_binary[0]);
6424 if (err != IA_CSS_SUCCESS) {
6425 IA_CSS_LEAVE_ERR_PRIVATE(err);
6426 return err;
6427 }
6428 }
6429
6430 return IA_CSS_SUCCESS;
6431}
6432
6433static enum ia_css_err
6434allocate_delay_frames(struct ia_css_pipe *pipe)
6435{
6436 unsigned int num_delay_frames = 0, i = 0;
6437 unsigned int dvs_frame_delay = 0;
6438 struct ia_css_frame_info ref_info;
6439 enum ia_css_err err = IA_CSS_SUCCESS;
6440 enum ia_css_pipe_id mode = IA_CSS_PIPE_ID_VIDEO;
6441 struct ia_css_frame **delay_frames = NULL;
6442
6443 IA_CSS_ENTER_PRIVATE("");
6444
6445 if (pipe == NULL) {
158aeefc 6446 IA_CSS_ERROR("Invalid args - pipe %p", pipe);
a49d2536
AC
6447 return IA_CSS_ERR_INVALID_ARGUMENTS;
6448 }
6449
6450 mode = pipe->mode;
6451 dvs_frame_delay = pipe->dvs_frame_delay;
6452
6453 if (dvs_frame_delay > 0)
6454 num_delay_frames = dvs_frame_delay + 1;
6455
6456 switch (mode) {
6457 case IA_CSS_PIPE_ID_CAPTURE:
6458 {
6459 struct ia_css_capture_settings *mycs_capture = &pipe->pipe_settings.capture;
6460 (void)mycs_capture;
6461 return err;
6462 }
6463 break;
6464 case IA_CSS_PIPE_ID_VIDEO:
6465 {
6466 struct ia_css_video_settings *mycs_video = &pipe->pipe_settings.video;
6467 ref_info = mycs_video->video_binary.internal_frame_info;
6468 /*The ref frame expects
6469 * 1. Y plane
6470 * 2. UV plane with line interleaving, like below
6471 * UUUUUU(width/2 times) VVVVVVVV..(width/2 times)
6472 *
6473 * This format is not YUV420(which has Y, U and V planes).
6474 * Its closer to NV12, except that the UV plane has UV
6475 * interleaving, like UVUVUVUVUVUVUVUVU...
6476 *
6477 * TODO: make this ref_frame format as a separate frame format
6478 */
6479 ref_info.format = IA_CSS_FRAME_FORMAT_NV12;
6480 delay_frames = mycs_video->delay_frames;
6481 }
6482 break;
6483 case IA_CSS_PIPE_ID_PREVIEW:
6484 {
6485 struct ia_css_preview_settings *mycs_preview = &pipe->pipe_settings.preview;
6486 ref_info = mycs_preview->preview_binary.internal_frame_info;
6487 /*The ref frame expects
6488 * 1. Y plane
6489 * 2. UV plane with line interleaving, like below
6490 * UUUUUU(width/2 times) VVVVVVVV..(width/2 times)
6491 *
6492 * This format is not YUV420(which has Y, U and V planes).
6493 * Its closer to NV12, except that the UV plane has UV
6494 * interleaving, like UVUVUVUVUVUVUVUVU...
6495 *
6496 * TODO: make this ref_frame format as a separate frame format
6497 */
6498 ref_info.format = IA_CSS_FRAME_FORMAT_NV12;
6499 delay_frames = mycs_preview->delay_frames;
6500 }
6501 break;
6502 default:
6503 return IA_CSS_ERR_INVALID_ARGUMENTS;
6504
6505 }
6506
6507 ref_info.raw_bit_depth = SH_CSS_REF_BIT_DEPTH;
6508
6509 assert(num_delay_frames <= MAX_NUM_VIDEO_DELAY_FRAMES);
6510 for (i = 0; i < num_delay_frames; i++) {
6511 err = ia_css_frame_allocate_from_info(&delay_frames[i], &ref_info);
6512 if (err != IA_CSS_SUCCESS)
6513 return err;
a49d2536
AC
6514 }
6515 IA_CSS_LEAVE_PRIVATE("");
6516 return IA_CSS_SUCCESS;
6517}
6518
6519static enum ia_css_err load_advanced_binaries(
6520 struct ia_css_pipe *pipe)
6521{
6522 struct ia_css_frame_info pre_in_info, gdc_in_info,
6523 post_in_info, post_out_info,
6524 vf_info, *vf_pp_in_info, *pipe_out_info,
6525 *pipe_vf_out_info;
6526 bool need_pp;
6527 bool need_isp_copy = true;
6528 enum ia_css_err err = IA_CSS_SUCCESS;
6529
6530 IA_CSS_ENTER_PRIVATE("");
6531
6532 assert(pipe != NULL);
6533 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || pipe->mode == IA_CSS_PIPE_ID_COPY);
6534 if (pipe->pipe_settings.capture.pre_isp_binary.info)
6535 return IA_CSS_SUCCESS;
6536 pipe_out_info = &pipe->output_info[0];
6537 pipe_vf_out_info = &pipe->vf_output_info[0];
6538
6539 vf_info = *pipe_vf_out_info;
6540 err = ia_css_util_check_vf_out_info(pipe_out_info, &vf_info);
6541 if (err != IA_CSS_SUCCESS)
6542 return err;
6543 need_pp = need_capture_pp(pipe);
6544
6545 ia_css_frame_info_set_format(&vf_info,
6546 IA_CSS_FRAME_FORMAT_YUV_LINE);
6547
6548 /* we build up the pipeline starting at the end */
6549 /* Capture post-processing */
6550 if (need_pp) {
6551 struct ia_css_binary_descr capture_pp_descr;
6552
6553 ia_css_pipe_get_capturepp_binarydesc(pipe,
6554 &capture_pp_descr, &post_out_info, pipe_out_info, &vf_info);
6555 err = ia_css_binary_find(&capture_pp_descr,
6556 &pipe->pipe_settings.capture.capture_pp_binary);
6557 if (err != IA_CSS_SUCCESS)
6558 return err;
6559 } else {
6560 post_out_info = *pipe_out_info;
6561 }
6562
6563 /* Post-gdc */
6564 {
6565 struct ia_css_binary_descr post_gdc_descr;
6566
6567 ia_css_pipe_get_post_gdc_binarydesc(pipe,
6568 &post_gdc_descr, &post_in_info, &post_out_info, &vf_info);
6569 err = ia_css_binary_find(&post_gdc_descr,
6570 &pipe->pipe_settings.capture.post_isp_binary);
6571 if (err != IA_CSS_SUCCESS)
6572 return err;
6573 }
6574
6575 /* Gdc */
6576 {
6577 struct ia_css_binary_descr gdc_descr;
6578
6579 ia_css_pipe_get_gdc_binarydesc(pipe, &gdc_descr, &gdc_in_info,
6580 &pipe->pipe_settings.capture.post_isp_binary.in_frame_info);
6581 err = ia_css_binary_find(&gdc_descr,
6582 &pipe->pipe_settings.capture.anr_gdc_binary);
6583 if (err != IA_CSS_SUCCESS)
6584 return err;
6585 }
6586 pipe->pipe_settings.capture.anr_gdc_binary.left_padding =
6587 pipe->pipe_settings.capture.post_isp_binary.left_padding;
6588
6589 /* Pre-gdc */
6590 {
6591 struct ia_css_binary_descr pre_gdc_descr;
6592
6593 ia_css_pipe_get_pre_gdc_binarydesc(pipe, &pre_gdc_descr, &pre_in_info,
6594 &pipe->pipe_settings.capture.anr_gdc_binary.in_frame_info);
6595 err = ia_css_binary_find(&pre_gdc_descr,
6596 &pipe->pipe_settings.capture.pre_isp_binary);
6597 if (err != IA_CSS_SUCCESS)
6598 return err;
6599 }
6600 pipe->pipe_settings.capture.pre_isp_binary.left_padding =
6601 pipe->pipe_settings.capture.anr_gdc_binary.left_padding;
6602
6603 /* Viewfinder post-processing */
6604 if (need_pp) {
6605 vf_pp_in_info =
6606 &pipe->pipe_settings.capture.capture_pp_binary.vf_frame_info;
6607 } else {
6608 vf_pp_in_info =
6609 &pipe->pipe_settings.capture.post_isp_binary.vf_frame_info;
6610 }
6611
6612 {
6613 struct ia_css_binary_descr vf_pp_descr;
6614
6615 ia_css_pipe_get_vfpp_binarydesc(pipe,
6616 &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info);
6617 err = ia_css_binary_find(&vf_pp_descr,
6618 &pipe->pipe_settings.capture.vf_pp_binary);
6619 if (err != IA_CSS_SUCCESS)
6620 return err;
6621 }
6622
6623 /* Copy */
6624#ifdef USE_INPUT_SYSTEM_VERSION_2401
6625 /* For CSI2+, only the direct sensor mode/online requires ISP copy */
6626 need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
6627#endif
6628 if (need_isp_copy)
6629 load_copy_binary(pipe,
6630 &pipe->pipe_settings.capture.copy_binary,
6631 &pipe->pipe_settings.capture.pre_isp_binary);
6632
6633 return err;
6634}
6635
6636static enum ia_css_err load_bayer_isp_binaries(
6637 struct ia_css_pipe *pipe)
6638{
6639 struct ia_css_frame_info pre_isp_in_info, *pipe_out_info;
6640 enum ia_css_err err = IA_CSS_SUCCESS;
6641 struct ia_css_binary_descr pre_de_descr;
6642
6643 IA_CSS_ENTER_PRIVATE("");
6644 assert(pipe != NULL);
6645 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || pipe->mode == IA_CSS_PIPE_ID_COPY);
6646 pipe_out_info = &pipe->output_info[0];
6647
6648 if (pipe->pipe_settings.capture.pre_isp_binary.info)
6649 return IA_CSS_SUCCESS;
6650
6651 err = ia_css_frame_check_info(pipe_out_info);
6652 if (err != IA_CSS_SUCCESS)
6653 return err;
6654
6655 ia_css_pipe_get_pre_de_binarydesc(pipe, &pre_de_descr,
6656 &pre_isp_in_info,
6657 pipe_out_info);
6658
6659 err = ia_css_binary_find(&pre_de_descr,
6660 &pipe->pipe_settings.capture.pre_isp_binary);
6661
6662 return err;
6663}
6664
6665static enum ia_css_err load_low_light_binaries(
6666 struct ia_css_pipe *pipe)
6667{
6668 struct ia_css_frame_info pre_in_info, anr_in_info,
6669 post_in_info, post_out_info,
6670 vf_info, *pipe_vf_out_info, *pipe_out_info,
6671 *vf_pp_in_info;
6672 bool need_pp;
6673 bool need_isp_copy = true;
6674 enum ia_css_err err = IA_CSS_SUCCESS;
6675
6676 IA_CSS_ENTER_PRIVATE("");
6677 assert(pipe != NULL);
6678 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || pipe->mode == IA_CSS_PIPE_ID_COPY);
6679
6680 if (pipe->pipe_settings.capture.pre_isp_binary.info)
6681 return IA_CSS_SUCCESS;
6682 pipe_vf_out_info = &pipe->vf_output_info[0];
6683 pipe_out_info = &pipe->output_info[0];
6684
6685 vf_info = *pipe_vf_out_info;
6686 err = ia_css_util_check_vf_out_info(pipe_out_info,
6687 &vf_info);
6688 if (err != IA_CSS_SUCCESS)
6689 return err;
6690 need_pp = need_capture_pp(pipe);
6691
6692 ia_css_frame_info_set_format(&vf_info,
6693 IA_CSS_FRAME_FORMAT_YUV_LINE);
6694
6695 /* we build up the pipeline starting at the end */
6696 /* Capture post-processing */
6697 if (need_pp) {
6698 struct ia_css_binary_descr capture_pp_descr;
6699
6700 ia_css_pipe_get_capturepp_binarydesc(pipe,
6701 &capture_pp_descr, &post_out_info, pipe_out_info, &vf_info);
6702 err = ia_css_binary_find(&capture_pp_descr,
6703 &pipe->pipe_settings.capture.capture_pp_binary);
6704 if (err != IA_CSS_SUCCESS)
6705 return err;
6706 } else {
6707 post_out_info = *pipe_out_info;
6708 }
6709
6710 /* Post-anr */
6711 {
6712 struct ia_css_binary_descr post_anr_descr;
6713
6714 ia_css_pipe_get_post_anr_binarydesc(pipe,
6715 &post_anr_descr, &post_in_info, &post_out_info, &vf_info);
6716 err = ia_css_binary_find(&post_anr_descr,
6717 &pipe->pipe_settings.capture.post_isp_binary);
6718 if (err != IA_CSS_SUCCESS)
6719 return err;
6720 }
6721
6722 /* Anr */
6723 {
6724 struct ia_css_binary_descr anr_descr;
6725
6726 ia_css_pipe_get_anr_binarydesc(pipe, &anr_descr, &anr_in_info,
6727 &pipe->pipe_settings.capture.post_isp_binary.in_frame_info);
6728 err = ia_css_binary_find(&anr_descr,
6729 &pipe->pipe_settings.capture.anr_gdc_binary);
6730 if (err != IA_CSS_SUCCESS)
6731 return err;
6732 }
6733 pipe->pipe_settings.capture.anr_gdc_binary.left_padding =
6734 pipe->pipe_settings.capture.post_isp_binary.left_padding;
6735
6736 /* Pre-anr */
6737 {
6738 struct ia_css_binary_descr pre_anr_descr;
6739
6740 ia_css_pipe_get_pre_anr_binarydesc(pipe, &pre_anr_descr, &pre_in_info,
6741 &pipe->pipe_settings.capture.anr_gdc_binary.in_frame_info);
6742 err = ia_css_binary_find(&pre_anr_descr,
6743 &pipe->pipe_settings.capture.pre_isp_binary);
6744 if (err != IA_CSS_SUCCESS)
6745 return err;
6746 }
6747 pipe->pipe_settings.capture.pre_isp_binary.left_padding =
6748 pipe->pipe_settings.capture.anr_gdc_binary.left_padding;
6749
6750 /* Viewfinder post-processing */
6751 if (need_pp) {
6752 vf_pp_in_info =
6753 &pipe->pipe_settings.capture.capture_pp_binary.vf_frame_info;
6754 } else {
6755 vf_pp_in_info =
6756 &pipe->pipe_settings.capture.post_isp_binary.vf_frame_info;
6757 }
6758
6759 {
6760 struct ia_css_binary_descr vf_pp_descr;
6761
6762 ia_css_pipe_get_vfpp_binarydesc(pipe,
6763 &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info);
6764 err = ia_css_binary_find(&vf_pp_descr,
6765 &pipe->pipe_settings.capture.vf_pp_binary);
6766 if (err != IA_CSS_SUCCESS)
6767 return err;
6768 }
6769
6770 /* Copy */
6771#ifdef USE_INPUT_SYSTEM_VERSION_2401
6772 /* For CSI2+, only the direct sensor mode/online requires ISP copy */
6773 need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
6774#endif
6775 if (need_isp_copy)
6776 err = load_copy_binary(pipe,
6777 &pipe->pipe_settings.capture.copy_binary,
6778 &pipe->pipe_settings.capture.pre_isp_binary);
6779
6780 return err;
6781}
6782
6783static bool copy_on_sp(struct ia_css_pipe *pipe)
6784{
6785 bool rval;
6786
6787 assert(pipe != NULL);
6788 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "copy_on_sp() enter:\n");
6789
6790 rval = true;
6791
6792 rval &= (pipe->mode == IA_CSS_PIPE_ID_CAPTURE);
6793
6794 rval &= (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW);
6795
6796 rval &= ((pipe->stream->config.input_config.format == IA_CSS_STREAM_FORMAT_BINARY_8) ||
6797 (pipe->config.mode == IA_CSS_PIPE_MODE_COPY));
6798
6799 return rval;
6800}
6801
6802static enum ia_css_err load_capture_binaries(
6803 struct ia_css_pipe *pipe)
6804{
6805 enum ia_css_err err = IA_CSS_SUCCESS;
6806 bool must_be_raw;
6807
6808 IA_CSS_ENTER_PRIVATE("");
6809 assert(pipe != NULL);
6810 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || pipe->mode == IA_CSS_PIPE_ID_COPY);
6811
6812 if (pipe->pipe_settings.capture.primary_binary[0].info) {
6813 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
6814 return IA_CSS_SUCCESS;
6815 }
6816
6817 /* in primary, advanced,low light or bayer,
6818 the input format must be raw */
6819 must_be_raw =
6820 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_ADVANCED ||
6821 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER ||
6822 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT;
6823 err = ia_css_util_check_input(&pipe->stream->config, must_be_raw, false);
6824 if (err != IA_CSS_SUCCESS) {
6825 IA_CSS_LEAVE_ERR_PRIVATE(err);
6826 return err;
6827 }
6828 if (copy_on_sp(pipe) &&
6829 pipe->stream->config.input_config.format == IA_CSS_STREAM_FORMAT_BINARY_8) {
6830 ia_css_frame_info_init(
6831 &pipe->output_info[0],
6832 JPEG_BYTES,
6833 1,
6834 IA_CSS_FRAME_FORMAT_BINARY_8,
6835 0);
6836 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
6837 return IA_CSS_SUCCESS;
6838 }
6839
6840 switch (pipe->config.default_capture_config.mode) {
6841 case IA_CSS_CAPTURE_MODE_RAW:
6842 err = load_copy_binaries(pipe);
6843#if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2401)
6844 if (err == IA_CSS_SUCCESS)
6845 pipe->pipe_settings.capture.copy_binary.online = pipe->stream->config.online;
6846#endif
6847 break;
6848 case IA_CSS_CAPTURE_MODE_BAYER:
6849 err = load_bayer_isp_binaries(pipe);
6850 break;
6851 case IA_CSS_CAPTURE_MODE_PRIMARY:
6852 err = load_primary_binaries(pipe);
6853 break;
6854 case IA_CSS_CAPTURE_MODE_ADVANCED:
6855 err = load_advanced_binaries(pipe);
6856 break;
6857 case IA_CSS_CAPTURE_MODE_LOW_LIGHT:
6858 err = load_low_light_binaries(pipe);
6859 break;
6860 }
6861 if (err != IA_CSS_SUCCESS) {
6862 IA_CSS_LEAVE_ERR_PRIVATE(err);
6863 return err;
6864 }
6865
6866 IA_CSS_LEAVE_ERR_PRIVATE(err);
6867 return err;
6868}
6869
6870static enum ia_css_err
6871unload_capture_binaries(struct ia_css_pipe *pipe)
6872{
6873 unsigned int i;
6874 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
6875
6876 if ((pipe == NULL) || ((pipe->mode != IA_CSS_PIPE_ID_CAPTURE) && (pipe->mode != IA_CSS_PIPE_ID_COPY))) {
6877 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
6878 return IA_CSS_ERR_INVALID_ARGUMENTS;
6879 }
6880 ia_css_binary_unload(&pipe->pipe_settings.capture.copy_binary);
6881 for (i = 0; i < MAX_NUM_PRIMARY_STAGES; i++)
6882 ia_css_binary_unload(&pipe->pipe_settings.capture.primary_binary[i]);
6883 ia_css_binary_unload(&pipe->pipe_settings.capture.pre_isp_binary);
6884 ia_css_binary_unload(&pipe->pipe_settings.capture.anr_gdc_binary);
6885 ia_css_binary_unload(&pipe->pipe_settings.capture.post_isp_binary);
6886 ia_css_binary_unload(&pipe->pipe_settings.capture.capture_pp_binary);
6887 ia_css_binary_unload(&pipe->pipe_settings.capture.capture_ldc_binary);
6888 ia_css_binary_unload(&pipe->pipe_settings.capture.vf_pp_binary);
6889
6890 for (i = 0; i < pipe->pipe_settings.capture.num_yuv_scaler; i++)
6891 ia_css_binary_unload(&pipe->pipe_settings.capture.yuv_scaler_binary[i]);
6892
94853b65 6893 kfree(pipe->pipe_settings.capture.is_output_stage);
a49d2536 6894 pipe->pipe_settings.capture.is_output_stage = NULL;
94853b65 6895 kfree(pipe->pipe_settings.capture.yuv_scaler_binary);
a49d2536
AC
6896 pipe->pipe_settings.capture.yuv_scaler_binary = NULL;
6897
6898 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
6899 return IA_CSS_SUCCESS;
6900}
6901
6902static bool
6903need_downscaling(const struct ia_css_resolution in_res,
6904 const struct ia_css_resolution out_res)
6905{
6906
6907 if (in_res.width > out_res.width || in_res.height > out_res.height)
6908 return true;
6909
6910 return false;
6911}
6912
6913static bool
6914need_yuv_scaler_stage(const struct ia_css_pipe *pipe)
6915{
6916 unsigned int i;
6917 struct ia_css_resolution in_res, out_res;
6918
6919 bool need_format_conversion = false;
6920
6921 IA_CSS_ENTER_PRIVATE("");
6922 assert(pipe != NULL);
6923 assert(pipe->mode == IA_CSS_PIPE_ID_YUVPP);
6924
6925 /* TODO: make generic function */
6926 need_format_conversion =
6927 ((pipe->stream->config.input_config.format == IA_CSS_STREAM_FORMAT_YUV420_8_LEGACY) &&
6928 (pipe->output_info[0].format != IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8));
6929
6930 in_res = pipe->config.input_effective_res;
6931
6932 if (pipe->config.enable_dz)
6933 return true;
6934
6935 if ((pipe->output_info[0].res.width != 0) && need_format_conversion)
6936 return true;
6937
6938 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
6939 out_res = pipe->output_info[i].res;
6940
6941 /* A non-zero width means it is a valid output port */
6942 if ((out_res.width != 0) && need_downscaling(in_res, out_res))
6943 return true;
6944 }
6945
6946 return false;
6947}
6948
6949/* TODO: it is temporarily created from ia_css_pipe_create_cas_scaler_desc */
6950/* which has some hard-coded knowledge which prevents reuse of the function. */
6951/* Later, merge this with ia_css_pipe_create_cas_scaler_desc */
6952static enum ia_css_err ia_css_pipe_create_cas_scaler_desc_single_output(
6953 struct ia_css_frame_info *cas_scaler_in_info,
6954 struct ia_css_frame_info *cas_scaler_out_info,
6955 struct ia_css_frame_info *cas_scaler_vf_info,
6956 struct ia_css_cas_binary_descr *descr)
6957{
6958 unsigned int i;
6959 unsigned int hor_ds_factor = 0, ver_ds_factor = 0;
6960 enum ia_css_err err = IA_CSS_SUCCESS;
6961 struct ia_css_frame_info tmp_in_info = IA_CSS_BINARY_DEFAULT_FRAME_INFO;
6962
6963 unsigned max_scale_factor_per_stage = MAX_PREFERRED_YUV_DS_PER_STEP;
6964
6965 assert(cas_scaler_in_info != NULL);
6966 assert(cas_scaler_out_info != NULL);
6967
6968 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_pipe_create_cas_scaler_desc() enter:\n");
6969
6970 /* We assume that this function is used only for single output port case. */
6971 descr->num_output_stage = 1;
6972
6973 hor_ds_factor = CEIL_DIV(cas_scaler_in_info->res.width , cas_scaler_out_info->res.width);
6974 ver_ds_factor = CEIL_DIV(cas_scaler_in_info->res.height, cas_scaler_out_info->res.height);
6975 /* use the same horizontal and vertical downscaling factor for simplicity */
6976 assert(hor_ds_factor == ver_ds_factor);
6977
6978 i = 1;
6979 while (i < hor_ds_factor) {
6980 descr->num_stage++;
6981 i *= max_scale_factor_per_stage;
6982 }
6983
94853b65 6984 descr->in_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), GFP_KERNEL);
bbae6156 6985 if (!descr->in_info) {
a49d2536
AC
6986 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
6987 goto ERR;
6988 }
94853b65 6989 descr->internal_out_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), GFP_KERNEL);
bbae6156 6990 if (!descr->internal_out_info) {
a49d2536
AC
6991 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
6992 goto ERR;
6993 }
94853b65 6994 descr->out_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), GFP_KERNEL);
bbae6156 6995 if (!descr->out_info) {
a49d2536
AC
6996 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
6997 goto ERR;
6998 }
94853b65 6999 descr->vf_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), GFP_KERNEL);
bbae6156 7000 if (!descr->vf_info) {
a49d2536
AC
7001 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7002 goto ERR;
7003 }
94853b65 7004 descr->is_output_stage = kmalloc(descr->num_stage * sizeof(bool), GFP_KERNEL);
bbae6156 7005 if (!descr->is_output_stage) {
a49d2536
AC
7006 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7007 goto ERR;
7008 }
7009
7010 tmp_in_info = *cas_scaler_in_info;
7011 for (i = 0; i < descr->num_stage; i++) {
7012
7013 descr->in_info[i] = tmp_in_info;
7014 if ((tmp_in_info.res.width / max_scale_factor_per_stage) <= cas_scaler_out_info->res.width) {
7015 descr->is_output_stage[i] = true;
7016 if ((descr->num_output_stage > 1) && (i != (descr->num_stage - 1))) {
7017 descr->internal_out_info[i].res.width = cas_scaler_out_info->res.width;
7018 descr->internal_out_info[i].res.height = cas_scaler_out_info->res.height;
7019 descr->internal_out_info[i].padded_width = cas_scaler_out_info->padded_width;
7020 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
7021 } else {
7022 assert(i == (descr->num_stage - 1));
7023 descr->internal_out_info[i].res.width = 0;
7024 descr->internal_out_info[i].res.height = 0;
7025 }
7026 descr->out_info[i].res.width = cas_scaler_out_info->res.width;
7027 descr->out_info[i].res.height = cas_scaler_out_info->res.height;
7028 descr->out_info[i].padded_width = cas_scaler_out_info->padded_width;
7029 descr->out_info[i].format = cas_scaler_out_info->format;
7030 if (cas_scaler_vf_info != NULL) {
7031 descr->vf_info[i].res.width = cas_scaler_vf_info->res.width;
7032 descr->vf_info[i].res.height = cas_scaler_vf_info->res.height;
7033 descr->vf_info[i].padded_width = cas_scaler_vf_info->padded_width;
7034 ia_css_frame_info_set_format(&descr->vf_info[i], IA_CSS_FRAME_FORMAT_YUV_LINE);
7035 } else {
7036 descr->vf_info[i].res.width = 0;
7037 descr->vf_info[i].res.height = 0;
7038 descr->vf_info[i].padded_width = 0;
7039 }
7040 } else {
7041 descr->is_output_stage[i] = false;
7042 descr->internal_out_info[i].res.width = tmp_in_info.res.width / max_scale_factor_per_stage;
7043 descr->internal_out_info[i].res.height = tmp_in_info.res.height / max_scale_factor_per_stage;
7044 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
7045 ia_css_frame_info_init(&descr->internal_out_info[i],
7046 tmp_in_info.res.width / max_scale_factor_per_stage,
7047 tmp_in_info.res.height / max_scale_factor_per_stage,
7048 IA_CSS_FRAME_FORMAT_YUV420, 0);
7049 descr->out_info[i].res.width = 0;
7050 descr->out_info[i].res.height = 0;
7051 descr->vf_info[i].res.width = 0;
7052 descr->vf_info[i].res.height = 0;
7053 }
7054 tmp_in_info = descr->internal_out_info[i];
7055 }
7056ERR:
7057 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_pipe_create_cas_scaler_desc() leave, err=%d\n",
7058 err);
7059 return err;
7060}
7061
94853b65 7062/* FIXME: merge most of this and single output version */
a49d2536
AC
7063static enum ia_css_err ia_css_pipe_create_cas_scaler_desc(struct ia_css_pipe *pipe,
7064 struct ia_css_cas_binary_descr *descr)
7065{
7066 struct ia_css_frame_info in_info = IA_CSS_BINARY_DEFAULT_FRAME_INFO;
7067 struct ia_css_frame_info *out_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
7068 struct ia_css_frame_info *vf_out_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
7069 struct ia_css_frame_info tmp_in_info = IA_CSS_BINARY_DEFAULT_FRAME_INFO;
7070 unsigned int i, j;
7071 unsigned int hor_scale_factor[IA_CSS_PIPE_MAX_OUTPUT_STAGE],
7072 ver_scale_factor[IA_CSS_PIPE_MAX_OUTPUT_STAGE],
7073 scale_factor = 0;
7074 unsigned int num_stages = 0;
7075 enum ia_css_err err = IA_CSS_SUCCESS;
7076
7077 unsigned max_scale_factor_per_stage = MAX_PREFERRED_YUV_DS_PER_STEP;
7078
7079 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_pipe_create_cas_scaler_desc() enter:\n");
7080
7081 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
7082 out_info[i] = NULL;
7083 vf_out_info[i] = NULL;
7084 hor_scale_factor[i] = 0;
7085 ver_scale_factor[i] = 0;
7086 }
7087
7088 in_info.res = pipe->config.input_effective_res;
7089 in_info.padded_width = in_info.res.width;
7090 descr->num_output_stage = 0;
7091 /* Find out how much scaling we need for each output */
7092 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
7093 if (pipe->output_info[i].res.width != 0) {
7094 out_info[i] = &pipe->output_info[i];
7095 if (pipe->vf_output_info[i].res.width != 0)
7096 vf_out_info[i] = &pipe->vf_output_info[i];
7097 descr->num_output_stage += 1;
7098 }
7099
7100 if (out_info[i] != NULL) {
7101 hor_scale_factor[i] = CEIL_DIV(in_info.res.width, out_info[i]->res.width);
7102 ver_scale_factor[i] = CEIL_DIV(in_info.res.height, out_info[i]->res.height);
7103 /* use the same horizontal and vertical scaling factor for simplicity */
7104 assert(hor_scale_factor[i] == ver_scale_factor[i]);
7105 scale_factor = 1;
7106 do {
7107 num_stages++;
7108 scale_factor *= max_scale_factor_per_stage;
7109 } while (scale_factor < hor_scale_factor[i]);
7110
7111 in_info.res = out_info[i]->res;
7112 }
7113 }
7114
7115 if (need_yuv_scaler_stage(pipe) && (num_stages == 0))
7116 num_stages = 1;
7117
7118 descr->num_stage = num_stages;
7119
94853b65 7120 descr->in_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), GFP_KERNEL);
bbae6156 7121 if (!descr->in_info) {
a49d2536
AC
7122 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7123 goto ERR;
7124 }
94853b65 7125 descr->internal_out_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), GFP_KERNEL);
bbae6156 7126 if (!descr->internal_out_info) {
a49d2536
AC
7127 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7128 goto ERR;
7129 }
94853b65 7130 descr->out_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), GFP_KERNEL);
bbae6156 7131 if (!descr->out_info) {
a49d2536
AC
7132 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7133 goto ERR;
7134 }
94853b65 7135 descr->vf_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), GFP_KERNEL);
bbae6156 7136 if (!descr->vf_info) {
a49d2536
AC
7137 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7138 goto ERR;
7139 }
94853b65 7140 descr->is_output_stage = kmalloc(descr->num_stage * sizeof(bool), GFP_KERNEL);
a49d2536
AC
7141 if (descr->is_output_stage == NULL) {
7142 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7143 goto ERR;
7144 }
7145
7146 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
7147 if (out_info[i]) {
7148 if (i > 0) {
7149 assert((out_info[i-1]->res.width >= out_info[i]->res.width) &&
7150 (out_info[i-1]->res.height >= out_info[i]->res.height));
7151 }
7152 }
7153 }
7154
7155 tmp_in_info.res = pipe->config.input_effective_res;
7156 tmp_in_info.format = IA_CSS_FRAME_FORMAT_YUV420;
7157 for (i = 0, j = 0; i < descr->num_stage; i++) {
7158 assert(j < 2);
7159 assert(out_info[j] != NULL);
7160
7161 descr->in_info[i] = tmp_in_info;
7162 if ((tmp_in_info.res.width / max_scale_factor_per_stage) <= out_info[j]->res.width) {
7163 descr->is_output_stage[i] = true;
7164 if ((descr->num_output_stage > 1) && (i != (descr->num_stage - 1))) {
7165 descr->internal_out_info[i].res.width = out_info[j]->res.width;
7166 descr->internal_out_info[i].res.height = out_info[j]->res.height;
7167 descr->internal_out_info[i].padded_width = out_info[j]->padded_width;
7168 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
7169 } else {
7170 assert(i == (descr->num_stage - 1));
7171 descr->internal_out_info[i].res.width = 0;
7172 descr->internal_out_info[i].res.height = 0;
7173 }
7174 descr->out_info[i].res.width = out_info[j]->res.width;
7175 descr->out_info[i].res.height = out_info[j]->res.height;
7176 descr->out_info[i].padded_width = out_info[j]->padded_width;
7177 descr->out_info[i].format = out_info[j]->format;
7178 if (vf_out_info[j] != NULL) {
7179 descr->vf_info[i].res.width = vf_out_info[j]->res.width;
7180 descr->vf_info[i].res.height = vf_out_info[j]->res.height;
7181 descr->vf_info[i].padded_width = vf_out_info[j]->padded_width;
7182 ia_css_frame_info_set_format(&descr->vf_info[i], IA_CSS_FRAME_FORMAT_YUV_LINE);
7183 } else {
7184 descr->vf_info[i].res.width = 0;
7185 descr->vf_info[i].res.height = 0;
7186 descr->vf_info[i].padded_width = 0;
7187 }
7188 j++;
7189 } else {
7190 descr->is_output_stage[i] = false;
7191 descr->internal_out_info[i].res.width = tmp_in_info.res.width / max_scale_factor_per_stage;
7192 descr->internal_out_info[i].res.height = tmp_in_info.res.height / max_scale_factor_per_stage;
7193 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
7194 ia_css_frame_info_init(&descr->internal_out_info[i],
7195 tmp_in_info.res.width / max_scale_factor_per_stage,
7196 tmp_in_info.res.height / max_scale_factor_per_stage,
7197 IA_CSS_FRAME_FORMAT_YUV420, 0);
7198 descr->out_info[i].res.width = 0;
7199 descr->out_info[i].res.height = 0;
7200 descr->vf_info[i].res.width = 0;
7201 descr->vf_info[i].res.height = 0;
7202 }
7203 tmp_in_info = descr->internal_out_info[i];
7204 }
7205ERR:
7206 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_pipe_create_cas_scaler_desc() leave, err=%d\n",
7207 err);
7208 return err;
7209}
7210
7211static void ia_css_pipe_destroy_cas_scaler_desc(struct ia_css_cas_binary_descr *descr)
7212{
7213 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_pipe_destroy_cas_scaler_desc() enter:\n");
94853b65 7214 kfree(descr->in_info);
a49d2536 7215 descr->in_info = NULL;
94853b65 7216 kfree(descr->internal_out_info);
a49d2536 7217 descr->internal_out_info = NULL;
94853b65 7218 kfree(descr->out_info);
a49d2536 7219 descr->out_info = NULL;
94853b65 7220 kfree(descr->vf_info);
a49d2536 7221 descr->vf_info = NULL;
94853b65 7222 kfree(descr->is_output_stage);
a49d2536
AC
7223 descr->is_output_stage = NULL;
7224 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_pipe_destroy_cas_scaler_desc() leave\n");
7225}
7226
7227static enum ia_css_err
7228load_yuvpp_binaries(struct ia_css_pipe *pipe)
7229{
7230 enum ia_css_err err = IA_CSS_SUCCESS;
7231 bool need_scaler = false;
7232 struct ia_css_frame_info *vf_pp_in_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
7233 struct ia_css_yuvpp_settings *mycs;
7234 struct ia_css_binary *next_binary;
7235 struct ia_css_cas_binary_descr cas_scaler_descr = IA_CSS_DEFAULT_CAS_BINARY_DESCR;
7236 unsigned int i, j;
7237 bool need_isp_copy_binary = false;
7238
7239 IA_CSS_ENTER_PRIVATE("");
7240 assert(pipe != NULL);
7241 assert(pipe->stream != NULL);
7242 assert(pipe->mode == IA_CSS_PIPE_ID_YUVPP);
7243
7244 if (pipe->pipe_settings.yuvpp.copy_binary.info)
7245 goto ERR;
7246
7247 /* Set both must_be_raw and must_be_yuv to false then yuvpp can take rgb inputs */
7248 err = ia_css_util_check_input(&pipe->stream->config, false, false);
7249 if (err != IA_CSS_SUCCESS)
7250 goto ERR;
7251
7252 mycs = &pipe->pipe_settings.yuvpp;
7253
7254 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
7255 if (pipe->vf_output_info[i].res.width != 0) {
7256 err = ia_css_util_check_vf_out_info(&pipe->output_info[i],
7257 &pipe->vf_output_info[i]);
7258 if (err != IA_CSS_SUCCESS)
7259 goto ERR;
7260 }
7261 vf_pp_in_info[i] = NULL;
7262 }
7263
7264 need_scaler = need_yuv_scaler_stage(pipe);
7265
7266 /* we build up the pipeline starting at the end */
7267 /* Capture post-processing */
7268 if (need_scaler) {
7269 struct ia_css_binary_descr yuv_scaler_descr;
7270
7271 err = ia_css_pipe_create_cas_scaler_desc(pipe,
7272 &cas_scaler_descr);
7273 if (err != IA_CSS_SUCCESS)
7274 goto ERR;
7275 mycs->num_output = cas_scaler_descr.num_output_stage;
7276 mycs->num_yuv_scaler = cas_scaler_descr.num_stage;
94853b65
AC
7277 mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage *
7278 sizeof(struct ia_css_binary), GFP_KERNEL);
bbae6156 7279 if (!mycs->yuv_scaler_binary) {
a49d2536
AC
7280 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7281 goto ERR;
7282 }
94853b65
AC
7283 mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage *
7284 sizeof(bool), GFP_KERNEL);
bbae6156 7285 if (!mycs->is_output_stage) {
a49d2536
AC
7286 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7287 goto ERR;
7288 }
7289 for (i = 0; i < cas_scaler_descr.num_stage; i++) {
7290 mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i];
7291 ia_css_pipe_get_yuvscaler_binarydesc(pipe,
7292 &yuv_scaler_descr, &cas_scaler_descr.in_info[i],
7293 &cas_scaler_descr.out_info[i],
7294 &cas_scaler_descr.internal_out_info[i],
7295 &cas_scaler_descr.vf_info[i]);
7296 err = ia_css_binary_find(&yuv_scaler_descr,
7297 &mycs->yuv_scaler_binary[i]);
7298 if (err != IA_CSS_SUCCESS)
7299 goto ERR;
7300 }
7301 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
7302 } else {
7303 mycs->num_output = 1;
7304 }
7305
7306 if (need_scaler) {
7307 next_binary = &mycs->yuv_scaler_binary[0];
7308 } else {
7309 next_binary = NULL;
7310 }
7311
7312#if defined(USE_INPUT_SYSTEM_VERSION_2401)
7313 /*
7314 * NOTES
7315 * - Why does the "yuvpp" pipe needs "isp_copy_binary" (i.e. ISP Copy) when
7316 * its input is "IA_CSS_STREAM_FORMAT_YUV422_8"?
7317 *
7318 * In most use cases, the first stage in the "yuvpp" pipe is the "yuv_scale_
7319 * binary". However, the "yuv_scale_binary" does NOT support the input-frame
7320 * format as "IA_CSS_STREAM _FORMAT_YUV422_8".
7321 *
7322 * Hence, the "isp_copy_binary" is required to be present in front of the "yuv
7323 * _scale_binary". It would translate the input-frame to the frame formats that
7324 * are supported by the "yuv_scale_binary".
7325 *
7326 * Please refer to "FrameWork/css/isp/pipes/capture_pp/capture_pp_1.0/capture_
7327 * pp_defs.h" for the list of input-frame formats that are supported by the
7328 * "yuv_scale_binary".
7329 */
7330 need_isp_copy_binary =
7331 (pipe->stream->config.input_config.format == IA_CSS_STREAM_FORMAT_YUV422_8);
7332#else /* !USE_INPUT_SYSTEM_VERSION_2401 */
7333 need_isp_copy_binary = true;
7334#endif /* USE_INPUT_SYSTEM_VERSION_2401 */
7335
7336 if (need_isp_copy_binary) {
7337 err = load_copy_binary(pipe,
7338 &mycs->copy_binary,
7339 next_binary);
7340
7341 if (err != IA_CSS_SUCCESS)
7342 goto ERR;
7343
7344 /*
7345 * NOTES
7346 * - Why is "pipe->pipe_settings.capture.copy_binary.online" specified?
7347 *
7348 * In some use cases, the first stage in the "yuvpp" pipe is the
7349 * "isp_copy_binary". The "isp_copy_binary" is designed to process
7350 * the input from either the system DDR or from the IPU internal VMEM.
7351 * So it provides the flag "online" to specify where its input is from,
7352 * i.e.:
7353 *
7354 * (1) "online <= true", the input is from the IPU internal VMEM.
7355 * (2) "online <= false", the input is from the system DDR.
7356 *
7357 * In other use cases, the first stage in the "yuvpp" pipe is the
7358 * "yuv_scale_binary". "The "yuv_scale_binary" is designed to process the
7359 * input ONLY from the system DDR. So it does not provide the flag "online"
7360 * to specify where its input is from.
7361 */
7362 pipe->pipe_settings.capture.copy_binary.online = pipe->stream->config.online;
7363 }
7364
7365 /* Viewfinder post-processing */
7366 if (need_scaler) {
7367 for (i = 0, j = 0; i < mycs->num_yuv_scaler; i++) {
7368 if (mycs->is_output_stage[i]) {
7369 assert(j < 2);
7370 vf_pp_in_info[j] =
7371 &mycs->yuv_scaler_binary[i].vf_frame_info;
7372 j++;
7373 }
7374 }
7375 mycs->num_vf_pp = j;
7376 } else {
7377 vf_pp_in_info[0] =
7378 &mycs->copy_binary.vf_frame_info;
7379 for (i = 1; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
7380 vf_pp_in_info[i] = NULL;
7381 }
7382 mycs->num_vf_pp = 1;
7383 }
94853b65
AC
7384 mycs->vf_pp_binary = kzalloc(mycs->num_vf_pp * sizeof(struct ia_css_binary),
7385 GFP_KERNEL);
bbae6156 7386 if (!mycs->vf_pp_binary) {
a49d2536
AC
7387 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7388 goto ERR;
7389 }
7390
7391 {
7392 struct ia_css_binary_descr vf_pp_descr;
7393
7394 for (i = 0; i < mycs->num_vf_pp; i++) {
7395 if (pipe->vf_output_info[i].res.width != 0) {
7396 ia_css_pipe_get_vfpp_binarydesc(pipe,
7397 &vf_pp_descr, vf_pp_in_info[i], &pipe->vf_output_info[i]);
7398 err = ia_css_binary_find(&vf_pp_descr, &mycs->vf_pp_binary[i]);
7399 if (err != IA_CSS_SUCCESS)
7400 goto ERR;
7401 }
7402 }
7403 }
7404
7405 if (err != IA_CSS_SUCCESS)
7406 goto ERR;
7407
7408ERR:
7409 if (need_scaler) {
7410 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
7411 }
7412 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "load_yuvpp_binaries() leave, err=%d\n",
7413 err);
7414 return err;
7415}
7416
7417static enum ia_css_err
7418unload_yuvpp_binaries(struct ia_css_pipe *pipe)
7419{
7420 unsigned int i;
7421 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
7422
7423 if ((pipe == NULL) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) {
7424 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
7425 return IA_CSS_ERR_INVALID_ARGUMENTS;
7426 }
7427 ia_css_binary_unload(&pipe->pipe_settings.yuvpp.copy_binary);
7428 for (i = 0; i < pipe->pipe_settings.yuvpp.num_yuv_scaler; i++) {
7429 ia_css_binary_unload(&pipe->pipe_settings.yuvpp.yuv_scaler_binary[i]);
7430 }
7431 for (i = 0; i < pipe->pipe_settings.yuvpp.num_vf_pp; i++) {
7432 ia_css_binary_unload(&pipe->pipe_settings.yuvpp.vf_pp_binary[i]);
7433 }
94853b65 7434 kfree(pipe->pipe_settings.yuvpp.is_output_stage);
a49d2536 7435 pipe->pipe_settings.yuvpp.is_output_stage = NULL;
94853b65 7436 kfree(pipe->pipe_settings.yuvpp.yuv_scaler_binary);
a49d2536 7437 pipe->pipe_settings.yuvpp.yuv_scaler_binary = NULL;
94853b65 7438 kfree(pipe->pipe_settings.yuvpp.vf_pp_binary);
a49d2536
AC
7439 pipe->pipe_settings.yuvpp.vf_pp_binary = NULL;
7440
7441 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
7442 return IA_CSS_SUCCESS;
7443}
7444
7445static enum ia_css_err yuvpp_start(struct ia_css_pipe *pipe)
7446{
7447 struct ia_css_binary *copy_binary;
7448 enum ia_css_err err = IA_CSS_SUCCESS;
7449 enum sh_css_pipe_config_override copy_ovrd;
7450 enum ia_css_input_mode yuvpp_pipe_input_mode;
7451
7452 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
7453 if ((pipe == NULL) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) {
7454 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
7455 return IA_CSS_ERR_INVALID_ARGUMENTS;
7456 }
7457
7458 yuvpp_pipe_input_mode = pipe->stream->config.mode;
7459
7460 copy_binary = &pipe->pipe_settings.yuvpp.copy_binary;
7461
7462 sh_css_metrics_start_frame();
7463
7464 /* multi stream video needs mipi buffers */
7465
7466#if !defined(HAS_NO_INPUT_SYSTEM) && ( defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401) )
7467 err = send_mipi_frames(pipe);
7468 if (err != IA_CSS_SUCCESS) {
7469 IA_CSS_LEAVE_ERR_PRIVATE(err);
7470 return err;
7471 }
7472#endif
7473
7474 {
7475 unsigned int thread_id;
7476
7477 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
7478 copy_ovrd = 1 << thread_id;
7479 }
7480
7481 start_pipe(pipe, copy_ovrd, yuvpp_pipe_input_mode);
7482
7483 IA_CSS_LEAVE_ERR_PRIVATE(err);
7484 return err;
7485}
7486
7487static enum ia_css_err
7488sh_css_pipe_unload_binaries(struct ia_css_pipe *pipe)
7489{
7490 enum ia_css_err err = IA_CSS_SUCCESS;
7491 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
7492
7493 if (pipe == NULL) {
7494 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
7495 return IA_CSS_ERR_INVALID_ARGUMENTS;
7496 }
7497 /* PIPE_MODE_COPY has no binaries, but has output frames to outside*/
7498 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY) {
7499 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
7500 return IA_CSS_SUCCESS;
7501 }
7502
7503 switch (pipe->mode) {
7504 case IA_CSS_PIPE_ID_PREVIEW:
7505 err = unload_preview_binaries(pipe);
7506 break;
7507 case IA_CSS_PIPE_ID_VIDEO:
7508 err = unload_video_binaries(pipe);
7509 break;
7510 case IA_CSS_PIPE_ID_CAPTURE:
7511 err = unload_capture_binaries(pipe);
7512 break;
7513 case IA_CSS_PIPE_ID_YUVPP:
7514 err = unload_yuvpp_binaries(pipe);
7515 break;
7516 default:
7517 break;
7518 }
7519 IA_CSS_LEAVE_ERR_PRIVATE(err);
7520 return err;
7521}
7522
7523static enum ia_css_err
7524sh_css_pipe_load_binaries(struct ia_css_pipe *pipe)
7525{
7526 enum ia_css_err err = IA_CSS_SUCCESS;
7527
7528 assert(pipe != NULL);
7529 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "sh_css_pipe_load_binaries() enter:\n");
7530
7531 /* PIPE_MODE_COPY has no binaries, but has output frames to outside*/
7532 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY)
7533 return err;
7534
7535 switch (pipe->mode) {
7536 case IA_CSS_PIPE_ID_PREVIEW:
7537 err = load_preview_binaries(pipe);
7538 break;
7539 case IA_CSS_PIPE_ID_VIDEO:
7540 err = load_video_binaries(pipe);
7541 break;
7542 case IA_CSS_PIPE_ID_CAPTURE:
7543 err = load_capture_binaries(pipe);
7544 break;
7545 case IA_CSS_PIPE_ID_YUVPP:
7546 err = load_yuvpp_binaries(pipe);
7547 break;
7548 case IA_CSS_PIPE_ID_ACC:
7549 break;
7550 default:
7551 err = IA_CSS_ERR_INTERNAL_ERROR;
7552 break;
7553 }
7554 if (err != IA_CSS_SUCCESS) {
7555 if (sh_css_pipe_unload_binaries(pipe) != IA_CSS_SUCCESS) {
7556 /* currently css does not support multiple error returns in a single function,
7557 * using IA_CSS_ERR_INTERNAL_ERROR in this case */
7558 err = IA_CSS_ERR_INTERNAL_ERROR;
7559 }
7560 }
7561 return err;
7562}
7563
7564static enum ia_css_err
7565create_host_yuvpp_pipeline(struct ia_css_pipe *pipe)
7566{
7567 struct ia_css_pipeline *me;
7568 enum ia_css_err err = IA_CSS_SUCCESS;
7569 struct ia_css_pipeline_stage *vf_pp_stage = NULL,
7570 *copy_stage = NULL,
7571 *yuv_scaler_stage = NULL;
7572 struct ia_css_binary *copy_binary,
7573 *vf_pp_binary,
7574 *yuv_scaler_binary;
7575 bool need_scaler = false;
7576 unsigned int num_stage, num_vf_pp_stage, num_output_stage;
7577 unsigned int i, j;
7578
7579 struct ia_css_frame *in_frame = NULL;
7580 struct ia_css_frame *out_frame[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
7581 struct ia_css_frame *bin_out_frame[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
7582 struct ia_css_frame *vf_frame[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
7583 struct ia_css_pipeline_stage_desc stage_desc;
7584 bool need_in_frameinfo_memory = false;
7585#ifdef USE_INPUT_SYSTEM_VERSION_2401
7586 bool sensor = false;
7587 bool buffered_sensor = false;
7588 bool online = false;
7589 bool continuous = false;
7590#endif
7591
7592 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
7593 if ((pipe == NULL) || (pipe->stream == NULL) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) {
7594 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
7595 return IA_CSS_ERR_INVALID_ARGUMENTS;
7596 }
7597 me = &pipe->pipeline;
7598 ia_css_pipeline_clean(me);
7599 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
7600 out_frame[i] = NULL;
7601 vf_frame[i] = NULL;
7602 }
7603 ia_css_pipe_util_create_output_frames(bin_out_frame);
7604 num_stage = pipe->pipe_settings.yuvpp.num_yuv_scaler;
7605 num_vf_pp_stage = pipe->pipe_settings.yuvpp.num_vf_pp;
7606 num_output_stage = pipe->pipe_settings.yuvpp.num_output;
7607
7608#ifdef USE_INPUT_SYSTEM_VERSION_2401
7609 /* When the input system is 2401, always enable 'in_frameinfo_memory'
7610 * except for the following:
7611 * - Direct Sensor Mode Online Capture
7612 * - Direct Sensor Mode Continuous Capture
7613 * - Buffered Sensor Mode Continous Capture
7614 */
7615 sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
7616 buffered_sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR;
7617 online = pipe->stream->config.online;
7618 continuous = pipe->stream->config.continuous;
7619 need_in_frameinfo_memory =
7620 !((sensor && (online || continuous)) || (buffered_sensor && continuous));
7621#else
7622 /* Construct in_frame info (only in case we have dynamic input */
7623 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
7624#endif
7625 /* the input frame can come from:
7626 * a) memory: connect yuvscaler to me->in_frame
7627 * b) sensor, via copy binary: connect yuvscaler to copy binary later on */
7628 if (need_in_frameinfo_memory) {
7629 /* TODO: improve for different input formats. */
7630
7631 /*
7632 * "pipe->stream->config.input_config.format" represents the sensor output
7633 * frame format, e.g. YUV422 8-bit.
7634 *
7635 * "in_frame_format" represents the imaging pipe's input frame format, e.g.
7636 * Bayer-Quad RAW.
7637 */
7638 int in_frame_format;
7639 if (pipe->stream->config.input_config.format == IA_CSS_STREAM_FORMAT_YUV420_8_LEGACY) {
7640 in_frame_format = IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8;
7641 } else if (pipe->stream->config.input_config.format == IA_CSS_STREAM_FORMAT_YUV422_8) {
7642 /*
7643 * When the sensor output frame format is "IA_CSS_STREAM_FORMAT_YUV422_8",
7644 * the "isp_copy_var" binary is selected as the first stage in the yuvpp
7645 * pipe.
7646 *
7647 * For the "isp_copy_var" binary, it reads the YUV422-8 pixels from
7648 * the frame buffer (at DDR) to the frame-line buffer (at VMEM).
7649 *
7650 * By now, the "isp_copy_var" binary does NOT provide a separated
7651 * frame-line buffer to store the YUV422-8 pixels. Instead, it stores
7652 * the YUV422-8 pixels in the frame-line buffer which is designed to
7653 * store the Bayer-Quad RAW pixels.
7654 *
7655 * To direct the "isp_copy_var" binary reading from the RAW frame-line
7656 * buffer, its input frame format must be specified as "IA_CSS_FRAME_
7657 * FORMAT_RAW".
7658 */
7659 in_frame_format = IA_CSS_FRAME_FORMAT_RAW;
7660 } else {
7661 in_frame_format = IA_CSS_FRAME_FORMAT_NV12;
7662 }
7663
7664 err = init_in_frameinfo_memory_defaults(pipe,
7665 &me->in_frame,
7666 in_frame_format);
7667
7668 if (err != IA_CSS_SUCCESS) {
7669 IA_CSS_LEAVE_ERR_PRIVATE(err);
7670 return err;
7671 }
7672
7673 in_frame = &me->in_frame;
7674 } else {
7675 in_frame = NULL;
7676 }
7677
7678 for (i = 0; i < num_output_stage; i++) {
7679 assert(i < IA_CSS_PIPE_MAX_OUTPUT_STAGE);
7680 if (pipe->output_info[i].res.width != 0) {
7681 err = init_out_frameinfo_defaults(pipe, &me->out_frame[i], i);
7682 if (err != IA_CSS_SUCCESS) {
7683 IA_CSS_LEAVE_ERR_PRIVATE(err);
7684 return err;
7685 }
7686 out_frame[i] = &me->out_frame[i];
7687 }
7688
7689 /* Construct vf_frame info (only in case we have VF) */
7690 if (pipe->vf_output_info[i].res.width != 0) {
7691 err = init_vf_frameinfo_defaults(pipe, &me->vf_frame[i], i);
7692 if (err != IA_CSS_SUCCESS) {
7693 IA_CSS_LEAVE_ERR_PRIVATE(err);
7694 return err;
7695 }
7696 vf_frame[i] = &me->vf_frame[i];
7697 }
7698 }
7699
7700 copy_binary = &pipe->pipe_settings.yuvpp.copy_binary;
7701 vf_pp_binary = pipe->pipe_settings.yuvpp.vf_pp_binary;
7702 yuv_scaler_binary = pipe->pipe_settings.yuvpp.yuv_scaler_binary;
7703 need_scaler = need_yuv_scaler_stage(pipe);
7704
7705 if (pipe->pipe_settings.yuvpp.copy_binary.info) {
7706
7707 struct ia_css_frame *in_frame_local = NULL;
7708
7709#ifdef USE_INPUT_SYSTEM_VERSION_2401
7710 /* After isp copy is enabled in_frame needs to be passed. */
7711 if (!online)
7712 in_frame_local = in_frame;
7713#endif
7714
7715 if (need_scaler) {
7716 ia_css_pipe_util_set_output_frames(bin_out_frame, 0, NULL);
7717 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
7718 bin_out_frame, in_frame_local, NULL);
7719 } else {
7720 ia_css_pipe_util_set_output_frames(bin_out_frame, 0, out_frame[0]);
7721 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
7722 bin_out_frame, in_frame_local, NULL);
7723 }
7724
7725 err = ia_css_pipeline_create_and_add_stage(me,
7726 &stage_desc,
7727 &copy_stage);
7728
7729 if (err != IA_CSS_SUCCESS) {
7730 IA_CSS_LEAVE_ERR_PRIVATE(err);
7731 return err;
7732 }
7733
7734 if (copy_stage) {
7735 /* if we use yuv scaler binary, vf output should be from there */
7736 copy_stage->args.copy_vf = !need_scaler;
7737 /* for yuvpp pipe, it should always be enabled */
7738 copy_stage->args.copy_output = true;
7739 /* connect output of copy binary to input of yuv scaler */
7740 in_frame = copy_stage->args.out_frame[0];
7741 }
7742 }
7743
7744 if (need_scaler) {
7745 struct ia_css_frame *tmp_out_frame = NULL;
7746 struct ia_css_frame *tmp_vf_frame = NULL;
7747 struct ia_css_frame *tmp_in_frame = in_frame;
7748
7749 for (i = 0, j = 0; i < num_stage; i++) {
7750 assert(j < num_output_stage);
7751 if (pipe->pipe_settings.yuvpp.is_output_stage[i] == true) {
7752 tmp_out_frame = out_frame[j];
7753 tmp_vf_frame = vf_frame[j];
7754 } else {
7755 tmp_out_frame = NULL;
7756 tmp_vf_frame = NULL;
7757 }
7758
7759 err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame,
7760 NULL,
7761 &yuv_scaler_binary[i],
7762 &yuv_scaler_stage);
7763
7764 if (err != IA_CSS_SUCCESS) {
7765 IA_CSS_LEAVE_ERR_PRIVATE(err);
7766 return err;
7767 }
7768 /* we use output port 1 as internal output port */
7769 tmp_in_frame = yuv_scaler_stage->args.out_frame[1];
7770 if (pipe->pipe_settings.yuvpp.is_output_stage[i] == true) {
7771 if (tmp_vf_frame && (tmp_vf_frame->info.res.width != 0)) {
7772 in_frame = yuv_scaler_stage->args.out_vf_frame;
7773 err = add_vf_pp_stage(pipe, in_frame, tmp_vf_frame, &vf_pp_binary[j],
7774 &vf_pp_stage);
7775
7776 if (err != IA_CSS_SUCCESS) {
7777 IA_CSS_LEAVE_ERR_PRIVATE(err);
7778 return err;
7779 }
7780 }
7781 j++;
7782 }
7783 }
7784 } else if (copy_stage != NULL) {
7785 if (vf_frame[0] != NULL && vf_frame[0]->info.res.width != 0) {
7786 in_frame = copy_stage->args.out_vf_frame;
7787 err = add_vf_pp_stage(pipe, in_frame, vf_frame[0], &vf_pp_binary[0],
7788 &vf_pp_stage);
7789 }
7790 if (err != IA_CSS_SUCCESS) {
7791 IA_CSS_LEAVE_ERR_PRIVATE(err);
7792 return err;
7793 }
7794 }
7795
7796 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
7797
7798 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
7799
7800 return IA_CSS_SUCCESS;
7801}
7802
7803static enum ia_css_err
7804create_host_copy_pipeline(struct ia_css_pipe *pipe,
7805 unsigned max_input_width,
7806 struct ia_css_frame *out_frame)
7807{
7808 struct ia_css_pipeline *me;
7809 enum ia_css_err err = IA_CSS_SUCCESS;
7810 struct ia_css_pipeline_stage_desc stage_desc;
7811
7812 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7813 "create_host_copy_pipeline() enter:\n");
7814
7815 /* pipeline already created as part of create_host_pipeline_structure */
7816 me = &pipe->pipeline;
7817 ia_css_pipeline_clean(me);
7818
7819 /* Construct out_frame info */
7820 out_frame->contiguous = false;
7821 out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
7822
7823 if (copy_on_sp(pipe) &&
7824 pipe->stream->config.input_config.format == IA_CSS_STREAM_FORMAT_BINARY_8) {
7825 ia_css_frame_info_init(
7826 &out_frame->info,
7827 JPEG_BYTES,
7828 1,
7829 IA_CSS_FRAME_FORMAT_BINARY_8,
7830 0);
7831 } else if (out_frame->info.format == IA_CSS_FRAME_FORMAT_RAW) {
7832 out_frame->info.raw_bit_depth =
7833 ia_css_pipe_util_pipe_input_format_bpp(pipe);
7834 }
7835
7836 me->num_stages = 1;
7837 me->pipe_id = IA_CSS_PIPE_ID_COPY;
7838 pipe->mode = IA_CSS_PIPE_ID_COPY;
7839
7840 ia_css_pipe_get_sp_func_stage_desc(&stage_desc, out_frame,
7841 IA_CSS_PIPELINE_RAW_COPY, max_input_width);
7842 err = ia_css_pipeline_create_and_add_stage(me,
7843 &stage_desc,
7844 NULL);
7845
7846 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
7847
7848 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7849 "create_host_copy_pipeline() leave:\n");
7850
7851 return err;
7852}
7853
7854static enum ia_css_err
7855create_host_isyscopy_capture_pipeline(struct ia_css_pipe *pipe)
7856{
7857 struct ia_css_pipeline *me = &pipe->pipeline;
7858 enum ia_css_err err = IA_CSS_SUCCESS;
7859 struct ia_css_pipeline_stage_desc stage_desc;
7860 struct ia_css_frame *out_frame = &me->out_frame[0];
7861 struct ia_css_pipeline_stage *out_stage = NULL;
7862 unsigned int thread_id;
7863 enum sh_css_queue_id queue_id;
7864 unsigned int max_input_width = MAX_VECTORS_PER_INPUT_LINE_CONT * ISP_VEC_NELEMS;
7865
7866 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7867 "create_host_isyscopy_capture_pipeline() enter:\n");
7868 ia_css_pipeline_clean(me);
7869
7870 /* Construct out_frame info */
7871 err = sh_css_pipe_get_output_frame_info(pipe, &out_frame->info, 0);
7872 if (err != IA_CSS_SUCCESS)
7873 return err;
7874 out_frame->contiguous = false;
7875 out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
7876 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
7877 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, thread_id, &queue_id);
7878 out_frame->dynamic_queue_id = queue_id;
7879 out_frame->buf_type = IA_CSS_BUFFER_TYPE_OUTPUT_FRAME;
7880
7881 me->num_stages = 1;
7882 me->pipe_id = IA_CSS_PIPE_ID_CAPTURE;
7883 pipe->mode = IA_CSS_PIPE_ID_CAPTURE;
7884 ia_css_pipe_get_sp_func_stage_desc(&stage_desc, out_frame,
7885 IA_CSS_PIPELINE_ISYS_COPY, max_input_width);
7886 err = ia_css_pipeline_create_and_add_stage(me,
7887 &stage_desc, &out_stage);
7888 if(err != IA_CSS_SUCCESS)
7889 return err;
7890
7891 ia_css_pipeline_finalize_stages(me, pipe->stream->config.continuous);
7892
7893 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7894 "create_host_isyscopy_capture_pipeline() leave:\n");
7895
7896 return err;
7897}
7898
7899static enum ia_css_err
7900create_host_regular_capture_pipeline(struct ia_css_pipe *pipe)
7901{
7902 struct ia_css_pipeline *me;
7903 enum ia_css_err err = IA_CSS_SUCCESS;
7904 enum ia_css_capture_mode mode;
7905 struct ia_css_pipeline_stage *current_stage = NULL;
7906 struct ia_css_pipeline_stage *yuv_scaler_stage = NULL;
7907 struct ia_css_binary *copy_binary,
7908 *primary_binary[MAX_NUM_PRIMARY_STAGES],
7909 *vf_pp_binary,
7910 *pre_isp_binary,
7911 *anr_gdc_binary,
7912 *post_isp_binary,
7913 *yuv_scaler_binary,
7914 *capture_pp_binary,
7915 *capture_ldc_binary;
7916 bool need_pp = false;
7917 bool raw;
7918
7919 struct ia_css_frame *in_frame;
7920 struct ia_css_frame *out_frame;
7921 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
7922 struct ia_css_frame *vf_frame;
7923 struct ia_css_pipeline_stage_desc stage_desc;
7924 bool need_in_frameinfo_memory = false;
7925#ifdef USE_INPUT_SYSTEM_VERSION_2401
7926 bool sensor = false;
7927 bool buffered_sensor = false;
7928 bool online = false;
7929 bool continuous = false;
7930#endif
7931 unsigned int i, num_yuv_scaler, num_primary_stage;
7932 bool need_yuv_pp = false;
7933 bool *is_output_stage = NULL;
7934 bool need_ldc = false;
7935
7936 IA_CSS_ENTER_PRIVATE("");
7937 assert(pipe != NULL);
7938 assert(pipe->stream != NULL);
7939 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || pipe->mode == IA_CSS_PIPE_ID_COPY);
7940
7941 me = &pipe->pipeline;
7942 mode = pipe->config.default_capture_config.mode;
7943 raw = (mode == IA_CSS_CAPTURE_MODE_RAW);
7944 ia_css_pipeline_clean(me);
7945 ia_css_pipe_util_create_output_frames(out_frames);
7946
7947#ifdef USE_INPUT_SYSTEM_VERSION_2401
7948 /* When the input system is 2401, always enable 'in_frameinfo_memory'
7949 * except for the following:
7950 * - Direct Sensor Mode Online Capture
7951 * - Direct Sensor Mode Online Capture
7952 * - Direct Sensor Mode Continuous Capture
7953 * - Buffered Sensor Mode Continous Capture
7954 */
7955 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR);
7956 buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR);
7957 online = pipe->stream->config.online;
7958 continuous = pipe->stream->config.continuous;
7959 need_in_frameinfo_memory =
7960 !((sensor && (online || continuous)) || (buffered_sensor && (online || continuous)));
7961#else
7962 /* Construct in_frame info (only in case we have dynamic input */
7963 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
7964#endif
7965 if (need_in_frameinfo_memory) {
7966 err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame, IA_CSS_FRAME_FORMAT_RAW);
7967 if (err != IA_CSS_SUCCESS) {
7968 IA_CSS_LEAVE_ERR_PRIVATE(err);
7969 return err;
7970 }
7971
7972 in_frame = &me->in_frame;
7973 } else {
7974 in_frame = NULL;
7975 }
7976
7977 err = init_out_frameinfo_defaults(pipe, &me->out_frame[0], 0);
7978 if (err != IA_CSS_SUCCESS) {
7979 IA_CSS_LEAVE_ERR_PRIVATE(err);
7980 return err;
7981 }
7982 out_frame = &me->out_frame[0];
7983
7984 /* Construct vf_frame info (only in case we have VF) */
7985 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
7986 if (mode == IA_CSS_CAPTURE_MODE_RAW || mode == IA_CSS_CAPTURE_MODE_BAYER) {
7987 /* These modes don't support viewfinder output */
7988 vf_frame = NULL;
7989 } else {
7990 init_vf_frameinfo_defaults(pipe, &me->vf_frame[0], 0);
7991 vf_frame = &me->vf_frame[0];
7992 }
7993 } else {
7994 vf_frame = NULL;
7995 }
7996
7997 copy_binary = &pipe->pipe_settings.capture.copy_binary;
7998 num_primary_stage = pipe->pipe_settings.capture.num_primary_stage;
7999 if ((num_primary_stage == 0) && (mode == IA_CSS_CAPTURE_MODE_PRIMARY)) {
8000 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR);
8001 return IA_CSS_ERR_INTERNAL_ERROR;
8002 }
8003 for (i = 0; i < num_primary_stage; i++) {
8004 primary_binary[i] = &pipe->pipe_settings.capture.primary_binary[i];
8005 }
8006 vf_pp_binary = &pipe->pipe_settings.capture.vf_pp_binary;
8007 pre_isp_binary = &pipe->pipe_settings.capture.pre_isp_binary;
8008 anr_gdc_binary = &pipe->pipe_settings.capture.anr_gdc_binary;
8009 post_isp_binary = &pipe->pipe_settings.capture.post_isp_binary;
8010 capture_pp_binary = &pipe->pipe_settings.capture.capture_pp_binary;
8011 yuv_scaler_binary = pipe->pipe_settings.capture.yuv_scaler_binary;
8012 num_yuv_scaler = pipe->pipe_settings.capture.num_yuv_scaler;
8013 is_output_stage = pipe->pipe_settings.capture.is_output_stage;
8014 capture_ldc_binary = &pipe->pipe_settings.capture.capture_ldc_binary;
8015
8016 need_pp = (need_capture_pp(pipe) || pipe->output_stage) &&
8017 mode != IA_CSS_CAPTURE_MODE_RAW &&
8018 mode != IA_CSS_CAPTURE_MODE_BAYER;
8019 need_yuv_pp = (yuv_scaler_binary != NULL && yuv_scaler_binary->info != NULL);
8020 need_ldc = (capture_ldc_binary != NULL && capture_ldc_binary->info != NULL);
8021
8022 if (pipe->pipe_settings.capture.copy_binary.info) {
8023 if (raw) {
8024 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
8025#if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2401)
8026 if (!continuous) {
8027 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
8028 out_frames, in_frame, NULL);
8029 } else {
8030 in_frame = pipe->stream->last_pipe->continuous_frames[0];
8031 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
8032 out_frames, in_frame, NULL);
8033 }
8034#else
8035 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
8036 out_frames, NULL, NULL);
8037#endif
8038 } else {
8039 ia_css_pipe_util_set_output_frames(out_frames, 0, in_frame);
8040 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
8041 out_frames, NULL, NULL);
8042 }
8043
8044 err = ia_css_pipeline_create_and_add_stage(me,
8045 &stage_desc,
8046 &current_stage);
8047 if (err != IA_CSS_SUCCESS) {
8048 IA_CSS_LEAVE_ERR_PRIVATE(err);
8049 return err;
8050 }
8051 } else if (pipe->stream->config.continuous) {
8052 in_frame = pipe->stream->last_pipe->continuous_frames[0];
8053 }
8054
8055 if (mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
8056 unsigned int frm;
8057 struct ia_css_frame *local_in_frame = NULL;
8058 struct ia_css_frame *local_out_frame = NULL;
8059
8060 for (i = 0; i < num_primary_stage; i++) {
8061 if (i == 0)
8062 local_in_frame = in_frame;
8063 else
8064 local_in_frame = NULL;
8065#ifndef ISP2401
8066 if (!need_pp && (i == num_primary_stage - 1))
8067#else
8068 if (!need_pp && (i == num_primary_stage - 1) && !need_ldc)
8069#endif
8070 local_out_frame = out_frame;
8071 else
8072 local_out_frame = NULL;
8073 ia_css_pipe_util_set_output_frames(out_frames, 0, local_out_frame);
8074/*
8075 * WARNING: The #if def flag has been added below as a
8076 * temporary solution to solve the problem of enabling the
8077 * view finder in a single binary in a capture flow. The
8078 * vf-pp stage has been removed from Skycam in the solution
8079 * provided. The vf-pp stage should be re-introduced when
8080 * required. This * should not be considered as a clean solution.
8081 * Proper investigation should be done to come up with the clean
8082 * solution.
8083 * */
8084 ia_css_pipe_get_generic_stage_desc(&stage_desc, primary_binary[i],
8085 out_frames, local_in_frame, NULL);
8086 err = ia_css_pipeline_create_and_add_stage(me,
8087 &stage_desc,
8088 &current_stage);
8089 if (err != IA_CSS_SUCCESS) {
8090 IA_CSS_LEAVE_ERR_PRIVATE(err);
8091 return err;
8092 }
8093 }
8094 (void)frm;
8095 /* If we use copy iso primary,
8096 the input must be yuv iso raw */
8097 current_stage->args.copy_vf =
8098 primary_binary[0]->info->sp.pipeline.mode ==
8099 IA_CSS_BINARY_MODE_COPY;
8100 current_stage->args.copy_output = current_stage->args.copy_vf;
8101 } else if (mode == IA_CSS_CAPTURE_MODE_ADVANCED ||
8102 mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) {
8103 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
8104 ia_css_pipe_get_generic_stage_desc(&stage_desc, pre_isp_binary,
8105 out_frames, in_frame, NULL);
8106 err = ia_css_pipeline_create_and_add_stage(me,
8107 &stage_desc, NULL);
8108 if (err != IA_CSS_SUCCESS) {
8109 IA_CSS_LEAVE_ERR_PRIVATE(err);
8110 return err;
8111 }
8112 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
8113 ia_css_pipe_get_generic_stage_desc(&stage_desc, anr_gdc_binary,
8114 out_frames, NULL, NULL);
8115 err = ia_css_pipeline_create_and_add_stage(me,
8116 &stage_desc, NULL);
8117 if (err != IA_CSS_SUCCESS) {
8118 IA_CSS_LEAVE_ERR_PRIVATE(err);
8119 return err;
8120 }
8121
8122 if(need_pp) {
8123 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
8124 ia_css_pipe_get_generic_stage_desc(&stage_desc, post_isp_binary,
8125 out_frames, NULL, NULL);
8126 } else {
8127 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
8128 ia_css_pipe_get_generic_stage_desc(&stage_desc, post_isp_binary,
8129 out_frames, NULL, NULL);
8130 }
8131
8132 err = ia_css_pipeline_create_and_add_stage(me,
8133 &stage_desc, &current_stage);
8134 if (err != IA_CSS_SUCCESS) {
8135 IA_CSS_LEAVE_ERR_PRIVATE(err);
8136 return err;
8137 }
8138 } else if (mode == IA_CSS_CAPTURE_MODE_BAYER) {
8139 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
8140 ia_css_pipe_get_generic_stage_desc(&stage_desc, pre_isp_binary,
8141 out_frames, in_frame, NULL);
8142 err = ia_css_pipeline_create_and_add_stage(me,
8143 &stage_desc,
8144 NULL);
8145 if (err != IA_CSS_SUCCESS) {
8146 IA_CSS_LEAVE_ERR_PRIVATE(err);
8147 return err;
8148 }
8149 }
8150
8151#ifndef ISP2401
8152 if (need_pp && current_stage) {
8153 struct ia_css_frame *local_in_frame = NULL;
8154 local_in_frame = current_stage->args.out_frame[0];
8155
8156 if(need_ldc) {
8157 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
8158 ia_css_pipe_get_generic_stage_desc(&stage_desc, capture_ldc_binary,
8159 out_frames, local_in_frame, NULL);
8160 err = ia_css_pipeline_create_and_add_stage(me,
8161 &stage_desc,
8162 &current_stage);
8163 local_in_frame = current_stage->args.out_frame[0];
8164 }
8165 err = add_capture_pp_stage(pipe, me, local_in_frame, need_yuv_pp ? NULL : out_frame,
8166#else
8167 /* ldc and capture_pp not supported in same pipeline */
8168 if (need_ldc && current_stage) {
8169 in_frame = current_stage->args.out_frame[0];
8170 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
8171 ia_css_pipe_get_generic_stage_desc(&stage_desc, capture_ldc_binary,
8172 out_frames, in_frame, NULL);
8173 err = ia_css_pipeline_create_and_add_stage(me,
8174 &stage_desc,
8175 NULL);
8176 } else if (need_pp && current_stage) {
8177 in_frame = current_stage->args.out_frame[0];
8178 err = add_capture_pp_stage(pipe, me, in_frame, need_yuv_pp ? NULL : out_frame,
8179#endif
8180 capture_pp_binary,
8181 &current_stage);
8182 if (err != IA_CSS_SUCCESS) {
8183 IA_CSS_LEAVE_ERR_PRIVATE(err);
8184 return err;
8185 }
8186 }
8187
8188 if (need_yuv_pp && current_stage) {
8189 struct ia_css_frame *tmp_in_frame = current_stage->args.out_frame[0];
8190 struct ia_css_frame *tmp_out_frame = NULL;
8191
8192 for (i = 0; i < num_yuv_scaler; i++) {
8193 if (is_output_stage[i] == true)
8194 tmp_out_frame = out_frame;
8195 else
8196 tmp_out_frame = NULL;
8197
8198 err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame,
8199 NULL,
8200 &yuv_scaler_binary[i],
8201 &yuv_scaler_stage);
8202 if (err != IA_CSS_SUCCESS) {
8203 IA_CSS_LEAVE_ERR_PRIVATE(err);
8204 return err;
8205 }
8206 /* we use output port 1 as internal output port */
8207 tmp_in_frame = yuv_scaler_stage->args.out_frame[1];
8208 }
8209 }
8210
8211/*
8212 * WARNING: The #if def flag has been added below as a
8213 * temporary solution to solve the problem of enabling the
8214 * view finder in a single binary in a capture flow. The vf-pp
8215 * stage has been removed from Skycam in the solution provided.
8216 * The vf-pp stage should be re-introduced when required. This
8217 * should not be considered as a clean solution. Proper
8218 * investigation should be done to come up with the clean solution.
8219 * */
8220 if (mode != IA_CSS_CAPTURE_MODE_RAW && mode != IA_CSS_CAPTURE_MODE_BAYER && current_stage && vf_frame) {
8221 in_frame = current_stage->args.out_vf_frame;
8222 err = add_vf_pp_stage(pipe, in_frame, vf_frame, vf_pp_binary,
8223 &current_stage);
8224 if (err != IA_CSS_SUCCESS) {
8225 IA_CSS_LEAVE_ERR_PRIVATE(err);
8226 return err;
8227 }
8228 }
8229 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
8230
8231 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8232 "create_host_regular_capture_pipeline() leave:\n");
8233
8234 return IA_CSS_SUCCESS;
8235}
8236
8237static enum ia_css_err
8238create_host_capture_pipeline(struct ia_css_pipe *pipe)
8239{
8240 enum ia_css_err err = IA_CSS_SUCCESS;
8241
8242 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
8243
8244 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY)
8245 err = create_host_isyscopy_capture_pipeline(pipe);
8246 else
8247 err = create_host_regular_capture_pipeline(pipe);
8248 if (err != IA_CSS_SUCCESS) {
8249 IA_CSS_LEAVE_ERR_PRIVATE(err);
8250 return err;
8251 }
8252
8253 IA_CSS_LEAVE_ERR_PRIVATE(err);
8254
8255 return err;
8256}
8257
8258static enum ia_css_err capture_start(
8259 struct ia_css_pipe *pipe)
8260{
8261 struct ia_css_pipeline *me;
8262
8263 enum ia_css_err err = IA_CSS_SUCCESS;
8264 enum sh_css_pipe_config_override copy_ovrd;
8265
8266 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
8267 if (pipe == NULL) {
8268 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
8269 return IA_CSS_ERR_INVALID_ARGUMENTS;
8270 }
8271
8272 me = &pipe->pipeline;
8273
8274 if ((pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW ||
8275 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER ) &&
8276 (pipe->config.mode != IA_CSS_PIPE_MODE_COPY)) {
8277 if (copy_on_sp(pipe)) {
8278 err = start_copy_on_sp(pipe, &me->out_frame[0]);
8279 IA_CSS_LEAVE_ERR_PRIVATE(err);
8280 return err;
8281 }
8282 }
8283
8284#if defined(USE_INPUT_SYSTEM_VERSION_2)
8285 /* old isys: need to send_mipi_frames() in all pipe modes */
8286 err = send_mipi_frames(pipe);
8287 if (err != IA_CSS_SUCCESS) {
8288 IA_CSS_LEAVE_ERR_PRIVATE(err);
8289 return err;
8290 }
8291#elif defined(USE_INPUT_SYSTEM_VERSION_2401)
8292 if (pipe->config.mode != IA_CSS_PIPE_MODE_COPY) {
8293 err = send_mipi_frames(pipe);
8294 if (err != IA_CSS_SUCCESS) {
8295 IA_CSS_LEAVE_ERR_PRIVATE(err);
8296 return err;
8297 }
8298 }
8299
8300#endif
8301
8302 {
8303 unsigned int thread_id;
8304
8305 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
8306 copy_ovrd = 1 << thread_id;
8307
8308 }
8309 start_pipe(pipe, copy_ovrd, pipe->stream->config.mode);
8310
8311#if !defined(HAS_NO_INPUT_SYSTEM) && !defined(USE_INPUT_SYSTEM_VERSION_2401)
8312 /*
8313 * old isys: for IA_CSS_PIPE_MODE_COPY pipe, isys rx has to be configured,
8314 * which is currently done in start_binary(); but COPY pipe contains no binary,
8315 * and does not call start_binary(); so we need to configure the rx here.
8316 */
8317 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY && pipe->stream->reconfigure_css_rx) {
8318 ia_css_isys_rx_configure(&pipe->stream->csi_rx_config, pipe->stream->config.mode);
8319 pipe->stream->reconfigure_css_rx = false;
8320 }
8321#endif
8322
8323 IA_CSS_LEAVE_ERR_PRIVATE(err);
8324 return err;
8325
8326}
8327
8328static enum ia_css_err
8329sh_css_pipe_get_output_frame_info(struct ia_css_pipe *pipe,
8330 struct ia_css_frame_info *info,
8331 unsigned int idx)
8332{
8333 enum ia_css_err err = IA_CSS_SUCCESS;
8334
8335 assert(pipe != NULL);
8336 assert(info != NULL);
8337
8338 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8339 "sh_css_pipe_get_output_frame_info() enter:\n");
8340
8341 *info = pipe->output_info[idx];
8342 if (copy_on_sp(pipe) &&
8343 pipe->stream->config.input_config.format == IA_CSS_STREAM_FORMAT_BINARY_8) {
8344 ia_css_frame_info_init(
8345 info,
8346 JPEG_BYTES,
8347 1,
8348 IA_CSS_FRAME_FORMAT_BINARY_8,
8349 0);
8350 } else if (info->format == IA_CSS_FRAME_FORMAT_RAW ||
8351 info->format == IA_CSS_FRAME_FORMAT_RAW_PACKED) {
8352 info->raw_bit_depth =
8353 ia_css_pipe_util_pipe_input_format_bpp(pipe);
8354
8355 }
8356
8357 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8358 "sh_css_pipe_get_output_frame_info() leave:\n");
8359 return err;
8360}
8361
8362#if !defined(HAS_NO_INPUT_SYSTEM)
8363void
8364ia_css_stream_send_input_frame(const struct ia_css_stream *stream,
8365 const unsigned short *data,
8366 unsigned int width,
8367 unsigned int height)
8368{
8369 assert(stream != NULL);
8370
8371 ia_css_inputfifo_send_input_frame(
8372 data, width, height,
8373 stream->config.channel_id,
8374 stream->config.input_config.format,
8375 stream->config.pixels_per_clock == 2);
8376}
8377
8378void
8379ia_css_stream_start_input_frame(const struct ia_css_stream *stream)
8380{
8381 assert(stream != NULL);
8382
8383 ia_css_inputfifo_start_frame(
8384 stream->config.channel_id,
8385 stream->config.input_config.format,
8386 stream->config.pixels_per_clock == 2);
8387}
8388
8389void
8390ia_css_stream_send_input_line(const struct ia_css_stream *stream,
8391 const unsigned short *data,
8392 unsigned int width,
8393 const unsigned short *data2,
8394 unsigned int width2)
8395{
8396 assert(stream != NULL);
8397
8398 ia_css_inputfifo_send_line(stream->config.channel_id,
8399 data, width, data2, width2);
8400}
8401
8402void
8403ia_css_stream_send_input_embedded_line(const struct ia_css_stream *stream,
8404 enum ia_css_stream_format format,
8405 const unsigned short *data,
8406 unsigned int width)
8407{
8408 assert(stream != NULL);
8409 if (data == NULL || width == 0)
8410 return;
8411 ia_css_inputfifo_send_embedded_line(stream->config.channel_id,
8412 format, data, width);
8413}
8414
8415void
8416ia_css_stream_end_input_frame(const struct ia_css_stream *stream)
8417{
8418 assert(stream != NULL);
8419
8420 ia_css_inputfifo_end_frame(stream->config.channel_id);
8421}
8422#endif
8423
8424static void
8425append_firmware(struct ia_css_fw_info **l, struct ia_css_fw_info *firmware)
8426{
8427 IA_CSS_ENTER_PRIVATE("l = %p, firmware = %p", l , firmware);
8428 if (l == NULL) {
8429 IA_CSS_ERROR("NULL fw_info");
8430 IA_CSS_LEAVE_PRIVATE("");
8431 return;
8432 }
8433 while (*l)
8434 l = &(*l)->next;
8435 *l = firmware;
8436 /*firmware->next = NULL;*/ /* when multiple acc extensions are loaded, 'next' can be not NULL */
8437 IA_CSS_LEAVE_PRIVATE("");
8438}
8439
8440static void
8441remove_firmware(struct ia_css_fw_info **l, struct ia_css_fw_info *firmware)
8442{
8443 assert(*l);
8444 assert(firmware);
8445 (void)l;
8446 (void)firmware;
8447 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "remove_firmware() enter:\n");
8448
8449 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "remove_firmware() leave:\n");
8450 return; /* removing single and multiple firmware is handled in acc_unload_extension() */
8451}
8452
f16595ae 8453static enum ia_css_err upload_isp_code(struct ia_css_fw_info *firmware)
a49d2536
AC
8454{
8455 hrt_vaddress binary;
8456
8457 if (firmware == NULL) {
8458 IA_CSS_ERROR("NULL input parameter");
8459 return IA_CSS_ERR_INVALID_ARGUMENTS;
8460 }
8461 binary = firmware->info.isp.xmem_addr;
8462
8463 if (!binary) {
8464 unsigned size = firmware->blob.size;
8465 const unsigned char *blob;
8466 const unsigned char *binary_name;
8467 binary_name =
8468 (const unsigned char *)(IA_CSS_EXT_ISP_PROG_NAME(
8469 firmware));
8470 blob = binary_name +
8471 strlen((const char *)binary_name) +
8472 1;
8473 binary = sh_css_load_blob(blob, size);
8474 firmware->info.isp.xmem_addr = binary;
8475 }
8476
8477 if (!binary)
8478 return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
8479 return IA_CSS_SUCCESS;
8480}
a49d2536
AC
8481
8482static enum ia_css_err
8483acc_load_extension(struct ia_css_fw_info *firmware)
8484{
a49d2536
AC
8485 enum ia_css_err err;
8486 struct ia_css_fw_info *hd = firmware;
8487 while (hd){
8488 err = upload_isp_code(hd);
8489 if (err != IA_CSS_SUCCESS)
8490 return err;
8491 hd = hd->next;
8492 }
a49d2536
AC
8493
8494 if (firmware == NULL)
8495 return IA_CSS_ERR_INVALID_ARGUMENTS;
8496 firmware->loaded = true;
8497 return IA_CSS_SUCCESS;
8498}
8499
8500static void
8501acc_unload_extension(struct ia_css_fw_info *firmware)
8502{
8503 struct ia_css_fw_info *hd = firmware;
8504 struct ia_css_fw_info *hdn = NULL;
8505
8506 if (firmware == NULL) /* should not happen */
8507 return;
8508 /* unload and remove multiple firmwares */
8509 while (hd){
8510 hdn = (hd->next) ? &(*hd->next) : NULL;
8511 if (hd->info.isp.xmem_addr) {
f5a6ddaa 8512 hmm_free(hd->info.isp.xmem_addr);
a49d2536
AC
8513 hd->info.isp.xmem_addr = mmgr_NULL;
8514 }
8515 hd->isp_code = NULL;
8516 hd->next = NULL;
8517 hd = hdn;
8518 }
8519
8520 firmware->loaded = false;
8521}
8522/* Load firmware for extension */
8523static enum ia_css_err
8524ia_css_pipe_load_extension(struct ia_css_pipe *pipe,
8525 struct ia_css_fw_info *firmware)
8526{
8527 enum ia_css_err err = IA_CSS_SUCCESS;
8528
8529 IA_CSS_ENTER_PRIVATE("fw = %p pipe = %p", firmware, pipe);
8530
8531 if ((firmware == NULL) || (pipe == NULL)) {
8532 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
8533 return IA_CSS_ERR_INVALID_ARGUMENTS;
8534 }
8535
8536 if (firmware->info.isp.type == IA_CSS_ACC_OUTPUT) {
8537 if (&pipe->output_stage != NULL)
8538 append_firmware(&pipe->output_stage, firmware);
8539 else {
8540 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR);
8541 return IA_CSS_ERR_INTERNAL_ERROR;
8542 }
8543 }
8544 else if (firmware->info.isp.type == IA_CSS_ACC_VIEWFINDER) {
8545 if (&pipe->vf_stage != NULL)
8546 append_firmware(&pipe->vf_stage, firmware);
8547 else {
8548 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR);
8549 return IA_CSS_ERR_INTERNAL_ERROR;
8550 }
8551 }
8552 err = acc_load_extension(firmware);
8553
8554 IA_CSS_LEAVE_ERR_PRIVATE(err);
8555 return err;
8556}
8557
8558/* Unload firmware for extension */
8559static void
8560ia_css_pipe_unload_extension(struct ia_css_pipe *pipe,
8561 struct ia_css_fw_info *firmware)
8562{
8563 IA_CSS_ENTER_PRIVATE("fw = %p pipe = %p", firmware, pipe);
8564
8565 if ((firmware == NULL) || (pipe == NULL)) {
8566 IA_CSS_ERROR("NULL input parameters");
8567 IA_CSS_LEAVE_PRIVATE("");
8568 return;
8569 }
8570
8571 if (firmware->info.isp.type == IA_CSS_ACC_OUTPUT)
8572 remove_firmware(&pipe->output_stage, firmware);
8573 else if (firmware->info.isp.type == IA_CSS_ACC_VIEWFINDER)
8574 remove_firmware(&pipe->vf_stage, firmware);
8575 acc_unload_extension(firmware);
8576
8577 IA_CSS_LEAVE_PRIVATE("");
8578}
8579
8580bool
8581ia_css_pipeline_uses_params(struct ia_css_pipeline *me)
8582{
8583 struct ia_css_pipeline_stage *stage;
8584
8585 assert(me != NULL);
8586
8587 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8588 "ia_css_pipeline_uses_params() enter: me=%p\n", me);
8589
8590 for (stage = me->stages; stage; stage = stage->next)
8591 if (stage->binary_info && stage->binary_info->enable.params) {
8592 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8593 "ia_css_pipeline_uses_params() leave: "
8594 "return_bool=true\n");
8595 return true;
8596 }
8597 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8598 "ia_css_pipeline_uses_params() leave: return_bool=false\n");
8599 return false;
8600}
8601
8602static enum ia_css_err
8603sh_css_pipeline_add_acc_stage(struct ia_css_pipeline *pipeline,
8604 const void *acc_fw)
8605{
8606 struct ia_css_fw_info *fw = (struct ia_css_fw_info *)acc_fw;
8607 /* In QoS case, load_extension already called, so skipping */
8608 enum ia_css_err err = IA_CSS_SUCCESS;
8609 if (fw->loaded == false)
8610 err = acc_load_extension(fw);
8611
8612 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8613 "sh_css_pipeline_add_acc_stage() enter: pipeline=%p,"
8614 " acc_fw=%p\n", pipeline, acc_fw);
8615
8616 if (err == IA_CSS_SUCCESS) {
8617 struct ia_css_pipeline_stage_desc stage_desc;
8618 ia_css_pipe_get_acc_stage_desc(&stage_desc, NULL, fw);
8619 err = ia_css_pipeline_create_and_add_stage(pipeline,
8620 &stage_desc,
8621 NULL);
8622 }
8623
8624 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8625 "sh_css_pipeline_add_acc_stage() leave: return_err=%d\n",err);
8626 return err;
8627}
8628
d929fb4e 8629/*
a49d2536
AC
8630 * @brief Tag a specific frame in continuous capture.
8631 * Refer to "sh_css_internal.h" for details.
8632 */
8633enum ia_css_err ia_css_stream_capture_frame(struct ia_css_stream *stream,
8634 unsigned int exp_id)
8635{
8636 struct sh_css_tag_descr tag_descr;
8637 uint32_t encoded_tag_descr;
8638 enum ia_css_err err;
8639
8640 assert(stream != NULL);
8641 IA_CSS_ENTER("exp_id=%d", exp_id);
8642
8643 /* Only continuous streams have a tagger */
8644 if (exp_id == 0 || !stream->config.continuous) {
8645 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
8646 return IA_CSS_ERR_INVALID_ARGUMENTS;
8647 }
8648
8649 if (!sh_css_sp_is_running()) {
8650 /* SP is not running. The queues are not valid */
8651 IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE);
8652 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
8653 }
8654
8655 /* Create the tag descriptor from the parameters */
8656 sh_css_create_tag_descr(0, 0, 0, exp_id, &tag_descr);
8657 /* Encode the tag descriptor into a 32-bit value */
8658 encoded_tag_descr = sh_css_encode_tag_descr(&tag_descr);
8659 /* Enqueue the encoded tag to the host2sp queue.
8660 * Note: The pipe and stage IDs for tag_cmd queue are hard-coded to 0
8661 * on both host and the SP side.
8662 * It is mainly because it is enough to have only one tag_cmd queue */
8663 err= ia_css_bufq_enqueue_tag_cmd(encoded_tag_descr);
8664
8665 IA_CSS_LEAVE_ERR(err);
8666 return err;
8667}
8668
d929fb4e 8669/*
a49d2536
AC
8670 * @brief Configure the continuous capture.
8671 * Refer to "sh_css_internal.h" for details.
8672 */
8673enum ia_css_err ia_css_stream_capture(
8674 struct ia_css_stream *stream,
8675 int num_captures,
8676 unsigned int skip,
8677 int offset)
8678{
8679 struct sh_css_tag_descr tag_descr;
8680 unsigned int encoded_tag_descr;
8681 enum ia_css_err return_err;
8682
8683 if (stream == NULL)
8684 return IA_CSS_ERR_INVALID_ARGUMENTS;
8685
8686 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8687 "ia_css_stream_capture() enter: num_captures=%d,"
8688 " skip=%d, offset=%d\n", num_captures, skip,offset);
8689
8690 /* Check if the tag descriptor is valid */
8691 if (num_captures < SH_CSS_MINIMUM_TAG_ID) {
b5eb7ac1
MCC
8692 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8693 "ia_css_stream_capture() leave: return_err=%d\n",
8694 IA_CSS_ERR_INVALID_ARGUMENTS);
a49d2536
AC
8695 return IA_CSS_ERR_INVALID_ARGUMENTS;
8696 }
8697
8698 /* Create the tag descriptor from the parameters */
8699 sh_css_create_tag_descr(num_captures, skip, offset, 0, &tag_descr);
8700
8701
8702 /* Encode the tag descriptor into a 32-bit value */
8703 encoded_tag_descr = sh_css_encode_tag_descr(&tag_descr);
8704
8705 if (!sh_css_sp_is_running()) {
8706 /* SP is not running. The queues are not valid */
8707 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8708 "ia_css_stream_capture() leaving:"
8709 "queues unavailable\n");
8710 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
8711 }
8712
8713 /* Enqueue the encoded tag to the host2sp queue.
8714 * Note: The pipe and stage IDs for tag_cmd queue are hard-coded to 0
8715 * on both host and the SP side.
8716 * It is mainly because it is enough to have only one tag_cmd queue */
8717 return_err = ia_css_bufq_enqueue_tag_cmd((uint32_t)encoded_tag_descr);
8718
8719 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8720 "ia_css_stream_capture() leave: return_err=%d\n",
8721 return_err);
8722
8723 return return_err;
8724}
8725
8726void ia_css_stream_request_flash(struct ia_css_stream *stream)
8727{
8728 (void)stream;
8729
8730 assert(stream != NULL);
8731 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_request_flash() enter: void\n");
8732
8733#ifndef ISP2401
8734 sh_css_write_host2sp_command(host2sp_cmd_start_flash);
8735#else
8736 if (sh_css_sp_is_running()) {
8737 if (!sh_css_write_host2sp_command(host2sp_cmd_start_flash)) {
8738 IA_CSS_ERROR("Call to 'sh-css_write_host2sp_command()' failed");
8739 ia_css_debug_dump_sp_sw_debug_info();
8740 ia_css_debug_dump_debug_info(NULL);
8741 }
8742 } else
8743 IA_CSS_LOG("SP is not running!");
8744
8745#endif
8746 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8747 "ia_css_stream_request_flash() leave: return_void\n");
8748}
8749
8750static void
8751sh_css_init_host_sp_control_vars(void)
8752{
8753 const struct ia_css_fw_info *fw;
8754 unsigned int HIVE_ADDR_ia_css_ispctrl_sp_isp_started;
8755
8756 unsigned int HIVE_ADDR_host_sp_queues_initialized;
8757 unsigned int HIVE_ADDR_sp_sleep_mode;
8758 unsigned int HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb;
8759#ifndef ISP2401
8760 unsigned int HIVE_ADDR_sp_stop_copy_preview;
8761#endif
8762 unsigned int HIVE_ADDR_host_sp_com;
8763 unsigned int o = offsetof(struct host_sp_communication, host2sp_command)
8764 / sizeof(int);
8765
8766#if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
8767 unsigned int i;
8768#endif
8769
8770 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8771 "sh_css_init_host_sp_control_vars() enter: void\n");
8772
8773 fw = &sh_css_sp_fw;
8774 HIVE_ADDR_ia_css_ispctrl_sp_isp_started = fw->info.sp.isp_started;
8775
8776 HIVE_ADDR_host_sp_queues_initialized =
8777 fw->info.sp.host_sp_queues_initialized;
8778 HIVE_ADDR_sp_sleep_mode = fw->info.sp.sleep_mode;
8779 HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb = fw->info.sp.invalidate_tlb;
8780#ifndef ISP2401
8781 HIVE_ADDR_sp_stop_copy_preview = fw->info.sp.stop_copy_preview;
8782#endif
8783 HIVE_ADDR_host_sp_com = fw->info.sp.host_sp_com;
8784
8785 (void)HIVE_ADDR_ia_css_ispctrl_sp_isp_started; /* Suppres warnings in CRUN */
8786
8787 (void)HIVE_ADDR_sp_sleep_mode;
8788 (void)HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb;
8789#ifndef ISP2401
8790 (void)HIVE_ADDR_sp_stop_copy_preview;
8791#endif
8792 (void)HIVE_ADDR_host_sp_com;
8793
8794 sp_dmem_store_uint32(SP0_ID,
8795 (unsigned int)sp_address_of(ia_css_ispctrl_sp_isp_started),
8796 (uint32_t)(0));
8797
8798 sp_dmem_store_uint32(SP0_ID,
8799 (unsigned int)sp_address_of(host_sp_queues_initialized),
8800 (uint32_t)(0));
8801 sp_dmem_store_uint32(SP0_ID,
8802 (unsigned int)sp_address_of(sp_sleep_mode),
8803 (uint32_t)(0));
8804 sp_dmem_store_uint32(SP0_ID,
8805 (unsigned int)sp_address_of(ia_css_dmaproxy_sp_invalidate_tlb),
8806 (uint32_t)(false));
8807#ifndef ISP2401
8808 sp_dmem_store_uint32(SP0_ID,
8809 (unsigned int)sp_address_of(sp_stop_copy_preview),
8810 my_css.stop_copy_preview?(uint32_t)(1):(uint32_t)(0));
8811#endif
8812 store_sp_array_uint(host_sp_com, o, host2sp_cmd_ready);
8813
8814#if !defined(HAS_NO_INPUT_SYSTEM)
8815 for (i = 0; i < N_CSI_PORTS; i++) {
8816 sh_css_update_host2sp_num_mipi_frames
8817 (my_css.num_mipi_frames[i]);
8818 }
8819#endif
8820
8821 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8822 "sh_css_init_host_sp_control_vars() leave: return_void\n");
8823}
8824
d929fb4e 8825/*
a49d2536
AC
8826 * create the internal structures and fill in the configuration data
8827 */
8828void ia_css_pipe_config_defaults(struct ia_css_pipe_config *pipe_config)
8829{
8830 struct ia_css_pipe_config def_config = DEFAULT_PIPE_CONFIG;
8831
8832 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_config_defaults()\n");
8833 *pipe_config = def_config;
8834}
8835
8836void
8837ia_css_pipe_extra_config_defaults(struct ia_css_pipe_extra_config *extra_config)
8838{
8839 if (extra_config == NULL) {
8840 IA_CSS_ERROR("NULL input parameter");
8841 return;
8842 }
8843
8844 extra_config->enable_raw_binning = false;
8845 extra_config->enable_yuv_ds = false;
8846 extra_config->enable_high_speed = false;
8847 extra_config->enable_dvs_6axis = false;
8848 extra_config->enable_reduced_pipe = false;
8849 extra_config->disable_vf_pp = false;
8850 extra_config->enable_fractional_ds = false;
8851}
8852
8853void ia_css_stream_config_defaults(struct ia_css_stream_config *stream_config)
8854{
8855 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_config_defaults()\n");
8856 assert(stream_config != NULL);
8857 memset(stream_config, 0, sizeof(*stream_config));
8858 stream_config->online = true;
8859 stream_config->left_padding = -1;
8860 stream_config->pixels_per_clock = 1;
8861 /* temporary default value for backwards compatibility.
8862 * This field used to be hardcoded within CSS but this has now
8863 * been moved to the stream_config struct. */
8864 stream_config->source.port.rxcount = 0x04040404;
8865}
8866
8867static enum ia_css_err
8868ia_css_acc_pipe_create(struct ia_css_pipe *pipe)
8869{
8870 enum ia_css_err err = IA_CSS_SUCCESS;
8871
8872 if (pipe == NULL) {
8873 IA_CSS_ERROR("NULL input parameter");
8874 return IA_CSS_ERR_INVALID_ARGUMENTS;
8875 }
8876
8877 /* There is not meaning for num_execs = 0 semantically. Run atleast once. */
8878 if (pipe->config.acc_num_execs == 0)
8879 pipe->config.acc_num_execs = 1;
8880
8881 if (pipe->config.acc_extension) {
8882 err = ia_css_pipe_load_extension(pipe, pipe->config.acc_extension);
8883 }
8884
8885 return err;
8886}
8887
8888enum ia_css_err
8889ia_css_pipe_create(const struct ia_css_pipe_config *config,
8890 struct ia_css_pipe **pipe)
8891{
8892#ifndef ISP2401
8893 if (config == NULL)
8894#else
8895 enum ia_css_err err = IA_CSS_SUCCESS;
8896 IA_CSS_ENTER_PRIVATE("config = %p, pipe = %p", config, pipe);
8897
8898 if (config == NULL) {
8899 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
8900#endif
8901 return IA_CSS_ERR_INVALID_ARGUMENTS;
8902#ifndef ISP2401
8903 if (pipe == NULL)
8904#else
8905 }
8906 if (pipe == NULL) {
8907 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
8908#endif
8909 return IA_CSS_ERR_INVALID_ARGUMENTS;
8910#ifndef ISP2401
8911 return ia_css_pipe_create_extra(config, NULL, pipe);
8912#else
8913 }
8914
8915 err = ia_css_pipe_create_extra(config, NULL, pipe);
8916
8917 if(err == IA_CSS_SUCCESS) {
8918 IA_CSS_LOG("pipe created successfuly = %p", *pipe);
8919 }
8920
8921 IA_CSS_LEAVE_ERR_PRIVATE(err);
8922
8923 return err;
8924#endif
8925}
8926
8927enum ia_css_err
8928ia_css_pipe_create_extra(const struct ia_css_pipe_config *config,
8929 const struct ia_css_pipe_extra_config *extra_config,
8930 struct ia_css_pipe **pipe)
8931{
8932 enum ia_css_err err = IA_CSS_ERR_INTERNAL_ERROR;
8933 struct ia_css_pipe *internal_pipe = NULL;
8934 unsigned int i;
8935
8936 IA_CSS_ENTER_PRIVATE("config = %p, extra_config = %p and pipe = %p", config, extra_config, pipe);
8937
8938 /* do not allow to create more than the maximum limit */
8939 if (my_css.pipe_counter >= IA_CSS_PIPELINE_NUM_MAX) {
8940 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_RESOURCE_EXHAUSTED);
8941 return IA_CSS_ERR_INVALID_ARGUMENTS;
8942 }
8943
8944 if ((pipe == NULL) || (config == NULL)) {
8945 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
8946 return IA_CSS_ERR_INVALID_ARGUMENTS;
8947 }
8948
8949 ia_css_debug_dump_pipe_config(config);
8950 ia_css_debug_dump_pipe_extra_config(extra_config);
8951
8952 err = create_pipe(config->mode, &internal_pipe, false);
8953 if (err != IA_CSS_SUCCESS) {
8954 IA_CSS_LEAVE_ERR_PRIVATE(err);
8955 return err;
8956 }
8957
8958 /* now we have a pipe structure to fill */
8959 internal_pipe->config = *config;
8960 if (extra_config)
8961 internal_pipe->extra_config = *extra_config;
8962 else
8963 ia_css_pipe_extra_config_defaults(&internal_pipe->extra_config);
8964
8965 if (config->mode == IA_CSS_PIPE_MODE_ACC) {
8966 /* Temporary hack to migrate acceleration to CSS 2.0.
8967 * In the future the code for all pipe types should be
8968 * unified. */
8969 *pipe = internal_pipe;
8970 if (!internal_pipe->config.acc_extension &&
8971 internal_pipe->config.num_acc_stages == 0){ /* if no acc binary and no standalone stage */
8972 *pipe = NULL;
8973 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
8974 return IA_CSS_SUCCESS;
8975 }
8976 return ia_css_acc_pipe_create(internal_pipe);
8977 }
8978
8979 /* Use config value when dvs_frame_delay setting equal to 2, otherwise always 1 by default */
8980 if (internal_pipe->config.dvs_frame_delay == IA_CSS_FRAME_DELAY_2)
8981 internal_pipe->dvs_frame_delay = 2;
8982 else
8983 internal_pipe->dvs_frame_delay = 1;
8984
8985
8986 /* we still keep enable_raw_binning for backward compatibility, for any new
8987 fractional bayer downscaling, we should use bayer_ds_out_res. if both are
8988 specified, bayer_ds_out_res will take precedence.if none is specified, we
8989 set bayer_ds_out_res equal to IF output resolution(IF may do cropping on
8990 sensor output) or use default decimation factor 1. */
8991 if (internal_pipe->extra_config.enable_raw_binning &&
8992 internal_pipe->config.bayer_ds_out_res.width) {
8993 /* fill some code here, if no code is needed, please remove it during integration */
8994 }
8995
8996 /* YUV downscaling */
8997 if ((internal_pipe->config.vf_pp_in_res.width ||
8998 internal_pipe->config.capt_pp_in_res.width)) {
8999 enum ia_css_frame_format format;
9000 if (internal_pipe->config.vf_pp_in_res.width) {
9001 format = IA_CSS_FRAME_FORMAT_YUV_LINE;
9002 ia_css_frame_info_init(
9003 &internal_pipe->vf_yuv_ds_input_info,
9004 internal_pipe->config.vf_pp_in_res.width,
9005 internal_pipe->config.vf_pp_in_res.height,
9006 format, 0);
9007 }
9008 if (internal_pipe->config.capt_pp_in_res.width) {
9009 format = IA_CSS_FRAME_FORMAT_YUV420;
9010 ia_css_frame_info_init(
9011 &internal_pipe->out_yuv_ds_input_info,
9012 internal_pipe->config.capt_pp_in_res.width,
9013 internal_pipe->config.capt_pp_in_res.height,
9014 format, 0);
9015 }
9016 }
9017 if (internal_pipe->config.vf_pp_in_res.width &&
9018 internal_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) {
9019 ia_css_frame_info_init(
9020 &internal_pipe->vf_yuv_ds_input_info,
9021 internal_pipe->config.vf_pp_in_res.width,
9022 internal_pipe->config.vf_pp_in_res.height,
9023 IA_CSS_FRAME_FORMAT_YUV_LINE, 0);
9024 }
9025 /* handle bayer downscaling output info */
9026 if (internal_pipe->config.bayer_ds_out_res.width) {
9027 ia_css_frame_info_init(
9028 &internal_pipe->bds_output_info,
9029 internal_pipe->config.bayer_ds_out_res.width,
9030 internal_pipe->config.bayer_ds_out_res.height,
9031 IA_CSS_FRAME_FORMAT_RAW, 0);
9032 }
9033
9034 /* handle output info, assume always needed */
9035 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
9036 if (internal_pipe->config.output_info[i].res.width) {
9037 err = sh_css_pipe_configure_output(
9038 internal_pipe,
9039 internal_pipe->config.output_info[i].res.width,
9040 internal_pipe->config.output_info[i].res.height,
9041 internal_pipe->config.output_info[i].padded_width,
9042 internal_pipe->config.output_info[i].format,
9043 i);
9044 if (err != IA_CSS_SUCCESS) {
9045 IA_CSS_LEAVE_ERR_PRIVATE(err);
9046 sh_css_free(internal_pipe);
9047 internal_pipe = NULL;
9048 return err;
9049 }
9050 }
9051
9052 /* handle vf output info, when configured */
9053 internal_pipe->enable_viewfinder[i] = (internal_pipe->config.vf_output_info[i].res.width != 0);
9054 if (internal_pipe->config.vf_output_info[i].res.width) {
9055 err = sh_css_pipe_configure_viewfinder(
9056 internal_pipe,
9057 internal_pipe->config.vf_output_info[i].res.width,
9058 internal_pipe->config.vf_output_info[i].res.height,
9059 internal_pipe->config.vf_output_info[i].padded_width,
9060 internal_pipe->config.vf_output_info[i].format,
9061 i);
9062 if (err != IA_CSS_SUCCESS) {
9063 IA_CSS_LEAVE_ERR_PRIVATE(err);
9064 sh_css_free(internal_pipe);
9065 internal_pipe = NULL;
9066 return err;
9067 }
9068 }
9069 }
9070 if (internal_pipe->config.acc_extension) {
9071 err = ia_css_pipe_load_extension(internal_pipe,
9072 internal_pipe->config.acc_extension);
9073 if (err != IA_CSS_SUCCESS) {
9074 IA_CSS_LEAVE_ERR_PRIVATE(err);
9075 sh_css_free(internal_pipe);
9076 return err;
9077 }
9078 }
9079 /* set all info to zeroes first */
9080 memset(&internal_pipe->info, 0, sizeof(internal_pipe->info));
9081
9082 /* all went well, return the pipe */
9083 *pipe = internal_pipe;
9084 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
9085 return IA_CSS_SUCCESS;
9086}
9087
9088
9089enum ia_css_err
9090ia_css_pipe_get_info(const struct ia_css_pipe *pipe,
9091 struct ia_css_pipe_info *pipe_info)
9092{
9093 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
9094 "ia_css_pipe_get_info()\n");
9095 assert(pipe_info != NULL);
9096 if (pipe_info == NULL) {
9097 ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR,
9098 "ia_css_pipe_get_info: pipe_info cannot be NULL\n");
9099 return IA_CSS_ERR_INVALID_ARGUMENTS;
9100 }
9101 if (pipe == NULL || pipe->stream == NULL) {
9102 ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR,
9103 "ia_css_pipe_get_info: ia_css_stream_create needs to"
9104 " be called before ia_css_[stream/pipe]_get_info\n");
9105 return IA_CSS_ERR_INVALID_ARGUMENTS;
9106 }
9107 /* we succeeded return the info */
9108 *pipe_info = pipe->info;
9109 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_get_info() leave\n");
9110 return IA_CSS_SUCCESS;
9111}
9112
9113bool ia_css_pipe_has_dvs_stats(struct ia_css_pipe_info *pipe_info)
9114{
9115 unsigned int i;
9116
9117 if (pipe_info != NULL) {
9118 for (i = 0; i < IA_CSS_DVS_STAT_NUM_OF_LEVELS; i++) {
9119 if (pipe_info->grid_info.dvs_grid.dvs_stat_grid_info.grd_cfg[i].grd_start.enable)
9120 return true;
9121 }
9122 }
9123
9124 return false;
9125}
9126
9127#ifdef ISP2401
9128enum ia_css_err
9129ia_css_pipe_override_frame_format(struct ia_css_pipe *pipe,
9130 int pin_index,
9131 enum ia_css_frame_format new_format)
9132{
9133 enum ia_css_err err = IA_CSS_SUCCESS;
9134
9135 IA_CSS_ENTER_PRIVATE("pipe = %p, pin_index = %d, new_formats = %d", pipe, pin_index, new_format);
9136
9137 if (NULL == pipe) {
9138 IA_CSS_ERROR("pipe is not set");
9139 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9140 IA_CSS_LEAVE_ERR_PRIVATE(err);
9141 return err;
9142 }
9143 if (0 != pin_index && 1 != pin_index) {
9144 IA_CSS_ERROR("pin index is not valid");
9145 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9146 IA_CSS_LEAVE_ERR_PRIVATE(err);
9147 return err;
9148 }
9149 if (IA_CSS_FRAME_FORMAT_NV12_TILEY != new_format) {
9150 IA_CSS_ERROR("new format is not valid");
9151 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9152 IA_CSS_LEAVE_ERR_PRIVATE(err);
9153 return err;
9154 } else {
9155 err = ia_css_pipe_check_format(pipe, new_format);
9156 if (IA_CSS_SUCCESS == err) {
9157 if (pin_index == 0) {
9158 pipe->output_info[0].format = new_format;
9159 } else {
9160 pipe->vf_output_info[0].format = new_format;
9161 }
9162 }
9163 }
9164 IA_CSS_LEAVE_ERR_PRIVATE(err);
9165 return err;
9166}
9167
9168#endif
9169#if defined(USE_INPUT_SYSTEM_VERSION_2)
9170/* Configuration of INPUT_SYSTEM_VERSION_2401 is done on SP */
9171static enum ia_css_err
9172ia_css_stream_configure_rx(struct ia_css_stream *stream)
9173{
9174 struct ia_css_input_port *config;
9175 assert(stream != NULL);
9176
9177 config = &stream->config.source.port;
9178/* AM: this code is not reliable, especially for 2400 */
9179 if (config->num_lanes == 1)
9180 stream->csi_rx_config.mode = MONO_1L_1L_0L;
9181 else if (config->num_lanes == 2)
9182 stream->csi_rx_config.mode = MONO_2L_1L_0L;
9183 else if (config->num_lanes == 3)
9184 stream->csi_rx_config.mode = MONO_3L_1L_0L;
9185 else if (config->num_lanes == 4)
9186 stream->csi_rx_config.mode = MONO_4L_1L_0L;
9187 else if (config->num_lanes != 0)
9188 return IA_CSS_ERR_INVALID_ARGUMENTS;
9189
9190 if (config->port > IA_CSS_CSI2_PORT2)
9191 return IA_CSS_ERR_INVALID_ARGUMENTS;
9192 stream->csi_rx_config.port =
9193 ia_css_isys_port_to_mipi_port(config->port);
9194 stream->csi_rx_config.timeout = config->timeout;
9195 stream->csi_rx_config.initcount = 0;
9196 stream->csi_rx_config.synccount = 0x28282828;
9197 stream->csi_rx_config.rxcount = config->rxcount;
9198 if (config->compression.type == IA_CSS_CSI2_COMPRESSION_TYPE_NONE)
9199 stream->csi_rx_config.comp = MIPI_PREDICTOR_NONE;
9200 else {
9201 /* not implemented yet, requires extension of the rx_cfg_t
9202 * struct */
9203 return IA_CSS_ERR_INVALID_ARGUMENTS;
9204 }
9205 stream->csi_rx_config.is_two_ppc = (stream->config.pixels_per_clock == 2);
9206 stream->reconfigure_css_rx = true;
9207 return IA_CSS_SUCCESS;
9208}
9209#endif
9210
9211static struct ia_css_pipe *
9212find_pipe(struct ia_css_pipe *pipes[],
9213 unsigned int num_pipes,
9214 enum ia_css_pipe_mode mode,
9215 bool copy_pipe)
9216{
9217 unsigned i;
9218 assert(pipes != NULL);
9219 for (i = 0; i < num_pipes; i++) {
9220 assert(pipes[i] != NULL);
9221 if (pipes[i]->config.mode != mode)
9222 continue;
9223 if (copy_pipe && pipes[i]->mode != IA_CSS_PIPE_ID_COPY)
9224 continue;
9225 return pipes[i];
9226 }
9227 return NULL;
9228}
9229
9230static enum ia_css_err
9231ia_css_acc_stream_create(struct ia_css_stream *stream)
9232{
9233 int i;
9234 enum ia_css_err err = IA_CSS_SUCCESS;
9235
9236 assert(stream != NULL);
9237 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
9238
9239 if (stream == NULL) {
9240 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
9241 return IA_CSS_ERR_INVALID_ARGUMENTS;
9242 }
9243
9244 for (i = 0; i < stream->num_pipes; i++) {
9245 struct ia_css_pipe *pipe = stream->pipes[i];
9246 assert(pipe != NULL);
9247 if (pipe == NULL) {
9248 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
9249 return IA_CSS_ERR_INVALID_ARGUMENTS;
9250 }
9251
9252 pipe->stream = stream;
9253 }
9254
9255 /* Map SP threads before doing anything. */
9256 err = map_sp_threads(stream, true);
9257 if (err != IA_CSS_SUCCESS) {
9258 IA_CSS_LEAVE_ERR_PRIVATE(err);
9259 return err;
9260 }
9261
9262 for (i = 0; i < stream->num_pipes; i++) {
9263 struct ia_css_pipe *pipe = stream->pipes[i];
9264 assert(pipe != NULL);
9265 ia_css_pipe_map_queue(pipe, true);
9266 }
9267
9268 err = create_host_pipeline_structure(stream);
9269 if (err != IA_CSS_SUCCESS) {
9270 IA_CSS_LEAVE_ERR_PRIVATE(err);
9271 return err;
9272 }
9273
9274 stream->started = false;
9275
9276
9277 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
9278
9279 return IA_CSS_SUCCESS;
9280}
9281
9282static enum ia_css_err
9283metadata_info_init(const struct ia_css_metadata_config *mdc,
9284 struct ia_css_metadata_info *md)
9285{
9286 /* Either both width and height should be set or neither */
9287 if ((mdc->resolution.height > 0) ^ (mdc->resolution.width > 0))
9288 return IA_CSS_ERR_INVALID_ARGUMENTS;
9289
9290 md->resolution = mdc->resolution;
9291 /* We round up the stride to a multiple of the width
9292 * of the port going to DDR, this is a HW requirements (DMA). */
9293 md->stride = CEIL_MUL(mdc->resolution.width, HIVE_ISP_DDR_WORD_BYTES);
9294 md->size = mdc->resolution.height * md->stride;
9295 return IA_CSS_SUCCESS;
9296}
9297
9298#ifdef ISP2401
9299static enum ia_css_err check_pipe_resolutions(const struct ia_css_pipe *pipe)
9300{
9301 enum ia_css_err err = IA_CSS_SUCCESS;
9302
9303 IA_CSS_ENTER_PRIVATE("");
9304
9305 if (!pipe || !pipe->stream) {
9306 IA_CSS_ERROR("null arguments");
9307 err = IA_CSS_ERR_INTERNAL_ERROR;
9308 goto EXIT;
9309 }
9310
9311 if (ia_css_util_check_res(pipe->config.input_effective_res.width,
9312 pipe->config.input_effective_res.height) != IA_CSS_SUCCESS) {
9313 IA_CSS_ERROR("effective resolution not supported");
9314 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9315 goto EXIT;
9316 }
9317 if (!ia_css_util_resolution_is_zero(pipe->stream->config.input_config.input_res)) {
9318 if (!ia_css_util_res_leq(pipe->config.input_effective_res,
9319 pipe->stream->config.input_config.input_res)) {
9320 IA_CSS_ERROR("effective resolution is larger than input resolution");
9321 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9322 goto EXIT;
9323 }
9324 }
9325 if (!ia_css_util_resolution_is_even(pipe->config.output_info[0].res)) {
9326 IA_CSS_ERROR("output resolution must be even");
9327 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9328 goto EXIT;
9329 }
9330 if (!ia_css_util_resolution_is_even(pipe->config.vf_output_info[0].res)) {
9331 IA_CSS_ERROR("VF resolution must be even");
9332 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9333 goto EXIT;
9334 }
9335EXIT:
9336 IA_CSS_LEAVE_ERR_PRIVATE(err);
9337 return err;
9338}
9339
9340#endif
9341
9342enum ia_css_err
9343ia_css_stream_create(const struct ia_css_stream_config *stream_config,
9344 int num_pipes,
9345 struct ia_css_pipe *pipes[],
9346 struct ia_css_stream **stream)
9347{
9348 struct ia_css_pipe *curr_pipe;
9349 struct ia_css_stream *curr_stream = NULL;
9350 bool spcopyonly;
9351 bool sensor_binning_changed;
9352 int i, j;
9353 enum ia_css_err err = IA_CSS_ERR_INTERNAL_ERROR;
9354 struct ia_css_metadata_info md_info;
9355#ifndef ISP2401
9356 struct ia_css_resolution effective_res;
9357#else
9358#ifdef USE_INPUT_SYSTEM_VERSION_2401
9359 bool aspect_ratio_crop_enabled = false;
9360#endif
9361#endif
9362
9363 IA_CSS_ENTER("num_pipes=%d", num_pipes);
9364 ia_css_debug_dump_stream_config(stream_config, num_pipes);
9365
9366 /* some checks */
9367 if (num_pipes == 0 ||
9368 stream == NULL ||
9369 pipes == NULL) {
9370 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9371 IA_CSS_LEAVE_ERR(err);
9372 return err;
9373 }
9374
9375#if defined(USE_INPUT_SYSTEM_VERSION_2)
9376 /* We don't support metadata for JPEG stream, since they both use str2mem */
9377 if (stream_config->input_config.format == IA_CSS_STREAM_FORMAT_BINARY_8 &&
9378 stream_config->metadata_config.resolution.height > 0) {
9379 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9380 IA_CSS_LEAVE_ERR(err);
9381 return err;
9382 }
9383#endif
9384
9385#ifdef USE_INPUT_SYSTEM_VERSION_2401
9386 if (stream_config->online && stream_config->pack_raw_pixels) {
9387 IA_CSS_LOG("online and pack raw is invalid on input system 2401");
9388 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9389 IA_CSS_LEAVE_ERR(err);
9390 return err;
9391 }
9392#endif
9393
9394#if !defined(HAS_NO_INPUT_SYSTEM)
9395 ia_css_debug_pipe_graph_dump_stream_config(stream_config);
9396
9397 /* check if mipi size specified */
9398 if (stream_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
9399#ifdef USE_INPUT_SYSTEM_VERSION_2401
9400 if (!stream_config->online)
9401#endif
9402 {
9403 unsigned int port = (unsigned int) stream_config->source.port.port;
9404 if (port >= N_MIPI_PORT_ID) {
9405 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9406 IA_CSS_LEAVE_ERR(err);
9407 return err;
9408 }
9409
9410 if (my_css.size_mem_words != 0){
9411 my_css.mipi_frame_size[port] = my_css.size_mem_words;
9412 } else if (stream_config->mipi_buffer_config.size_mem_words != 0) {
9413 my_css.mipi_frame_size[port] = stream_config->mipi_buffer_config.size_mem_words;
9414 } else {
9415 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
9416 "ia_css_stream_create() exit: error, need to set mipi frame size.\n");
9417 assert(stream_config->mipi_buffer_config.size_mem_words != 0);
9418 err = IA_CSS_ERR_INTERNAL_ERROR;
9419 IA_CSS_LEAVE_ERR(err);
9420 return err;
9421 }
9422
9423 if (my_css.size_mem_words != 0) {
9424 my_css.num_mipi_frames[port] = 2; /* Temp change: Default for backwards compatibility. */
9425 } else if (stream_config->mipi_buffer_config.nof_mipi_buffers != 0) {
9426 my_css.num_mipi_frames[port] = stream_config->mipi_buffer_config.nof_mipi_buffers;
9427 } else {
9428 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
9429 "ia_css_stream_create() exit: error, need to set number of mipi frames.\n");
9430 assert(stream_config->mipi_buffer_config.nof_mipi_buffers != 0);
9431 err = IA_CSS_ERR_INTERNAL_ERROR;
9432 IA_CSS_LEAVE_ERR(err);
9433 return err;
9434 }
9435
9436 }
9437#endif
9438
9439 /* Currently we only supported metadata up to a certain size. */
9440 err = metadata_info_init(&stream_config->metadata_config, &md_info);
9441 if (err != IA_CSS_SUCCESS) {
9442 IA_CSS_LEAVE_ERR(err);
9443 return err;
9444 }
9445
9446 /* allocate the stream instance */
94853b65 9447 curr_stream = kmalloc(sizeof(struct ia_css_stream), GFP_KERNEL);
bbae6156 9448 if (!curr_stream) {
a49d2536
AC
9449 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
9450 IA_CSS_LEAVE_ERR(err);
9451 return err;
9452 }
9453 /* default all to 0 */
9454 memset(curr_stream, 0, sizeof(struct ia_css_stream));
9455 curr_stream->info.metadata_info = md_info;
9456
9457 /* allocate pipes */
9458 curr_stream->num_pipes = num_pipes;
94853b65 9459 curr_stream->pipes = kzalloc(num_pipes * sizeof(struct ia_css_pipe *), GFP_KERNEL);
bbae6156 9460 if (!curr_stream->pipes) {
a49d2536 9461 curr_stream->num_pipes = 0;
94853b65 9462 kfree(curr_stream);
a49d2536
AC
9463 curr_stream = NULL;
9464 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
9465 IA_CSS_LEAVE_ERR(err);
9466 return err;
9467 }
9468 /* store pipes */
9469 spcopyonly = (num_pipes == 1) && (pipes[0]->config.mode == IA_CSS_PIPE_MODE_COPY);
9470 for (i = 0; i < num_pipes; i++)
9471 curr_stream->pipes [i] = pipes[i];
9472 curr_stream->last_pipe = curr_stream->pipes[0];
9473 /* take over stream config */
9474 curr_stream->config = *stream_config;
9475
9476#if defined(USE_INPUT_SYSTEM_VERSION_2401) && defined(CSI2P_DISABLE_ISYS2401_ONLINE_MODE)
9477 if (stream_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR &&
9478 stream_config->online)
9479 curr_stream->config.online = false;
9480#endif
9481
9482#ifdef USE_INPUT_SYSTEM_VERSION_2401
9483 if (curr_stream->config.online) {
9484 curr_stream->config.source.port.num_lanes = stream_config->source.port.num_lanes;
9485 curr_stream->config.mode = IA_CSS_INPUT_MODE_BUFFERED_SENSOR;
9486 }
9487#endif
9488 /* in case driver doesn't configure init number of raw buffers, configure it here */
9489 if (curr_stream->config.target_num_cont_raw_buf == 0)
9490 curr_stream->config.target_num_cont_raw_buf = NUM_CONTINUOUS_FRAMES;
9491 if (curr_stream->config.init_num_cont_raw_buf == 0)
9492 curr_stream->config.init_num_cont_raw_buf = curr_stream->config.target_num_cont_raw_buf;
9493
9494 /* Enable locking & unlocking of buffers in RAW buffer pool */
9495 if (curr_stream->config.ia_css_enable_raw_buffer_locking)
9496 sh_css_sp_configure_enable_raw_pool_locking(
9497 curr_stream->config.lock_all);
9498
9499 /* copy mode specific stuff */
9500 switch (curr_stream->config.mode) {
9501 case IA_CSS_INPUT_MODE_SENSOR:
9502 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR:
9503#if defined(USE_INPUT_SYSTEM_VERSION_2)
9504 ia_css_stream_configure_rx(curr_stream);
9505#endif
9506 break;
9507 case IA_CSS_INPUT_MODE_TPG:
9508#if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
9509 IA_CSS_LOG("tpg_configuration: x_mask=%d, y_mask=%d, x_delta=%d, y_delta=%d, xy_mask=%d",
9510 curr_stream->config.source.tpg.x_mask,
9511 curr_stream->config.source.tpg.y_mask,
9512 curr_stream->config.source.tpg.x_delta,
9513 curr_stream->config.source.tpg.y_delta,
9514 curr_stream->config.source.tpg.xy_mask);
9515
9516 sh_css_sp_configure_tpg(
9517 curr_stream->config.source.tpg.x_mask,
9518 curr_stream->config.source.tpg.y_mask,
9519 curr_stream->config.source.tpg.x_delta,
9520 curr_stream->config.source.tpg.y_delta,
9521 curr_stream->config.source.tpg.xy_mask);
9522#endif
9523 break;
9524 case IA_CSS_INPUT_MODE_PRBS:
9525#if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
9526 IA_CSS_LOG("mode prbs");
9527 sh_css_sp_configure_prbs(curr_stream->config.source.prbs.seed);
9528#endif
9529 break;
9530 case IA_CSS_INPUT_MODE_MEMORY:
9531 IA_CSS_LOG("mode memory");
9532 curr_stream->reconfigure_css_rx = false;
9533 break;
9534 default:
9535 IA_CSS_LOG("mode sensor/default");
9536 }
9537
9538#ifdef ISP2401
9539#ifdef USE_INPUT_SYSTEM_VERSION_2401
9540 err = aspect_ratio_crop_init(curr_stream,
9541 pipes,
9542 &aspect_ratio_crop_enabled);
9543 if (err != IA_CSS_SUCCESS) {
9544 IA_CSS_LEAVE_ERR(err);
9545 return err;
9546 }
9547#endif
9548
9549#endif
9550 for (i = 0; i < num_pipes; i++) {
9551#ifdef ISP2401
9552 struct ia_css_resolution effective_res;
9553#endif
9554 curr_pipe = pipes[i];
9555 /* set current stream */
9556 curr_pipe->stream = curr_stream;
9557 /* take over effective info */
9558
9559 effective_res = curr_pipe->config.input_effective_res;
9560 if (effective_res.height == 0 || effective_res.width == 0) {
9561 effective_res = curr_pipe->stream->config.input_config.effective_res;
9562#ifdef ISP2401
9563
9564#if defined(USE_INPUT_SYSTEM_VERSION_2401)
9565 /* The aspect ratio cropping is currently only
9566 * supported on the new input system. */
9567 if (aspect_ratio_crop_check(aspect_ratio_crop_enabled, curr_pipe)) {
9568
9569 struct ia_css_resolution crop_res;
9570
9571 err = aspect_ratio_crop(curr_pipe, &crop_res);
9572 if (err == IA_CSS_SUCCESS) {
9573 effective_res = crop_res;
9574 } else {
9575 /* in case of error fallback to default
9576 * effective resolution from driver. */
9577 IA_CSS_LOG("aspect_ratio_crop() failed with err(%d)", err);
9578 }
9579 }
9580#endif
9581#endif
9582 curr_pipe->config.input_effective_res = effective_res;
9583 }
9584 IA_CSS_LOG("effective_res=%dx%d",
9585 effective_res.width,
9586 effective_res.height);
9587 }
9588
9589#ifdef ISP2401
9590 for (i = 0; i < num_pipes; i++) {
9591 if (pipes[i]->config.mode != IA_CSS_PIPE_MODE_ACC &&
9592 pipes[i]->config.mode != IA_CSS_PIPE_MODE_COPY) {
9593 err = check_pipe_resolutions(pipes[i]);
9594 if (err != IA_CSS_SUCCESS) {
9595 goto ERR;
9596 }
9597 }
9598 }
9599
9600#endif
9601 err = ia_css_stream_isp_parameters_init(curr_stream);
9602 if (err != IA_CSS_SUCCESS)
9603 goto ERR;
9604 IA_CSS_LOG("isp_params_configs: %p", curr_stream->isp_params_configs);
9605
9606 if (num_pipes == 1 && pipes[0]->config.mode == IA_CSS_PIPE_MODE_ACC) {
9607 *stream = curr_stream;
9608 err = ia_css_acc_stream_create(curr_stream);
9609 goto ERR;
9610 }
9611 /* sensor binning */
9612 if (!spcopyonly){
9613 sensor_binning_changed =
9614 sh_css_params_set_binning_factor(curr_stream, curr_stream->config.sensor_binning_factor);
9615 } else {
9616 sensor_binning_changed = false;
9617 }
9618
9619 IA_CSS_LOG("sensor_binning=%d, changed=%d",
9620 curr_stream->config.sensor_binning_factor, sensor_binning_changed);
9621 /* loop over pipes */
9622 IA_CSS_LOG("num_pipes=%d", num_pipes);
9623 curr_stream->cont_capt = false;
9624 /* Temporary hack: we give the preview pipe a reference to the capture
9625 * pipe in continuous capture mode. */
9626 if (curr_stream->config.continuous) {
9627 /* Search for the preview pipe and create the copy pipe */
9628 struct ia_css_pipe *preview_pipe;
9629 struct ia_css_pipe *video_pipe;
9630 struct ia_css_pipe *acc_pipe;
9631 struct ia_css_pipe *capture_pipe = NULL;
9632 struct ia_css_pipe *copy_pipe = NULL;
9633
9634 if (num_pipes >= 2) {
9635 curr_stream->cont_capt = true;
9636 curr_stream->disable_cont_vf = curr_stream->config.disable_cont_viewfinder;
9637#ifndef ISP2401
9638 curr_stream->stop_copy_preview = my_css.stop_copy_preview;
9639#endif
9640 }
9641
9642 /* Create copy pipe here, since it may not be exposed to the driver */
9643 preview_pipe = find_pipe(pipes, num_pipes,
9644 IA_CSS_PIPE_MODE_PREVIEW, false);
9645 video_pipe = find_pipe(pipes, num_pipes,
9646 IA_CSS_PIPE_MODE_VIDEO, false);
9647 acc_pipe = find_pipe(pipes, num_pipes,
9648 IA_CSS_PIPE_MODE_ACC, false);
9649 if (acc_pipe && num_pipes == 2 && curr_stream->cont_capt == true)
9650 curr_stream->cont_capt = false; /* preview + QoS case will not need cont_capt switch */
9651 if (curr_stream->cont_capt == true) {
9652 capture_pipe = find_pipe(pipes, num_pipes,
9653 IA_CSS_PIPE_MODE_CAPTURE, false);
9654 if (capture_pipe == NULL) {
9655 err = IA_CSS_ERR_INTERNAL_ERROR;
9656 goto ERR;
9657 }
9658 }
9659 /* We do not support preview and video pipe at the same time */
9660 if (preview_pipe && video_pipe) {
9661 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9662 goto ERR;
9663 }
9664
9665 if (preview_pipe && !preview_pipe->pipe_settings.preview.copy_pipe) {
9666 err = create_pipe(IA_CSS_PIPE_MODE_CAPTURE, &copy_pipe, true);
9667 if (err != IA_CSS_SUCCESS)
9668 goto ERR;
9669 ia_css_pipe_config_defaults(&copy_pipe->config);
9670 preview_pipe->pipe_settings.preview.copy_pipe = copy_pipe;
9671 copy_pipe->stream = curr_stream;
9672 }
9673 if (preview_pipe && (curr_stream->cont_capt == true)) {
9674 preview_pipe->pipe_settings.preview.capture_pipe = capture_pipe;
9675 }
9676 if (video_pipe && !video_pipe->pipe_settings.video.copy_pipe) {
9677 err = create_pipe(IA_CSS_PIPE_MODE_CAPTURE, &copy_pipe, true);
9678 if (err != IA_CSS_SUCCESS)
9679 goto ERR;
9680 ia_css_pipe_config_defaults(&copy_pipe->config);
9681 video_pipe->pipe_settings.video.copy_pipe = copy_pipe;
9682 copy_pipe->stream = curr_stream;
9683 }
9684 if (video_pipe && (curr_stream->cont_capt == true)) {
9685 video_pipe->pipe_settings.video.capture_pipe = capture_pipe;
9686 }
9687 if (preview_pipe && acc_pipe) {
9688 preview_pipe->pipe_settings.preview.acc_pipe = acc_pipe;
9689 }
9690 }
9691 for (i = 0; i < num_pipes; i++) {
9692 curr_pipe = pipes[i];
9693 /* set current stream */
9694 curr_pipe->stream = curr_stream;
9695#ifndef ISP2401
9696 /* take over effective info */
9697
9698 effective_res = curr_pipe->config.input_effective_res;
a49d2536
AC
9699 err = ia_css_util_check_res(
9700 effective_res.width,
9701 effective_res.height);
9702 if (err != IA_CSS_SUCCESS)
9703 goto ERR;
9704#endif
9705 /* sensor binning per pipe */
9706 if (sensor_binning_changed)
9707 sh_css_pipe_free_shading_table(curr_pipe);
9708 }
9709
9710 /* now pipes have been configured, info should be available */
9711 for (i = 0; i < num_pipes; i++) {
9712 struct ia_css_pipe_info *pipe_info = NULL;
9713 curr_pipe = pipes[i];
9714
9715 err = sh_css_pipe_load_binaries(curr_pipe);
9716 if (err != IA_CSS_SUCCESS)
9717 goto ERR;
9718
a49d2536
AC
9719 /* handle each pipe */
9720 pipe_info = &curr_pipe->info;
9721 for (j = 0; j < IA_CSS_PIPE_MAX_OUTPUT_STAGE; j++) {
9722 err = sh_css_pipe_get_output_frame_info(curr_pipe,
9723 &pipe_info->output_info[j], j);
9724 if (err != IA_CSS_SUCCESS)
9725 goto ERR;
9726 }
9727#ifdef ISP2401
9728 pipe_info->output_system_in_res_info = curr_pipe->config.output_system_in_res;
9729#endif
9730 if (!spcopyonly){
9731 err = sh_css_pipe_get_shading_info(curr_pipe,
9732#ifndef ISP2401
9733 &pipe_info->shading_info);
9734#else
9735 &pipe_info->shading_info, &curr_pipe->config);
9736#endif
9737 if (err != IA_CSS_SUCCESS)
9738 goto ERR;
9739 err = sh_css_pipe_get_grid_info(curr_pipe,
9740 &pipe_info->grid_info);
9741 if (err != IA_CSS_SUCCESS)
9742 goto ERR;
9743 for (j = 0; j < IA_CSS_PIPE_MAX_OUTPUT_STAGE; j++) {
9744 sh_css_pipe_get_viewfinder_frame_info(curr_pipe,
9745 &pipe_info->vf_output_info[j], j);
9746 if (err != IA_CSS_SUCCESS)
9747 goto ERR;
9748 }
9749 }
9750
9751 my_css.active_pipes[ia_css_pipe_get_pipe_num(curr_pipe)] = curr_pipe;
9752 }
9753
9754 curr_stream->started = false;
9755
9756 /* Map SP threads before doing anything. */
9757 err = map_sp_threads(curr_stream, true);
9758 if (err != IA_CSS_SUCCESS) {
9759 IA_CSS_LOG("map_sp_threads: return_err=%d", err);
9760 goto ERR;
9761 }
9762
9763 for (i = 0; i < num_pipes; i++) {
9764 curr_pipe = pipes[i];
9765 ia_css_pipe_map_queue(curr_pipe, true);
9766 }
9767
9768 /* Create host side pipeline objects without stages */
9769 err = create_host_pipeline_structure(curr_stream);
9770 if (err != IA_CSS_SUCCESS) {
9771 IA_CSS_LOG("create_host_pipeline_structure: return_err=%d", err);
9772 goto ERR;
9773 }
9774
9775 /* assign curr_stream */
9776 *stream = curr_stream;
9777
9778ERR:
9779#ifndef ISP2401
9780 if (err == IA_CSS_SUCCESS)
9781 {
9782 /* working mode: enter into the seed list */
b5eb7ac1
MCC
9783 if (my_css_save.mode == sh_css_mode_working) {
9784 for (i = 0; i < MAX_ACTIVE_STREAMS; i++)
9785 if (!my_css_save.stream_seeds[i].stream) {
9786 IA_CSS_LOG("entered stream into loc=%d", i);
9787 my_css_save.stream_seeds[i].orig_stream = stream;
9788 my_css_save.stream_seeds[i].stream = curr_stream;
9789 my_css_save.stream_seeds[i].num_pipes = num_pipes;
9790 my_css_save.stream_seeds[i].stream_config = *stream_config;
9791 for (j = 0; j < num_pipes; j++) {
9792 my_css_save.stream_seeds[i].pipe_config[j] = pipes[j]->config;
9793 my_css_save.stream_seeds[i].pipes[j] = pipes[j];
9794 my_css_save.stream_seeds[i].orig_pipes[j] = &pipes[j];
9795 }
9796 break;
a49d2536 9797 }
b5eb7ac1 9798 }
a49d2536
AC
9799#else
9800 if (err == IA_CSS_SUCCESS) {
9801 err = ia_css_save_stream(curr_stream);
9802#endif
9803 } else {
9804 ia_css_stream_destroy(curr_stream);
9805 }
9806#ifndef ISP2401
9807 IA_CSS_LEAVE("return_err=%d mode=%d", err, my_css_save.mode);
9808#else
9809 IA_CSS_LEAVE("return_err=%d", err);
9810#endif
9811 return err;
9812}
9813
9814enum ia_css_err
9815ia_css_stream_destroy(struct ia_css_stream *stream)
9816{
9817 int i;
9818 enum ia_css_err err = IA_CSS_SUCCESS;
9819#ifdef ISP2401
9820 enum ia_css_err err1 = IA_CSS_SUCCESS;
9821 enum ia_css_err err2 = IA_CSS_SUCCESS;
9822#endif
9823
9824 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
9825 if (stream == NULL) {
9826 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9827 IA_CSS_LEAVE_ERR_PRIVATE(err);
9828 return err;
9829 }
9830
9831 ia_css_stream_isp_parameters_uninit(stream);
9832
9833 if ((stream->last_pipe != NULL) &&
9834 ia_css_pipeline_is_mapped(stream->last_pipe->pipe_num)) {
9835#if defined(USE_INPUT_SYSTEM_VERSION_2401)
9836 for (i = 0; i < stream->num_pipes; i++) {
9837 struct ia_css_pipe *entry = stream->pipes[i];
9838 unsigned int sp_thread_id;
9839 struct sh_css_sp_pipeline_terminal *sp_pipeline_input_terminal;
9840
9841 assert(entry != NULL);
9842 if (entry != NULL) {
9843 /* get the SP thread id */
9844 if (ia_css_pipeline_get_sp_thread_id(
9845 ia_css_pipe_get_pipe_num(entry), &sp_thread_id) != true)
9846 return IA_CSS_ERR_INTERNAL_ERROR;
9847 /* get the target input terminal */
9848 sp_pipeline_input_terminal =
9849 &(sh_css_sp_group.pipe_io[sp_thread_id].input);
9850
9851 for (i = 0; i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++) {
9852 ia_css_isys_stream_h isys_stream =
9853 &(sp_pipeline_input_terminal->context.virtual_input_system_stream[i]);
9854 if (stream->config.isys_config[i].valid && isys_stream->valid)
9855 ia_css_isys_stream_destroy(isys_stream);
9856 }
9857 }
9858 }
9859#ifndef ISP2401
9860 if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
9861#else
9862 if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR ||
9863 stream->config.mode == IA_CSS_INPUT_MODE_TPG ||
9864 stream->config.mode == IA_CSS_INPUT_MODE_PRBS) {
9865#endif
9866 for (i = 0; i < stream->num_pipes; i++) {
9867 struct ia_css_pipe *entry = stream->pipes[i];
9868 /* free any mipi frames that are remaining:
9869 * some test stream create-destroy cycles do not generate output frames
9870 * and the mipi buffer is not freed in the deque function
9871 */
9872 if (entry != NULL)
9873 free_mipi_frames(entry);
9874 }
9875 }
9876 stream_unregister_with_csi_rx(stream);
9877#endif
9878
9879 for (i = 0; i < stream->num_pipes; i++) {
9880 struct ia_css_pipe *curr_pipe = stream->pipes[i];
9881 assert(curr_pipe != NULL);
9882 ia_css_pipe_map_queue(curr_pipe, false);
9883 }
9884
9885 err = map_sp_threads(stream, false);
9886 if (err != IA_CSS_SUCCESS) {
9887 IA_CSS_LEAVE_ERR_PRIVATE(err);
9888 return err;
9889 }
9890 }
9891
9892 /* remove references from pipes to stream */
9893 for (i = 0; i < stream->num_pipes; i++) {
9894 struct ia_css_pipe *entry = stream->pipes[i];
9895 assert(entry != NULL);
9896 if (entry != NULL) {
9897 /* clear reference to stream */
9898 entry->stream = NULL;
9899 /* check internal copy pipe */
9900 if (entry->mode == IA_CSS_PIPE_ID_PREVIEW &&
9901 entry->pipe_settings.preview.copy_pipe) {
9902 IA_CSS_LOG("clearing stream on internal preview copy pipe");
9903 entry->pipe_settings.preview.copy_pipe->stream = NULL;
9904 }
9905 if (entry->mode == IA_CSS_PIPE_ID_VIDEO &&
9906 entry->pipe_settings.video.copy_pipe) {
9907 IA_CSS_LOG("clearing stream on internal video copy pipe");
9908 entry->pipe_settings.video.copy_pipe->stream = NULL;
9909 }
9910 err = sh_css_pipe_unload_binaries(entry);
9911 }
9912 }
9913 /* free associated memory of stream struct */
94853b65 9914 kfree(stream->pipes);
a49d2536
AC
9915 stream->pipes = NULL;
9916 stream->num_pipes = 0;
9917#ifndef ISP2401
9918 /* working mode: take out of the seed list */
9919 if (my_css_save.mode == sh_css_mode_working)
9920 for(i=0;i<MAX_ACTIVE_STREAMS;i++)
9921 if (my_css_save.stream_seeds[i].stream == stream)
9922 {
9923 IA_CSS_LOG("took out stream %d", i);
9924 my_css_save.stream_seeds[i].stream = NULL;
9925 break;
9926 }
9927#else
9928 err2 = ia_css_save_restore_remove_stream(stream);
9929
9930 err1 = (err != IA_CSS_SUCCESS) ? err : err2;
9931#endif
94853b65 9932 kfree(stream);
a49d2536
AC
9933#ifndef ISP2401
9934 IA_CSS_LEAVE_ERR(err);
9935#else
9936 IA_CSS_LEAVE_ERR(err1);
9937#endif
9938
9939#ifndef ISP2401
9940 return err;
9941#else
9942 return err1;
9943#endif
9944}
9945
9946enum ia_css_err
9947ia_css_stream_get_info(const struct ia_css_stream *stream,
9948 struct ia_css_stream_info *stream_info)
9949{
9950 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_info: enter/exit\n");
9951 assert(stream != NULL);
9952 assert(stream_info != NULL);
9953
9954 *stream_info = stream->info;
9955 return IA_CSS_SUCCESS;
9956}
9957
9958/*
9959 * Rebuild a stream, including allocating structs, setting configuration and
9960 * building the required pipes.
9961 * The data is taken from the css_save struct updated upon stream creation.
9962 * The stream handle is used to identify the correct entry in the css_save struct
9963 */
9964enum ia_css_err
9965ia_css_stream_load(struct ia_css_stream *stream)
9966{
9967#ifndef ISP2401
9968 int i;
9969 enum ia_css_err err;
9970 assert(stream != NULL);
9971 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_load() enter, \n");
b5eb7ac1
MCC
9972 for (i = 0; i < MAX_ACTIVE_STREAMS; i++) {
9973 if (my_css_save.stream_seeds[i].stream == stream) {
a49d2536 9974 int j;
b5eb7ac1
MCC
9975 for ( j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++) {
9976 if ((err = ia_css_pipe_create(&(my_css_save.stream_seeds[i].pipe_config[j]), &my_css_save.stream_seeds[i].pipes[j])) != IA_CSS_SUCCESS) {
9977 if (j) {
a49d2536
AC
9978 int k;
9979 for(k=0;k<j;k++)
9980 ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[k]);
9981 }
0d82b57c 9982 return err;
a49d2536 9983 }
b5eb7ac1
MCC
9984 }
9985 err = ia_css_stream_create(&(my_css_save.stream_seeds[i].stream_config),
9986 my_css_save.stream_seeds[i].num_pipes,
9987 my_css_save.stream_seeds[i].pipes,
9988 &(my_css_save.stream_seeds[i].stream));
9989 if (err != IA_CSS_SUCCESS) {
a49d2536 9990 ia_css_stream_destroy(stream);
b5eb7ac1 9991 for (j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++)
a49d2536 9992 ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[j]);
0d82b57c 9993 return err;
a49d2536
AC
9994 }
9995 break;
9996 }
b5eb7ac1 9997 }
a49d2536 9998 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_load() exit, \n");
0d82b57c 9999 return IA_CSS_SUCCESS;
a49d2536
AC
10000#else
10001 /* TODO remove function - DEPRECATED */
10002 (void)stream;
10003 return IA_CSS_ERR_NOT_SUPPORTED;
10004#endif
10005}
10006
10007enum ia_css_err
10008ia_css_stream_start(struct ia_css_stream *stream)
10009{
10010 enum ia_css_err err = IA_CSS_SUCCESS;
10011 IA_CSS_ENTER("stream = %p", stream);
10012 if ((stream == NULL) || (stream->last_pipe == NULL)) {
10013 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
10014 return IA_CSS_ERR_INVALID_ARGUMENTS;
10015 }
10016 IA_CSS_LOG("starting %d", stream->last_pipe->mode);
10017
10018 sh_css_sp_set_disable_continuous_viewfinder(stream->disable_cont_vf);
10019
10020 /* Create host side pipeline. */
10021 err = create_host_pipeline(stream);
10022 if (err != IA_CSS_SUCCESS) {
10023 IA_CSS_LEAVE_ERR(err);
10024 return err;
10025 }
10026
10027#if !defined(HAS_NO_INPUT_SYSTEM)
10028#if defined(USE_INPUT_SYSTEM_VERSION_2401)
10029 if((stream->config.mode == IA_CSS_INPUT_MODE_SENSOR) ||
10030 (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR))
10031 stream_register_with_csi_rx(stream);
10032#endif
10033#endif
10034
10035#if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
10036 /* Initialize mipi size checks */
10037 if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
10038 {
10039 unsigned int idx;
10040 unsigned int port = (unsigned int) (stream->config.source.port.port) ;
10041
10042 for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT; idx++) {
10043 sh_css_sp_group.config.mipi_sizes_for_check[port][idx] = sh_css_get_mipi_sizes_for_check(port, idx);
10044 }
10045 }
10046#endif
10047
10048#if !defined(HAS_NO_INPUT_SYSTEM)
10049 if (stream->config.mode != IA_CSS_INPUT_MODE_MEMORY) {
10050 err = sh_css_config_input_network(stream);
10051 if (err != IA_CSS_SUCCESS)
10052 return err;
10053 }
10054#endif /* !HAS_NO_INPUT_SYSTEM */
10055
10056 err = sh_css_pipe_start(stream);
10057 IA_CSS_LEAVE_ERR(err);
10058 return err;
10059}
10060
10061enum ia_css_err
10062ia_css_stream_stop(struct ia_css_stream *stream)
10063{
10064 enum ia_css_err err = IA_CSS_SUCCESS;
10065
10066 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_stop() enter/exit\n");
10067 assert(stream != NULL);
10068 assert(stream->last_pipe != NULL);
10069 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_stop: stopping %d\n",
10070 stream->last_pipe->mode);
10071
10072#if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
10073 /* De-initialize mipi size checks */
10074 if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
10075 {
10076 unsigned int idx;
10077 unsigned int port = (unsigned int) (stream->config.source.port.port) ;
10078
10079 for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT; idx++) {
10080 sh_css_sp_group.config.mipi_sizes_for_check[port][idx] = 0;
10081 }
10082 }
10083#endif
10084#ifndef ISP2401
10085 err = ia_css_pipeline_request_stop(&stream->last_pipe->pipeline);
10086#else
10087
10088 err = sh_css_pipes_stop(stream);
10089#endif
10090 if (err != IA_CSS_SUCCESS)
10091 return err;
10092
10093 /* Ideally, unmapping should happen after pipeline_stop, but current
10094 * semantics do not allow that. */
10095 /* err = map_sp_threads(stream, false); */
10096
10097 return err;
10098}
10099
10100bool
10101ia_css_stream_has_stopped(struct ia_css_stream *stream)
10102{
10103 bool stopped;
10104 assert(stream != NULL);
10105
10106#ifndef ISP2401
10107 stopped = ia_css_pipeline_has_stopped(&stream->last_pipe->pipeline);
10108#else
10109 stopped = sh_css_pipes_have_stopped(stream);
10110#endif
10111
10112 return stopped;
10113}
10114
10115#ifndef ISP2401
10116/*
10117 * Destroy the stream and all the pipes related to it.
10118 * The stream handle is used to identify the correct entry in the css_save struct
10119 */
10120enum ia_css_err
10121ia_css_stream_unload(struct ia_css_stream *stream)
10122{
10123 int i;
10124 assert(stream != NULL);
10125 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_unload() enter, \n");
10126 /* some checks */
10127 assert (stream != NULL);
10128 for(i=0;i<MAX_ACTIVE_STREAMS;i++)
10129 if (my_css_save.stream_seeds[i].stream == stream)
10130 {
10131 int j;
10132 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_unload(): unloading %d (%p)\n", i, my_css_save.stream_seeds[i].stream);
10133 ia_css_stream_destroy(stream);
10134 for(j=0;j<my_css_save.stream_seeds[i].num_pipes;j++)
10135 ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[j]);
10136 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_unload(): after unloading %d (%p)\n", i, my_css_save.stream_seeds[i].stream);
10137 break;
10138 }
10139 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_unload() exit, \n");
0d82b57c 10140 return IA_CSS_SUCCESS;
a49d2536
AC
10141}
10142
10143#endif
10144enum ia_css_err
10145ia_css_temp_pipe_to_pipe_id(const struct ia_css_pipe *pipe, enum ia_css_pipe_id *pipe_id)
10146{
10147 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_temp_pipe_to_pipe_id() enter/exit\n");
10148 if (pipe != NULL)
10149 *pipe_id = pipe->mode;
10150 else
10151 *pipe_id = IA_CSS_PIPE_ID_COPY;
10152
10153 return IA_CSS_SUCCESS;
10154}
10155
10156enum ia_css_stream_format
10157ia_css_stream_get_format(const struct ia_css_stream *stream)
10158{
10159 return stream->config.input_config.format;
10160}
10161
10162bool
10163ia_css_stream_get_two_pixels_per_clock(const struct ia_css_stream *stream)
10164{
10165 return (stream->config.pixels_per_clock == 2);
10166}
10167
10168struct ia_css_binary *
10169ia_css_stream_get_shading_correction_binary(const struct ia_css_stream *stream)
10170{
10171 struct ia_css_pipe *pipe;
10172
10173 assert(stream != NULL);
10174
10175 pipe = stream->pipes[0];
10176
10177 if (stream->num_pipes == 2) {
10178 assert(stream->pipes[1] != NULL);
10179 if (stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_VIDEO ||
10180 stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_PREVIEW)
10181 pipe = stream->pipes[1];
10182 }
10183
10184 return ia_css_pipe_get_shading_correction_binary(pipe);
10185}
10186
10187struct ia_css_binary *
10188ia_css_stream_get_dvs_binary(const struct ia_css_stream *stream)
10189{
10190 int i;
10191 struct ia_css_pipe *video_pipe = NULL;
10192
10193 /* First we find the video pipe */
10194 for (i=0; i<stream->num_pipes; i++) {
10195 struct ia_css_pipe *pipe = stream->pipes[i];
10196 if (pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) {
10197 video_pipe = pipe;
10198 break;
10199 }
10200 }
10201 if (video_pipe)
10202 return &video_pipe->pipe_settings.video.video_binary;
10203 return NULL;
10204}
10205
10206struct ia_css_binary *
10207ia_css_stream_get_3a_binary(const struct ia_css_stream *stream)
10208{
10209 struct ia_css_pipe *pipe;
10210 struct ia_css_binary *s3a_binary = NULL;
10211
10212 assert(stream != NULL);
10213
10214 pipe = stream->pipes[0];
10215
10216 if (stream->num_pipes == 2) {
10217 assert(stream->pipes[1] != NULL);
10218 if (stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_VIDEO ||
10219 stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_PREVIEW)
10220 pipe = stream->pipes[1];
10221 }
10222
10223 s3a_binary = ia_css_pipe_get_s3a_binary(pipe);
10224
10225 return s3a_binary;
10226}
10227
10228
10229enum ia_css_err
10230ia_css_stream_set_output_padded_width(struct ia_css_stream *stream, unsigned int output_padded_width)
10231{
10232 enum ia_css_err err = IA_CSS_SUCCESS;
10233
10234 struct ia_css_pipe *pipe;
10235
10236 assert(stream != NULL);
10237
10238 pipe = stream->last_pipe;
10239
10240 assert(pipe != NULL);
10241
10242 /* set the config also just in case (redundant info? why do we save config in pipe?) */
10243 pipe->config.output_info[IA_CSS_PIPE_OUTPUT_STAGE_0].padded_width = output_padded_width;
10244 pipe->output_info[IA_CSS_PIPE_OUTPUT_STAGE_0].padded_width = output_padded_width;
10245
10246 return err;
10247}
10248
10249static struct ia_css_binary *
10250ia_css_pipe_get_shading_correction_binary(const struct ia_css_pipe *pipe)
10251{
10252 struct ia_css_binary *binary = NULL;
10253
10254 assert(pipe != NULL);
10255
10256 switch (pipe->config.mode) {
10257 case IA_CSS_PIPE_MODE_PREVIEW:
10258 binary = (struct ia_css_binary *)&pipe->pipe_settings.preview.preview_binary;
10259 break;
10260 case IA_CSS_PIPE_MODE_VIDEO:
10261 binary = (struct ia_css_binary *)&pipe->pipe_settings.video.video_binary;
10262 break;
10263 case IA_CSS_PIPE_MODE_CAPTURE:
10264 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
10265 unsigned int i;
10266
10267 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
10268 if (pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.sc) {
10269 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.primary_binary[i];
10270 break;
10271 }
10272 }
10273 }
10274 else if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER)
10275 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
10276 else if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_ADVANCED ||
10277 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) {
10278 if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_1)
10279 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
10280 else if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_2_2)
10281 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.post_isp_binary;
10282 }
10283 break;
10284 default:
10285 break;
10286 }
10287
10288 if (binary && binary->info->sp.enable.sc)
10289 return binary;
10290
10291 return NULL;
10292}
10293
10294static struct ia_css_binary *
10295ia_css_pipe_get_s3a_binary(const struct ia_css_pipe *pipe)
10296{
10297 struct ia_css_binary *binary = NULL;
10298
10299 assert(pipe != NULL);
10300
10301 switch (pipe->config.mode) {
10302 case IA_CSS_PIPE_MODE_PREVIEW:
10303 binary = (struct ia_css_binary*)&pipe->pipe_settings.preview.preview_binary;
10304 break;
10305 case IA_CSS_PIPE_MODE_VIDEO:
10306 binary = (struct ia_css_binary*)&pipe->pipe_settings.video.video_binary;
10307 break;
10308 case IA_CSS_PIPE_MODE_CAPTURE:
10309 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
10310 unsigned int i;
10311 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
10312 if (pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.s3a) {
10313 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.primary_binary[i];
10314 break;
10315 }
10316 }
10317 }
10318 else if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER)
10319 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
10320 else if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_ADVANCED ||
10321 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) {
10322 if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_1)
10323 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
10324 else if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_2_2)
10325 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.post_isp_binary;
10326 else
10327 assert(0);
10328 }
10329 break;
10330 default:
10331 break;
10332 }
10333
10334 if (binary && !binary->info->sp.enable.s3a)
10335 binary = NULL;
10336
10337 return binary;
10338}
10339
10340static struct ia_css_binary *
10341ia_css_pipe_get_sdis_binary(const struct ia_css_pipe *pipe)
10342{
10343 struct ia_css_binary *binary = NULL;
10344
10345 assert(pipe != NULL);
10346
10347 switch (pipe->config.mode) {
10348 case IA_CSS_PIPE_MODE_VIDEO:
10349 binary = (struct ia_css_binary*)&pipe->pipe_settings.video.video_binary;
10350 break;
10351 default:
10352 break;
10353 }
10354
10355 if (binary && !binary->info->sp.enable.dis)
10356 binary = NULL;
10357
10358 return binary;
10359}
10360
10361struct ia_css_pipeline *
10362ia_css_pipe_get_pipeline(const struct ia_css_pipe *pipe)
10363{
10364 assert(pipe != NULL);
10365
10366 return (struct ia_css_pipeline*)&pipe->pipeline;
10367}
10368
10369unsigned int
10370ia_css_pipe_get_pipe_num(const struct ia_css_pipe *pipe)
10371{
10372 assert(pipe != NULL);
10373
10374 /* KW was not sure this function was not returning a value
10375 that was out of range; so added an assert, and, for the
10376 case when asserts are not enabled, clip to the largest
10377 value; pipe_num is unsigned so the value cannot be too small
10378 */
10379 assert(pipe->pipe_num < IA_CSS_PIPELINE_NUM_MAX);
10380
10381 if (pipe->pipe_num >= IA_CSS_PIPELINE_NUM_MAX)
10382 return (IA_CSS_PIPELINE_NUM_MAX - 1);
10383
10384 return pipe->pipe_num;
10385}
10386
10387
10388unsigned int
10389ia_css_pipe_get_isp_pipe_version(const struct ia_css_pipe *pipe)
10390{
10391 assert(pipe != NULL);
10392
10393 return (unsigned int)pipe->config.isp_pipe_version;
10394}
10395
a49d2536
AC
10396#define SP_START_TIMEOUT_US 30000000
10397
a49d2536
AC
10398enum ia_css_err
10399ia_css_start_sp(void)
10400{
10401 unsigned long timeout;
10402 enum ia_css_err err = IA_CSS_SUCCESS;
10403
10404 IA_CSS_ENTER("");
a49d2536
AC
10405 sh_css_sp_start_isp();
10406
10407 /* waiting for the SP is completely started */
10408 timeout = SP_START_TIMEOUT_US;
10409 while((ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_INITIALIZED) && timeout) {
10410 timeout--;
10411 hrt_sleep();
10412 }
10413 if (timeout == 0) {
10414 IA_CSS_ERROR("timeout during SP initialization");
10415 return IA_CSS_ERR_INTERNAL_ERROR;
10416 }
10417
10418 /* Workaround, in order to run two streams in parallel. See TASK 4271*/
10419 /* TODO: Fix this. */
10420
10421 sh_css_init_host_sp_control_vars();
10422
10423 /* buffers should be initialized only when sp is started */
10424 /* AM: At the moment it will be done only when there is no stream active. */
10425
10426 sh_css_setup_queues();
10427 ia_css_bufq_dump_queue_info();
10428
a49d2536
AC
10429#ifdef ISP2401
10430 if (ia_css_is_system_mode_suspend_or_resume() == false) { /* skip in suspend/resume flow */
10431 ia_css_set_system_mode(IA_CSS_SYS_MODE_WORKING);
10432 }
10433#endif
10434 IA_CSS_LEAVE_ERR(err);
10435 return err;
10436}
10437
d929fb4e 10438/*
a49d2536
AC
10439 * Time to wait SP for termincate. Only condition when this can happen
10440 * is a fatal hw failure, but we must be able to detect this and emit
10441 * a proper error trace.
10442 */
10443#define SP_SHUTDOWN_TIMEOUT_US 200000
10444
a49d2536
AC
10445enum ia_css_err
10446ia_css_stop_sp(void)
10447{
10448 unsigned long timeout;
10449 enum ia_css_err err = IA_CSS_SUCCESS;
10450
10451 IA_CSS_ENTER("void");
10452
10453 if (!sh_css_sp_is_running()) {
10454 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10455 IA_CSS_LEAVE("SP already stopped : return_err=%d", err);
10456
10457 /* Return an error - stop SP should not have been called by driver */
10458 return err;
10459 }
10460
10461 /* For now, stop whole SP */
10462#ifndef ISP2401
10463 sh_css_write_host2sp_command(host2sp_cmd_terminate);
10464#else
10465 if (!sh_css_write_host2sp_command(host2sp_cmd_terminate)) {
10466 IA_CSS_ERROR("Call to 'sh-css_write_host2sp_command()' failed");
10467 ia_css_debug_dump_sp_sw_debug_info();
10468 ia_css_debug_dump_debug_info(NULL);
10469 }
10470#endif
10471 sh_css_sp_set_sp_running(false);
10472
10473 timeout = SP_SHUTDOWN_TIMEOUT_US;
10474 while (!ia_css_spctrl_is_idle(SP0_ID) && timeout) {
10475 timeout--;
10476 hrt_sleep();
10477 }
10478 if ((ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_TERMINATED))
10479 IA_CSS_WARNING("SP has not terminated (SW)");
10480
10481 if (timeout == 0) {
10482 IA_CSS_WARNING("SP is not idle");
10483 ia_css_debug_dump_sp_sw_debug_info();
10484 }
10485 timeout = SP_SHUTDOWN_TIMEOUT_US;
10486 while (!isp_ctrl_getbit(ISP0_ID, ISP_SC_REG, ISP_IDLE_BIT) && timeout) {
10487 timeout--;
10488 hrt_sleep();
10489 }
10490 if (timeout == 0) {
10491 IA_CSS_WARNING("ISP is not idle");
10492 ia_css_debug_dump_sp_sw_debug_info();
10493 }
10494
10495 sh_css_hmm_buffer_record_uninit();
10496
10497#ifndef ISP2401
10498 /* clear pending param sets from refcount */
10499 sh_css_param_clear_param_sets();
10500#else
10501 if (ia_css_is_system_mode_suspend_or_resume() == false) { /* skip in suspend/resume flow */
10502 /* clear pending param sets from refcount */
10503 sh_css_param_clear_param_sets();
10504 ia_css_set_system_mode(IA_CSS_SYS_MODE_INIT); /* System is initialized but not 'running' */
10505 }
10506#endif
10507
a49d2536
AC
10508 IA_CSS_LEAVE_ERR(err);
10509 return err;
10510}
10511
10512enum ia_css_err
10513ia_css_update_continuous_frames(struct ia_css_stream *stream)
10514{
10515 struct ia_css_pipe *pipe;
10516 unsigned int i;
10517
10518 ia_css_debug_dtrace(
10519 IA_CSS_DEBUG_TRACE,
10520 "sh_css_update_continuous_frames() enter:\n");
10521
10522 if (stream == NULL) {
10523 ia_css_debug_dtrace(
10524 IA_CSS_DEBUG_TRACE,
10525 "sh_css_update_continuous_frames() leave: invalid stream, return_void\n");
b5eb7ac1 10526 return IA_CSS_ERR_INVALID_ARGUMENTS;
a49d2536
AC
10527 }
10528
10529 pipe = stream->continuous_pipe;
10530
10531 for (i = stream->config.init_num_cont_raw_buf;
10532 i < stream->config.target_num_cont_raw_buf; i++) {
10533 sh_css_update_host2sp_offline_frame(i,
10534 pipe->continuous_frames[i], pipe->cont_md_buffers[i]);
10535 }
10536 sh_css_update_host2sp_cont_num_raw_frames
10537 (stream->config.target_num_cont_raw_buf, true);
10538 ia_css_debug_dtrace(
10539 IA_CSS_DEBUG_TRACE,
10540 "sh_css_update_continuous_frames() leave: return_void\n");
10541
10542 return IA_CSS_SUCCESS;
10543}
10544
10545void ia_css_pipe_map_queue(struct ia_css_pipe *pipe, bool map)
10546{
10547 unsigned int thread_id;
10548 enum ia_css_pipe_id pipe_id;
10549 unsigned int pipe_num;
10550 bool need_input_queue;
10551
10552 IA_CSS_ENTER("");
10553 assert(pipe != NULL);
10554
10555 pipe_id = pipe->mode;
10556 pipe_num = pipe->pipe_num;
10557
10558 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
10559
10560#if defined(HAS_NO_INPUT_SYSTEM) || defined(USE_INPUT_SYSTEM_VERSION_2401)
10561 need_input_queue = true;
10562#else
10563 need_input_queue = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
10564#endif
10565
10566 /* map required buffer queues to resources */
10567 /* TODO: to be improved */
10568 if (pipe->mode == IA_CSS_PIPE_ID_PREVIEW) {
10569 if (need_input_queue)
10570 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10571 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10572 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10573 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
10574#if defined SH_CSS_ENABLE_METADATA
10575 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10576#endif
10577 if (pipe->pipe_settings.preview.preview_binary.info &&
10578 pipe->pipe_settings.preview.preview_binary.info->sp.enable.s3a)
10579 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
10580 } else if (pipe->mode == IA_CSS_PIPE_ID_CAPTURE) {
10581 unsigned int i;
10582
10583 if (need_input_queue)
10584 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10585 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10586 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME, map);
10587 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10588 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
10589#if defined SH_CSS_ENABLE_METADATA
10590 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10591#endif
10592 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
10593 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
10594 if (pipe->pipe_settings.capture.primary_binary[i].info &&
10595 pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.s3a) {
10596 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
10597 break;
10598 }
10599 }
10600 } else if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_ADVANCED ||
10601 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT ||
10602 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER) {
10603 if (pipe->pipe_settings.capture.pre_isp_binary.info &&
10604 pipe->pipe_settings.capture.pre_isp_binary.info->sp.enable.s3a)
10605 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
10606 }
10607 } else if (pipe->mode == IA_CSS_PIPE_ID_VIDEO) {
10608 if (need_input_queue)
10609 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10610 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10611 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0])
10612 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME, map);
10613 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10614 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
10615#if defined SH_CSS_ENABLE_METADATA
10616 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10617#endif
10618 if (pipe->pipe_settings.video.video_binary.info &&
10619 pipe->pipe_settings.video.video_binary.info->sp.enable.s3a)
10620 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
10621 if (pipe->pipe_settings.video.video_binary.info &&
10622 (pipe->pipe_settings.video.video_binary.info->sp.enable.dis
10623 ))
10624 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_DIS_STATISTICS, map);
10625 } else if (pipe->mode == IA_CSS_PIPE_ID_COPY) {
10626 if (need_input_queue)
10627 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10628 if (!pipe->stream->config.continuous)
10629 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10630#if defined SH_CSS_ENABLE_METADATA
10631 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10632#endif
10633 } else if (pipe->mode == IA_CSS_PIPE_ID_ACC) {
10634 if (need_input_queue)
10635 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10636 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10637 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10638 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
10639#if defined SH_CSS_ENABLE_METADATA
10640 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10641#endif
10642 } else if (pipe->mode == IA_CSS_PIPE_ID_YUVPP) {
10643 unsigned int idx;
10644 for (idx = 0; idx < IA_CSS_PIPE_MAX_OUTPUT_STAGE; idx++) {
10645 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx, map);
10646 if (pipe->enable_viewfinder[idx])
10647 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx, map);
10648 }
10649 if (need_input_queue)
10650 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10651 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10652#if defined SH_CSS_ENABLE_METADATA
10653 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10654#endif
10655 }
10656 IA_CSS_LEAVE("");
10657}
10658
10659#if CONFIG_ON_FRAME_ENQUEUE()
10660static enum ia_css_err set_config_on_frame_enqueue(struct ia_css_frame_info *info, struct frame_data_wrapper *frame)
10661{
10662 frame->config_on_frame_enqueue.padded_width = 0;
10663
10664 /* currently we support configuration on frame enqueue only on YUV formats */
10665 /* on other formats the padded_width is zeroed for no configuration override */
10666 switch (info->format) {
10667 case IA_CSS_FRAME_FORMAT_YUV420:
10668 case IA_CSS_FRAME_FORMAT_NV12:
10669 if (info->padded_width > info->res.width)
10670 {
10671 frame->config_on_frame_enqueue.padded_width = info->padded_width;
10672 }
10673 else if ((info->padded_width < info->res.width) && (info->padded_width > 0))
10674 {
10675 return IA_CSS_ERR_INVALID_ARGUMENTS;
10676 }
10677 /* nothing to do if width == padded width or padded width is zeroed (the same) */
10678 break;
10679 default:
10680 break;
10681 }
10682
10683 return IA_CSS_SUCCESS;
10684}
10685#endif
10686
10687enum ia_css_err
10688ia_css_unlock_raw_frame(struct ia_css_stream *stream, uint32_t exp_id)
10689{
10690 enum ia_css_err ret;
10691
10692 IA_CSS_ENTER("");
10693
10694 /* Only continuous streams have a tagger to which we can send the
10695 * unlock message. */
10696 if (stream == NULL || !stream->config.continuous) {
10697 IA_CSS_ERROR("invalid stream pointer");
10698 return IA_CSS_ERR_INVALID_ARGUMENTS;
10699 }
10700
10701 if (exp_id > IA_CSS_ISYS_MAX_EXPOSURE_ID ||
10702 exp_id < IA_CSS_ISYS_MIN_EXPOSURE_ID) {
10703 IA_CSS_ERROR("invalid expsure ID: %d\n", exp_id);
10704 return IA_CSS_ERR_INVALID_ARGUMENTS;
10705 }
10706
10707 /* Send the event. Since we verified that the exp_id is valid,
10708 * we can safely assign it to an 8-bit argument here. */
10709 ret = ia_css_bufq_enqueue_psys_event(
10710 IA_CSS_PSYS_SW_EVENT_UNLOCK_RAW_BUFFER, exp_id, 0, 0);
10711
10712 IA_CSS_LEAVE_ERR(ret);
10713 return ret;
10714}
10715
d929fb4e 10716/* @brief Set the state (Enable or Disable) of the Extension stage in the
a49d2536
AC
10717 * given pipe.
10718 */
10719enum ia_css_err
10720ia_css_pipe_set_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle, bool enable)
10721{
10722 unsigned int thread_id;
10723 struct ia_css_pipeline_stage *stage;
10724 enum ia_css_err err = IA_CSS_SUCCESS;
10725
10726 IA_CSS_ENTER("");
10727
10728 /* Parameter Check */
10729 if (pipe == NULL || pipe->stream == NULL) {
10730 IA_CSS_ERROR("Invalid Pipe.");
10731 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10732 } else if (!(pipe->config.acc_extension)) {
10733 IA_CSS_ERROR("Invalid Pipe(No Extension Firmware)");
10734 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10735 } else if (!sh_css_sp_is_running()) {
10736 IA_CSS_ERROR("Leaving: queue unavailable.");
10737 err = IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
10738 } else {
10739 /* Query the threadid and stage_num for the Extension firmware*/
10740 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
10741 err = ia_css_pipeline_get_stage_from_fw(&(pipe->pipeline), fw_handle, &stage);
10742 if (err == IA_CSS_SUCCESS) {
10743 /* Set the Extension State;. TODO: Add check for stage firmware.type (QOS)*/
10744 err = ia_css_bufq_enqueue_psys_event(
10745 (uint8_t) IA_CSS_PSYS_SW_EVENT_STAGE_ENABLE_DISABLE,
10746 (uint8_t) thread_id,
10747 (uint8_t) stage->stage_num,
10748 (enable == true) ? 1 : 0);
10749 if (err == IA_CSS_SUCCESS) {
10750 if(enable)
10751 SH_CSS_QOS_STAGE_ENABLE(&(sh_css_sp_group.pipe[thread_id]),stage->stage_num);
10752 else
10753 SH_CSS_QOS_STAGE_DISABLE(&(sh_css_sp_group.pipe[thread_id]),stage->stage_num);
10754 }
10755 }
10756 }
10757 IA_CSS_LEAVE("err:%d handle:%u enable:%d", err, fw_handle, enable);
10758 return err;
10759}
10760
d929fb4e 10761/* @brief Get the state (Enable or Disable) of the Extension stage in the
a49d2536
AC
10762 * given pipe.
10763 */
10764enum ia_css_err
10765ia_css_pipe_get_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle, bool *enable)
10766{
10767 struct ia_css_pipeline_stage *stage;
10768 unsigned int thread_id;
10769 enum ia_css_err err = IA_CSS_SUCCESS;
10770
10771 IA_CSS_ENTER("");
10772
10773 /* Parameter Check */
10774 if (pipe == NULL || pipe->stream == NULL) {
10775 IA_CSS_ERROR("Invalid Pipe.");
10776 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10777 } else if (!(pipe->config.acc_extension)) {
10778 IA_CSS_ERROR("Invalid Pipe (No Extension Firmware).");
10779 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10780 } else if (!sh_css_sp_is_running()) {
10781 IA_CSS_ERROR("Leaving: queue unavailable.");
10782 err = IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
10783 } else {
10784 /* Query the threadid and stage_num corresponding to the Extension firmware*/
10785 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
10786 err = ia_css_pipeline_get_stage_from_fw(&pipe->pipeline, fw_handle, &stage);
10787
10788 if (err == IA_CSS_SUCCESS) {
10789 /* Get the Extension State */
10790 *enable = (SH_CSS_QOS_STAGE_IS_ENABLED(&(sh_css_sp_group.pipe[thread_id]),stage->stage_num)) ? true : false;
10791 }
10792 }
10793 IA_CSS_LEAVE("err:%d handle:%u enable:%d", err, fw_handle, *enable);
10794 return err;
10795}
10796
10797#ifdef ISP2401
10798enum ia_css_err
10799ia_css_pipe_update_qos_ext_mapped_arg(struct ia_css_pipe *pipe, uint32_t fw_handle,
10800 struct ia_css_isp_param_css_segments *css_seg, struct ia_css_isp_param_isp_segments *isp_seg)
10801{
a49d2536
AC
10802 unsigned int HIVE_ADDR_sp_group;
10803 static struct sh_css_sp_group sp_group;
a49d2536
AC
10804 static struct sh_css_sp_stage sp_stage;
10805 static struct sh_css_isp_stage isp_stage;
10806 const struct ia_css_fw_info *fw;
10807 unsigned int thread_id;
10808 struct ia_css_pipeline_stage *stage;
10809 enum ia_css_err err = IA_CSS_SUCCESS;
10810 int stage_num = 0;
10811 enum ia_css_isp_memories mem;
10812 bool enabled;
10813
10814 IA_CSS_ENTER("");
10815
10816 fw = &sh_css_sp_fw;
10817
10818 /* Parameter Check */
10819 if (pipe == NULL || pipe->stream == NULL) {
10820 IA_CSS_ERROR("Invalid Pipe.");
10821 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10822 } else if (!(pipe->config.acc_extension)) {
10823 IA_CSS_ERROR("Invalid Pipe (No Extension Firmware).");
10824 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10825 } else if (!sh_css_sp_is_running()) {
10826 IA_CSS_ERROR("Leaving: queue unavailable.");
10827 err = IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
10828 } else {
10829 /* Query the thread_id and stage_num corresponding to the Extension firmware */
10830 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
10831 err = ia_css_pipeline_get_stage_from_fw(&(pipe->pipeline), fw_handle, &stage);
10832 if (err == IA_CSS_SUCCESS) {
10833 /* Get the Extension State */
10834 enabled = (SH_CSS_QOS_STAGE_IS_ENABLED(&(sh_css_sp_group.pipe[thread_id]), stage->stage_num)) ? true : false;
10835 /* Update mapped arg only when extension stage is not enabled */
10836 if (enabled) {
10837 IA_CSS_ERROR("Leaving: cannot update when stage is enabled.");
10838 err = IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
10839 } else {
10840 stage_num = stage->stage_num;
10841
a49d2536
AC
10842 HIVE_ADDR_sp_group = fw->info.sp.group;
10843 sp_dmem_load(SP0_ID,
10844 (unsigned int)sp_address_of(sp_group),
10845 &sp_group, sizeof(struct sh_css_sp_group));
10846 mmgr_load(sp_group.pipe[thread_id].sp_stage_addr[stage_num],
10847 &sp_stage, sizeof(struct sh_css_sp_stage));
a49d2536
AC
10848
10849 mmgr_load(sp_stage.isp_stage_addr,
10850 &isp_stage, sizeof(struct sh_css_isp_stage));
10851
10852 for (mem = 0; mem < N_IA_CSS_ISP_MEMORIES; mem++) {
10853 isp_stage.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].address =
10854 css_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].address;
10855 isp_stage.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].size =
10856 css_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].size;
10857 isp_stage.binary_info.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].address =
10858 isp_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].address;
10859 isp_stage.binary_info.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].size =
10860 isp_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].size;
10861 }
10862
10863 mmgr_store(sp_stage.isp_stage_addr,
10864 &isp_stage, sizeof(struct sh_css_isp_stage));
10865 }
10866 }
10867 }
10868 IA_CSS_LEAVE("err:%d handle:%u", err, fw_handle);
10869 return err;
10870}
10871
10872#ifdef USE_INPUT_SYSTEM_VERSION_2401
10873static enum ia_css_err
10874aspect_ratio_crop_init(struct ia_css_stream *curr_stream,
10875 struct ia_css_pipe *pipes[],
10876 bool *do_crop_status)
10877{
10878 enum ia_css_err err = IA_CSS_SUCCESS;
10879 int i;
10880 struct ia_css_pipe *curr_pipe;
10881 uint32_t pipe_mask = 0;
10882
10883 if ((curr_stream == NULL) ||
10884 (curr_stream->num_pipes == 0) ||
10885 (pipes == NULL) ||
10886 (do_crop_status == NULL)) {
10887 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10888 IA_CSS_LEAVE_ERR(err);
10889 return err;
10890 }
10891
10892 for (i = 0; i < curr_stream->num_pipes; i++) {
10893 curr_pipe = pipes[i];
10894 pipe_mask |= (1 << curr_pipe->config.mode);
10895 }
10896
10897 *do_crop_status =
10898 (((pipe_mask & (1 << IA_CSS_PIPE_MODE_PREVIEW)) ||
10899 (pipe_mask & (1 << IA_CSS_PIPE_MODE_VIDEO))) &&
10900 (pipe_mask & (1 << IA_CSS_PIPE_MODE_CAPTURE)) &&
10901 curr_stream->config.continuous);
10902 return IA_CSS_SUCCESS;
10903}
10904
10905static bool
10906aspect_ratio_crop_check(bool enabled, struct ia_css_pipe *curr_pipe)
10907{
10908 bool status = false;
10909
10910 if ((curr_pipe != NULL) && enabled) {
10911 if ((curr_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) ||
10912 (curr_pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) ||
10913 (curr_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE))
10914 status = true;
10915 }
10916
10917 return status;
10918}
10919
10920static enum ia_css_err
10921aspect_ratio_crop(struct ia_css_pipe *curr_pipe,
10922 struct ia_css_resolution *effective_res)
10923{
10924 enum ia_css_err err = IA_CSS_SUCCESS;
10925 struct ia_css_resolution crop_res;
10926 struct ia_css_resolution *in_res = NULL;
10927 struct ia_css_resolution *out_res = NULL;
10928 bool use_bds_output_info = false;
10929 bool use_vf_pp_in_res = false;
10930 bool use_capt_pp_in_res = false;
10931
10932 if ((curr_pipe == NULL) ||
10933 (effective_res == NULL)) {
10934 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10935 IA_CSS_LEAVE_ERR(err);
10936 return err;
10937 }
10938
10939 if ((curr_pipe->config.mode != IA_CSS_PIPE_MODE_PREVIEW) &&
10940 (curr_pipe->config.mode != IA_CSS_PIPE_MODE_VIDEO) &&
10941 (curr_pipe->config.mode != IA_CSS_PIPE_MODE_CAPTURE)) {
10942 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10943 IA_CSS_LEAVE_ERR(err);
10944 return err;
10945 }
10946
10947 use_bds_output_info =
10948 ((curr_pipe->bds_output_info.res.width != 0) &&
10949 (curr_pipe->bds_output_info.res.height != 0));
10950
10951 use_vf_pp_in_res =
10952 ((curr_pipe->config.vf_pp_in_res.width != 0) &&
10953 (curr_pipe->config.vf_pp_in_res.height != 0));
10954
10955 use_capt_pp_in_res =
10956 ((curr_pipe->config.capt_pp_in_res.width != 0) &&
10957 (curr_pipe->config.capt_pp_in_res.height != 0));
10958
10959 in_res = &curr_pipe->stream->config.input_config.effective_res;
10960 out_res = &curr_pipe->output_info[0].res;
10961
10962 switch (curr_pipe->config.mode) {
10963 case IA_CSS_PIPE_MODE_PREVIEW:
10964 if (use_bds_output_info)
10965 out_res = &curr_pipe->bds_output_info.res;
10966 else if (use_vf_pp_in_res)
10967 out_res = &curr_pipe->config.vf_pp_in_res;
10968 break;
10969 case IA_CSS_PIPE_MODE_VIDEO:
10970 if (use_bds_output_info)
10971 out_res = &curr_pipe->bds_output_info.res;
10972 break;
10973 case IA_CSS_PIPE_MODE_CAPTURE:
10974 if (use_capt_pp_in_res)
10975 out_res = &curr_pipe->config.capt_pp_in_res;
10976 break;
10977 case IA_CSS_PIPE_MODE_ACC:
10978 case IA_CSS_PIPE_MODE_COPY:
10979 case IA_CSS_PIPE_MODE_YUVPP:
10980 default:
10981 IA_CSS_ERROR("aspect ratio cropping invalid args: mode[%d]\n",
10982 curr_pipe->config.mode);
10983 assert(0);
10984 break;
10985 }
10986
10987 err = ia_css_frame_find_crop_resolution(in_res, out_res, &crop_res);
10988 if (err == IA_CSS_SUCCESS) {
10989 *effective_res = crop_res;
10990 } else {
10991 /* in case of error fallback to default
10992 * effective resolution from driver. */
10993 IA_CSS_LOG("ia_css_frame_find_crop_resolution() failed with err(%d)", err);
10994 }
10995 return err;
10996}
10997#endif
10998
10999#endif
11000static void
11001sh_css_hmm_buffer_record_init(void)
11002{
11003 int i;
11004
11005#ifndef ISP2401
11006 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
11007 sh_css_hmm_buffer_record_reset(&hmm_buffer_record[i]);
11008#else
11009 if (ia_css_is_system_mode_suspend_or_resume() == false) { /* skip in suspend/resume flow */
11010 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
11011 sh_css_hmm_buffer_record_reset(&hmm_buffer_record[i]);
11012 }
11013#endif
11014 }
11015}
11016
11017static void
11018sh_css_hmm_buffer_record_uninit(void)
11019{
11020 int i;
11021 struct sh_css_hmm_buffer_record *buffer_record = NULL;
11022
11023#ifndef ISP2401
11024 buffer_record = &hmm_buffer_record[0];
11025 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
11026 if (buffer_record->in_use) {
11027 if (buffer_record->h_vbuf != NULL)
11028 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &buffer_record->h_vbuf);
11029 sh_css_hmm_buffer_record_reset(buffer_record);
11030#else
11031 if (ia_css_is_system_mode_suspend_or_resume() == false) { /* skip in suspend/resume flow */
11032 buffer_record = &hmm_buffer_record[0];
11033 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
11034 if (buffer_record->in_use) {
11035 if (buffer_record->h_vbuf != NULL)
11036 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &buffer_record->h_vbuf);
11037 sh_css_hmm_buffer_record_reset(buffer_record);
11038 }
11039 buffer_record++;
11040#endif
11041 }
11042#ifndef ISP2401
11043 buffer_record++;
11044#endif
11045 }
11046}
11047
11048static void
11049sh_css_hmm_buffer_record_reset(struct sh_css_hmm_buffer_record *buffer_record)
11050{
11051 assert(buffer_record != NULL);
11052 buffer_record->in_use = false;
11053 buffer_record->type = IA_CSS_BUFFER_TYPE_INVALID;
11054 buffer_record->h_vbuf = NULL;
11055 buffer_record->kernel_ptr = 0;
11056}
11057
a49d2536
AC
11058static struct sh_css_hmm_buffer_record
11059*sh_css_hmm_buffer_record_acquire(struct ia_css_rmgr_vbuf_handle *h_vbuf,
a49d2536
AC
11060 enum ia_css_buffer_type type,
11061 hrt_address kernel_ptr)
11062{
11063 int i;
11064 struct sh_css_hmm_buffer_record *buffer_record = NULL;
a49d2536 11065 struct sh_css_hmm_buffer_record *out_buffer_record = NULL;
a49d2536
AC
11066
11067 assert(h_vbuf != NULL);
11068 assert((type > IA_CSS_BUFFER_TYPE_INVALID) && (type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE));
11069 assert(kernel_ptr != 0);
11070
11071 buffer_record = &hmm_buffer_record[0];
11072 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
11073 if (buffer_record->in_use == false) {
11074 buffer_record->in_use = true;
11075 buffer_record->type = type;
11076 buffer_record->h_vbuf = h_vbuf;
11077 buffer_record->kernel_ptr = kernel_ptr;
a49d2536 11078 out_buffer_record = buffer_record;
a49d2536
AC
11079 break;
11080 }
11081 buffer_record++;
11082 }
11083
a49d2536 11084 return out_buffer_record;
a49d2536
AC
11085}
11086
11087static struct sh_css_hmm_buffer_record
11088*sh_css_hmm_buffer_record_validate(hrt_vaddress ddr_buffer_addr,
11089 enum ia_css_buffer_type type)
11090{
11091 int i;
11092 struct sh_css_hmm_buffer_record *buffer_record = NULL;
11093 bool found_record = false;
11094
11095 buffer_record = &hmm_buffer_record[0];
11096 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
11097 if ((buffer_record->in_use == true) &&
11098 (buffer_record->type == type) &&
11099 (buffer_record->h_vbuf != NULL) &&
11100 (buffer_record->h_vbuf->vptr == ddr_buffer_addr)) {
11101 found_record = true;
11102 break;
11103 }
11104 buffer_record++;
11105 }
11106
11107 if (found_record == true)
11108 return buffer_record;
11109 else
11110 return NULL;
11111}