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{
 540        if (!frame)
 541                return -EINVAL;
 542
 543        switch (frame->info.format) {
 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{
 571        if (!frame)
 572                return -EINVAL;
 573
 574        switch (frame->info.format) {
 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{
 612        if (!frame)
 613                return -EINVAL;
 614
 615        switch (frame->info.format) {
 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{
 737        int err = 0;
 738        int i;
 739
 740        assert(args);
 741
 742        if (args->in_frame)
 743                err = set_input_frame_buffer(args->in_frame);
 744        if (!err && args->out_vf_frame)
 745                err = set_view_finder_buffer(args->out_vf_frame);
 746        for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) {
 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{
 791        int err;
 792
 793        err = ia_css_isp_param_copy_isp_mem_if_to_ddr(
 794            &binary->css_params,
 795            &binary->mem_params,
 796            IA_CSS_PARAM_CLASS_CONFIG);
 797        if (err)
 798                return err;
 799        err = ia_css_isp_param_copy_isp_mem_if_to_ddr(
 800            &binary->css_params,
 801            &binary->mem_params,
 802            IA_CSS_PARAM_CLASS_STATE);
 803        if (err)
 804                return err;
 805        return 0;
 806}
 807
 808static bool
 809is_sp_stage(struct ia_css_pipeline_stage *stage)
 810{
 811        assert(stage);
 812        return stage->sp_func != IA_CSS_PIPELINE_NO_FUNC;
 813}
 814
 815static int
 816configure_isp_from_args(
 817    const struct sh_css_sp_pipeline *pipeline,
 818    const struct ia_css_binary      *binary,
 819    const struct sh_css_binary_args *args,
 820    bool two_ppc,
 821    bool deinterleaved)
 822{
 823        ia_css_fpn_configure(binary,  &binary->in_frame_info);
 824        ia_css_crop_configure(binary, &args->delay_frames[0]->info);
 825        ia_css_qplane_configure(pipeline, binary, &binary->in_frame_info);
 826        ia_css_output0_configure(binary, &args->out_frame[0]->info);
 827        ia_css_output1_configure(binary, &args->out_vf_frame->info);
 828        ia_css_copy_output_configure(binary, args->copy_output);
 829        ia_css_output0_configure(binary, &args->out_frame[0]->info);
 830#ifdef ISP2401
 831        ia_css_sc_configure(binary, pipeline->shading.internal_frame_origin_x_bqs_on_sctbl,
 832                            pipeline->shading.internal_frame_origin_y_bqs_on_sctbl);
 833#endif
 834        ia_css_iterator_configure(binary, &args->in_frame->info);
 835        ia_css_dvs_configure(binary, &args->out_frame[0]->info);
 836        ia_css_output_configure(binary, &args->out_frame[0]->info);
 837        ia_css_raw_configure(pipeline, binary, &args->in_frame->info, &binary->in_frame_info, two_ppc, deinterleaved);
 838
 839        /*
 840         * FIXME: args->delay_frames can be NULL here
 841         *
 842         * Somehow, the driver at the Intel Atom Yocto tree doesn't seem to
 843         * suffer from the same issue.
 844         *
 845         * Anyway, the function below should now handle a NULL delay_frames
 846         * without crashing, but the pipeline should likely be built without
 847         * adding it at the first place (or there are a hidden bug somewhere)
 848         */
 849        ia_css_ref_configure(binary, args->delay_frames, pipeline->dvs_frame_delay);
 850        ia_css_tnr_configure(binary, args->tnr_frames);
 851        ia_css_bayer_io_config(binary, args);
 852        return 0;
 853}
 854
 855static void
 856initialize_isp_states(const struct ia_css_binary *binary)
 857{
 858        unsigned int i;
 859
 860        if (!binary->info->mem_offsets.offsets.state)
 861                return;
 862        for (i = 0; i < IA_CSS_NUM_STATE_IDS; i++) {
 863                ia_css_kernel_init_state[i](binary);
 864        }
 865}
 866
 867static void
 868initialize_frame_buffer_attribute(struct ia_css_buffer_sp *buf_attr)
 869{
 870        buf_attr->buf_src.queue_id = SH_CSS_INVALID_QUEUE_ID;
 871        buf_attr->buf_type = IA_CSS_BUFFER_TYPE_INVALID;
 872}
 873
 874static void
 875initialize_stage_frames(struct ia_css_frames_sp *frames)
 876{
 877        unsigned int i;
 878
 879        initialize_frame_buffer_attribute(&frames->in.buf_attr);
 880        for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) {
 881                initialize_frame_buffer_attribute(&frames->out[i].buf_attr);
 882        }
 883        initialize_frame_buffer_attribute(&frames->out_vf.buf_attr);
 884        initialize_frame_buffer_attribute(&frames->s3a_buf);
 885        initialize_frame_buffer_attribute(&frames->dvs_buf);
 886#if defined SH_CSS_ENABLE_METADATA
 887        initialize_frame_buffer_attribute(&frames->metadata_buf);
 888#endif
 889}
 890
 891static int
 892sh_css_sp_init_stage(struct ia_css_binary *binary,
 893                     const char *binary_name,
 894                     const struct ia_css_blob_info *blob_info,
 895                     const struct sh_css_binary_args *args,
 896                     unsigned int pipe_num,
 897                     unsigned int stage,
 898                     bool xnr,
 899                     const struct ia_css_isp_param_css_segments *isp_mem_if,
 900                     unsigned int if_config_index,
 901                     bool two_ppc)
 902{
 903        const struct ia_css_binary_xinfo *xinfo;
 904        const struct ia_css_binary_info  *info;
 905        int err = 0;
 906        int i;
 907        struct ia_css_pipe *pipe = NULL;
 908        unsigned int thread_id;
 909        enum sh_css_queue_id queue_id;
 910        bool continuous = sh_css_continuous_is_enabled((uint8_t)pipe_num);
 911
 912        assert(binary);
 913        assert(blob_info);
 914        assert(args);
 915        assert(isp_mem_if);
 916
 917        xinfo = binary->info;
 918        info  = &xinfo->sp;
 919        {
 920                /*
 921                 * Clear sh_css_sp_stage for easy debugging.
 922                 * program_input_circuit must be saved as it is set outside
 923                 * this function.
 924                 */
 925                u8 program_input_circuit;
 926
 927                program_input_circuit = sh_css_sp_stage.program_input_circuit;
 928                memset(&sh_css_sp_stage, 0, sizeof(sh_css_sp_stage));
 929                sh_css_sp_stage.program_input_circuit = (uint8_t)program_input_circuit;
 930        }
 931
 932        ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
 933
 934        if (!info) {
 935                sh_css_sp_group.pipe[thread_id].sp_stage_addr[stage] = mmgr_NULL;
 936                return 0;
 937        }
 938
 939#if defined(ISP2401)
 940        (void)continuous;
 941        sh_css_sp_stage.deinterleaved = 0;
 942#else
 943        sh_css_sp_stage.deinterleaved = ((stage == 0) && continuous);
 944#endif
 945
 946        initialize_stage_frames(&sh_css_sp_stage.frames);
 947        /*
 948         * TODO: Make the Host dynamically determine
 949         * the stage type.
 950         */
 951        sh_css_sp_stage.stage_type = SH_CSS_ISP_STAGE_TYPE;
 952        sh_css_sp_stage.num             = (uint8_t)stage;
 953        sh_css_sp_stage.isp_online      = (uint8_t)binary->online;
 954        sh_css_sp_stage.isp_copy_vf     = (uint8_t)args->copy_vf;
 955        sh_css_sp_stage.isp_copy_output = (uint8_t)args->copy_output;
 956        sh_css_sp_stage.enable.vf_output = (args->out_vf_frame != NULL);
 957
 958        /* Copy the frame infos first, to be overwritten by the frames,
 959           if these are present.
 960        */
 961        sh_css_sp_stage.frames.effective_in_res.width = binary->effective_in_frame_res.width;
 962        sh_css_sp_stage.frames.effective_in_res.height = binary->effective_in_frame_res.height;
 963
 964        ia_css_frame_info_to_frame_sp_info(&sh_css_sp_stage.frames.in.info,
 965                                           &binary->in_frame_info);
 966        for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) {
 967                ia_css_frame_info_to_frame_sp_info(&sh_css_sp_stage.frames.out[i].info,
 968                                                   &binary->out_frame_info[i]);
 969        }
 970        ia_css_frame_info_to_frame_sp_info(&sh_css_sp_stage.frames.internal_frame_info,
 971                                           &binary->internal_frame_info);
 972        sh_css_sp_stage.dvs_envelope.width    = binary->dvs_envelope.width;
 973        sh_css_sp_stage.dvs_envelope.height   = binary->dvs_envelope.height;
 974        sh_css_sp_stage.isp_pipe_version      = (uint8_t)info->pipeline.isp_pipe_version;
 975        sh_css_sp_stage.isp_deci_log_factor   = (uint8_t)binary->deci_factor_log2;
 976        sh_css_sp_stage.isp_vf_downscale_bits = (uint8_t)binary->vf_downscale_log2;
 977
 978        sh_css_sp_stage.if_config_index = (uint8_t)if_config_index;
 979
 980        sh_css_sp_stage.sp_enable_xnr = (uint8_t)xnr;
 981        sh_css_sp_stage.xmem_bin_addr = xinfo->xmem_addr;
 982        sh_css_sp_stage.xmem_map_addr = sh_css_params_ddr_address_map();
 983        sh_css_isp_stage.blob_info = *blob_info;
 984        sh_css_stage_write_binary_info((struct ia_css_binary_info *)info);
 985
 986        /* Make sure binary name is smaller than allowed string size */
 987        assert(strlen(binary_name) < SH_CSS_MAX_BINARY_NAME - 1);
 988        strscpy(sh_css_isp_stage.binary_name, binary_name, SH_CSS_MAX_BINARY_NAME);
 989        sh_css_isp_stage.mem_initializers = *isp_mem_if;
 990
 991        /*
 992         * Even when a stage does not need uds and does not params,
 993         * ia_css_uds_sp_scale_params() seems to be called (needs
 994         * further investigation). This function can not deal with
 995         * dx, dy = {0, 0}
 996         */
 997
 998        err = sh_css_sp_write_frame_pointers(args);
 999        /* TODO: move it to a better place */
1000        if (binary->info->sp.enable.s3a) {
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                ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_DIS_STATISTICS, thread_id,
1009                                               &queue_id);
1010                sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.dvs_buf, queue_id,
1011                                                    mmgr_EXCEPTION,
1012                                                    IA_CSS_BUFFER_TYPE_DIS_STATISTICS);
1013        }
1014#if defined SH_CSS_ENABLE_METADATA
1015        ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_METADATA, thread_id, &queue_id);
1016        sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.metadata_buf, queue_id, mmgr_EXCEPTION, IA_CSS_BUFFER_TYPE_METADATA);
1017#endif
1018        if (err)
1019                return err;
1020
1021#ifdef ISP2401
1022        if (stage == 0) {
1023                pipe = find_pipe_by_num(sh_css_sp_group.pipe[thread_id].pipe_num);
1024                if (!pipe)
1025                        return -EINVAL;
1026
1027                if (args->in_frame)
1028                        ia_css_get_crop_offsets(pipe, &args->in_frame->info);
1029                else
1030                        ia_css_get_crop_offsets(pipe, &binary->in_frame_info);
1031        }
1032#else
1033        (void)pipe; /*avoid build warning*/
1034#endif
1035
1036        err = configure_isp_from_args(&sh_css_sp_group.pipe[thread_id],
1037                                      binary, args, two_ppc, sh_css_sp_stage.deinterleaved);
1038        if (err)
1039                return err;
1040
1041        initialize_isp_states(binary);
1042
1043        /* we do this only for preview pipe because in fill_binary_info function
1044         * we assign vf_out res to out res, but for ISP internal processing, we need
1045         * the original out res. for video pipe, it has two output pins --- out and
1046         * vf_out, so it can keep these two resolutions already. */
1047        if (binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_PREVIEW &&
1048            (binary->vf_downscale_log2 > 0)) {
1049                /* TODO: Remove this after preview output decimation is fixed
1050                 * by configuring out&vf info fiels properly */
1051                sh_css_sp_stage.frames.out[0].info.padded_width
1052                <<= binary->vf_downscale_log2;
1053                sh_css_sp_stage.frames.out[0].info.res.width
1054                <<= binary->vf_downscale_log2;
1055                sh_css_sp_stage.frames.out[0].info.res.height
1056                <<= binary->vf_downscale_log2;
1057        }
1058        err = copy_isp_mem_if_to_ddr(binary);
1059        if (err)
1060                return err;
1061
1062        return 0;
1063}
1064
1065static int
1066sp_init_stage(struct ia_css_pipeline_stage *stage,
1067              unsigned int pipe_num,
1068              bool xnr,
1069              unsigned int if_config_index,
1070              bool two_ppc)
1071{
1072        struct ia_css_binary *binary;
1073        const struct ia_css_fw_info *firmware;
1074        const struct sh_css_binary_args *args;
1075        unsigned int stage_num;
1076        /*
1077         * Initialiser required because of the "else" path below.
1078         * Is this a valid path ?
1079         */
1080        const char *binary_name = "";
1081        const struct ia_css_binary_xinfo *info = NULL;
1082        /* note: the var below is made static as it is quite large;
1083           if it is not static it ends up on the stack which could
1084           cause issues for drivers
1085        */
1086        static struct ia_css_binary tmp_binary;
1087        const struct ia_css_blob_info *blob_info = NULL;
1088        struct ia_css_isp_param_css_segments isp_mem_if;
1089        /* LA: should be ia_css_data, should not contain host pointer.
1090           However, CSS/DDR pointer is not available yet.
1091           Hack is to store it in params->ddr_ptrs and then copy it late in the SP just before vmem init.
1092           TODO: Call this after CSS/DDR allocation and store that pointer.
1093           Best is to allocate it at stage creation time together with host pointer.
1094           Remove vmem from params.
1095        */
1096        struct ia_css_isp_param_css_segments *mem_if = &isp_mem_if;
1097
1098        int err = 0;
1099
1100        assert(stage);
1101
1102        binary = stage->binary;
1103        firmware = stage->firmware;
1104        args = &stage->args;
1105        stage_num = stage->stage_num;
1106
1107        if (binary) {
1108                info = binary->info;
1109                binary_name = (const char *)(info->blob->name);
1110                blob_info = &info->blob->header.blob;
1111                ia_css_init_memory_interface(mem_if, &binary->mem_params, &binary->css_params);
1112        } else if (firmware) {
1113                const struct ia_css_frame_info *out_infos[IA_CSS_BINARY_MAX_OUTPUT_PORTS] = {NULL};
1114
1115                if (args->out_frame[0])
1116                        out_infos[0] = &args->out_frame[0]->info;
1117                info = &firmware->info.isp;
1118                ia_css_binary_fill_info(info, false, false,
1119                                        ATOMISP_INPUT_FORMAT_RAW_10,
1120                                        args->in_frame  ? &args->in_frame->info  : NULL,
1121                                        NULL,
1122                                        out_infos,
1123                                        args->out_vf_frame ? &args->out_vf_frame->info
1124                                        : NULL,
1125                                        &tmp_binary,
1126                                        NULL,
1127                                        -1, true);
1128                binary = &tmp_binary;
1129                binary->info = info;
1130                binary_name = IA_CSS_EXT_ISP_PROG_NAME(firmware);
1131                blob_info = &firmware->blob;
1132                mem_if = (struct ia_css_isp_param_css_segments *)&firmware->mem_initializers;
1133        } else {
1134                /* SP stage */
1135                assert(stage->sp_func != IA_CSS_PIPELINE_NO_FUNC);
1136                /* binary and blob_info are now NULL.
1137                   These will be passed to sh_css_sp_init_stage
1138                   and dereferenced there, so passing a NULL
1139                   pointer is no good. return an error */
1140                return -EINVAL;
1141        }
1142
1143        err = sh_css_sp_init_stage(binary,
1144                                   (const char *)binary_name,
1145                                   blob_info,
1146                                   args,
1147                                   pipe_num,
1148                                   stage_num,
1149                                   xnr,
1150                                   mem_if,
1151                                   if_config_index,
1152                                   two_ppc);
1153        return err;
1154}
1155
1156static void
1157sp_init_sp_stage(struct ia_css_pipeline_stage *stage,
1158                 unsigned int pipe_num,
1159                 bool two_ppc,
1160                 enum sh_css_pipe_config_override copy_ovrd,
1161                 unsigned int if_config_index)
1162{
1163        const struct sh_css_binary_args *args = &stage->args;
1164
1165        assert(stage);
1166        switch (stage->sp_func) {
1167        case IA_CSS_PIPELINE_RAW_COPY:
1168                sh_css_sp_start_raw_copy(args->out_frame[0],
1169                                         pipe_num, two_ppc,
1170                                         stage->max_input_width,
1171                                         copy_ovrd, if_config_index);
1172                break;
1173        case IA_CSS_PIPELINE_BIN_COPY:
1174                assert(false); /* TBI */
1175                break;
1176        case IA_CSS_PIPELINE_ISYS_COPY:
1177                sh_css_sp_start_isys_copy(args->out_frame[0],
1178                                          pipe_num, stage->max_input_width, if_config_index);
1179                break;
1180        case IA_CSS_PIPELINE_NO_FUNC:
1181                assert(false);
1182                break;
1183        }
1184}
1185
1186void
1187sh_css_sp_init_pipeline(struct ia_css_pipeline *me,
1188                        enum ia_css_pipe_id id,
1189                        u8 pipe_num,
1190                        bool xnr,
1191                        bool two_ppc,
1192                        bool continuous,
1193                        bool offline,
1194                        unsigned int required_bds_factor,
1195                        enum sh_css_pipe_config_override copy_ovrd,
1196                        enum ia_css_input_mode input_mode,
1197                        const struct ia_css_metadata_config *md_config,
1198                        const struct ia_css_metadata_info *md_info,
1199                        const enum mipi_port_id port_id,
1200                        const struct ia_css_coordinate
1201                        *internal_frame_origin_bqs_on_sctbl, /* Origin of internal frame
1202                                                        positioned on shading table at shading correction in ISP. */
1203                        const struct ia_css_isp_parameters *params
1204                       )
1205{
1206        /* Get first stage */
1207        struct ia_css_pipeline_stage *stage        = NULL;
1208        struct ia_css_binary         *first_binary = NULL;
1209        struct ia_css_pipe *pipe = NULL;
1210        unsigned int num;
1211
1212        enum ia_css_pipe_id pipe_id = id;
1213        unsigned int thread_id;
1214        u8 if_config_index, tmp_if_config_index;
1215
1216        assert(me);
1217
1218        assert(me->stages);
1219
1220        first_binary = me->stages->binary;
1221
1222        if (input_mode == IA_CSS_INPUT_MODE_SENSOR ||
1223            input_mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
1224                assert(port_id < N_MIPI_PORT_ID);
1225                if (port_id >= N_MIPI_PORT_ID) /* should not happen but KW does not know */
1226                        return; /* we should be able to return an error */
1227                if_config_index  = (uint8_t)(port_id - MIPI_PORT0_ID);
1228        } else if (input_mode == IA_CSS_INPUT_MODE_MEMORY) {
1229                if_config_index = SH_CSS_IF_CONFIG_NOT_NEEDED;
1230        } else {
1231                if_config_index = 0x0;
1232        }
1233
1234        ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
1235        memset(&sh_css_sp_group.pipe[thread_id], 0, sizeof(struct sh_css_sp_pipeline));
1236
1237        /* Count stages */
1238        for (stage = me->stages, num = 0; stage; stage = stage->next, num++) {
1239                stage->stage_num = num;
1240                ia_css_debug_pipe_graph_dump_stage(stage, id);
1241        }
1242        me->num_stages = num;
1243
1244        if (first_binary) {
1245                /* Init pipeline data */
1246                sh_css_sp_init_group(two_ppc, first_binary->input_format,
1247                                     offline, if_config_index);
1248        } /* if (first_binary != NULL) */
1249
1250        /* Signal the host immediately after start for SP_ISYS_COPY only */
1251        if ((me->num_stages == 1) && me->stages &&
1252            (me->stages->sp_func == IA_CSS_PIPELINE_ISYS_COPY))
1253                sh_css_sp_group.config.no_isp_sync = true;
1254
1255        /* Init stage data */
1256        sh_css_init_host2sp_frame_data();
1257
1258        sh_css_sp_group.pipe[thread_id].num_stages = 0;
1259        sh_css_sp_group.pipe[thread_id].pipe_id = pipe_id;
1260        sh_css_sp_group.pipe[thread_id].thread_id = thread_id;
1261        sh_css_sp_group.pipe[thread_id].pipe_num = pipe_num;
1262        sh_css_sp_group.pipe[thread_id].num_execs = me->num_execs;
1263        sh_css_sp_group.pipe[thread_id].pipe_qos_config = me->pipe_qos_config;
1264        sh_css_sp_group.pipe[thread_id].required_bds_factor = required_bds_factor;
1265        sh_css_sp_group.pipe[thread_id].input_system_mode
1266        = (uint32_t)input_mode;
1267        sh_css_sp_group.pipe[thread_id].port_id = port_id;
1268        sh_css_sp_group.pipe[thread_id].dvs_frame_delay = (uint32_t)me->dvs_frame_delay;
1269
1270        /* TODO: next indicates from which queues parameters need to be
1271                 sampled, needs checking/improvement */
1272        if (ia_css_pipeline_uses_params(me)) {
1273                sh_css_sp_group.pipe[thread_id].pipe_config =
1274                SH_CSS_PIPE_CONFIG_SAMPLE_PARAMS << thread_id;
1275        }
1276
1277        /* For continuous use-cases, SP copy is responsible for sampling the
1278         * parameters */
1279        if (continuous)
1280                sh_css_sp_group.pipe[thread_id].pipe_config = 0;
1281
1282        sh_css_sp_group.pipe[thread_id].inout_port_config = me->inout_port_config;
1283
1284        pipe = find_pipe_by_num(pipe_num);
1285        assert(pipe);
1286        if (!pipe) {
1287                return;
1288        }
1289        sh_css_sp_group.pipe[thread_id].scaler_pp_lut = sh_css_pipe_get_pp_gdc_lut(pipe);
1290
1291#if defined(SH_CSS_ENABLE_METADATA)
1292        if (md_info && md_info->size > 0) {
1293                sh_css_sp_group.pipe[thread_id].metadata.width  = md_info->resolution.width;
1294                sh_css_sp_group.pipe[thread_id].metadata.height = md_info->resolution.height;
1295                sh_css_sp_group.pipe[thread_id].metadata.stride = md_info->stride;
1296                sh_css_sp_group.pipe[thread_id].metadata.size   = md_info->size;
1297                ia_css_isys_convert_stream_format_to_mipi_format(
1298                    md_config->data_type, MIPI_PREDICTOR_NONE,
1299                    &sh_css_sp_group.pipe[thread_id].metadata.format);
1300        }
1301#else
1302        (void)md_config;
1303        (void)md_info;
1304#endif
1305
1306#if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS)
1307        sh_css_sp_group.pipe[thread_id].output_frame_queue_id = (uint32_t)SH_CSS_INVALID_QUEUE_ID;
1308        if (pipe_id != IA_CSS_PIPE_ID_COPY) {
1309                ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, thread_id,
1310                                               (enum sh_css_queue_id *)(
1311                                                   &sh_css_sp_group.pipe[thread_id].output_frame_queue_id));
1312        }
1313#endif
1314
1315        if (IS_ISP2401) {
1316                /* For the shading correction type 1 (the legacy shading table conversion in css is not used),
1317                * the parameters are passed to the isp for the shading table centering.
1318                */
1319                if (internal_frame_origin_bqs_on_sctbl &&
1320                    params && params->shading_settings.enable_shading_table_conversion == 0) {
1321                        sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_x_bqs_on_sctbl
1322                        = (uint32_t)internal_frame_origin_bqs_on_sctbl->x;
1323                        sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_y_bqs_on_sctbl
1324                        = (uint32_t)internal_frame_origin_bqs_on_sctbl->y;
1325                } else {
1326                        sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_x_bqs_on_sctbl =
1327                        0;
1328                        sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_y_bqs_on_sctbl =
1329                        0;
1330                }
1331        }
1332
1333        IA_CSS_LOG("pipe_id %d port_config %08x",
1334                   pipe_id, sh_css_sp_group.pipe[thread_id].inout_port_config);
1335
1336        for (stage = me->stages, num = 0; stage; stage = stage->next, num++) {
1337                sh_css_sp_group.pipe[thread_id].num_stages++;
1338                if (is_sp_stage(stage)) {
1339                        sp_init_sp_stage(stage, pipe_num, two_ppc,
1340                                         copy_ovrd, if_config_index);
1341                } else {
1342                        if ((stage->stage_num != 0) ||
1343                            SH_CSS_PIPE_PORT_CONFIG_IS_CONTINUOUS(me->inout_port_config))
1344                                tmp_if_config_index = SH_CSS_IF_CONFIG_NOT_NEEDED;
1345                        else
1346                                tmp_if_config_index = if_config_index;
1347                        sp_init_stage(stage, pipe_num,
1348                                      xnr, tmp_if_config_index, two_ppc);
1349                }
1350
1351                store_sp_stage_data(pipe_id, pipe_num, num);
1352        }
1353        sh_css_sp_group.pipe[thread_id].pipe_config |= (uint32_t)
1354                (me->acquire_isp_each_stage << IA_CSS_ACQUIRE_ISP_POS);
1355        store_sp_group_data();
1356}
1357
1358void
1359sh_css_sp_uninit_pipeline(unsigned int pipe_num)
1360{
1361        unsigned int thread_id;
1362
1363        ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
1364        /*memset(&sh_css_sp_group.pipe[thread_id], 0, sizeof(struct sh_css_sp_pipeline));*/
1365        sh_css_sp_group.pipe[thread_id].num_stages = 0;
1366}
1367
1368bool sh_css_write_host2sp_command(enum host2sp_commands host2sp_command)
1369{
1370        unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1371        unsigned int offset = (unsigned int)offsetof(struct host_sp_communication,
1372                              host2sp_command)
1373                              / sizeof(int);
1374        enum host2sp_commands last_cmd = host2sp_cmd_error;
1375        (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
1376
1377        /* Previous command must be handled by SP (by design) */
1378        last_cmd = load_sp_array_uint(host_sp_com, offset);
1379        if (last_cmd != host2sp_cmd_ready)
1380                IA_CSS_ERROR("last host command not handled by SP(%d)", last_cmd);
1381
1382        store_sp_array_uint(host_sp_com, offset, host2sp_command);
1383
1384        return (last_cmd == host2sp_cmd_ready);
1385}
1386
1387enum host2sp_commands
1388sh_css_read_host2sp_command(void)
1389{
1390        unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1391        unsigned int offset = (unsigned int)offsetof(struct host_sp_communication, host2sp_command)
1392        / sizeof(int);
1393        (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
1394        return (enum host2sp_commands)load_sp_array_uint(host_sp_com, offset);
1395}
1396
1397/*
1398 * Frame data is no longer part of the sp_stage structure but part of a
1399 * separate structure. The aim is to make the sp_data struct static
1400 * (it defines a pipeline) and that the dynamic (per frame) data is stored
1401 * separetly.
1402 *
1403 * This function must be called first every where were you start constructing
1404 * a new pipeline by defining one or more stages with use of variable
1405 * sh_css_sp_stage. Even the special cases like accelerator and copy_frame
1406 * These have a pipeline of just 1 stage.
1407 */
1408void
1409sh_css_init_host2sp_frame_data(void)
1410{
1411        /* Clean table */
1412        unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1413
1414        (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
1415        /*
1416         * rvanimme: don't clean it to save static frame info line ref_in
1417         * ref_out, and tnr_frames. Once this static data is in a
1418         * separate data struct, this may be enable (but still, there is
1419         * no need for it)
1420         */
1421}
1422
1423/*
1424 * @brief Update the offline frame information in host_sp_communication.
1425 * Refer to "sh_css_sp.h" for more details.
1426 */
1427void
1428sh_css_update_host2sp_offline_frame(
1429    unsigned int frame_num,
1430    struct ia_css_frame *frame,
1431    struct ia_css_metadata *metadata)
1432{
1433        unsigned int HIVE_ADDR_host_sp_com;
1434        unsigned int offset;
1435
1436        assert(frame_num < NUM_CONTINUOUS_FRAMES);
1437
1438        /* Write new frame data into SP DMEM */
1439        HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1440        offset = (unsigned int)offsetof(struct host_sp_communication,
1441                                        host2sp_offline_frames)
1442                 / sizeof(int);
1443        offset += frame_num;
1444        store_sp_array_uint(host_sp_com, offset, frame ? frame->data : 0);
1445
1446        /* Write metadata buffer into SP DMEM */
1447        offset = (unsigned int)offsetof(struct host_sp_communication,
1448                                        host2sp_offline_metadata)
1449                 / sizeof(int);
1450        offset += frame_num;
1451        store_sp_array_uint(host_sp_com, offset, metadata ? metadata->address : 0);
1452}
1453
1454/*
1455 * @brief Update the mipi frame information in host_sp_communication.
1456 * Refer to "sh_css_sp.h" for more details.
1457 */
1458void
1459sh_css_update_host2sp_mipi_frame(
1460    unsigned int frame_num,
1461    struct ia_css_frame *frame)
1462{
1463        unsigned int HIVE_ADDR_host_sp_com;
1464        unsigned int offset;
1465
1466        /* MIPI buffers are dedicated to port, so now there are more of them. */
1467        assert(frame_num < (N_CSI_PORTS * NUM_MIPI_FRAMES_PER_STREAM));
1468
1469        /* Write new frame data into SP DMEM */
1470        HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1471        offset = (unsigned int)offsetof(struct host_sp_communication,
1472                                        host2sp_mipi_frames)
1473                 / sizeof(int);
1474        offset += frame_num;
1475
1476        store_sp_array_uint(host_sp_com, offset,
1477                            frame ? frame->data : 0);
1478}
1479
1480/*
1481 * @brief Update the mipi metadata information in host_sp_communication.
1482 * Refer to "sh_css_sp.h" for more details.
1483 */
1484void
1485sh_css_update_host2sp_mipi_metadata(
1486    unsigned int frame_num,
1487    struct ia_css_metadata *metadata)
1488{
1489        unsigned int HIVE_ADDR_host_sp_com;
1490        unsigned int o;
1491
1492        /* MIPI buffers are dedicated to port, so now there are more of them. */
1493        assert(frame_num < (N_CSI_PORTS * NUM_MIPI_FRAMES_PER_STREAM));
1494
1495        /* Write new frame data into SP DMEM */
1496        HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1497        o = offsetof(struct host_sp_communication, host2sp_mipi_metadata)
1498            / sizeof(int);
1499        o += frame_num;
1500        store_sp_array_uint(host_sp_com, o,
1501                            metadata ? metadata->address : 0);
1502}
1503
1504void
1505sh_css_update_host2sp_num_mipi_frames(unsigned int num_frames)
1506{
1507        unsigned int HIVE_ADDR_host_sp_com;
1508        unsigned int offset;
1509
1510        /* Write new frame data into SP DMEM */
1511        HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1512        offset = (unsigned int)offsetof(struct host_sp_communication,
1513                                        host2sp_num_mipi_frames)
1514                 / sizeof(int);
1515
1516        store_sp_array_uint(host_sp_com, offset, num_frames);
1517}
1518
1519void
1520sh_css_update_host2sp_cont_num_raw_frames(unsigned int num_frames,
1521        bool set_avail)
1522{
1523        const struct ia_css_fw_info *fw;
1524        unsigned int HIVE_ADDR_host_sp_com;
1525        unsigned int extra_num_frames, avail_num_frames;
1526        unsigned int offset, offset_extra;
1527
1528        /* Write new frame data into SP DMEM */
1529        fw = &sh_css_sp_fw;
1530        HIVE_ADDR_host_sp_com = fw->info.sp.host_sp_com;
1531        if (set_avail) {
1532                offset = (unsigned int)offsetof(struct host_sp_communication,
1533                                                host2sp_cont_avail_num_raw_frames)
1534                         / sizeof(int);
1535                avail_num_frames = load_sp_array_uint(host_sp_com, offset);
1536                extra_num_frames = num_frames - avail_num_frames;
1537                offset_extra = (unsigned int)offsetof(struct host_sp_communication,
1538                                                      host2sp_cont_extra_num_raw_frames)
1539                               / sizeof(int);
1540                store_sp_array_uint(host_sp_com, offset_extra, extra_num_frames);
1541        } else
1542                offset = (unsigned int)offsetof(struct host_sp_communication,
1543                                                host2sp_cont_target_num_raw_frames)
1544                         / sizeof(int);
1545
1546        store_sp_array_uint(host_sp_com, offset, num_frames);
1547}
1548
1549void
1550sh_css_event_init_irq_mask(void)
1551{
1552        int i;
1553        unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1554        unsigned int offset;
1555        struct sh_css_event_irq_mask event_irq_mask_init;
1556
1557        event_irq_mask_init.or_mask  = IA_CSS_EVENT_TYPE_ALL;
1558        event_irq_mask_init.and_mask = IA_CSS_EVENT_TYPE_NONE;
1559        (void)HIVE_ADDR_host_sp_com; /* Suppress warnings in CRUN */
1560
1561        assert(sizeof(event_irq_mask_init) % HRT_BUS_BYTES == 0);
1562        for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
1563                offset = (unsigned int)offsetof(struct host_sp_communication,
1564                                                host2sp_event_irq_mask[i]);
1565                assert(offset % HRT_BUS_BYTES == 0);
1566                sp_dmem_store(SP0_ID,
1567                              (unsigned int)sp_address_of(host_sp_com) + offset,
1568                              &event_irq_mask_init, sizeof(event_irq_mask_init));
1569        }
1570}
1571
1572int
1573ia_css_pipe_set_irq_mask(struct ia_css_pipe *pipe,
1574                         unsigned int or_mask,
1575                         unsigned int and_mask)
1576{
1577        unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1578        unsigned int offset;
1579        struct sh_css_event_irq_mask event_irq_mask;
1580        unsigned int pipe_num;
1581
1582        assert(pipe);
1583
1584        assert(IA_CSS_PIPE_ID_NUM == NR_OF_PIPELINES);
1585        /* Linux kernel does not have UINT16_MAX
1586         * Therefore decided to comment out these 2 asserts for Linux
1587         * Alternatives that were not chosen:
1588         * - add a conditional #define for UINT16_MAX
1589         * - compare with (uint16_t)~0 or 0xffff
1590         * - different assert for Linux and Windows
1591         */
1592
1593        (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
1594
1595        IA_CSS_LOG("or_mask=%x, and_mask=%x", or_mask, and_mask);
1596        event_irq_mask.or_mask  = (uint16_t)or_mask;
1597        event_irq_mask.and_mask = (uint16_t)and_mask;
1598
1599        pipe_num = ia_css_pipe_get_pipe_num(pipe);
1600        if (pipe_num >= IA_CSS_PIPE_ID_NUM)
1601                return -EINVAL;
1602        offset = (unsigned int)offsetof(struct host_sp_communication,
1603                                        host2sp_event_irq_mask[pipe_num]);
1604        assert(offset % HRT_BUS_BYTES == 0);
1605        sp_dmem_store(SP0_ID,
1606                      (unsigned int)sp_address_of(host_sp_com) + offset,
1607                      &event_irq_mask, sizeof(event_irq_mask));
1608
1609        return 0;
1610}
1611
1612int
1613ia_css_event_get_irq_mask(const struct ia_css_pipe *pipe,
1614                          unsigned int *or_mask,
1615                          unsigned int *and_mask)
1616{
1617        unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1618        unsigned int offset;
1619        struct sh_css_event_irq_mask event_irq_mask;
1620        unsigned int pipe_num;
1621
1622        (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
1623
1624        IA_CSS_ENTER_LEAVE("");
1625
1626        assert(pipe);
1627        assert(IA_CSS_PIPE_ID_NUM == NR_OF_PIPELINES);
1628
1629        pipe_num = ia_css_pipe_get_pipe_num(pipe);
1630        if (pipe_num >= IA_CSS_PIPE_ID_NUM)
1631                return -EINVAL;
1632        offset = (unsigned int)offsetof(struct host_sp_communication,
1633                                        host2sp_event_irq_mask[pipe_num]);
1634        assert(offset % HRT_BUS_BYTES == 0);
1635        sp_dmem_load(SP0_ID,
1636                     (unsigned int)sp_address_of(host_sp_com) + offset,
1637                     &event_irq_mask, sizeof(event_irq_mask));
1638
1639        if (or_mask)
1640                *or_mask = event_irq_mask.or_mask;
1641
1642        if (and_mask)
1643                *and_mask = event_irq_mask.and_mask;
1644
1645        return 0;
1646}
1647
1648void
1649sh_css_sp_set_sp_running(bool flag)
1650{
1651        sp_running = flag;
1652}
1653
1654bool
1655sh_css_sp_is_running(void)
1656{
1657        return sp_running;
1658}
1659
1660void
1661sh_css_sp_start_isp(void)
1662{
1663        const struct ia_css_fw_info *fw;
1664        unsigned int HIVE_ADDR_sp_sw_state;
1665
1666        fw = &sh_css_sp_fw;
1667        HIVE_ADDR_sp_sw_state = fw->info.sp.sw_state;
1668
1669        if (sp_running)
1670                return;
1671
1672        (void)HIVE_ADDR_sp_sw_state; /* Suppres warnings in CRUN */
1673
1674        /* no longer here, sp started immediately */
1675        /*ia_css_debug_pipe_graph_dump_epilogue();*/
1676
1677        store_sp_group_data();
1678        store_sp_per_frame_data(fw);
1679
1680        sp_dmem_store_uint32(SP0_ID,
1681                             (unsigned int)sp_address_of(sp_sw_state),
1682                             (uint32_t)(IA_CSS_SP_SW_TERMINATED));
1683
1684        /* Note 1: The sp_start_isp function contains a wait till
1685         * the input network is configured by the SP.
1686         * Note 2: Not all SP binaries supports host2sp_commands.
1687         * In case a binary does support it, the host2sp_command
1688         * will have status cmd_ready after return of the function
1689         * sh_css_hrt_sp_start_isp. There is no race-condition here
1690         * because only after the process_frame command has been
1691         * received, the SP starts configuring the input network.
1692         */
1693
1694        /* we need to set sp_running before we call ia_css_mmu_invalidate_cache
1695         * as ia_css_mmu_invalidate_cache checks on sp_running to
1696         * avoid that it accesses dmem while the SP is not powered
1697         */
1698        sp_running = true;
1699        ia_css_mmu_invalidate_cache();
1700        /* Invalidate all MMU caches */
1701        mmu_invalidate_cache_all();
1702
1703        ia_css_spctrl_start(SP0_ID);
1704}
1705
1706bool
1707ia_css_isp_has_started(void)
1708{
1709        const struct ia_css_fw_info *fw = &sh_css_sp_fw;
1710        unsigned int HIVE_ADDR_ia_css_ispctrl_sp_isp_started = fw->info.sp.isp_started;
1711        (void)HIVE_ADDR_ia_css_ispctrl_sp_isp_started; /* Suppres warnings in CRUN */
1712
1713        return (bool)load_sp_uint(ia_css_ispctrl_sp_isp_started);
1714}
1715
1716/*
1717 * @brief Initialize the DMA software-mask in the debug mode.
1718 * Refer to "sh_css_sp.h" for more details.
1719 */
1720bool
1721sh_css_sp_init_dma_sw_reg(int dma_id)
1722{
1723        int i;
1724
1725        /* enable all the DMA channels */
1726        for (i = 0; i < N_DMA_CHANNEL_ID; i++) {
1727                /* enable the writing request */
1728                sh_css_sp_set_dma_sw_reg(dma_id,
1729                                         i,
1730                                         0,
1731                                         true);
1732                /* enable the reading request */
1733                sh_css_sp_set_dma_sw_reg(dma_id,
1734                                         i,
1735                                         1,
1736                                         true);
1737        }
1738
1739        return true;
1740}
1741
1742/*
1743 * @brief Set the DMA software-mask in the debug mode.
1744 * Refer to "sh_css_sp.h" for more details.
1745 */
1746bool
1747sh_css_sp_set_dma_sw_reg(int dma_id,
1748                         int channel_id,
1749                         int request_type,
1750                         bool enable)
1751{
1752        u32 sw_reg;
1753        u32 bit_val;
1754        u32 bit_offset;
1755        u32 bit_mask;
1756
1757        (void)dma_id;
1758
1759        assert(channel_id >= 0 && channel_id < N_DMA_CHANNEL_ID);
1760        assert(request_type >= 0);
1761
1762        /* get the software-mask */
1763        sw_reg =
1764            sh_css_sp_group.debug.dma_sw_reg;
1765
1766        /* get the offest of the target bit */
1767        bit_offset = (8 * request_type) + channel_id;
1768
1769        /* clear the value of the target bit */
1770        bit_mask = ~(1 << bit_offset);
1771        sw_reg &= bit_mask;
1772
1773        /* set the value of the bit for the DMA channel */
1774        bit_val = enable ? 1 : 0;
1775        bit_val <<= bit_offset;
1776        sw_reg |= bit_val;
1777
1778        /* update the software status of DMA channels */
1779        sh_css_sp_group.debug.dma_sw_reg = sw_reg;
1780
1781        return true;
1782}
1783
1784void
1785sh_css_sp_reset_global_vars(void)
1786{
1787        memset(&sh_css_sp_group, 0, sizeof(struct sh_css_sp_group));
1788        memset(&sh_css_sp_stage, 0, sizeof(struct sh_css_sp_stage));
1789        memset(&sh_css_isp_stage, 0, sizeof(struct sh_css_isp_stage));
1790        memset(&sh_css_sp_output, 0, sizeof(struct sh_css_sp_output));
1791        memset(&per_frame_data, 0, sizeof(struct sh_css_sp_per_frame_data));
1792}
1793