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