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