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