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