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