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