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