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