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