media: atomisp: Fix me->stages error checking in sh_css_sp_init_pipeline()
[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(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 #include "atomisp_internal.h"
55
56 #ifndef offsetof
57 #define offsetof(T, x) ((unsigned int)&(((T *)0)->x))
58 #endif
59
60 #define IA_CSS_INCLUDE_CONFIGURATIONS
61 #include "ia_css_isp_configs.h"
62 #define IA_CSS_INCLUDE_STATES
63 #include "ia_css_isp_states.h"
64
65 #include "isp/kernels/ipu2_io_ls/bayer_io_ls/ia_css_bayer_io.host.h"
66
67 struct sh_css_sp_group          sh_css_sp_group;
68 struct sh_css_sp_stage          sh_css_sp_stage;
69 struct sh_css_isp_stage         sh_css_isp_stage;
70 static struct sh_css_sp_output          sh_css_sp_output;
71 static struct sh_css_sp_per_frame_data per_frame_data;
72
73 /* true if SP supports frame loop and host2sp_commands */
74 /* For the moment there is only code that sets this bool to true */
75 /* TODO: add code that sets this bool to false */
76 static bool sp_running;
77
78 static int
79 set_output_frame_buffer(const struct ia_css_frame *frame,
80                         unsigned int idx);
81
82 static void
83 sh_css_copy_buffer_attr_to_spbuffer(struct ia_css_buffer_sp *dest_buf,
84                                     const enum sh_css_queue_id queue_id,
85                                     const ia_css_ptr xmem_addr,
86                                     const enum ia_css_buffer_type buf_type);
87
88 static void
89 initialize_frame_buffer_attribute(struct ia_css_buffer_sp *buf_attr);
90
91 static void
92 initialize_stage_frames(struct ia_css_frames_sp *frames);
93
94 /* This data is stored every frame */
95 void
96 store_sp_group_data(void)
97 {
98         per_frame_data.sp_group_addr = sh_css_store_sp_group_to_ddr();
99 }
100
101 static void
102 copy_isp_stage_to_sp_stage(void)
103 {
104         /* [WW07.5]type casting will cause potential issues */
105         sh_css_sp_stage.num_stripes = (uint8_t)
106                                       sh_css_isp_stage.binary_info.iterator.num_stripes;
107         sh_css_sp_stage.row_stripes_height = (uint16_t)
108                                              sh_css_isp_stage.binary_info.iterator.row_stripes_height;
109         sh_css_sp_stage.row_stripes_overlap_lines = (uint16_t)
110                 sh_css_isp_stage.binary_info.iterator.row_stripes_overlap_lines;
111         sh_css_sp_stage.top_cropping = (uint16_t)
112                                        sh_css_isp_stage.binary_info.pipeline.top_cropping;
113         /* moved to sh_css_sp_init_stage
114            sh_css_sp_stage.enable.vf_output =
115            sh_css_isp_stage.binary_info.enable.vf_veceven ||
116            sh_css_isp_stage.binary_info.num_output_pins > 1;
117         */
118         sh_css_sp_stage.enable.sdis = sh_css_isp_stage.binary_info.enable.dis;
119         sh_css_sp_stage.enable.s3a = sh_css_isp_stage.binary_info.enable.s3a;
120 }
121
122 void
123 store_sp_stage_data(enum ia_css_pipe_id id, unsigned int pipe_num,
124                     unsigned int stage)
125 {
126         unsigned int thread_id;
127
128         ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
129         copy_isp_stage_to_sp_stage();
130         if (id != IA_CSS_PIPE_ID_COPY)
131                 sh_css_sp_stage.isp_stage_addr =
132                     sh_css_store_isp_stage_to_ddr(pipe_num, stage);
133         sh_css_sp_group.pipe[thread_id].sp_stage_addr[stage] =
134             sh_css_store_sp_stage_to_ddr(pipe_num, stage);
135
136         /* Clear for next frame */
137         sh_css_sp_stage.program_input_circuit = false;
138 }
139
140 static void
141 store_sp_per_frame_data(const struct ia_css_fw_info *fw)
142 {
143         unsigned int HIVE_ADDR_sp_per_frame_data = 0;
144
145         assert(fw);
146
147         switch (fw->type) {
148         case ia_css_sp_firmware:
149                 HIVE_ADDR_sp_per_frame_data = fw->info.sp.per_frame_data;
150                 break;
151         case ia_css_acc_firmware:
152                 HIVE_ADDR_sp_per_frame_data = fw->info.acc.per_frame_data;
153                 break;
154         case ia_css_isp_firmware:
155                 return;
156         }
157
158         sp_dmem_store(SP0_ID,
159                       (unsigned int)sp_address_of(sp_per_frame_data),
160                       &per_frame_data,
161                       sizeof(per_frame_data));
162 }
163
164 static void
165 sh_css_store_sp_per_frame_data(enum ia_css_pipe_id pipe_id,
166                                unsigned int pipe_num,
167                                const struct ia_css_fw_info *sp_fw)
168 {
169         if (!sp_fw)
170                 sp_fw = &sh_css_sp_fw;
171
172         store_sp_stage_data(pipe_id, pipe_num, 0);
173         store_sp_group_data();
174         store_sp_per_frame_data(sp_fw);
175 }
176
177 #if SP_DEBUG != SP_DEBUG_NONE
178
179 void
180 sh_css_sp_get_debug_state(struct sh_css_sp_debug_state *state)
181 {
182         const struct ia_css_fw_info *fw = &sh_css_sp_fw;
183         unsigned int HIVE_ADDR_sp_output = fw->info.sp.output;
184         unsigned int i;
185         unsigned int offset = (unsigned int)offsetof(struct sh_css_sp_output,
186                               debug) / sizeof(int);
187
188         assert(state);
189
190         (void)HIVE_ADDR_sp_output; /* To get rid of warning in CRUN */
191         for (i = 0; i < sizeof(*state) / sizeof(int); i++)
192                 ((unsigned *)state)[i] = load_sp_array_uint(sp_output, i + offset);
193 }
194
195 #endif
196
197 void
198 sh_css_sp_start_binary_copy(unsigned int pipe_num,
199                             struct ia_css_frame *out_frame,
200                             unsigned int two_ppc)
201 {
202         enum ia_css_pipe_id pipe_id;
203         unsigned int thread_id;
204         struct sh_css_sp_pipeline *pipe;
205         u8 stage_num = 0;
206
207         assert(out_frame);
208         pipe_id = IA_CSS_PIPE_ID_CAPTURE;
209         ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
210         pipe = &sh_css_sp_group.pipe[thread_id];
211
212         pipe->copy.bin.bytes_available = out_frame->data_bytes;
213         pipe->num_stages = 1;
214         pipe->pipe_id = pipe_id;
215         pipe->pipe_num = pipe_num;
216         pipe->thread_id = thread_id;
217         pipe->pipe_config = 0x0; /* No parameters */
218         pipe->pipe_qos_config = QOS_INVALID;
219
220         if (pipe->inout_port_config == 0) {
221                 SH_CSS_PIPE_PORT_CONFIG_SET(pipe->inout_port_config,
222                                             (uint8_t)SH_CSS_PORT_INPUT,
223                                             (uint8_t)SH_CSS_HOST_TYPE, 1);
224                 SH_CSS_PIPE_PORT_CONFIG_SET(pipe->inout_port_config,
225                                             (uint8_t)SH_CSS_PORT_OUTPUT,
226                                             (uint8_t)SH_CSS_HOST_TYPE, 1);
227         }
228         IA_CSS_LOG("pipe_id %d port_config %08x",
229                    pipe->pipe_id, pipe->inout_port_config);
230
231 #if !defined(ISP2401)
232         sh_css_sp_group.config.input_formatter.isp_2ppc = (uint8_t)two_ppc;
233 #else
234         (void)two_ppc;
235 #endif
236
237         sh_css_sp_stage.num = stage_num;
238         sh_css_sp_stage.stage_type = SH_CSS_SP_STAGE_TYPE;
239         sh_css_sp_stage.func =
240             (unsigned int)IA_CSS_PIPELINE_BIN_COPY;
241
242         set_output_frame_buffer(out_frame, 0);
243
244         /* sp_bin_copy_init on the SP does not deal with dynamica/static yet */
245         /* For now always update the dynamic data from out frames. */
246         sh_css_store_sp_per_frame_data(pipe_id, pipe_num, &sh_css_sp_fw);
247 }
248
249 static void
250 sh_css_sp_start_raw_copy(struct ia_css_frame *out_frame,
251                          unsigned int pipe_num,
252                          unsigned int two_ppc,
253                          unsigned int max_input_width,
254                          enum sh_css_pipe_config_override pipe_conf_override,
255                          unsigned int if_config_index)
256 {
257         enum ia_css_pipe_id pipe_id;
258         unsigned int thread_id;
259         u8 stage_num = 0;
260         struct sh_css_sp_pipeline *pipe;
261
262         assert(out_frame);
263
264         {
265                 /*
266                  * Clear sh_css_sp_stage for easy debugging.
267                  * program_input_circuit must be saved as it is set outside
268                  * this function.
269                  */
270                 u8 program_input_circuit;
271
272                 program_input_circuit = sh_css_sp_stage.program_input_circuit;
273                 memset(&sh_css_sp_stage, 0, sizeof(sh_css_sp_stage));
274                 sh_css_sp_stage.program_input_circuit = program_input_circuit;
275         }
276
277         pipe_id = IA_CSS_PIPE_ID_COPY;
278         ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
279         pipe = &sh_css_sp_group.pipe[thread_id];
280
281         pipe->copy.raw.height       = out_frame->frame_info.res.height;
282         pipe->copy.raw.width        = out_frame->frame_info.res.width;
283         pipe->copy.raw.padded_width  = out_frame->frame_info.padded_width;
284         pipe->copy.raw.raw_bit_depth = out_frame->frame_info.raw_bit_depth;
285         pipe->copy.raw.max_input_width = max_input_width;
286         pipe->num_stages = 1;
287         pipe->pipe_id = pipe_id;
288         /* TODO: next indicates from which queues parameters need to be
289                  sampled, needs checking/improvement */
290         if (pipe_conf_override == SH_CSS_PIPE_CONFIG_OVRD_NO_OVRD)
291                 pipe->pipe_config =
292                     (SH_CSS_PIPE_CONFIG_SAMPLE_PARAMS << thread_id);
293         else
294                 pipe->pipe_config = pipe_conf_override;
295
296         pipe->pipe_qos_config = QOS_INVALID;
297
298         if (pipe->inout_port_config == 0) {
299                 SH_CSS_PIPE_PORT_CONFIG_SET(pipe->inout_port_config,
300                                             (uint8_t)SH_CSS_PORT_INPUT,
301                                             (uint8_t)SH_CSS_HOST_TYPE, 1);
302                 SH_CSS_PIPE_PORT_CONFIG_SET(pipe->inout_port_config,
303                                             (uint8_t)SH_CSS_PORT_OUTPUT,
304                                             (uint8_t)SH_CSS_HOST_TYPE, 1);
305         }
306         IA_CSS_LOG("pipe_id %d port_config %08x",
307                    pipe->pipe_id, pipe->inout_port_config);
308
309 #if !defined(ISP2401)
310         sh_css_sp_group.config.input_formatter.isp_2ppc = (uint8_t)two_ppc;
311 #else
312         (void)two_ppc;
313 #endif
314
315         sh_css_sp_stage.num = stage_num;
316         sh_css_sp_stage.xmem_bin_addr = 0x0;
317         sh_css_sp_stage.stage_type = SH_CSS_SP_STAGE_TYPE;
318         sh_css_sp_stage.func = (unsigned int)IA_CSS_PIPELINE_RAW_COPY;
319         sh_css_sp_stage.if_config_index = (uint8_t)if_config_index;
320         set_output_frame_buffer(out_frame, 0);
321
322         ia_css_debug_pipe_graph_dump_sp_raw_copy(out_frame);
323 }
324
325 static void
326 sh_css_sp_start_isys_copy(struct ia_css_frame *out_frame,
327                           unsigned int pipe_num, unsigned int max_input_width,
328                           unsigned int if_config_index)
329 {
330         enum ia_css_pipe_id pipe_id;
331         unsigned int thread_id;
332         u8 stage_num = 0;
333         struct sh_css_sp_pipeline *pipe;
334         enum sh_css_queue_id queue_id;
335
336         assert(out_frame);
337
338         {
339                 /*
340                  * Clear sh_css_sp_stage for easy debugging.
341                  * program_input_circuit must be saved as it is set outside
342                  * this function.
343                  */
344                 u8 program_input_circuit;
345
346                 program_input_circuit = sh_css_sp_stage.program_input_circuit;
347                 memset(&sh_css_sp_stage, 0, sizeof(sh_css_sp_stage));
348                 sh_css_sp_stage.program_input_circuit = program_input_circuit;
349         }
350
351         pipe_id = IA_CSS_PIPE_ID_COPY;
352         ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
353         pipe = &sh_css_sp_group.pipe[thread_id];
354
355         pipe->copy.raw.height           = out_frame->frame_info.res.height;
356         pipe->copy.raw.width            = out_frame->frame_info.res.width;
357         pipe->copy.raw.padded_width     = out_frame->frame_info.padded_width;
358         pipe->copy.raw.raw_bit_depth    = out_frame->frame_info.raw_bit_depth;
359         pipe->copy.raw.max_input_width  = max_input_width;
360         pipe->num_stages                = 1;
361         pipe->pipe_id                   = pipe_id;
362         pipe->pipe_config               = 0x0;  /* No parameters */
363         pipe->pipe_qos_config           = QOS_INVALID;
364
365         initialize_stage_frames(&sh_css_sp_stage.frames);
366         sh_css_sp_stage.num = stage_num;
367         sh_css_sp_stage.xmem_bin_addr = 0x0;
368         sh_css_sp_stage.stage_type = SH_CSS_SP_STAGE_TYPE;
369         sh_css_sp_stage.func = (unsigned int)IA_CSS_PIPELINE_ISYS_COPY;
370         sh_css_sp_stage.if_config_index = (uint8_t)if_config_index;
371
372         set_output_frame_buffer(out_frame, 0);
373
374         if (pipe->metadata.height > 0) {
375                 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_METADATA, thread_id,
376                                                &queue_id);
377                 sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.metadata_buf,
378                                                     queue_id, mmgr_EXCEPTION,
379                                                     IA_CSS_BUFFER_TYPE_METADATA);
380         }
381
382         ia_css_debug_pipe_graph_dump_sp_raw_copy(out_frame);
383 }
384
385 unsigned int
386 sh_css_sp_get_binary_copy_size(void)
387 {
388         const struct ia_css_fw_info *fw = &sh_css_sp_fw;
389         unsigned int HIVE_ADDR_sp_output = fw->info.sp.output;
390         unsigned int offset = (unsigned int)offsetof(struct sh_css_sp_output,
391                               bin_copy_bytes_copied) / sizeof(int);
392         (void)HIVE_ADDR_sp_output; /* To get rid of warning in CRUN */
393         return load_sp_array_uint(sp_output, offset);
394 }
395
396 unsigned int
397 sh_css_sp_get_sw_interrupt_value(unsigned int irq)
398 {
399         const struct ia_css_fw_info *fw = &sh_css_sp_fw;
400         unsigned int HIVE_ADDR_sp_output = fw->info.sp.output;
401         unsigned int offset = (unsigned int)offsetof(struct sh_css_sp_output,
402                               sw_interrupt_value)
403                               / sizeof(int);
404         (void)HIVE_ADDR_sp_output; /* To get rid of warning in CRUN */
405         return load_sp_array_uint(sp_output, offset + irq);
406 }
407
408 static void
409 sh_css_copy_buffer_attr_to_spbuffer(struct ia_css_buffer_sp *dest_buf,
410                                     const enum sh_css_queue_id queue_id,
411                                     const ia_css_ptr xmem_addr,
412                                     const enum ia_css_buffer_type buf_type)
413 {
414         assert(buf_type < IA_CSS_NUM_BUFFER_TYPE);
415         if (queue_id > SH_CSS_INVALID_QUEUE_ID) {
416                 /*
417                  * value >=0 indicates that function init_frame_pointers()
418                  * should use the dynamic data address
419                  */
420                 assert(queue_id < SH_CSS_MAX_NUM_QUEUES);
421
422                 /* Klocwork assumes assert can be disabled;
423                    Since we can get there with any type, and it does not
424                    know that frame_in->dynamic_data_index can only be set
425                    for one of the types in the assert) it has to assume we
426                    can get here for any type. however this could lead to an
427                    out of bounds reference when indexing buf_type about 10
428                    lines below. In order to satisfy KW an additional if
429                    has been added. This one will always yield true.
430                  */
431                 if ((queue_id < SH_CSS_MAX_NUM_QUEUES)) {
432                         dest_buf->buf_src.queue_id = queue_id;
433                 }
434         } else {
435                 assert(xmem_addr != mmgr_EXCEPTION);
436                 dest_buf->buf_src.xmem_addr = xmem_addr;
437         }
438         dest_buf->buf_type = buf_type;
439 }
440
441 static void
442 sh_css_copy_frame_to_spframe(struct ia_css_frame_sp *sp_frame_out,
443                              const struct ia_css_frame *frame_in)
444 {
445         assert(frame_in);
446
447         ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
448                             "sh_css_copy_frame_to_spframe():\n");
449
450         sh_css_copy_buffer_attr_to_spbuffer(&sp_frame_out->buf_attr,
451                                             frame_in->dynamic_queue_id,
452                                             frame_in->data,
453                                             frame_in->buf_type);
454
455         ia_css_frame_info_to_frame_sp_info(&sp_frame_out->info, &frame_in->frame_info);
456
457         switch (frame_in->frame_info.format) {
458         case IA_CSS_FRAME_FORMAT_RAW_PACKED:
459         case IA_CSS_FRAME_FORMAT_RAW:
460                 sp_frame_out->planes.raw.offset = frame_in->planes.raw.offset;
461                 break;
462         case IA_CSS_FRAME_FORMAT_RGB565:
463         case IA_CSS_FRAME_FORMAT_RGBA888:
464                 sp_frame_out->planes.rgb.offset = frame_in->planes.rgb.offset;
465                 break;
466         case IA_CSS_FRAME_FORMAT_PLANAR_RGB888:
467                 sp_frame_out->planes.planar_rgb.r.offset =
468                     frame_in->planes.planar_rgb.r.offset;
469                 sp_frame_out->planes.planar_rgb.g.offset =
470                     frame_in->planes.planar_rgb.g.offset;
471                 sp_frame_out->planes.planar_rgb.b.offset =
472                     frame_in->planes.planar_rgb.b.offset;
473                 break;
474         case IA_CSS_FRAME_FORMAT_YUYV:
475         case IA_CSS_FRAME_FORMAT_UYVY:
476         case IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8:
477         case IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8:
478         case IA_CSS_FRAME_FORMAT_YUV_LINE:
479                 sp_frame_out->planes.yuyv.offset = frame_in->planes.yuyv.offset;
480                 break;
481         case IA_CSS_FRAME_FORMAT_NV11:
482         case IA_CSS_FRAME_FORMAT_NV12:
483         case IA_CSS_FRAME_FORMAT_NV12_16:
484         case IA_CSS_FRAME_FORMAT_NV12_TILEY:
485         case IA_CSS_FRAME_FORMAT_NV21:
486         case IA_CSS_FRAME_FORMAT_NV16:
487         case IA_CSS_FRAME_FORMAT_NV61:
488                 sp_frame_out->planes.nv.y.offset =
489                     frame_in->planes.nv.y.offset;
490                 sp_frame_out->planes.nv.uv.offset =
491                     frame_in->planes.nv.uv.offset;
492                 break;
493         case IA_CSS_FRAME_FORMAT_YUV420:
494         case IA_CSS_FRAME_FORMAT_YUV422:
495         case IA_CSS_FRAME_FORMAT_YUV444:
496         case IA_CSS_FRAME_FORMAT_YUV420_16:
497         case IA_CSS_FRAME_FORMAT_YUV422_16:
498         case IA_CSS_FRAME_FORMAT_YV12:
499         case IA_CSS_FRAME_FORMAT_YV16:
500                 sp_frame_out->planes.yuv.y.offset =
501                     frame_in->planes.yuv.y.offset;
502                 sp_frame_out->planes.yuv.u.offset =
503                     frame_in->planes.yuv.u.offset;
504                 sp_frame_out->planes.yuv.v.offset =
505                     frame_in->planes.yuv.v.offset;
506                 break;
507         case IA_CSS_FRAME_FORMAT_QPLANE6:
508                 sp_frame_out->planes.plane6.r.offset =
509                     frame_in->planes.plane6.r.offset;
510                 sp_frame_out->planes.plane6.r_at_b.offset =
511                     frame_in->planes.plane6.r_at_b.offset;
512                 sp_frame_out->planes.plane6.gr.offset =
513                     frame_in->planes.plane6.gr.offset;
514                 sp_frame_out->planes.plane6.gb.offset =
515                     frame_in->planes.plane6.gb.offset;
516                 sp_frame_out->planes.plane6.b.offset =
517                     frame_in->planes.plane6.b.offset;
518                 sp_frame_out->planes.plane6.b_at_r.offset =
519                     frame_in->planes.plane6.b_at_r.offset;
520                 break;
521         case IA_CSS_FRAME_FORMAT_BINARY_8:
522                 sp_frame_out->planes.binary.data.offset =
523                     frame_in->planes.binary.data.offset;
524                 break;
525         default:
526                 /* This should not happen, but in case it does,
527                  * nullify the planes
528                  */
529                 memset(&sp_frame_out->planes, 0, sizeof(sp_frame_out->planes));
530                 break;
531         }
532 }
533
534 static int
535 set_input_frame_buffer(const struct ia_css_frame *frame)
536 {
537         if (!frame)
538                 return -EINVAL;
539
540         switch (frame->frame_info.format) {
541         case IA_CSS_FRAME_FORMAT_QPLANE6:
542         case IA_CSS_FRAME_FORMAT_YUV420_16:
543         case IA_CSS_FRAME_FORMAT_RAW_PACKED:
544         case IA_CSS_FRAME_FORMAT_RAW:
545         case IA_CSS_FRAME_FORMAT_YUV420:
546         case IA_CSS_FRAME_FORMAT_YUYV:
547         case IA_CSS_FRAME_FORMAT_YUV_LINE:
548         case IA_CSS_FRAME_FORMAT_NV12:
549         case IA_CSS_FRAME_FORMAT_NV12_16:
550         case IA_CSS_FRAME_FORMAT_NV12_TILEY:
551         case IA_CSS_FRAME_FORMAT_NV21:
552         case IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8:
553         case IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8:
554         case IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_10:
555                 break;
556         default:
557                 return -EINVAL;
558         }
559         sh_css_copy_frame_to_spframe(&sh_css_sp_stage.frames.in, frame);
560
561         return 0;
562 }
563
564 static int
565 set_output_frame_buffer(const struct ia_css_frame *frame,
566                         unsigned int idx)
567 {
568         if (!frame)
569                 return -EINVAL;
570
571         switch (frame->frame_info.format) {
572         case IA_CSS_FRAME_FORMAT_YUV420:
573         case IA_CSS_FRAME_FORMAT_YUV422:
574         case IA_CSS_FRAME_FORMAT_YUV444:
575         case IA_CSS_FRAME_FORMAT_YV12:
576         case IA_CSS_FRAME_FORMAT_YV16:
577         case IA_CSS_FRAME_FORMAT_YUV420_16:
578         case IA_CSS_FRAME_FORMAT_YUV422_16:
579         case IA_CSS_FRAME_FORMAT_NV11:
580         case IA_CSS_FRAME_FORMAT_NV12:
581         case IA_CSS_FRAME_FORMAT_NV12_16:
582         case IA_CSS_FRAME_FORMAT_NV12_TILEY:
583         case IA_CSS_FRAME_FORMAT_NV16:
584         case IA_CSS_FRAME_FORMAT_NV21:
585         case IA_CSS_FRAME_FORMAT_NV61:
586         case IA_CSS_FRAME_FORMAT_YUYV:
587         case IA_CSS_FRAME_FORMAT_UYVY:
588         case IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8:
589         case IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8:
590         case IA_CSS_FRAME_FORMAT_YUV_LINE:
591         case IA_CSS_FRAME_FORMAT_RGB565:
592         case IA_CSS_FRAME_FORMAT_RGBA888:
593         case IA_CSS_FRAME_FORMAT_PLANAR_RGB888:
594         case IA_CSS_FRAME_FORMAT_RAW:
595         case IA_CSS_FRAME_FORMAT_RAW_PACKED:
596         case IA_CSS_FRAME_FORMAT_QPLANE6:
597         case IA_CSS_FRAME_FORMAT_BINARY_8:
598                 break;
599         default:
600                 return -EINVAL;
601         }
602         sh_css_copy_frame_to_spframe(&sh_css_sp_stage.frames.out[idx], frame);
603         return 0;
604 }
605
606 static int
607 set_view_finder_buffer(const struct ia_css_frame *frame)
608 {
609         if (!frame)
610                 return -EINVAL;
611
612         switch (frame->frame_info.format) {
613         /* the dual output pin */
614         case IA_CSS_FRAME_FORMAT_NV12:
615         case IA_CSS_FRAME_FORMAT_NV12_16:
616         case IA_CSS_FRAME_FORMAT_NV21:
617         case IA_CSS_FRAME_FORMAT_YUYV:
618         case IA_CSS_FRAME_FORMAT_UYVY:
619         case IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8:
620         case IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8:
621         case IA_CSS_FRAME_FORMAT_YUV420:
622         case IA_CSS_FRAME_FORMAT_YV12:
623         case IA_CSS_FRAME_FORMAT_NV12_TILEY:
624
625         /* for vf_veceven */
626         case IA_CSS_FRAME_FORMAT_YUV_LINE:
627                 break;
628         default:
629                 return -EINVAL;
630         }
631
632         sh_css_copy_frame_to_spframe(&sh_css_sp_stage.frames.out_vf, frame);
633         return 0;
634 }
635
636 #if !defined(ISP2401)
637 void sh_css_sp_set_if_configs(
638     const input_formatter_cfg_t *config_a,
639     const input_formatter_cfg_t *config_b,
640     const uint8_t               if_config_index
641 )
642 {
643         assert(if_config_index < SH_CSS_MAX_IF_CONFIGS);
644         assert(config_a);
645
646         sh_css_sp_group.config.input_formatter.set[if_config_index].config_a =
647             *config_a;
648         sh_css_sp_group.config.input_formatter.a_changed = true;
649
650         if (config_b) {
651                 sh_css_sp_group.config.input_formatter.set[if_config_index].config_b =
652                     *config_b;
653                 sh_css_sp_group.config.input_formatter.b_changed = true;
654         }
655
656         return;
657 }
658 #endif
659
660 #if !defined(ISP2401)
661 void
662 sh_css_sp_program_input_circuit(int fmt_type,
663                                 int ch_id,
664                                 enum ia_css_input_mode input_mode)
665 {
666         sh_css_sp_group.config.input_circuit.no_side_band = false;
667         sh_css_sp_group.config.input_circuit.fmt_type     = fmt_type;
668         sh_css_sp_group.config.input_circuit.ch_id            = ch_id;
669         sh_css_sp_group.config.input_circuit.input_mode   = input_mode;
670         /*
671          * The SP group is only loaded at SP boot time and is read once
672          * change flags as "input_circuit_cfg_changed" must be reset on the SP
673          */
674         sh_css_sp_group.config.input_circuit_cfg_changed = true;
675         sh_css_sp_stage.program_input_circuit = true;
676 }
677 #endif
678
679 #if !defined(ISP2401)
680 void
681 sh_css_sp_configure_sync_gen(int width, int height,
682                              int hblank_cycles,
683                              int vblank_cycles)
684 {
685         sh_css_sp_group.config.sync_gen.width          = width;
686         sh_css_sp_group.config.sync_gen.height         = height;
687         sh_css_sp_group.config.sync_gen.hblank_cycles = hblank_cycles;
688         sh_css_sp_group.config.sync_gen.vblank_cycles = vblank_cycles;
689 }
690
691 void
692 sh_css_sp_configure_tpg(int x_mask,
693                         int y_mask,
694                         int x_delta,
695                         int y_delta,
696                         int xy_mask)
697 {
698         sh_css_sp_group.config.tpg.x_mask  = x_mask;
699         sh_css_sp_group.config.tpg.y_mask  = y_mask;
700         sh_css_sp_group.config.tpg.x_delta = x_delta;
701         sh_css_sp_group.config.tpg.y_delta = y_delta;
702         sh_css_sp_group.config.tpg.xy_mask = xy_mask;
703 }
704
705 void
706 sh_css_sp_configure_prbs(int seed)
707 {
708         sh_css_sp_group.config.prbs.seed = seed;
709 }
710 #endif
711
712 void
713 sh_css_sp_configure_enable_raw_pool_locking(bool lock_all)
714 {
715         sh_css_sp_group.config.enable_raw_pool_locking = true;
716         sh_css_sp_group.config.lock_all = lock_all;
717 }
718
719 void
720 sh_css_sp_enable_isys_event_queue(bool enable)
721 {
722         sh_css_sp_group.config.enable_isys_event_queue = enable;
723 }
724
725 void
726 sh_css_sp_set_disable_continuous_viewfinder(bool flag)
727 {
728         sh_css_sp_group.config.disable_cont_vf = flag;
729 }
730
731 static int
732 sh_css_sp_write_frame_pointers(const struct sh_css_binary_args *args)
733 {
734         int err = 0;
735         int i;
736
737         assert(args);
738
739         if (args->in_frame)
740                 err = set_input_frame_buffer(args->in_frame);
741         if (!err && args->out_vf_frame)
742                 err = set_view_finder_buffer(args->out_vf_frame);
743         for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) {
744                 if (!err && args->out_frame[i])
745                         err = set_output_frame_buffer(args->out_frame[i], i);
746         }
747
748         /* we don't pass this error back to the upper layer, so we add a assert here
749            because we actually hit the error here but it still works by accident... */
750         if (err) assert(false);
751         return err;
752 }
753
754 static void
755 sh_css_sp_init_group(bool two_ppc,
756                      enum atomisp_input_format input_format,
757                      bool no_isp_sync,
758                      uint8_t if_config_index)
759 {
760 #if !defined(ISP2401)
761         sh_css_sp_group.config.input_formatter.isp_2ppc = two_ppc;
762 #else
763         (void)two_ppc;
764 #endif
765
766         sh_css_sp_group.config.no_isp_sync = (uint8_t)no_isp_sync;
767         /* decide whether the frame is processed online or offline */
768         if (if_config_index == SH_CSS_IF_CONFIG_NOT_NEEDED) return;
769 #if !defined(ISP2401)
770         assert(if_config_index < SH_CSS_MAX_IF_CONFIGS);
771         sh_css_sp_group.config.input_formatter.set[if_config_index].stream_format =
772             input_format;
773 #else
774         (void)input_format;
775 #endif
776 }
777
778 void
779 sh_css_stage_write_binary_info(struct ia_css_binary_info *info)
780 {
781         assert(info);
782         sh_css_isp_stage.binary_info = *info;
783 }
784
785 static int
786 copy_isp_mem_if_to_ddr(struct ia_css_binary *binary)
787 {
788         int err;
789
790         err = ia_css_isp_param_copy_isp_mem_if_to_ddr(
791             &binary->css_params,
792             &binary->mem_params,
793             IA_CSS_PARAM_CLASS_CONFIG);
794         if (err)
795                 return err;
796         err = ia_css_isp_param_copy_isp_mem_if_to_ddr(
797             &binary->css_params,
798             &binary->mem_params,
799             IA_CSS_PARAM_CLASS_STATE);
800         if (err)
801                 return err;
802         return 0;
803 }
804
805 static bool
806 is_sp_stage(struct ia_css_pipeline_stage *stage)
807 {
808         assert(stage);
809         return stage->sp_func != IA_CSS_PIPELINE_NO_FUNC;
810 }
811
812 static int configure_isp_from_args(const struct sh_css_sp_pipeline *pipeline,
813                                    const struct ia_css_binary      *binary,
814                                    const struct sh_css_binary_args *args,
815                                    bool                            two_ppc,
816                                    bool                            deinterleaved)
817 {
818         int ret;
819
820         ret = ia_css_fpn_configure(binary,  &binary->in_frame_info);
821         if (ret)
822                 return ret;
823         ret = ia_css_crop_configure(binary, ia_css_frame_get_info(args->delay_frames[0]));
824         if (ret)
825                 return ret;
826         ret = ia_css_qplane_configure(pipeline, binary, &binary->in_frame_info);
827         if (ret)
828                 return ret;
829         ret = ia_css_output0_configure(binary, ia_css_frame_get_info(args->out_frame[0]));
830         if (ret)
831                 return ret;
832         ret = ia_css_output1_configure(binary, ia_css_frame_get_info(args->out_vf_frame));
833         if (ret)
834                 return ret;
835         ret = ia_css_copy_output_configure(binary, args->copy_output);
836         if (ret)
837                 return ret;
838         ret = ia_css_output0_configure(binary, ia_css_frame_get_info(args->out_frame[0]));
839         if (ret)
840                 return ret;
841         ret = ia_css_iterator_configure(binary, ia_css_frame_get_info(args->in_frame));
842         if (ret)
843                 return ret;
844         ret = ia_css_dvs_configure(binary, ia_css_frame_get_info(args->out_frame[0]));
845         if (ret)
846                 return ret;
847         ret = ia_css_output_configure(binary, ia_css_frame_get_info(args->out_frame[0]));
848         if (ret)
849                 return ret;
850         ret = ia_css_raw_configure(pipeline, binary, ia_css_frame_get_info(args->in_frame),
851                                    &binary->in_frame_info, two_ppc, deinterleaved);
852         if (ret)
853                 return ret;
854
855         /*
856          * FIXME: args->delay_frames can be NULL here
857          *
858          * Somehow, the driver at the Intel Atom Yocto tree doesn't seem to
859          * suffer from the same issue.
860          *
861          * Anyway, the function below should now handle a NULL delay_frames
862          * without crashing, but the pipeline should likely be built without
863          * adding it at the first place (or there are a hidden bug somewhere)
864          */
865         ret = ia_css_ref_configure(binary, args->delay_frames, pipeline->dvs_frame_delay);
866         if (ret)
867                 return ret;
868         ret = ia_css_tnr_configure(binary, args->tnr_frames);
869         if (ret)
870                 return ret;
871         return ia_css_bayer_io_config(binary, args);
872 }
873
874 static void
875 initialize_isp_states(const struct ia_css_binary *binary)
876 {
877         unsigned int i;
878
879         if (!binary->info->mem_offsets.offsets.state)
880                 return;
881         for (i = 0; i < IA_CSS_NUM_STATE_IDS; i++) {
882                 ia_css_kernel_init_state[i](binary);
883         }
884 }
885
886 static void
887 initialize_frame_buffer_attribute(struct ia_css_buffer_sp *buf_attr)
888 {
889         buf_attr->buf_src.queue_id = SH_CSS_INVALID_QUEUE_ID;
890         buf_attr->buf_type = IA_CSS_BUFFER_TYPE_INVALID;
891 }
892
893 static void
894 initialize_stage_frames(struct ia_css_frames_sp *frames)
895 {
896         unsigned int i;
897
898         initialize_frame_buffer_attribute(&frames->in.buf_attr);
899         for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) {
900                 initialize_frame_buffer_attribute(&frames->out[i].buf_attr);
901         }
902         initialize_frame_buffer_attribute(&frames->out_vf.buf_attr);
903         initialize_frame_buffer_attribute(&frames->s3a_buf);
904         initialize_frame_buffer_attribute(&frames->dvs_buf);
905         initialize_frame_buffer_attribute(&frames->metadata_buf);
906 }
907
908 static int
909 sh_css_sp_init_stage(struct ia_css_binary *binary,
910                      const char *binary_name,
911                      const struct ia_css_blob_info *blob_info,
912                      const struct sh_css_binary_args *args,
913                      unsigned int pipe_num,
914                      unsigned int stage,
915                      bool xnr,
916                      const struct ia_css_isp_param_css_segments *isp_mem_if,
917                      unsigned int if_config_index,
918                      bool two_ppc)
919 {
920         const struct ia_css_binary_xinfo *xinfo;
921         const struct ia_css_binary_info  *info;
922         int err = 0;
923         int i;
924         struct ia_css_pipe *pipe = NULL;
925         unsigned int thread_id;
926         enum sh_css_queue_id queue_id;
927         bool continuous = sh_css_continuous_is_enabled((uint8_t)pipe_num);
928
929         assert(binary);
930         assert(blob_info);
931         assert(args);
932         assert(isp_mem_if);
933
934         xinfo = binary->info;
935         info  = &xinfo->sp;
936         {
937                 /*
938                  * Clear sh_css_sp_stage for easy debugging.
939                  * program_input_circuit must be saved as it is set outside
940                  * this function.
941                  */
942                 u8 program_input_circuit;
943
944                 program_input_circuit = sh_css_sp_stage.program_input_circuit;
945                 memset(&sh_css_sp_stage, 0, sizeof(sh_css_sp_stage));
946                 sh_css_sp_stage.program_input_circuit = (uint8_t)program_input_circuit;
947         }
948
949         ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
950
951         if (!info) {
952                 sh_css_sp_group.pipe[thread_id].sp_stage_addr[stage] = mmgr_NULL;
953                 return 0;
954         }
955
956         if (IS_ISP2401)
957                 sh_css_sp_stage.deinterleaved = 0;
958         else
959                 sh_css_sp_stage.deinterleaved = ((stage == 0) && continuous);
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->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]->frame_info;
1128                 info = &firmware->info.isp;
1129                 ia_css_binary_fill_info(info, false, false,
1130                                         ATOMISP_INPUT_FORMAT_RAW_10,
1131                                         ia_css_frame_get_info(args->in_frame),
1132                                         NULL,
1133                                         out_infos,
1134                                         ia_css_frame_get_info(args->out_vf_frame),
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                 /* SP stage */
1145                 assert(stage->sp_func != IA_CSS_PIPELINE_NO_FUNC);
1146                 /* binary and blob_info are now NULL.
1147                    These will be passed to sh_css_sp_init_stage
1148                    and dereferenced there, so passing a NULL
1149                    pointer is no good. return an error */
1150                 return -EINVAL;
1151         }
1152
1153         err = sh_css_sp_init_stage(binary,
1154                                    (const char *)binary_name,
1155                                    blob_info,
1156                                    args,
1157                                    pipe_num,
1158                                    stage_num,
1159                                    xnr,
1160                                    mem_if,
1161                                    if_config_index,
1162                                    two_ppc);
1163         return err;
1164 }
1165
1166 static void
1167 sp_init_sp_stage(struct ia_css_pipeline_stage *stage,
1168                  unsigned int pipe_num,
1169                  bool two_ppc,
1170                  enum sh_css_pipe_config_override copy_ovrd,
1171                  unsigned int if_config_index)
1172 {
1173         const struct sh_css_binary_args *args = &stage->args;
1174
1175         assert(stage);
1176         switch (stage->sp_func) {
1177         case IA_CSS_PIPELINE_RAW_COPY:
1178                 sh_css_sp_start_raw_copy(args->out_frame[0],
1179                                          pipe_num, two_ppc,
1180                                          stage->max_input_width,
1181                                          copy_ovrd, if_config_index);
1182                 break;
1183         case IA_CSS_PIPELINE_BIN_COPY:
1184                 assert(false); /* TBI */
1185                 break;
1186         case IA_CSS_PIPELINE_ISYS_COPY:
1187                 sh_css_sp_start_isys_copy(args->out_frame[0],
1188                                           pipe_num, stage->max_input_width, if_config_index);
1189                 break;
1190         case IA_CSS_PIPELINE_NO_FUNC:
1191                 assert(false);
1192                 break;
1193         }
1194 }
1195
1196 void
1197 sh_css_sp_init_pipeline(struct ia_css_pipeline *me,
1198                         enum ia_css_pipe_id id,
1199                         u8 pipe_num,
1200                         bool xnr,
1201                         bool two_ppc,
1202                         bool continuous,
1203                         bool offline,
1204                         unsigned int required_bds_factor,
1205                         enum sh_css_pipe_config_override copy_ovrd,
1206                         enum ia_css_input_mode input_mode,
1207                         const struct ia_css_metadata_config *md_config,
1208                         const struct ia_css_metadata_info *md_info,
1209                         const enum mipi_port_id port_id)
1210 {
1211         /* Get first stage */
1212         struct ia_css_pipeline_stage *stage        = NULL;
1213         struct ia_css_binary         *first_binary = NULL;
1214         struct ia_css_pipe *pipe = NULL;
1215         unsigned int num;
1216         enum ia_css_pipe_id pipe_id = id;
1217         unsigned int thread_id;
1218         u8 if_config_index, tmp_if_config_index;
1219
1220         if (!me->stages) {
1221                 dev_err(atomisp_dev, "%s called on a pipeline without stages\n",
1222                         __func__);
1223                 return; /* FIXME should be able to return an error */
1224         }
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 &&
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 = QOS_INVALID;
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 }