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