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