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