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