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