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