linux/drivers/staging/media/atomisp/pci/sh_css_sp.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Support for Intel Camera Imaging ISP subsystem.
   4 * Copyright (c) 2015, Intel Corporation.
   5 *
   6 * This program is free software; you can redistribute it and/or modify it
   7 * under the terms and conditions of the GNU General Public License,
   8 * version 2, as published by the Free Software Foundation.
   9 *
  10 * This program is distributed in the hope it will be useful, but WITHOUT
  11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  13 * more details.
  14 */
  15
  16#include "hmm.h"
  17
  18#include "sh_css_sp.h"
  19
  20#if !defined(ISP2401)
  21#include "input_formatter.h"
  22#endif
  23
  24#include "dma.h"        /* N_DMA_CHANNEL_ID */
  25
  26#include "ia_css_buffer.h"
  27#include "ia_css_binary.h"
  28#include "sh_css_hrt.h"
  29#include "sh_css_defs.h"
  30#include "sh_css_internal.h"
  31#include "ia_css_control.h"
  32#include "ia_css_debug.h"
  33#include "ia_css_debug_pipe.h"
  34#include "ia_css_event_public.h"
  35#include "ia_css_mmu.h"
  36#include "ia_css_stream.h"
  37#include "ia_css_isp_param.h"
  38#include "sh_css_params.h"
  39#include "sh_css_legacy.h"
  40#include "ia_css_frame_comm.h"
  41#include "ia_css_isys.h"
  42
  43#include "gdc_device.h"                         /* HRT_GDC_N */
  44
  45/*#include "sp.h"*/     /* host2sp_enqueue_frame_data() */
  46
  47
  48#include "assert_support.h"
  49
  50#include "sw_event_global.h"                    /* Event IDs.*/
  51#include "ia_css_event.h"
  52#include "mmu_device.h"
  53#include "ia_css_spctrl.h"
  54
  55#ifndef offsetof
  56#define offsetof(T, x) ((unsigned int)&(((T *)0)->x))
  57#endif
  58
  59#define IA_CSS_INCLUDE_CONFIGURATIONS
  60#include "ia_css_isp_configs.h"
  61#define IA_CSS_INCLUDE_STATES
  62#include "ia_css_isp_states.h"
  63
  64#include "isp/kernels/ipu2_io_ls/bayer_io_ls/ia_css_bayer_io.host.h"
  65
  66struct sh_css_sp_group          sh_css_sp_group;
  67struct sh_css_sp_stage          sh_css_sp_stage;
  68struct sh_css_isp_stage         sh_css_isp_stage;
  69static struct sh_css_sp_output          sh_css_sp_output;
  70static struct sh_css_sp_per_frame_data per_frame_data;
  71
  72/* true if SP supports frame loop and host2sp_commands */
  73/* For the moment there is only code that sets this bool to true */
  74/* TODO: add code that sets this bool to false */
  75static bool sp_running;
  76
  77static int
  78set_output_frame_buffer(const struct ia_css_frame *frame,
  79                        unsigned int idx);
  80
  81static void
  82sh_css_copy_buffer_attr_to_spbuffer(struct ia_css_buffer_sp *dest_buf,
  83                                    const enum sh_css_queue_id queue_id,
  84                                    const ia_css_ptr xmem_addr,
  85                                    const enum ia_css_buffer_type buf_type);
  86
  87static void
  88initialize_frame_buffer_attribute(struct ia_css_buffer_sp *buf_attr);
  89
  90static void
  91initialize_stage_frames(struct ia_css_frames_sp *frames);
  92
  93/* This data is stored every frame */
  94void
  95store_sp_group_data(void)
  96{
  97        per_frame_data.sp_group_addr = sh_css_store_sp_group_to_ddr();
  98}
  99
 100static void
 101copy_isp_stage_to_sp_stage(void)
 102{
 103        /* [WW07.5]type casting will cause potential issues */
 104        sh_css_sp_stage.num_stripes = (uint8_t)
 105                                      sh_css_isp_stage.binary_info.iterator.num_stripes;
 106        sh_css_sp_stage.row_stripes_height = (uint16_t)
 107                                             sh_css_isp_stage.binary_info.iterator.row_stripes_height;
 108        sh_css_sp_stage.row_stripes_overlap_lines = (uint16_t)
 109                sh_css_isp_stage.binary_info.iterator.row_stripes_overlap_lines;
 110        sh_css_sp_stage.top_cropping = (uint16_t)
 111                                       sh_css_isp_stage.binary_info.pipeline.top_cropping;
 112        /* moved to sh_css_sp_init_stage
 113           sh_css_sp_stage.enable.vf_output =
 114           sh_css_isp_stage.binary_info.enable.vf_veceven ||
 115           sh_css_isp_stage.binary_info.num_output_pins > 1;
 116        */
 117        sh_css_sp_stage.enable.sdis = sh_css_isp_stage.binary_info.enable.dis;
 118        sh_css_sp_stage.enable.s3a = sh_css_isp_stage.binary_info.enable.s3a;
 119}
 120
 121void
 122store_sp_stage_data(enum ia_css_pipe_id id, unsigned int pipe_num,
 123                    unsigned int stage)
 124{
 125        unsigned int thread_id;
 126
 127        ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
 128        copy_isp_stage_to_sp_stage();
 129        if (id != IA_CSS_PIPE_ID_COPY)
 130                sh_css_sp_stage.isp_stage_addr =
 131                    sh_css_store_isp_stage_to_ddr(pipe_num, stage);
 132        sh_css_sp_group.pipe[thread_id].sp_stage_addr[stage] =
 133            sh_css_store_sp_stage_to_ddr(pipe_num, stage);
 134
 135        /* Clear for next frame */
 136        sh_css_sp_stage.program_input_circuit = false;
 137}
 138
 139static void
 140store_sp_per_frame_data(const struct ia_css_fw_info *fw)
 141{
 142        unsigned int HIVE_ADDR_sp_per_frame_data = 0;
 143
 144        assert(fw);
 145
 146        switch (fw->type) {
 147        case ia_css_sp_firmware:
 148                HIVE_ADDR_sp_per_frame_data = fw->info.sp.per_frame_data;
 149                break;
 150        case ia_css_acc_firmware:
 151                HIVE_ADDR_sp_per_frame_data = fw->info.acc.per_frame_data;
 152                break;
 153        case ia_css_isp_firmware:
 154                return;
 155        }
 156
 157        sp_dmem_store(SP0_ID,
 158                      (unsigned int)sp_address_of(sp_per_frame_data),
 159                      &per_frame_data,
 160                      sizeof(per_frame_data));
 161}
 162
 163static void
 164sh_css_store_sp_per_frame_data(enum ia_css_pipe_id pipe_id,
 165                               unsigned int pipe_num,
 166                               const struct ia_css_fw_info *sp_fw)
 167{
 168        if (!sp_fw)
 169                sp_fw = &sh_css_sp_fw;
 170
 171        store_sp_stage_data(pipe_id, pipe_num, 0);
 172        store_sp_group_data();
 173        store_sp_per_frame_data(sp_fw);
 174}
 175
 176#if SP_DEBUG != SP_DEBUG_NONE
 177
 178void
 179sh_css_sp_get_debug_state(struct sh_css_sp_debug_state *state)
 180{
 181        const struct ia_css_fw_info *fw = &sh_css_sp_fw;
 182        unsigned int HIVE_ADDR_sp_output = fw->info.sp.output;
 183        unsigned int i;
 184        unsigned int offset = (unsigned int)offsetof(struct sh_css_sp_output,
 185                              debug) / sizeof(int);
 186
 187        assert(state);
 188
 189        (void)HIVE_ADDR_sp_output; /* To get rid of warning in CRUN */
 190        for (i = 0; i < sizeof(*state) / sizeof(int); i++)
 191                ((unsigned *)state)[i] = load_sp_array_uint(sp_output, i + offset);
 192}
 193
 194#endif
 195
 196void
 197sh_css_sp_start_binary_copy(unsigned int pipe_num,
 198                            struct ia_css_frame *out_frame,
 199                            unsigned int two_ppc)
 200{
 201        enum ia_css_pipe_id pipe_id;
 202        unsigned int thread_id;
 203        struct sh_css_sp_pipeline *pipe;
 204        u8 stage_num = 0;
 205
 206        assert(out_frame);
 207        pipe_id = IA_CSS_PIPE_ID_CAPTURE;
 208        ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
 209        pipe = &sh_css_sp_group.pipe[thread_id];
 210
 211        pipe->copy.bin.bytes_available = out_frame->data_bytes;
 212        pipe->num_stages = 1;
 213        pipe->pipe_id = pipe_id;
 214        pipe->pipe_num = pipe_num;
 215        pipe->thread_id = thread_id;
 216        pipe->pipe_config = 0x0; /* No parameters */
 217        pipe->pipe_qos_config = QOS_INVALID;
 218
 219        if (pipe->inout_port_config == 0) {
 220                SH_CSS_PIPE_PORT_CONFIG_SET(pipe->inout_port_config,
 221                                            (uint8_t)SH_CSS_PORT_INPUT,
 222                                            (uint8_t)SH_CSS_HOST_TYPE, 1);
 223                SH_CSS_PIPE_PORT_CONFIG_SET(pipe->inout_port_config,
 224                                            (uint8_t)SH_CSS_PORT_OUTPUT,
 225                                            (uint8_t)SH_CSS_HOST_TYPE, 1);
 226        }
 227        IA_CSS_LOG("pipe_id %d port_config %08x",
 228                   pipe->pipe_id, pipe->inout_port_config);
 229
 230#if !defined(ISP2401)
 231        sh_css_sp_group.config.input_formatter.isp_2ppc = (uint8_t)two_ppc;
 232#else
 233        (void)two_ppc;
 234#endif
 235
 236        sh_css_sp_stage.num = stage_num;
 237        sh_css_sp_stage.stage_type = SH_CSS_SP_STAGE_TYPE;
 238        sh_css_sp_stage.func =
 239            (unsigned int)IA_CSS_PIPELINE_BIN_COPY;
 240
 241        set_output_frame_buffer(out_frame, 0);
 242
 243        /* sp_bin_copy_init on the SP does not deal with dynamica/static yet */
 244        /* For now always update the dynamic data from out frames. */
 245        sh_css_store_sp_per_frame_data(pipe_id, pipe_num, &sh_css_sp_fw);
 246}
 247
 248static void
 249sh_css_sp_start_raw_copy(struct ia_css_frame *out_frame,
 250                         unsigned int pipe_num,
 251                         unsigned int two_ppc,
 252                         unsigned int max_input_width,
 253                         enum sh_css_pipe_config_override pipe_conf_override,
 254                         unsigned int if_config_index)
 255{
 256        enum ia_css_pipe_id pipe_id;
 257        unsigned int thread_id;
 258        u8 stage_num = 0;
 259        struct sh_css_sp_pipeline *pipe;
 260
 261        assert(out_frame);
 262
 263        {
 264                /*
 265                 * Clear sh_css_sp_stage for easy debugging.
 266                 * program_input_circuit must be saved as it is set outside
 267                 * this function.
 268                 */
 269                u8 program_input_circuit;
 270
 271                program_input_circuit = sh_css_sp_stage.program_input_circuit;
 272                memset(&sh_css_sp_stage, 0, sizeof(sh_css_sp_stage));
 273                sh_css_sp_stage.program_input_circuit = program_input_circuit;
 274        }
 275
 276        pipe_id = IA_CSS_PIPE_ID_COPY;
 277        ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
 278        pipe = &sh_css_sp_group.pipe[thread_id];
 279
 280        pipe->copy.raw.height       = out_frame->info.res.height;
 281        pipe->copy.raw.width        = out_frame->info.res.width;
 282        pipe->copy.raw.padded_width  = out_frame->info.padded_width;
 283        pipe->copy.raw.raw_bit_depth = out_frame->info.raw_bit_depth;
 284        pipe->copy.raw.max_input_width = max_input_width;
 285        pipe->num_stages = 1;
 286        pipe->pipe_id = pipe_id;
 287        /* TODO: next indicates from which queues parameters need to be
 288                 sampled, needs checking/improvement */
 289        if (pipe_conf_override == SH_CSS_PIPE_CONFIG_OVRD_NO_OVRD)
 290                pipe->pipe_config =
 291                    (SH_CSS_PIPE_CONFIG_SAMPLE_PARAMS << thread_id);
 292        else
 293                pipe->pipe_config = pipe_conf_override;
 294
 295        pipe->pipe_qos_config = QOS_INVALID;
 296
 297        if (pipe->inout_port_config == 0) {
 298                SH_CSS_PIPE_PORT_CONFIG_SET(pipe->inout_port_config,
 299                                            (uint8_t)SH_CSS_PORT_INPUT,
 300                                            (uint8_t)SH_CSS_HOST_TYPE, 1);
 301                SH_CSS_PIPE_PORT_CONFIG_SET(pipe->inout_port_config,
 302                                            (uint8_t)SH_CSS_PORT_OUTPUT,
 303                                            (uint8_t)SH_CSS_HOST_TYPE, 1);
 304        }
 305        IA_CSS_LOG("pipe_id %d port_config %08x",
 306                   pipe->pipe_id, pipe->inout_port_config);
 307
 308#if !defined(ISP2401)
 309        sh_css_sp_group.config.input_formatter.isp_2ppc = (uint8_t)two_ppc;
 310#else
 311        (void)two_ppc;
 312#endif
 313
 314        sh_css_sp_stage.num = stage_num;
 315        sh_css_sp_stage.xmem_bin_addr = 0x0;
 316        sh_css_sp_stage.stage_type = SH_CSS_SP_STAGE_TYPE;
 317        sh_css_sp_stage.func = (unsigned int)IA_CSS_PIPELINE_RAW_COPY;
 318        sh_css_sp_stage.if_config_index = (uint8_t)if_config_index;
 319        set_output_frame_buffer(out_frame, 0);
 320
 321        ia_css_debug_pipe_graph_dump_sp_raw_copy(out_frame);
 322}
 323
 324static void
 325sh_css_sp_start_isys_copy(struct ia_css_frame *out_frame,
 326                          unsigned int pipe_num, unsigned int max_input_width,
 327                          unsigned int if_config_index)
 328{
 329        enum ia_css_pipe_id pipe_id;
 330        unsigned int thread_id;
 331        u8 stage_num = 0;
 332        struct sh_css_sp_pipeline *pipe;
 333#if defined SH_CSS_ENABLE_METADATA
 334        enum sh_css_queue_id queue_id;
 335#endif
 336
 337        assert(out_frame);
 338
 339        {
 340                /*
 341                 * Clear sh_css_sp_stage for easy debugging.
 342                 * program_input_circuit must be saved as it is set outside
 343                 * this function.
 344                 */
 345                u8 program_input_circuit;
 346
 347                program_input_circuit = sh_css_sp_stage.program_input_circuit;
 348                memset(&sh_css_sp_stage, 0, sizeof(sh_css_sp_stage));
 349                sh_css_sp_stage.program_input_circuit = program_input_circuit;
 350        }
 351
 352        pipe_id = IA_CSS_PIPE_ID_COPY;
 353        ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
 354        pipe = &sh_css_sp_group.pipe[thread_id];
 355
 356        pipe->copy.raw.height           = out_frame->info.res.height;
 357        pipe->copy.raw.width            = out_frame->info.res.width;
 358        pipe->copy.raw.padded_width     = out_frame->info.padded_width;
 359        pipe->copy.raw.raw_bit_depth    = out_frame->info.raw_bit_depth;
 360        pipe->copy.raw.max_input_width  = max_input_width;
 361        pipe->num_stages                = 1;
 362        pipe->pipe_id                   = pipe_id;
 363        pipe->pipe_config               = 0x0;  /* No parameters */
 364        pipe->pipe_qos_config           = QOS_INVALID;
 365
 366        initialize_stage_frames(&sh_css_sp_stage.frames);
 367        sh_css_sp_stage.num = stage_num;
 368        sh_css_sp_stage.xmem_bin_addr = 0x0;
 369        sh_css_sp_stage.stage_type = SH_CSS_SP_STAGE_TYPE;
 370        sh_css_sp_stage.func = (unsigned int)IA_CSS_PIPELINE_ISYS_COPY;
 371        sh_css_sp_stage.if_config_index = (uint8_t)if_config_index;
 372
 373        set_output_frame_buffer(out_frame, 0);
 374
 375#if defined SH_CSS_ENABLE_METADATA
 376        if (pipe->metadata.height > 0) {
 377                ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_METADATA, thread_id,
 378                                               &queue_id);
 379                sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.metadata_buf,
 380                                                    queue_id, mmgr_EXCEPTION,
 381                                                    IA_CSS_BUFFER_TYPE_METADATA);
 382        }
 383#endif
 384
 385        ia_css_debug_pipe_graph_dump_sp_raw_copy(out_frame);
 386}
 387
 388unsigned int
 389sh_css_sp_get_binary_copy_size(void)
 390{
 391        const struct ia_css_fw_info *fw = &sh_css_sp_fw;
 392        unsigned int HIVE_ADDR_sp_output = fw->info.sp.output;
 393        unsigned int offset = (unsigned int)offsetof(struct sh_css_sp_output,
 394                              bin_copy_bytes_copied) / sizeof(int);
 395        (void)HIVE_ADDR_sp_output; /* To get rid of warning in CRUN */
 396        return load_sp_array_uint(sp_output, offset);
 397}
 398
 399unsigned int
 400sh_css_sp_get_sw_interrupt_value(unsigned int irq)
 401{
 402        const struct ia_css_fw_info *fw = &sh_css_sp_fw;
 403        unsigned int HIVE_ADDR_sp_output = fw->info.sp.output;
 404        unsigned int offset = (unsigned int)offsetof(struct sh_css_sp_output,
 405                              sw_interrupt_value)
 406                              / sizeof(int);
 407        (void)HIVE_ADDR_sp_output; /* To get rid of warning in CRUN */
 408        return load_sp_array_uint(sp_output, offset + irq);
 409}
 410
 411static void
 412sh_css_copy_buffer_attr_to_spbuffer(struct ia_css_buffer_sp *dest_buf,
 413                                    const enum sh_css_queue_id queue_id,
 414                                    const ia_css_ptr xmem_addr,
 415                                    const enum ia_css_buffer_type buf_type)
 416{
 417        assert(buf_type < IA_CSS_NUM_BUFFER_TYPE);
 418        if (queue_id > SH_CSS_INVALID_QUEUE_ID) {
 419                /*
 420                 * value >=0 indicates that function init_frame_pointers()
 421                 * should use the dynamic data address
 422                 */
 423                assert(queue_id < SH_CSS_MAX_NUM_QUEUES);
 424
 425                /* Klocwork assumes assert can be disabled;
 426                   Since we can get there with any type, and it does not
 427                   know that frame_in->dynamic_data_index can only be set
 428                   for one of the types in the assert) it has to assume we
 429                   can get here for any type. however this could lead to an
 430                   out of bounds reference when indexing buf_type about 10
 431                   lines below. In order to satisfy KW an additional if
 432                   has been added. This one will always yield true.
 433                 */
 434                if ((queue_id < SH_CSS_MAX_NUM_QUEUES)) {
 435                        dest_buf->buf_src.queue_id = queue_id;
 436                }
 437        } else {
 438                assert(xmem_addr != mmgr_EXCEPTION);
 439                dest_buf->buf_src.xmem_addr = xmem_addr;
 440        }
 441        dest_buf->buf_type = buf_type;
 442}
 443
 444static void
 445sh_css_copy_frame_to_spframe(struct ia_css_frame_sp *sp_frame_out,
 446                             const struct ia_css_frame *frame_in)
 447{
 448        assert(frame_in);
 449
 450        ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
 451                            "sh_css_copy_frame_to_spframe():\n");
 452
 453        sh_css_copy_buffer_attr_to_spbuffer(&sp_frame_out->buf_attr,
 454                                            frame_in->dynamic_queue_id,
 455                                            frame_in->data,
 456                                            frame_in->buf_type);
 457
 458        ia_css_frame_info_to_frame_sp_info(&sp_frame_out->info, &frame_in->info);
 459
 460        switch (frame_in->info.format) {
 461        case IA_CSS_FRAME_FORMAT_RAW_PACKED:
 462        case IA_CSS_FRAME_FORMAT_RAW:
 463                sp_frame_out->planes.raw.offset = frame_in->planes.raw.offset;
 464                break;
 465        case IA_CSS_FRAME_FORMAT_RGB565:
 466        case IA_CSS_FRAME_FORMAT_RGBA888:
 467                sp_frame_out->planes.rgb.offset = frame_in->planes.rgb.offset;
 468                break;
 469        case IA_CSS_FRAME_FORMAT_PLANAR_RGB888:
 470                sp_frame_out->planes.planar_rgb.r.offset =
 471                    frame_in->planes.planar_rgb.r.offset;
 472                sp_frame_out->planes.planar_rgb.g.offset =
 473                    frame_in->planes.planar_rgb.g.offset;
 474                sp_frame_out->planes.planar_rgb.b.offset =
 475                    frame_in->planes.planar_rgb.b.offset;
 476                break;
 477        case IA_CSS_FRAME_FORMAT_YUYV:
 478        case IA_CSS_FRAME_FORMAT_UYVY:
 479        case IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8:
 480        case IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8:
 481        case IA_CSS_FRAME_FORMAT_YUV_LINE:
 482                sp_frame_out->planes.yuyv.offset = frame_in->planes.yuyv.offset;
 483                break;
 484        case IA_CSS_FRAME_FORMAT_NV11:
 485        case IA_CSS_FRAME_FORMAT_NV12:
 486        case IA_CSS_FRAME_FORMAT_NV12_16:
 487        case IA_CSS_FRAME_FORMAT_NV12_TILEY:
 488        case IA_CSS_FRAME_FORMAT_NV21:
 489        case IA_CSS_FRAME_FORMAT_NV16:
 490        case IA_CSS_FRAME_FORMAT_NV61:
 491                sp_frame_out->planes.nv.y.offset =
 492                    frame_in->planes.nv.y.offset;
 493                sp_frame_out->planes.nv.uv.offset =
 494                    frame_in->planes.nv.uv.offset;
 495                break;
 496        case IA_CSS_FRAME_FORMAT_YUV420:
 497        case IA_CSS_FRAME_FORMAT_YUV422:
 498        case IA_CSS_FRAME_FORMAT_YUV444:
 499        case IA_CSS_FRAME_FORMAT_YUV420_16:
 500        case IA_CSS_FRAME_FORMAT_YUV422_16:
 501        case IA_CSS_FRAME_FORMAT_YV12:
 502        case IA_CSS_FRAME_FORMAT_YV16:
 503                sp_frame_out->planes.yuv.y.offset =
 504                    frame_in->planes.yuv.y.offset;
 505                sp_frame_out->planes.yuv.u.offset =
 506                    frame_in->planes.yuv.u.offset;
 507                sp_frame_out->planes.yuv.v.offset =
 508                    frame_in->planes.yuv.v.offset;
 509                break;
 510        case IA_CSS_FRAME_FORMAT_QPLANE6:
 511                sp_frame_out->planes.plane6.r.offset =
 512                    frame_in->planes.plane6.r.offset;
 513                sp_frame_out->planes.plane6.r_at_b.offset =
 514                    frame_in->planes.plane6.r_at_b.offset;
 515                sp_frame_out->planes.plane6.gr.offset =
 516                    frame_in->planes.plane6.gr.offset;
 517                sp_frame_out->planes.plane6.gb.offset =
 518                    frame_in->planes.plane6.gb.offset;
 519                sp_frame_out->planes.plane6.b.offset =
 520                    frame_in->planes.plane6.b.offset;
 521                sp_frame_out->planes.plane6.b_at_r.offset =
 522                    frame_in->planes.plane6.b_at_r.offset;
 523                break;
 524        case IA_CSS_FRAME_FORMAT_BINARY_8:
 525                sp_frame_out->planes.binary.data.offset =
 526                    frame_in->planes.binary.data.offset;
 527                break;
 528        default:
 529                /* This should not happen, but in case it does,
 530                 * nullify the planes
 531                 */
 532                memset(&sp_frame_out->planes, 0, sizeof(sp_frame_out->planes));
 533                break;
 534        }
 535}
 536
 537static int
 538set_input_frame_buffer(const struct ia_css_frame *frame) {
 539        if (!frame)
 540                return -EINVAL;
 541
 542        switch (frame->info.format)
 543        {
 544        case IA_CSS_FRAME_FORMAT_QPLANE6:
 545        case IA_CSS_FRAME_FORMAT_YUV420_16:
 546        case IA_CSS_FRAME_FORMAT_RAW_PACKED:
 547        case IA_CSS_FRAME_FORMAT_RAW:
 548        case IA_CSS_FRAME_FORMAT_YUV420:
 549        case IA_CSS_FRAME_FORMAT_YUYV:
 550        case IA_CSS_FRAME_FORMAT_YUV_LINE:
 551        case IA_CSS_FRAME_FORMAT_NV12:
 552        case IA_CSS_FRAME_FORMAT_NV12_16:
 553        case IA_CSS_FRAME_FORMAT_NV12_TILEY:
 554        case IA_CSS_FRAME_FORMAT_NV21:
 555        case IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8:
 556        case IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8:
 557        case IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_10:
 558                break;
 559        default:
 560                return -EINVAL;
 561        }
 562        sh_css_copy_frame_to_spframe(&sh_css_sp_stage.frames.in, frame);
 563
 564        return 0;
 565}
 566
 567static int
 568set_output_frame_buffer(const struct ia_css_frame *frame,
 569                        unsigned int idx) {
 570        if (!frame)
 571                return -EINVAL;
 572
 573        switch (frame->info.format)
 574        {
 575        case IA_CSS_FRAME_FORMAT_YUV420:
 576        case IA_CSS_FRAME_FORMAT_YUV422:
 577        case IA_CSS_FRAME_FORMAT_YUV444:
 578        case IA_CSS_FRAME_FORMAT_YV12:
 579        case IA_CSS_FRAME_FORMAT_YV16:
 580        case IA_CSS_FRAME_FORMAT_YUV420_16:
 581        case IA_CSS_FRAME_FORMAT_YUV422_16:
 582        case IA_CSS_FRAME_FORMAT_NV11:
 583        case IA_CSS_FRAME_FORMAT_NV12:
 584        case IA_CSS_FRAME_FORMAT_NV12_16:
 585        case IA_CSS_FRAME_FORMAT_NV12_TILEY:
 586        case IA_CSS_FRAME_FORMAT_NV16:
 587        case IA_CSS_FRAME_FORMAT_NV21:
 588        case IA_CSS_FRAME_FORMAT_NV61:
 589        case IA_CSS_FRAME_FORMAT_YUYV:
 590        case IA_CSS_FRAME_FORMAT_UYVY:
 591        case IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8:
 592        case IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8:
 593        case IA_CSS_FRAME_FORMAT_YUV_LINE:
 594        case IA_CSS_FRAME_FORMAT_RGB565:
 595        case IA_CSS_FRAME_FORMAT_RGBA888:
 596        case IA_CSS_FRAME_FORMAT_PLANAR_RGB888:
 597        case IA_CSS_FRAME_FORMAT_RAW:
 598        case IA_CSS_FRAME_FORMAT_RAW_PACKED:
 599        case IA_CSS_FRAME_FORMAT_QPLANE6:
 600        case IA_CSS_FRAME_FORMAT_BINARY_8:
 601                break;
 602        default:
 603                return -EINVAL;
 604        }
 605        sh_css_copy_frame_to_spframe(&sh_css_sp_stage.frames.out[idx], frame);
 606        return 0;
 607}
 608
 609static int
 610set_view_finder_buffer(const struct ia_css_frame *frame) {
 611        if (!frame)
 612                return -EINVAL;
 613
 614        switch (frame->info.format)
 615        {
 616        /* the dual output pin */
 617        case IA_CSS_FRAME_FORMAT_NV12:
 618        case IA_CSS_FRAME_FORMAT_NV12_16:
 619        case IA_CSS_FRAME_FORMAT_NV21:
 620        case IA_CSS_FRAME_FORMAT_YUYV:
 621        case IA_CSS_FRAME_FORMAT_UYVY:
 622        case IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8:
 623        case IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8:
 624        case IA_CSS_FRAME_FORMAT_YUV420:
 625        case IA_CSS_FRAME_FORMAT_YV12:
 626        case IA_CSS_FRAME_FORMAT_NV12_TILEY:
 627
 628        /* for vf_veceven */
 629        case IA_CSS_FRAME_FORMAT_YUV_LINE:
 630                break;
 631        default:
 632                return -EINVAL;
 633        }
 634
 635        sh_css_copy_frame_to_spframe(&sh_css_sp_stage.frames.out_vf, frame);
 636        return 0;
 637}
 638
 639#if !defined(ISP2401)
 640void sh_css_sp_set_if_configs(
 641    const input_formatter_cfg_t *config_a,
 642    const input_formatter_cfg_t *config_b,
 643    const uint8_t               if_config_index
 644)
 645{
 646        assert(if_config_index < SH_CSS_MAX_IF_CONFIGS);
 647        assert(config_a);
 648
 649        sh_css_sp_group.config.input_formatter.set[if_config_index].config_a =
 650            *config_a;
 651        sh_css_sp_group.config.input_formatter.a_changed = true;
 652
 653        if (config_b) {
 654                sh_css_sp_group.config.input_formatter.set[if_config_index].config_b =
 655                    *config_b;
 656                sh_css_sp_group.config.input_formatter.b_changed = true;
 657        }
 658
 659        return;
 660}
 661#endif
 662
 663#if !defined(ISP2401)
 664void
 665sh_css_sp_program_input_circuit(int fmt_type,
 666                                int ch_id,
 667                                enum ia_css_input_mode input_mode)
 668{
 669        sh_css_sp_group.config.input_circuit.no_side_band = false;
 670        sh_css_sp_group.config.input_circuit.fmt_type     = fmt_type;
 671        sh_css_sp_group.config.input_circuit.ch_id            = ch_id;
 672        sh_css_sp_group.config.input_circuit.input_mode   = input_mode;
 673        /*
 674         * The SP group is only loaded at SP boot time and is read once
 675         * change flags as "input_circuit_cfg_changed" must be reset on the SP
 676         */
 677        sh_css_sp_group.config.input_circuit_cfg_changed = true;
 678        sh_css_sp_stage.program_input_circuit = true;
 679}
 680#endif
 681
 682#if !defined(ISP2401)
 683void
 684sh_css_sp_configure_sync_gen(int width, int height,
 685                             int hblank_cycles,
 686                             int vblank_cycles)
 687{
 688        sh_css_sp_group.config.sync_gen.width          = width;
 689        sh_css_sp_group.config.sync_gen.height         = height;
 690        sh_css_sp_group.config.sync_gen.hblank_cycles = hblank_cycles;
 691        sh_css_sp_group.config.sync_gen.vblank_cycles = vblank_cycles;
 692}
 693
 694void
 695sh_css_sp_configure_tpg(int x_mask,
 696                        int y_mask,
 697                        int x_delta,
 698                        int y_delta,
 699                        int xy_mask)
 700{
 701        sh_css_sp_group.config.tpg.x_mask  = x_mask;
 702        sh_css_sp_group.config.tpg.y_mask  = y_mask;
 703        sh_css_sp_group.config.tpg.x_delta = x_delta;
 704        sh_css_sp_group.config.tpg.y_delta = y_delta;
 705        sh_css_sp_group.config.tpg.xy_mask = xy_mask;
 706}
 707
 708void
 709sh_css_sp_configure_prbs(int seed)
 710{
 711        sh_css_sp_group.config.prbs.seed = seed;
 712}
 713#endif
 714
 715void
 716sh_css_sp_configure_enable_raw_pool_locking(bool lock_all)
 717{
 718        sh_css_sp_group.config.enable_raw_pool_locking = true;
 719        sh_css_sp_group.config.lock_all = lock_all;
 720}
 721
 722void
 723sh_css_sp_enable_isys_event_queue(bool enable)
 724{
 725        sh_css_sp_group.config.enable_isys_event_queue = enable;
 726}
 727
 728void
 729sh_css_sp_set_disable_continuous_viewfinder(bool flag)
 730{
 731        sh_css_sp_group.config.disable_cont_vf = flag;
 732}
 733
 734static int
 735sh_css_sp_write_frame_pointers(const struct sh_css_binary_args *args) {
 736        int err = 0;
 737        int i;
 738
 739        assert(args);
 740
 741        if (args->in_frame)
 742                err = set_input_frame_buffer(args->in_frame);
 743        if (!err && args->out_vf_frame)
 744                err = set_view_finder_buffer(args->out_vf_frame);
 745        for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
 746        {
 747                if (!err && args->out_frame[i])
 748                        err = set_output_frame_buffer(args->out_frame[i], i);
 749        }
 750
 751        /* we don't pass this error back to the upper layer, so we add a assert here
 752           because we actually hit the error here but it still works by accident... */
 753        if (err) assert(false);
 754        return err;
 755}
 756
 757static void
 758sh_css_sp_init_group(bool two_ppc,
 759                     enum atomisp_input_format input_format,
 760                     bool no_isp_sync,
 761                     uint8_t if_config_index)
 762{
 763#if !defined(ISP2401)
 764        sh_css_sp_group.config.input_formatter.isp_2ppc = two_ppc;
 765#else
 766        (void)two_ppc;
 767#endif
 768
 769        sh_css_sp_group.config.no_isp_sync = (uint8_t)no_isp_sync;
 770        /* decide whether the frame is processed online or offline */
 771        if (if_config_index == SH_CSS_IF_CONFIG_NOT_NEEDED) return;
 772#if !defined(ISP2401)
 773        assert(if_config_index < SH_CSS_MAX_IF_CONFIGS);
 774        sh_css_sp_group.config.input_formatter.set[if_config_index].stream_format =
 775            input_format;
 776#else
 777        (void)input_format;
 778#endif
 779}
 780
 781void
 782sh_css_stage_write_binary_info(struct ia_css_binary_info *info)
 783{
 784        assert(info);
 785        sh_css_isp_stage.binary_info = *info;
 786}
 787
 788static int
 789copy_isp_mem_if_to_ddr(struct ia_css_binary *binary) {
 790        int err;
 791
 792        err = ia_css_isp_param_copy_isp_mem_if_to_ddr(
 793            &binary->css_params,
 794            &binary->mem_params,
 795            IA_CSS_PARAM_CLASS_CONFIG);
 796        if (err)
 797                return err;
 798        err = ia_css_isp_param_copy_isp_mem_if_to_ddr(
 799            &binary->css_params,
 800            &binary->mem_params,
 801            IA_CSS_PARAM_CLASS_STATE);
 802        if (err)
 803                return err;
 804        return 0;
 805}
 806
 807static bool
 808is_sp_stage(struct ia_css_pipeline_stage *stage)
 809{
 810        assert(stage);
 811        return stage->sp_func != IA_CSS_PIPELINE_NO_FUNC;
 812}
 813
 814static int
 815configure_isp_from_args(
 816    const struct sh_css_sp_pipeline *pipeline,
 817    const struct ia_css_binary      *binary,
 818    const struct sh_css_binary_args *args,
 819    bool two_ppc,
 820    bool deinterleaved) {
 821        ia_css_fpn_configure(binary,  &binary->in_frame_info);
 822        ia_css_crop_configure(binary, &args->delay_frames[0]->info);
 823        ia_css_qplane_configure(pipeline, binary, &binary->in_frame_info);
 824        ia_css_output0_configure(binary, &args->out_frame[0]->info);
 825        ia_css_output1_configure(binary, &args->out_vf_frame->info);
 826        ia_css_copy_output_configure(binary, args->copy_output);
 827        ia_css_output0_configure(binary, &args->out_frame[0]->info);
 828#ifdef ISP2401
 829        ia_css_sc_configure(binary, pipeline->shading.internal_frame_origin_x_bqs_on_sctbl,
 830                            pipeline->shading.internal_frame_origin_y_bqs_on_sctbl);
 831#endif
 832        ia_css_iterator_configure(binary, &args->in_frame->info);
 833        ia_css_dvs_configure(binary, &args->out_frame[0]->info);
 834        ia_css_output_configure(binary, &args->out_frame[0]->info);
 835        ia_css_raw_configure(pipeline, binary, &args->in_frame->info, &binary->in_frame_info, two_ppc, deinterleaved);
 836
 837        /*
 838         * FIXME: args->delay_frames can be NULL here
 839         *
 840         * Somehow, the driver at the Intel Atom Yocto tree doesn't seem to
 841         * suffer from the same issue.
 842         *
 843         * Anyway, the function below should now handle a NULL delay_frames
 844         * without crashing, but the pipeline should likely be built without
 845         * adding it at the first place (or there are a hidden bug somewhere)
 846         */
 847        ia_css_ref_configure(binary, args->delay_frames, pipeline->dvs_frame_delay);
 848        ia_css_tnr_configure(binary, args->tnr_frames);
 849        ia_css_bayer_io_config(binary, args);
 850        return 0;
 851}
 852
 853static void
 854initialize_isp_states(const struct ia_css_binary *binary)
 855{
 856        unsigned int i;
 857
 858        if (!binary->info->mem_offsets.offsets.state)
 859                return;
 860        for (i = 0; i < IA_CSS_NUM_STATE_IDS; i++) {
 861                ia_css_kernel_init_state[i](binary);
 862        }
 863}
 864
 865static void
 866initialize_frame_buffer_attribute(struct ia_css_buffer_sp *buf_attr)
 867{
 868        buf_attr->buf_src.queue_id = SH_CSS_INVALID_QUEUE_ID;
 869        buf_attr->buf_type = IA_CSS_BUFFER_TYPE_INVALID;
 870}
 871
 872static void
 873initialize_stage_frames(struct ia_css_frames_sp *frames)
 874{
 875        unsigned int i;
 876
 877        initialize_frame_buffer_attribute(&frames->in.buf_attr);
 878        for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) {
 879                initialize_frame_buffer_attribute(&frames->out[i].buf_attr);
 880        }
 881        initialize_frame_buffer_attribute(&frames->out_vf.buf_attr);
 882        initialize_frame_buffer_attribute(&frames->s3a_buf);
 883        initialize_frame_buffer_attribute(&frames->dvs_buf);
 884#if defined SH_CSS_ENABLE_METADATA
 885        initialize_frame_buffer_attribute(&frames->metadata_buf);
 886#endif
 887}
 888
 889static int
 890sh_css_sp_init_stage(struct ia_css_binary *binary,
 891                     const char *binary_name,
 892                     const struct ia_css_blob_info *blob_info,
 893                     const struct sh_css_binary_args *args,
 894                     unsigned int pipe_num,
 895                     unsigned int stage,
 896                     bool xnr,
 897                     const struct ia_css_isp_param_css_segments *isp_mem_if,
 898                     unsigned int if_config_index,
 899                     bool two_ppc) {
 900        const struct ia_css_binary_xinfo *xinfo;
 901        const struct ia_css_binary_info  *info;
 902        int err = 0;
 903        int i;
 904        struct ia_css_pipe *pipe = NULL;
 905        unsigned int thread_id;
 906        enum sh_css_queue_id queue_id;
 907        bool continuous = sh_css_continuous_is_enabled((uint8_t)pipe_num);
 908
 909        assert(binary);
 910        assert(blob_info);
 911        assert(args);
 912        assert(isp_mem_if);
 913
 914        xinfo = binary->info;
 915        info  = &xinfo->sp;
 916        {
 917                /*
 918                 * Clear sh_css_sp_stage for easy debugging.
 919                 * program_input_circuit must be saved as it is set outside
 920                 * this function.
 921                 */
 922                u8 program_input_circuit;
 923
 924                program_input_circuit = sh_css_sp_stage.program_input_circuit;
 925                memset(&sh_css_sp_stage, 0, sizeof(sh_css_sp_stage));
 926                sh_css_sp_stage.program_input_circuit = (uint8_t)program_input_circuit;
 927        }
 928
 929        ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
 930
 931        if (!info)
 932        {
 933                sh_css_sp_group.pipe[thread_id].sp_stage_addr[stage] = mmgr_NULL;
 934                return 0;
 935        }
 936
 937#if defined(ISP2401)
 938        (void)continuous;
 939        sh_css_sp_stage.deinterleaved = 0;
 940#else
 941        sh_css_sp_stage.deinterleaved = ((stage == 0) && continuous);
 942#endif
 943
 944        initialize_stage_frames(&sh_css_sp_stage.frames);
 945        /*
 946         * TODO: Make the Host dynamically determine
 947         * the stage type.
 948         */
 949        sh_css_sp_stage.stage_type = SH_CSS_ISP_STAGE_TYPE;
 950        sh_css_sp_stage.num             = (uint8_t)stage;
 951        sh_css_sp_stage.isp_online      = (uint8_t)binary->online;
 952        sh_css_sp_stage.isp_copy_vf     = (uint8_t)args->copy_vf;
 953        sh_css_sp_stage.isp_copy_output = (uint8_t)args->copy_output;
 954        sh_css_sp_stage.enable.vf_output = (args->out_vf_frame != NULL);
 955
 956        /* Copy the frame infos first, to be overwritten by the frames,
 957           if these are present.
 958        */
 959        sh_css_sp_stage.frames.effective_in_res.width = binary->effective_in_frame_res.width;
 960        sh_css_sp_stage.frames.effective_in_res.height = binary->effective_in_frame_res.height;
 961
 962        ia_css_frame_info_to_frame_sp_info(&sh_css_sp_stage.frames.in.info,
 963                                           &binary->in_frame_info);
 964        for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
 965        {
 966                ia_css_frame_info_to_frame_sp_info(&sh_css_sp_stage.frames.out[i].info,
 967                                                   &binary->out_frame_info[i]);
 968        }
 969        ia_css_frame_info_to_frame_sp_info(&sh_css_sp_stage.frames.internal_frame_info,
 970                                           &binary->internal_frame_info);
 971        sh_css_sp_stage.dvs_envelope.width    = binary->dvs_envelope.width;
 972        sh_css_sp_stage.dvs_envelope.height   = binary->dvs_envelope.height;
 973        sh_css_sp_stage.isp_pipe_version      = (uint8_t)info->pipeline.isp_pipe_version;
 974        sh_css_sp_stage.isp_deci_log_factor   = (uint8_t)binary->deci_factor_log2;
 975        sh_css_sp_stage.isp_vf_downscale_bits = (uint8_t)binary->vf_downscale_log2;
 976
 977        sh_css_sp_stage.if_config_index = (uint8_t)if_config_index;
 978
 979        sh_css_sp_stage.sp_enable_xnr = (uint8_t)xnr;
 980        sh_css_sp_stage.xmem_bin_addr = xinfo->xmem_addr;
 981        sh_css_sp_stage.xmem_map_addr = sh_css_params_ddr_address_map();
 982        sh_css_isp_stage.blob_info = *blob_info;
 983        sh_css_stage_write_binary_info((struct ia_css_binary_info *)info);
 984
 985        /* Make sure binary name is smaller than allowed string size */
 986        assert(strlen(binary_name) < SH_CSS_MAX_BINARY_NAME - 1);
 987        strscpy(sh_css_isp_stage.binary_name, binary_name, SH_CSS_MAX_BINARY_NAME);
 988        sh_css_isp_stage.mem_initializers = *isp_mem_if;
 989
 990        /*
 991         * Even when a stage does not need uds and does not params,
 992         * ia_css_uds_sp_scale_params() seems to be called (needs
 993         * further investigation). This function can not deal with
 994         * dx, dy = {0, 0}
 995         */
 996
 997        err = sh_css_sp_write_frame_pointers(args);
 998        /* TODO: move it to a better place */
 999        if (binary->info->sp.enable.s3a)
1000        {
1001                ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_3A_STATISTICS, thread_id,
1002                                               &queue_id);
1003                sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.s3a_buf, queue_id,
1004                                                    mmgr_EXCEPTION,
1005                                                    IA_CSS_BUFFER_TYPE_3A_STATISTICS);
1006        }
1007        if (binary->info->sp.enable.dis)
1008        {
1009                ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_DIS_STATISTICS, thread_id,
1010                                               &queue_id);
1011                sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.dvs_buf, queue_id,
1012                                                    mmgr_EXCEPTION,
1013                                                    IA_CSS_BUFFER_TYPE_DIS_STATISTICS);
1014        }
1015#if defined SH_CSS_ENABLE_METADATA
1016        ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_METADATA, thread_id, &queue_id);
1017        sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.metadata_buf, queue_id, mmgr_EXCEPTION, IA_CSS_BUFFER_TYPE_METADATA);
1018#endif
1019        if (err)
1020                return err;
1021
1022#ifdef ISP2401
1023        if (stage == 0) {
1024                pipe = find_pipe_by_num(sh_css_sp_group.pipe[thread_id].pipe_num);
1025                if (!pipe)
1026                        return -EINVAL;
1027
1028                if (args->in_frame)
1029                        ia_css_get_crop_offsets(pipe, &args->in_frame->info);
1030                else
1031                        ia_css_get_crop_offsets(pipe, &binary->in_frame_info);
1032        }
1033#else
1034        (void)pipe; /*avoid build warning*/
1035#endif
1036
1037        err = configure_isp_from_args(&sh_css_sp_group.pipe[thread_id],
1038                                      binary, args, two_ppc, sh_css_sp_stage.deinterleaved);
1039        if (err)
1040                return err;
1041
1042        initialize_isp_states(binary);
1043
1044        /* we do this only for preview pipe because in fill_binary_info function
1045         * we assign vf_out res to out res, but for ISP internal processing, we need
1046         * the original out res. for video pipe, it has two output pins --- out and
1047         * vf_out, so it can keep these two resolutions already. */
1048        if (binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_PREVIEW &&
1049            (binary->vf_downscale_log2 > 0))
1050        {
1051                /* TODO: Remove this after preview output decimation is fixed
1052                 * by configuring out&vf info fiels properly */
1053                sh_css_sp_stage.frames.out[0].info.padded_width
1054                <<= binary->vf_downscale_log2;
1055                sh_css_sp_stage.frames.out[0].info.res.width
1056                <<= binary->vf_downscale_log2;
1057                sh_css_sp_stage.frames.out[0].info.res.height
1058                <<= binary->vf_downscale_log2;
1059        }
1060        err = copy_isp_mem_if_to_ddr(binary);
1061        if (err)
1062                return err;
1063
1064        return 0;
1065}
1066
1067static int
1068sp_init_stage(struct ia_css_pipeline_stage *stage,
1069              unsigned int pipe_num,
1070              bool xnr,
1071              unsigned int if_config_index,
1072              bool two_ppc) {
1073        struct ia_css_binary *binary;
1074        const struct ia_css_fw_info *firmware;
1075        const struct sh_css_binary_args *args;
1076        unsigned int stage_num;
1077        /*
1078         * Initialiser required because of the "else" path below.
1079         * Is this a valid path ?
1080         */
1081        const char *binary_name = "";
1082        const struct ia_css_binary_xinfo *info = NULL;
1083        /* note: the var below is made static as it is quite large;
1084           if it is not static it ends up on the stack which could
1085           cause issues for drivers
1086        */
1087        static struct ia_css_binary tmp_binary;
1088        const struct ia_css_blob_info *blob_info = NULL;
1089        struct ia_css_isp_param_css_segments isp_mem_if;
1090        /* LA: should be ia_css_data, should not contain host pointer.
1091           However, CSS/DDR pointer is not available yet.
1092           Hack is to store it in params->ddr_ptrs and then copy it late in the SP just before vmem init.
1093           TODO: Call this after CSS/DDR allocation and store that pointer.
1094           Best is to allocate it at stage creation time together with host pointer.
1095           Remove vmem from params.
1096        */
1097        struct ia_css_isp_param_css_segments *mem_if = &isp_mem_if;
1098
1099        int err = 0;
1100
1101        assert(stage);
1102
1103        binary = stage->binary;
1104        firmware = stage->firmware;
1105        args = &stage->args;
1106        stage_num = stage->stage_num;
1107
1108        if (binary)
1109        {
1110                info = binary->info;
1111                binary_name = (const char *)(info->blob->name);
1112                blob_info = &info->blob->header.blob;
1113                ia_css_init_memory_interface(mem_if, &binary->mem_params, &binary->css_params);
1114        } else if (firmware)
1115        {
1116                const struct ia_css_frame_info *out_infos[IA_CSS_BINARY_MAX_OUTPUT_PORTS] = {NULL};
1117
1118                if (args->out_frame[0])
1119                        out_infos[0] = &args->out_frame[0]->info;
1120                info = &firmware->info.isp;
1121                ia_css_binary_fill_info(info, false, false,
1122                                        ATOMISP_INPUT_FORMAT_RAW_10,
1123                                        args->in_frame  ? &args->in_frame->info  : NULL,
1124                                        NULL,
1125                                        out_infos,
1126                                        args->out_vf_frame ? &args->out_vf_frame->info
1127                                        : NULL,
1128                                        &tmp_binary,
1129                                        NULL,
1130                                        -1, true);
1131                binary = &tmp_binary;
1132                binary->info = info;
1133                binary_name = IA_CSS_EXT_ISP_PROG_NAME(firmware);
1134                blob_info = &firmware->blob;
1135                mem_if = (struct ia_css_isp_param_css_segments *)&firmware->mem_initializers;
1136        } else
1137        {
1138                /* SP stage */
1139                assert(stage->sp_func != IA_CSS_PIPELINE_NO_FUNC);
1140                /* binary and blob_info are now NULL.
1141                   These will be passed to sh_css_sp_init_stage
1142                   and dereferenced there, so passing a NULL
1143                   pointer is no good. return an error */
1144                return -EINVAL;
1145        }
1146
1147        err = sh_css_sp_init_stage(binary,
1148                                   (const char *)binary_name,
1149                                   blob_info,
1150                                   args,
1151                                   pipe_num,
1152                                   stage_num,
1153                                   xnr,
1154                                   mem_if,
1155                                   if_config_index,
1156                                   two_ppc);
1157        return err;
1158}
1159
1160static void
1161sp_init_sp_stage(struct ia_css_pipeline_stage *stage,
1162                 unsigned int pipe_num,
1163                 bool two_ppc,
1164                 enum sh_css_pipe_config_override copy_ovrd,
1165                 unsigned int if_config_index)
1166{
1167        const struct sh_css_binary_args *args = &stage->args;
1168
1169        assert(stage);
1170        switch (stage->sp_func) {
1171        case IA_CSS_PIPELINE_RAW_COPY:
1172                sh_css_sp_start_raw_copy(args->out_frame[0],
1173                                         pipe_num, two_ppc,
1174                                         stage->max_input_width,
1175                                         copy_ovrd, if_config_index);
1176                break;
1177        case IA_CSS_PIPELINE_BIN_COPY:
1178                assert(false); /* TBI */
1179                break;
1180        case IA_CSS_PIPELINE_ISYS_COPY:
1181                sh_css_sp_start_isys_copy(args->out_frame[0],
1182                                          pipe_num, stage->max_input_width, if_config_index);
1183                break;
1184        case IA_CSS_PIPELINE_NO_FUNC:
1185                assert(false);
1186                break;
1187        }
1188}
1189
1190void
1191sh_css_sp_init_pipeline(struct ia_css_pipeline *me,
1192                        enum ia_css_pipe_id id,
1193                        u8 pipe_num,
1194                        bool xnr,
1195                        bool two_ppc,
1196                        bool continuous,
1197                        bool offline,
1198                        unsigned int required_bds_factor,
1199                        enum sh_css_pipe_config_override copy_ovrd,
1200                        enum ia_css_input_mode input_mode,
1201                        const struct ia_css_metadata_config *md_config,
1202                        const struct ia_css_metadata_info *md_info,
1203                        const enum mipi_port_id port_id,
1204                        const struct ia_css_coordinate
1205                        *internal_frame_origin_bqs_on_sctbl, /* Origin of internal frame
1206                                                        positioned on shading table at shading correction in ISP. */
1207                        const struct ia_css_isp_parameters *params
1208                       ) {
1209        /* Get first stage */
1210        struct ia_css_pipeline_stage *stage        = NULL;
1211        struct ia_css_binary         *first_binary = NULL;
1212        struct ia_css_pipe *pipe = NULL;
1213        unsigned int num;
1214
1215        enum ia_css_pipe_id pipe_id = id;
1216        unsigned int thread_id;
1217        u8 if_config_index, tmp_if_config_index;
1218
1219        assert(me);
1220
1221        assert(me->stages);
1222
1223        first_binary = me->stages->binary;
1224
1225        if (input_mode == IA_CSS_INPUT_MODE_SENSOR ||
1226            input_mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
1227        {
1228                assert(port_id < N_MIPI_PORT_ID);
1229                if (port_id >= N_MIPI_PORT_ID) /* should not happen but KW does not know */
1230                        return; /* we should be able to return an error */
1231                if_config_index  = (uint8_t)(port_id - MIPI_PORT0_ID);
1232        } else if (input_mode == IA_CSS_INPUT_MODE_MEMORY)
1233        {
1234                if_config_index = SH_CSS_IF_CONFIG_NOT_NEEDED;
1235        } else
1236        {
1237                if_config_index = 0x0;
1238        }
1239
1240        ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
1241        memset(&sh_css_sp_group.pipe[thread_id], 0, sizeof(struct sh_css_sp_pipeline));
1242
1243        /* Count stages */
1244        for (stage = me->stages, num = 0; stage; stage = stage->next, num++)
1245        {
1246                stage->stage_num = num;
1247                ia_css_debug_pipe_graph_dump_stage(stage, id);
1248        }
1249        me->num_stages = num;
1250
1251        if (first_binary)
1252        {
1253                /* Init pipeline data */
1254                sh_css_sp_init_group(two_ppc, first_binary->input_format,
1255                                     offline, if_config_index);
1256        } /* if (first_binary != NULL) */
1257
1258        /* Signal the host immediately after start for SP_ISYS_COPY only */
1259        if ((me->num_stages == 1) && me->stages &&
1260            (me->stages->sp_func == IA_CSS_PIPELINE_ISYS_COPY))
1261                sh_css_sp_group.config.no_isp_sync = true;
1262
1263        /* Init stage data */
1264        sh_css_init_host2sp_frame_data();
1265
1266        sh_css_sp_group.pipe[thread_id].num_stages = 0;
1267        sh_css_sp_group.pipe[thread_id].pipe_id = pipe_id;
1268        sh_css_sp_group.pipe[thread_id].thread_id = thread_id;
1269        sh_css_sp_group.pipe[thread_id].pipe_num = pipe_num;
1270        sh_css_sp_group.pipe[thread_id].num_execs = me->num_execs;
1271        sh_css_sp_group.pipe[thread_id].pipe_qos_config = me->pipe_qos_config;
1272        sh_css_sp_group.pipe[thread_id].required_bds_factor = required_bds_factor;
1273        sh_css_sp_group.pipe[thread_id].input_system_mode
1274        = (uint32_t)input_mode;
1275        sh_css_sp_group.pipe[thread_id].port_id = port_id;
1276        sh_css_sp_group.pipe[thread_id].dvs_frame_delay = (uint32_t)me->dvs_frame_delay;
1277
1278        /* TODO: next indicates from which queues parameters need to be
1279                 sampled, needs checking/improvement */
1280        if (ia_css_pipeline_uses_params(me))
1281        {
1282                sh_css_sp_group.pipe[thread_id].pipe_config =
1283                SH_CSS_PIPE_CONFIG_SAMPLE_PARAMS << thread_id;
1284        }
1285
1286        /* For continuous use-cases, SP copy is responsible for sampling the
1287         * parameters */
1288        if (continuous)
1289                sh_css_sp_group.pipe[thread_id].pipe_config = 0;
1290
1291        sh_css_sp_group.pipe[thread_id].inout_port_config = me->inout_port_config;
1292
1293        pipe = find_pipe_by_num(pipe_num);
1294        assert(pipe);
1295        if (!pipe)
1296        {
1297                return;
1298        }
1299        sh_css_sp_group.pipe[thread_id].scaler_pp_lut = sh_css_pipe_get_pp_gdc_lut(pipe);
1300
1301#if defined(SH_CSS_ENABLE_METADATA)
1302        if (md_info && md_info->size > 0)
1303        {
1304                sh_css_sp_group.pipe[thread_id].metadata.width  = md_info->resolution.width;
1305                sh_css_sp_group.pipe[thread_id].metadata.height = md_info->resolution.height;
1306                sh_css_sp_group.pipe[thread_id].metadata.stride = md_info->stride;
1307                sh_css_sp_group.pipe[thread_id].metadata.size   = md_info->size;
1308                ia_css_isys_convert_stream_format_to_mipi_format(
1309                    md_config->data_type, MIPI_PREDICTOR_NONE,
1310                    &sh_css_sp_group.pipe[thread_id].metadata.format);
1311        }
1312#else
1313        (void)md_config;
1314        (void)md_info;
1315#endif
1316
1317#if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS)
1318        sh_css_sp_group.pipe[thread_id].output_frame_queue_id = (uint32_t)SH_CSS_INVALID_QUEUE_ID;
1319        if (pipe_id != IA_CSS_PIPE_ID_COPY)
1320        {
1321                ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, thread_id,
1322                                               (enum sh_css_queue_id *)(
1323                                                   &sh_css_sp_group.pipe[thread_id].output_frame_queue_id));
1324        }
1325#endif
1326
1327        if (IS_ISP2401) {
1328                /* For the shading correction type 1 (the legacy shading table conversion in css is not used),
1329                * the parameters are passed to the isp for the shading table centering.
1330                */
1331                if (internal_frame_origin_bqs_on_sctbl &&
1332                    params && params->shading_settings.enable_shading_table_conversion == 0)
1333                {
1334                        sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_x_bqs_on_sctbl
1335                        = (uint32_t)internal_frame_origin_bqs_on_sctbl->x;
1336                        sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_y_bqs_on_sctbl
1337                        = (uint32_t)internal_frame_origin_bqs_on_sctbl->y;
1338                } else
1339                {
1340                        sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_x_bqs_on_sctbl =
1341                        0;
1342                        sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_y_bqs_on_sctbl =
1343                        0;
1344                }
1345        }
1346
1347        IA_CSS_LOG("pipe_id %d port_config %08x",
1348                   pipe_id, sh_css_sp_group.pipe[thread_id].inout_port_config);
1349
1350        for (stage = me->stages, num = 0; stage; stage = stage->next, num++)
1351        {
1352                sh_css_sp_group.pipe[thread_id].num_stages++;
1353                if (is_sp_stage(stage)) {
1354                        sp_init_sp_stage(stage, pipe_num, two_ppc,
1355                                         copy_ovrd, if_config_index);
1356                } else {
1357                        if ((stage->stage_num != 0) ||
1358                            SH_CSS_PIPE_PORT_CONFIG_IS_CONTINUOUS(me->inout_port_config))
1359                                tmp_if_config_index = SH_CSS_IF_CONFIG_NOT_NEEDED;
1360                        else
1361                                tmp_if_config_index = if_config_index;
1362                        sp_init_stage(stage, pipe_num,
1363                                      xnr, tmp_if_config_index, two_ppc);
1364                }
1365
1366                store_sp_stage_data(pipe_id, pipe_num, num);
1367        }
1368        sh_css_sp_group.pipe[thread_id].pipe_config |= (uint32_t)
1369                (me->acquire_isp_each_stage << IA_CSS_ACQUIRE_ISP_POS);
1370        store_sp_group_data();
1371}
1372
1373void
1374sh_css_sp_uninit_pipeline(unsigned int pipe_num)
1375{
1376        unsigned int thread_id;
1377
1378        ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
1379        /*memset(&sh_css_sp_group.pipe[thread_id], 0, sizeof(struct sh_css_sp_pipeline));*/
1380        sh_css_sp_group.pipe[thread_id].num_stages = 0;
1381}
1382
1383bool sh_css_write_host2sp_command(enum host2sp_commands host2sp_command)
1384{
1385        unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1386        unsigned int offset = (unsigned int)offsetof(struct host_sp_communication,
1387                              host2sp_command)
1388                              / sizeof(int);
1389        enum host2sp_commands last_cmd = host2sp_cmd_error;
1390        (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
1391
1392        /* Previous command must be handled by SP (by design) */
1393        last_cmd = load_sp_array_uint(host_sp_com, offset);
1394        if (last_cmd != host2sp_cmd_ready)
1395                IA_CSS_ERROR("last host command not handled by SP(%d)", last_cmd);
1396
1397        store_sp_array_uint(host_sp_com, offset, host2sp_command);
1398
1399        return (last_cmd == host2sp_cmd_ready);
1400}
1401
1402enum host2sp_commands
1403sh_css_read_host2sp_command(void) {
1404        unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1405        unsigned int offset = (unsigned int)offsetof(struct host_sp_communication, host2sp_command)
1406        / sizeof(int);
1407        (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
1408        return (enum host2sp_commands)load_sp_array_uint(host_sp_com, offset);
1409}
1410
1411/*
1412 * Frame data is no longer part of the sp_stage structure but part of a
1413 * separate structure. The aim is to make the sp_data struct static
1414 * (it defines a pipeline) and that the dynamic (per frame) data is stored
1415 * separetly.
1416 *
1417 * This function must be called first every where were you start constructing
1418 * a new pipeline by defining one or more stages with use of variable
1419 * sh_css_sp_stage. Even the special cases like accelerator and copy_frame
1420 * These have a pipeline of just 1 stage.
1421 */
1422void
1423sh_css_init_host2sp_frame_data(void)
1424{
1425        /* Clean table */
1426        unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1427
1428        (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
1429        /*
1430         * rvanimme: don't clean it to save static frame info line ref_in
1431         * ref_out, and tnr_frames. Once this static data is in a
1432         * separate data struct, this may be enable (but still, there is
1433         * no need for it)
1434         */
1435}
1436
1437/*
1438 * @brief Update the offline frame information in host_sp_communication.
1439 * Refer to "sh_css_sp.h" for more details.
1440 */
1441void
1442sh_css_update_host2sp_offline_frame(
1443    unsigned int frame_num,
1444    struct ia_css_frame *frame,
1445    struct ia_css_metadata *metadata)
1446{
1447        unsigned int HIVE_ADDR_host_sp_com;
1448        unsigned int offset;
1449
1450        assert(frame_num < NUM_CONTINUOUS_FRAMES);
1451
1452        /* Write new frame data into SP DMEM */
1453        HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1454        offset = (unsigned int)offsetof(struct host_sp_communication,
1455                                        host2sp_offline_frames)
1456                 / sizeof(int);
1457        offset += frame_num;
1458        store_sp_array_uint(host_sp_com, offset, frame ? frame->data : 0);
1459
1460        /* Write metadata buffer into SP DMEM */
1461        offset = (unsigned int)offsetof(struct host_sp_communication,
1462                                        host2sp_offline_metadata)
1463                 / sizeof(int);
1464        offset += frame_num;
1465        store_sp_array_uint(host_sp_com, offset, metadata ? metadata->address : 0);
1466}
1467
1468/*
1469 * @brief Update the mipi frame information in host_sp_communication.
1470 * Refer to "sh_css_sp.h" for more details.
1471 */
1472void
1473sh_css_update_host2sp_mipi_frame(
1474    unsigned int frame_num,
1475    struct ia_css_frame *frame)
1476{
1477        unsigned int HIVE_ADDR_host_sp_com;
1478        unsigned int offset;
1479
1480        /* MIPI buffers are dedicated to port, so now there are more of them. */
1481        assert(frame_num < (N_CSI_PORTS * NUM_MIPI_FRAMES_PER_STREAM));
1482
1483        /* Write new frame data into SP DMEM */
1484        HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1485        offset = (unsigned int)offsetof(struct host_sp_communication,
1486                                        host2sp_mipi_frames)
1487                 / sizeof(int);
1488        offset += frame_num;
1489
1490        store_sp_array_uint(host_sp_com, offset,
1491                            frame ? frame->data : 0);
1492}
1493
1494/*
1495 * @brief Update the mipi metadata information in host_sp_communication.
1496 * Refer to "sh_css_sp.h" for more details.
1497 */
1498void
1499sh_css_update_host2sp_mipi_metadata(
1500    unsigned int frame_num,
1501    struct ia_css_metadata *metadata)
1502{
1503        unsigned int HIVE_ADDR_host_sp_com;
1504        unsigned int o;
1505
1506        /* MIPI buffers are dedicated to port, so now there are more of them. */
1507        assert(frame_num < (N_CSI_PORTS * NUM_MIPI_FRAMES_PER_STREAM));
1508
1509        /* Write new frame data into SP DMEM */
1510        HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1511        o = offsetof(struct host_sp_communication, host2sp_mipi_metadata)
1512            / sizeof(int);
1513        o += frame_num;
1514        store_sp_array_uint(host_sp_com, o,
1515                            metadata ? metadata->address : 0);
1516}
1517
1518void
1519sh_css_update_host2sp_num_mipi_frames(unsigned int num_frames)
1520{
1521        unsigned int HIVE_ADDR_host_sp_com;
1522        unsigned int offset;
1523
1524        /* Write new frame data into SP DMEM */
1525        HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1526        offset = (unsigned int)offsetof(struct host_sp_communication,
1527                                        host2sp_num_mipi_frames)
1528                 / sizeof(int);
1529
1530        store_sp_array_uint(host_sp_com, offset, num_frames);
1531}
1532
1533void
1534sh_css_update_host2sp_cont_num_raw_frames(unsigned int num_frames,
1535        bool set_avail)
1536{
1537        const struct ia_css_fw_info *fw;
1538        unsigned int HIVE_ADDR_host_sp_com;
1539        unsigned int extra_num_frames, avail_num_frames;
1540        unsigned int offset, offset_extra;
1541
1542        /* Write new frame data into SP DMEM */
1543        fw = &sh_css_sp_fw;
1544        HIVE_ADDR_host_sp_com = fw->info.sp.host_sp_com;
1545        if (set_avail) {
1546                offset = (unsigned int)offsetof(struct host_sp_communication,
1547                                                host2sp_cont_avail_num_raw_frames)
1548                         / sizeof(int);
1549                avail_num_frames = load_sp_array_uint(host_sp_com, offset);
1550                extra_num_frames = num_frames - avail_num_frames;
1551                offset_extra = (unsigned int)offsetof(struct host_sp_communication,
1552                                                      host2sp_cont_extra_num_raw_frames)
1553                               / sizeof(int);
1554                store_sp_array_uint(host_sp_com, offset_extra, extra_num_frames);
1555        } else
1556                offset = (unsigned int)offsetof(struct host_sp_communication,
1557                                                host2sp_cont_target_num_raw_frames)
1558                         / sizeof(int);
1559
1560        store_sp_array_uint(host_sp_com, offset, num_frames);
1561}
1562
1563void
1564sh_css_event_init_irq_mask(void)
1565{
1566        int i;
1567        unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1568        unsigned int offset;
1569        struct sh_css_event_irq_mask event_irq_mask_init;
1570
1571        event_irq_mask_init.or_mask  = IA_CSS_EVENT_TYPE_ALL;
1572        event_irq_mask_init.and_mask = IA_CSS_EVENT_TYPE_NONE;
1573        (void)HIVE_ADDR_host_sp_com; /* Suppress warnings in CRUN */
1574
1575        assert(sizeof(event_irq_mask_init) % HRT_BUS_BYTES == 0);
1576        for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
1577                offset = (unsigned int)offsetof(struct host_sp_communication,
1578                                                host2sp_event_irq_mask[i]);
1579                assert(offset % HRT_BUS_BYTES == 0);
1580                sp_dmem_store(SP0_ID,
1581                              (unsigned int)sp_address_of(host_sp_com) + offset,
1582                              &event_irq_mask_init, sizeof(event_irq_mask_init));
1583        }
1584}
1585
1586int
1587ia_css_pipe_set_irq_mask(struct ia_css_pipe *pipe,
1588                         unsigned int or_mask,
1589                         unsigned int and_mask) {
1590        unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1591        unsigned int offset;
1592        struct sh_css_event_irq_mask event_irq_mask;
1593        unsigned int pipe_num;
1594
1595        assert(pipe);
1596
1597        assert(IA_CSS_PIPE_ID_NUM == NR_OF_PIPELINES);
1598        /* Linux kernel does not have UINT16_MAX
1599         * Therefore decided to comment out these 2 asserts for Linux
1600         * Alternatives that were not chosen:
1601         * - add a conditional #define for UINT16_MAX
1602         * - compare with (uint16_t)~0 or 0xffff
1603         * - different assert for Linux and Windows
1604         */
1605
1606        (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
1607
1608        IA_CSS_LOG("or_mask=%x, and_mask=%x", or_mask, and_mask);
1609        event_irq_mask.or_mask  = (uint16_t)or_mask;
1610        event_irq_mask.and_mask = (uint16_t)and_mask;
1611
1612        pipe_num = ia_css_pipe_get_pipe_num(pipe);
1613        if (pipe_num >= IA_CSS_PIPE_ID_NUM)
1614                return -EINVAL;
1615        offset = (unsigned int)offsetof(struct host_sp_communication,
1616                                        host2sp_event_irq_mask[pipe_num]);
1617        assert(offset % HRT_BUS_BYTES == 0);
1618        sp_dmem_store(SP0_ID,
1619                      (unsigned int)sp_address_of(host_sp_com) + offset,
1620                      &event_irq_mask, sizeof(event_irq_mask));
1621
1622        return 0;
1623}
1624
1625int
1626ia_css_event_get_irq_mask(const struct ia_css_pipe *pipe,
1627                          unsigned int *or_mask,
1628                          unsigned int *and_mask) {
1629        unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1630        unsigned int offset;
1631        struct sh_css_event_irq_mask event_irq_mask;
1632        unsigned int pipe_num;
1633
1634        (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
1635
1636        IA_CSS_ENTER_LEAVE("");
1637
1638        assert(pipe);
1639        assert(IA_CSS_PIPE_ID_NUM == NR_OF_PIPELINES);
1640
1641        pipe_num = ia_css_pipe_get_pipe_num(pipe);
1642        if (pipe_num >= IA_CSS_PIPE_ID_NUM)
1643                return -EINVAL;
1644        offset = (unsigned int)offsetof(struct host_sp_communication,
1645                                        host2sp_event_irq_mask[pipe_num]);
1646        assert(offset % HRT_BUS_BYTES == 0);
1647        sp_dmem_load(SP0_ID,
1648                     (unsigned int)sp_address_of(host_sp_com) + offset,
1649                     &event_irq_mask, sizeof(event_irq_mask));
1650
1651        if (or_mask)
1652                *or_mask = event_irq_mask.or_mask;
1653
1654        if (and_mask)
1655                *and_mask = event_irq_mask.and_mask;
1656
1657        return 0;
1658}
1659
1660void
1661sh_css_sp_set_sp_running(bool flag)
1662{
1663        sp_running = flag;
1664}
1665
1666bool
1667sh_css_sp_is_running(void)
1668{
1669        return sp_running;
1670}
1671
1672void
1673sh_css_sp_start_isp(void)
1674{
1675        const struct ia_css_fw_info *fw;
1676        unsigned int HIVE_ADDR_sp_sw_state;
1677
1678        fw = &sh_css_sp_fw;
1679        HIVE_ADDR_sp_sw_state = fw->info.sp.sw_state;
1680
1681        if (sp_running)
1682                return;
1683
1684        (void)HIVE_ADDR_sp_sw_state; /* Suppres warnings in CRUN */
1685
1686        /* no longer here, sp started immediately */
1687        /*ia_css_debug_pipe_graph_dump_epilogue();*/
1688
1689        store_sp_group_data();
1690        store_sp_per_frame_data(fw);
1691
1692        sp_dmem_store_uint32(SP0_ID,
1693                             (unsigned int)sp_address_of(sp_sw_state),
1694                             (uint32_t)(IA_CSS_SP_SW_TERMINATED));
1695
1696        /* Note 1: The sp_start_isp function contains a wait till
1697         * the input network is configured by the SP.
1698         * Note 2: Not all SP binaries supports host2sp_commands.
1699         * In case a binary does support it, the host2sp_command
1700         * will have status cmd_ready after return of the function
1701         * sh_css_hrt_sp_start_isp. There is no race-condition here
1702         * because only after the process_frame command has been
1703         * received, the SP starts configuring the input network.
1704         */
1705
1706        /* we need to set sp_running before we call ia_css_mmu_invalidate_cache
1707         * as ia_css_mmu_invalidate_cache checks on sp_running to
1708         * avoid that it accesses dmem while the SP is not powered
1709         */
1710        sp_running = true;
1711        ia_css_mmu_invalidate_cache();
1712        /* Invalidate all MMU caches */
1713        mmu_invalidate_cache_all();
1714
1715        ia_css_spctrl_start(SP0_ID);
1716}
1717
1718bool
1719ia_css_isp_has_started(void)
1720{
1721        const struct ia_css_fw_info *fw = &sh_css_sp_fw;
1722        unsigned int HIVE_ADDR_ia_css_ispctrl_sp_isp_started = fw->info.sp.isp_started;
1723        (void)HIVE_ADDR_ia_css_ispctrl_sp_isp_started; /* Suppres warnings in CRUN */
1724
1725        return (bool)load_sp_uint(ia_css_ispctrl_sp_isp_started);
1726}
1727
1728/*
1729 * @brief Initialize the DMA software-mask in the debug mode.
1730 * Refer to "sh_css_sp.h" for more details.
1731 */
1732bool
1733sh_css_sp_init_dma_sw_reg(int dma_id)
1734{
1735        int i;
1736
1737        /* enable all the DMA channels */
1738        for (i = 0; i < N_DMA_CHANNEL_ID; i++) {
1739                /* enable the writing request */
1740                sh_css_sp_set_dma_sw_reg(dma_id,
1741                                         i,
1742                                         0,
1743                                         true);
1744                /* enable the reading request */
1745                sh_css_sp_set_dma_sw_reg(dma_id,
1746                                         i,
1747                                         1,
1748                                         true);
1749        }
1750
1751        return true;
1752}
1753
1754/*
1755 * @brief Set the DMA software-mask in the debug mode.
1756 * Refer to "sh_css_sp.h" for more details.
1757 */
1758bool
1759sh_css_sp_set_dma_sw_reg(int dma_id,
1760                         int channel_id,
1761                         int request_type,
1762                         bool enable)
1763{
1764        u32 sw_reg;
1765        u32 bit_val;
1766        u32 bit_offset;
1767        u32 bit_mask;
1768
1769        (void)dma_id;
1770
1771        assert(channel_id >= 0 && channel_id < N_DMA_CHANNEL_ID);
1772        assert(request_type >= 0);
1773
1774        /* get the software-mask */
1775        sw_reg =
1776            sh_css_sp_group.debug.dma_sw_reg;
1777
1778        /* get the offest of the target bit */
1779        bit_offset = (8 * request_type) + channel_id;
1780
1781        /* clear the value of the target bit */
1782        bit_mask = ~(1 << bit_offset);
1783        sw_reg &= bit_mask;
1784
1785        /* set the value of the bit for the DMA channel */
1786        bit_val = enable ? 1 : 0;
1787        bit_val <<= bit_offset;
1788        sw_reg |= bit_val;
1789
1790        /* update the software status of DMA channels */
1791        sh_css_sp_group.debug.dma_sw_reg = sw_reg;
1792
1793        return true;
1794}
1795
1796void
1797sh_css_sp_reset_global_vars(void)
1798{
1799        memset(&sh_css_sp_group, 0, sizeof(struct sh_css_sp_group));
1800        memset(&sh_css_sp_stage, 0, sizeof(struct sh_css_sp_stage));
1801        memset(&sh_css_isp_stage, 0, sizeof(struct sh_css_isp_stage));
1802        memset(&sh_css_sp_output, 0, sizeof(struct sh_css_sp_output));
1803        memset(&per_frame_data, 0, sizeof(struct sh_css_sp_per_frame_data));
1804}
1805