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