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