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