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 if (!frame)
540 return -EINVAL;
541
542 switch (frame->info.format)
543 {
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 if (!frame)
571 return -EINVAL;
572
573 switch (frame->info.format)
574 {
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 if (!frame)
612 return -EINVAL;
613
614 switch (frame->info.format)
615 {
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 int err = 0;
737 int i;
738
739 assert(args);
740
741 if (args->in_frame)
742 err = set_input_frame_buffer(args->in_frame);
743 if (!err && args->out_vf_frame)
744 err = set_view_finder_buffer(args->out_vf_frame);
745 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
746 {
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 int err;
791
792 err = ia_css_isp_param_copy_isp_mem_if_to_ddr(
793 &binary->css_params,
794 &binary->mem_params,
795 IA_CSS_PARAM_CLASS_CONFIG);
796 if (err)
797 return err;
798 err = ia_css_isp_param_copy_isp_mem_if_to_ddr(
799 &binary->css_params,
800 &binary->mem_params,
801 IA_CSS_PARAM_CLASS_STATE);
802 if (err)
803 return err;
804 return 0;
805 }
806
807 static bool
is_sp_stage(struct ia_css_pipeline_stage * stage)808 is_sp_stage(struct ia_css_pipeline_stage *stage)
809 {
810 assert(stage);
811 return stage->sp_func != IA_CSS_PIPELINE_NO_FUNC;
812 }
813
814 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)815 configure_isp_from_args(
816 const struct sh_css_sp_pipeline *pipeline,
817 const struct ia_css_binary *binary,
818 const struct sh_css_binary_args *args,
819 bool two_ppc,
820 bool deinterleaved) {
821 ia_css_fpn_configure(binary, &binary->in_frame_info);
822 ia_css_crop_configure(binary, &args->delay_frames[0]->info);
823 ia_css_qplane_configure(pipeline, binary, &binary->in_frame_info);
824 ia_css_output0_configure(binary, &args->out_frame[0]->info);
825 ia_css_output1_configure(binary, &args->out_vf_frame->info);
826 ia_css_copy_output_configure(binary, args->copy_output);
827 ia_css_output0_configure(binary, &args->out_frame[0]->info);
828 #ifdef ISP2401
829 ia_css_sc_configure(binary, pipeline->shading.internal_frame_origin_x_bqs_on_sctbl,
830 pipeline->shading.internal_frame_origin_y_bqs_on_sctbl);
831 #endif
832 ia_css_iterator_configure(binary, &args->in_frame->info);
833 ia_css_dvs_configure(binary, &args->out_frame[0]->info);
834 ia_css_output_configure(binary, &args->out_frame[0]->info);
835 ia_css_raw_configure(pipeline, binary, &args->in_frame->info, &binary->in_frame_info, two_ppc, deinterleaved);
836
837 /*
838 * FIXME: args->delay_frames can be NULL here
839 *
840 * Somehow, the driver at the Intel Atom Yocto tree doesn't seem to
841 * suffer from the same issue.
842 *
843 * Anyway, the function below should now handle a NULL delay_frames
844 * without crashing, but the pipeline should likely be built without
845 * adding it at the first place (or there are a hidden bug somewhere)
846 */
847 ia_css_ref_configure(binary, args->delay_frames, pipeline->dvs_frame_delay);
848 ia_css_tnr_configure(binary, args->tnr_frames);
849 ia_css_bayer_io_config(binary, args);
850 return 0;
851 }
852
853 static void
initialize_isp_states(const struct ia_css_binary * binary)854 initialize_isp_states(const struct ia_css_binary *binary)
855 {
856 unsigned int i;
857
858 if (!binary->info->mem_offsets.offsets.state)
859 return;
860 for (i = 0; i < IA_CSS_NUM_STATE_IDS; i++) {
861 ia_css_kernel_init_state[i](binary);
862 }
863 }
864
865 static void
initialize_frame_buffer_attribute(struct ia_css_buffer_sp * buf_attr)866 initialize_frame_buffer_attribute(struct ia_css_buffer_sp *buf_attr)
867 {
868 buf_attr->buf_src.queue_id = SH_CSS_INVALID_QUEUE_ID;
869 buf_attr->buf_type = IA_CSS_BUFFER_TYPE_INVALID;
870 }
871
872 static void
initialize_stage_frames(struct ia_css_frames_sp * frames)873 initialize_stage_frames(struct ia_css_frames_sp *frames)
874 {
875 unsigned int i;
876
877 initialize_frame_buffer_attribute(&frames->in.buf_attr);
878 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) {
879 initialize_frame_buffer_attribute(&frames->out[i].buf_attr);
880 }
881 initialize_frame_buffer_attribute(&frames->out_vf.buf_attr);
882 initialize_frame_buffer_attribute(&frames->s3a_buf);
883 initialize_frame_buffer_attribute(&frames->dvs_buf);
884 #if defined SH_CSS_ENABLE_METADATA
885 initialize_frame_buffer_attribute(&frames->metadata_buf);
886 #endif
887 }
888
889 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)890 sh_css_sp_init_stage(struct ia_css_binary *binary,
891 const char *binary_name,
892 const struct ia_css_blob_info *blob_info,
893 const struct sh_css_binary_args *args,
894 unsigned int pipe_num,
895 unsigned int stage,
896 bool xnr,
897 const struct ia_css_isp_param_css_segments *isp_mem_if,
898 unsigned int if_config_index,
899 bool two_ppc) {
900 const struct ia_css_binary_xinfo *xinfo;
901 const struct ia_css_binary_info *info;
902 int err = 0;
903 int i;
904 struct ia_css_pipe *pipe = NULL;
905 unsigned int thread_id;
906 enum sh_css_queue_id queue_id;
907 bool continuous = sh_css_continuous_is_enabled((uint8_t)pipe_num);
908
909 assert(binary);
910 assert(blob_info);
911 assert(args);
912 assert(isp_mem_if);
913
914 xinfo = binary->info;
915 info = &xinfo->sp;
916 {
917 /*
918 * Clear sh_css_sp_stage for easy debugging.
919 * program_input_circuit must be saved as it is set outside
920 * this function.
921 */
922 u8 program_input_circuit;
923
924 program_input_circuit = sh_css_sp_stage.program_input_circuit;
925 memset(&sh_css_sp_stage, 0, sizeof(sh_css_sp_stage));
926 sh_css_sp_stage.program_input_circuit = (uint8_t)program_input_circuit;
927 }
928
929 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
930
931 if (!info)
932 {
933 sh_css_sp_group.pipe[thread_id].sp_stage_addr[stage] = mmgr_NULL;
934 return 0;
935 }
936
937 #if defined(ISP2401)
938 (void)continuous;
939 sh_css_sp_stage.deinterleaved = 0;
940 #else
941 sh_css_sp_stage.deinterleaved = ((stage == 0) && continuous);
942 #endif
943
944 initialize_stage_frames(&sh_css_sp_stage.frames);
945 /*
946 * TODO: Make the Host dynamically determine
947 * the stage type.
948 */
949 sh_css_sp_stage.stage_type = SH_CSS_ISP_STAGE_TYPE;
950 sh_css_sp_stage.num = (uint8_t)stage;
951 sh_css_sp_stage.isp_online = (uint8_t)binary->online;
952 sh_css_sp_stage.isp_copy_vf = (uint8_t)args->copy_vf;
953 sh_css_sp_stage.isp_copy_output = (uint8_t)args->copy_output;
954 sh_css_sp_stage.enable.vf_output = (args->out_vf_frame != NULL);
955
956 /* Copy the frame infos first, to be overwritten by the frames,
957 if these are present.
958 */
959 sh_css_sp_stage.frames.effective_in_res.width = binary->effective_in_frame_res.width;
960 sh_css_sp_stage.frames.effective_in_res.height = binary->effective_in_frame_res.height;
961
962 ia_css_frame_info_to_frame_sp_info(&sh_css_sp_stage.frames.in.info,
963 &binary->in_frame_info);
964 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
965 {
966 ia_css_frame_info_to_frame_sp_info(&sh_css_sp_stage.frames.out[i].info,
967 &binary->out_frame_info[i]);
968 }
969 ia_css_frame_info_to_frame_sp_info(&sh_css_sp_stage.frames.internal_frame_info,
970 &binary->internal_frame_info);
971 sh_css_sp_stage.dvs_envelope.width = binary->dvs_envelope.width;
972 sh_css_sp_stage.dvs_envelope.height = binary->dvs_envelope.height;
973 sh_css_sp_stage.isp_pipe_version = (uint8_t)info->pipeline.isp_pipe_version;
974 sh_css_sp_stage.isp_deci_log_factor = (uint8_t)binary->deci_factor_log2;
975 sh_css_sp_stage.isp_vf_downscale_bits = (uint8_t)binary->vf_downscale_log2;
976
977 sh_css_sp_stage.if_config_index = (uint8_t)if_config_index;
978
979 sh_css_sp_stage.sp_enable_xnr = (uint8_t)xnr;
980 sh_css_sp_stage.xmem_bin_addr = xinfo->xmem_addr;
981 sh_css_sp_stage.xmem_map_addr = sh_css_params_ddr_address_map();
982 sh_css_isp_stage.blob_info = *blob_info;
983 sh_css_stage_write_binary_info((struct ia_css_binary_info *)info);
984
985 /* Make sure binary name is smaller than allowed string size */
986 assert(strlen(binary_name) < SH_CSS_MAX_BINARY_NAME - 1);
987 strscpy(sh_css_isp_stage.binary_name, binary_name, SH_CSS_MAX_BINARY_NAME);
988 sh_css_isp_stage.mem_initializers = *isp_mem_if;
989
990 /*
991 * Even when a stage does not need uds and does not params,
992 * ia_css_uds_sp_scale_params() seems to be called (needs
993 * further investigation). This function can not deal with
994 * dx, dy = {0, 0}
995 */
996
997 err = sh_css_sp_write_frame_pointers(args);
998 /* TODO: move it to a better place */
999 if (binary->info->sp.enable.s3a)
1000 {
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 {
1009 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_DIS_STATISTICS, thread_id,
1010 &queue_id);
1011 sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.dvs_buf, queue_id,
1012 mmgr_EXCEPTION,
1013 IA_CSS_BUFFER_TYPE_DIS_STATISTICS);
1014 }
1015 #if defined SH_CSS_ENABLE_METADATA
1016 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_METADATA, thread_id, &queue_id);
1017 sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.metadata_buf, queue_id, mmgr_EXCEPTION, IA_CSS_BUFFER_TYPE_METADATA);
1018 #endif
1019 if (err)
1020 return err;
1021
1022 #ifdef ISP2401
1023 if (stage == 0) {
1024 pipe = find_pipe_by_num(sh_css_sp_group.pipe[thread_id].pipe_num);
1025 if (!pipe)
1026 return -EINVAL;
1027
1028 if (args->in_frame)
1029 ia_css_get_crop_offsets(pipe, &args->in_frame->info);
1030 else
1031 ia_css_get_crop_offsets(pipe, &binary->in_frame_info);
1032 }
1033 #else
1034 (void)pipe; /*avoid build warning*/
1035 #endif
1036
1037 err = configure_isp_from_args(&sh_css_sp_group.pipe[thread_id],
1038 binary, args, two_ppc, sh_css_sp_stage.deinterleaved);
1039 if (err)
1040 return err;
1041
1042 initialize_isp_states(binary);
1043
1044 /* we do this only for preview pipe because in fill_binary_info function
1045 * we assign vf_out res to out res, but for ISP internal processing, we need
1046 * the original out res. for video pipe, it has two output pins --- out and
1047 * vf_out, so it can keep these two resolutions already. */
1048 if (binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_PREVIEW &&
1049 (binary->vf_downscale_log2 > 0))
1050 {
1051 /* TODO: Remove this after preview output decimation is fixed
1052 * by configuring out&vf info fiels properly */
1053 sh_css_sp_stage.frames.out[0].info.padded_width
1054 <<= binary->vf_downscale_log2;
1055 sh_css_sp_stage.frames.out[0].info.res.width
1056 <<= binary->vf_downscale_log2;
1057 sh_css_sp_stage.frames.out[0].info.res.height
1058 <<= binary->vf_downscale_log2;
1059 }
1060 err = copy_isp_mem_if_to_ddr(binary);
1061 if (err)
1062 return err;
1063
1064 return 0;
1065 }
1066
1067 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)1068 sp_init_stage(struct ia_css_pipeline_stage *stage,
1069 unsigned int pipe_num,
1070 bool xnr,
1071 unsigned int if_config_index,
1072 bool two_ppc) {
1073 struct ia_css_binary *binary;
1074 const struct ia_css_fw_info *firmware;
1075 const struct sh_css_binary_args *args;
1076 unsigned int stage_num;
1077 /*
1078 * Initialiser required because of the "else" path below.
1079 * Is this a valid path ?
1080 */
1081 const char *binary_name = "";
1082 const struct ia_css_binary_xinfo *info = NULL;
1083 /* note: the var below is made static as it is quite large;
1084 if it is not static it ends up on the stack which could
1085 cause issues for drivers
1086 */
1087 static struct ia_css_binary tmp_binary;
1088 const struct ia_css_blob_info *blob_info = NULL;
1089 struct ia_css_isp_param_css_segments isp_mem_if;
1090 /* LA: should be ia_css_data, should not contain host pointer.
1091 However, CSS/DDR pointer is not available yet.
1092 Hack is to store it in params->ddr_ptrs and then copy it late in the SP just before vmem init.
1093 TODO: Call this after CSS/DDR allocation and store that pointer.
1094 Best is to allocate it at stage creation time together with host pointer.
1095 Remove vmem from params.
1096 */
1097 struct ia_css_isp_param_css_segments *mem_if = &isp_mem_if;
1098
1099 int err = 0;
1100
1101 assert(stage);
1102
1103 binary = stage->binary;
1104 firmware = stage->firmware;
1105 args = &stage->args;
1106 stage_num = stage->stage_num;
1107
1108 if (binary)
1109 {
1110 info = binary->info;
1111 binary_name = (const char *)(info->blob->name);
1112 blob_info = &info->blob->header.blob;
1113 ia_css_init_memory_interface(mem_if, &binary->mem_params, &binary->css_params);
1114 } else if (firmware)
1115 {
1116 const struct ia_css_frame_info *out_infos[IA_CSS_BINARY_MAX_OUTPUT_PORTS] = {NULL};
1117
1118 if (args->out_frame[0])
1119 out_infos[0] = &args->out_frame[0]->info;
1120 info = &firmware->info.isp;
1121 ia_css_binary_fill_info(info, false, false,
1122 ATOMISP_INPUT_FORMAT_RAW_10,
1123 args->in_frame ? &args->in_frame->info : NULL,
1124 NULL,
1125 out_infos,
1126 args->out_vf_frame ? &args->out_vf_frame->info
1127 : NULL,
1128 &tmp_binary,
1129 NULL,
1130 -1, true);
1131 binary = &tmp_binary;
1132 binary->info = info;
1133 binary_name = IA_CSS_EXT_ISP_PROG_NAME(firmware);
1134 blob_info = &firmware->blob;
1135 mem_if = (struct ia_css_isp_param_css_segments *)&firmware->mem_initializers;
1136 } else
1137 {
1138 /* SP stage */
1139 assert(stage->sp_func != IA_CSS_PIPELINE_NO_FUNC);
1140 /* binary and blob_info are now NULL.
1141 These will be passed to sh_css_sp_init_stage
1142 and dereferenced there, so passing a NULL
1143 pointer is no good. return an error */
1144 return -EINVAL;
1145 }
1146
1147 err = sh_css_sp_init_stage(binary,
1148 (const char *)binary_name,
1149 blob_info,
1150 args,
1151 pipe_num,
1152 stage_num,
1153 xnr,
1154 mem_if,
1155 if_config_index,
1156 two_ppc);
1157 return err;
1158 }
1159
1160 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)1161 sp_init_sp_stage(struct ia_css_pipeline_stage *stage,
1162 unsigned int pipe_num,
1163 bool two_ppc,
1164 enum sh_css_pipe_config_override copy_ovrd,
1165 unsigned int if_config_index)
1166 {
1167 const struct sh_css_binary_args *args = &stage->args;
1168
1169 assert(stage);
1170 switch (stage->sp_func) {
1171 case IA_CSS_PIPELINE_RAW_COPY:
1172 sh_css_sp_start_raw_copy(args->out_frame[0],
1173 pipe_num, two_ppc,
1174 stage->max_input_width,
1175 copy_ovrd, if_config_index);
1176 break;
1177 case IA_CSS_PIPELINE_BIN_COPY:
1178 assert(false); /* TBI */
1179 break;
1180 case IA_CSS_PIPELINE_ISYS_COPY:
1181 sh_css_sp_start_isys_copy(args->out_frame[0],
1182 pipe_num, stage->max_input_width, if_config_index);
1183 break;
1184 case IA_CSS_PIPELINE_NO_FUNC:
1185 assert(false);
1186 break;
1187 }
1188 }
1189
1190 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)1191 sh_css_sp_init_pipeline(struct ia_css_pipeline *me,
1192 enum ia_css_pipe_id id,
1193 u8 pipe_num,
1194 bool xnr,
1195 bool two_ppc,
1196 bool continuous,
1197 bool offline,
1198 unsigned int required_bds_factor,
1199 enum sh_css_pipe_config_override copy_ovrd,
1200 enum ia_css_input_mode input_mode,
1201 const struct ia_css_metadata_config *md_config,
1202 const struct ia_css_metadata_info *md_info,
1203 const enum mipi_port_id port_id,
1204 const struct ia_css_coordinate
1205 *internal_frame_origin_bqs_on_sctbl, /* Origin of internal frame
1206 positioned on shading table at shading correction in ISP. */
1207 const struct ia_css_isp_parameters *params
1208 ) {
1209 /* Get first stage */
1210 struct ia_css_pipeline_stage *stage = NULL;
1211 struct ia_css_binary *first_binary = NULL;
1212 struct ia_css_pipe *pipe = NULL;
1213 unsigned int num;
1214
1215 enum ia_css_pipe_id pipe_id = id;
1216 unsigned int thread_id;
1217 u8 if_config_index, tmp_if_config_index;
1218
1219 assert(me);
1220
1221 assert(me->stages);
1222
1223 first_binary = me->stages->binary;
1224
1225 if (input_mode == IA_CSS_INPUT_MODE_SENSOR ||
1226 input_mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
1227 {
1228 assert(port_id < N_MIPI_PORT_ID);
1229 if (port_id >= N_MIPI_PORT_ID) /* should not happen but KW does not know */
1230 return; /* we should be able to return an error */
1231 if_config_index = (uint8_t)(port_id - MIPI_PORT0_ID);
1232 } else if (input_mode == IA_CSS_INPUT_MODE_MEMORY)
1233 {
1234 if_config_index = SH_CSS_IF_CONFIG_NOT_NEEDED;
1235 } else
1236 {
1237 if_config_index = 0x0;
1238 }
1239
1240 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
1241 memset(&sh_css_sp_group.pipe[thread_id], 0, sizeof(struct sh_css_sp_pipeline));
1242
1243 /* Count stages */
1244 for (stage = me->stages, num = 0; stage; stage = stage->next, num++)
1245 {
1246 stage->stage_num = num;
1247 ia_css_debug_pipe_graph_dump_stage(stage, id);
1248 }
1249 me->num_stages = num;
1250
1251 if (first_binary)
1252 {
1253 /* Init pipeline data */
1254 sh_css_sp_init_group(two_ppc, first_binary->input_format,
1255 offline, if_config_index);
1256 } /* if (first_binary != NULL) */
1257
1258 /* Signal the host immediately after start for SP_ISYS_COPY only */
1259 if ((me->num_stages == 1) && me->stages &&
1260 (me->stages->sp_func == IA_CSS_PIPELINE_ISYS_COPY))
1261 sh_css_sp_group.config.no_isp_sync = true;
1262
1263 /* Init stage data */
1264 sh_css_init_host2sp_frame_data();
1265
1266 sh_css_sp_group.pipe[thread_id].num_stages = 0;
1267 sh_css_sp_group.pipe[thread_id].pipe_id = pipe_id;
1268 sh_css_sp_group.pipe[thread_id].thread_id = thread_id;
1269 sh_css_sp_group.pipe[thread_id].pipe_num = pipe_num;
1270 sh_css_sp_group.pipe[thread_id].num_execs = me->num_execs;
1271 sh_css_sp_group.pipe[thread_id].pipe_qos_config = me->pipe_qos_config;
1272 sh_css_sp_group.pipe[thread_id].required_bds_factor = required_bds_factor;
1273 sh_css_sp_group.pipe[thread_id].input_system_mode
1274 = (uint32_t)input_mode;
1275 sh_css_sp_group.pipe[thread_id].port_id = port_id;
1276 sh_css_sp_group.pipe[thread_id].dvs_frame_delay = (uint32_t)me->dvs_frame_delay;
1277
1278 /* TODO: next indicates from which queues parameters need to be
1279 sampled, needs checking/improvement */
1280 if (ia_css_pipeline_uses_params(me))
1281 {
1282 sh_css_sp_group.pipe[thread_id].pipe_config =
1283 SH_CSS_PIPE_CONFIG_SAMPLE_PARAMS << thread_id;
1284 }
1285
1286 /* For continuous use-cases, SP copy is responsible for sampling the
1287 * parameters */
1288 if (continuous)
1289 sh_css_sp_group.pipe[thread_id].pipe_config = 0;
1290
1291 sh_css_sp_group.pipe[thread_id].inout_port_config = me->inout_port_config;
1292
1293 pipe = find_pipe_by_num(pipe_num);
1294 assert(pipe);
1295 if (!pipe)
1296 {
1297 return;
1298 }
1299 sh_css_sp_group.pipe[thread_id].scaler_pp_lut = sh_css_pipe_get_pp_gdc_lut(pipe);
1300
1301 #if defined(SH_CSS_ENABLE_METADATA)
1302 if (md_info && md_info->size > 0)
1303 {
1304 sh_css_sp_group.pipe[thread_id].metadata.width = md_info->resolution.width;
1305 sh_css_sp_group.pipe[thread_id].metadata.height = md_info->resolution.height;
1306 sh_css_sp_group.pipe[thread_id].metadata.stride = md_info->stride;
1307 sh_css_sp_group.pipe[thread_id].metadata.size = md_info->size;
1308 ia_css_isys_convert_stream_format_to_mipi_format(
1309 md_config->data_type, MIPI_PREDICTOR_NONE,
1310 &sh_css_sp_group.pipe[thread_id].metadata.format);
1311 }
1312 #else
1313 (void)md_config;
1314 (void)md_info;
1315 #endif
1316
1317 #if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS)
1318 sh_css_sp_group.pipe[thread_id].output_frame_queue_id = (uint32_t)SH_CSS_INVALID_QUEUE_ID;
1319 if (pipe_id != IA_CSS_PIPE_ID_COPY)
1320 {
1321 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, thread_id,
1322 (enum sh_css_queue_id *)(
1323 &sh_css_sp_group.pipe[thread_id].output_frame_queue_id));
1324 }
1325 #endif
1326
1327 if (IS_ISP2401) {
1328 /* For the shading correction type 1 (the legacy shading table conversion in css is not used),
1329 * the parameters are passed to the isp for the shading table centering.
1330 */
1331 if (internal_frame_origin_bqs_on_sctbl &&
1332 params && params->shading_settings.enable_shading_table_conversion == 0)
1333 {
1334 sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_x_bqs_on_sctbl
1335 = (uint32_t)internal_frame_origin_bqs_on_sctbl->x;
1336 sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_y_bqs_on_sctbl
1337 = (uint32_t)internal_frame_origin_bqs_on_sctbl->y;
1338 } else
1339 {
1340 sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_x_bqs_on_sctbl =
1341 0;
1342 sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_y_bqs_on_sctbl =
1343 0;
1344 }
1345 }
1346
1347 IA_CSS_LOG("pipe_id %d port_config %08x",
1348 pipe_id, sh_css_sp_group.pipe[thread_id].inout_port_config);
1349
1350 for (stage = me->stages, num = 0; stage; stage = stage->next, num++)
1351 {
1352 sh_css_sp_group.pipe[thread_id].num_stages++;
1353 if (is_sp_stage(stage)) {
1354 sp_init_sp_stage(stage, pipe_num, two_ppc,
1355 copy_ovrd, if_config_index);
1356 } else {
1357 if ((stage->stage_num != 0) ||
1358 SH_CSS_PIPE_PORT_CONFIG_IS_CONTINUOUS(me->inout_port_config))
1359 tmp_if_config_index = SH_CSS_IF_CONFIG_NOT_NEEDED;
1360 else
1361 tmp_if_config_index = if_config_index;
1362 sp_init_stage(stage, pipe_num,
1363 xnr, tmp_if_config_index, two_ppc);
1364 }
1365
1366 store_sp_stage_data(pipe_id, pipe_num, num);
1367 }
1368 sh_css_sp_group.pipe[thread_id].pipe_config |= (uint32_t)
1369 (me->acquire_isp_each_stage << IA_CSS_ACQUIRE_ISP_POS);
1370 store_sp_group_data();
1371 }
1372
1373 void
sh_css_sp_uninit_pipeline(unsigned int pipe_num)1374 sh_css_sp_uninit_pipeline(unsigned int pipe_num)
1375 {
1376 unsigned int thread_id;
1377
1378 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
1379 /*memset(&sh_css_sp_group.pipe[thread_id], 0, sizeof(struct sh_css_sp_pipeline));*/
1380 sh_css_sp_group.pipe[thread_id].num_stages = 0;
1381 }
1382
sh_css_write_host2sp_command(enum host2sp_commands host2sp_command)1383 bool sh_css_write_host2sp_command(enum host2sp_commands host2sp_command)
1384 {
1385 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1386 unsigned int offset = (unsigned int)offsetof(struct host_sp_communication,
1387 host2sp_command)
1388 / sizeof(int);
1389 enum host2sp_commands last_cmd = host2sp_cmd_error;
1390 (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
1391
1392 /* Previous command must be handled by SP (by design) */
1393 last_cmd = load_sp_array_uint(host_sp_com, offset);
1394 if (last_cmd != host2sp_cmd_ready)
1395 IA_CSS_ERROR("last host command not handled by SP(%d)", last_cmd);
1396
1397 store_sp_array_uint(host_sp_com, offset, host2sp_command);
1398
1399 return (last_cmd == host2sp_cmd_ready);
1400 }
1401
1402 enum host2sp_commands
sh_css_read_host2sp_command(void)1403 sh_css_read_host2sp_command(void) {
1404 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1405 unsigned int offset = (unsigned int)offsetof(struct host_sp_communication, host2sp_command)
1406 / sizeof(int);
1407 (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
1408 return (enum host2sp_commands)load_sp_array_uint(host_sp_com, offset);
1409 }
1410
1411 /*
1412 * Frame data is no longer part of the sp_stage structure but part of a
1413 * separate structure. The aim is to make the sp_data struct static
1414 * (it defines a pipeline) and that the dynamic (per frame) data is stored
1415 * separetly.
1416 *
1417 * This function must be called first every where were you start constructing
1418 * a new pipeline by defining one or more stages with use of variable
1419 * sh_css_sp_stage. Even the special cases like accelerator and copy_frame
1420 * These have a pipeline of just 1 stage.
1421 */
1422 void
sh_css_init_host2sp_frame_data(void)1423 sh_css_init_host2sp_frame_data(void)
1424 {
1425 /* Clean table */
1426 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1427
1428 (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
1429 /*
1430 * rvanimme: don't clean it to save static frame info line ref_in
1431 * ref_out, and tnr_frames. Once this static data is in a
1432 * separate data struct, this may be enable (but still, there is
1433 * no need for it)
1434 */
1435 }
1436
1437 /*
1438 * @brief Update the offline frame information in host_sp_communication.
1439 * Refer to "sh_css_sp.h" for more details.
1440 */
1441 void
sh_css_update_host2sp_offline_frame(unsigned int frame_num,struct ia_css_frame * frame,struct ia_css_metadata * metadata)1442 sh_css_update_host2sp_offline_frame(
1443 unsigned int frame_num,
1444 struct ia_css_frame *frame,
1445 struct ia_css_metadata *metadata)
1446 {
1447 unsigned int HIVE_ADDR_host_sp_com;
1448 unsigned int offset;
1449
1450 assert(frame_num < NUM_CONTINUOUS_FRAMES);
1451
1452 /* Write new frame data into SP DMEM */
1453 HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1454 offset = (unsigned int)offsetof(struct host_sp_communication,
1455 host2sp_offline_frames)
1456 / sizeof(int);
1457 offset += frame_num;
1458 store_sp_array_uint(host_sp_com, offset, frame ? frame->data : 0);
1459
1460 /* Write metadata buffer into SP DMEM */
1461 offset = (unsigned int)offsetof(struct host_sp_communication,
1462 host2sp_offline_metadata)
1463 / sizeof(int);
1464 offset += frame_num;
1465 store_sp_array_uint(host_sp_com, offset, metadata ? metadata->address : 0);
1466 }
1467
1468 /*
1469 * @brief Update the mipi frame information in host_sp_communication.
1470 * Refer to "sh_css_sp.h" for more details.
1471 */
1472 void
sh_css_update_host2sp_mipi_frame(unsigned int frame_num,struct ia_css_frame * frame)1473 sh_css_update_host2sp_mipi_frame(
1474 unsigned int frame_num,
1475 struct ia_css_frame *frame)
1476 {
1477 unsigned int HIVE_ADDR_host_sp_com;
1478 unsigned int offset;
1479
1480 /* MIPI buffers are dedicated to port, so now there are more of them. */
1481 assert(frame_num < (N_CSI_PORTS * NUM_MIPI_FRAMES_PER_STREAM));
1482
1483 /* Write new frame data into SP DMEM */
1484 HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1485 offset = (unsigned int)offsetof(struct host_sp_communication,
1486 host2sp_mipi_frames)
1487 / sizeof(int);
1488 offset += frame_num;
1489
1490 store_sp_array_uint(host_sp_com, offset,
1491 frame ? frame->data : 0);
1492 }
1493
1494 /*
1495 * @brief Update the mipi metadata information in host_sp_communication.
1496 * Refer to "sh_css_sp.h" for more details.
1497 */
1498 void
sh_css_update_host2sp_mipi_metadata(unsigned int frame_num,struct ia_css_metadata * metadata)1499 sh_css_update_host2sp_mipi_metadata(
1500 unsigned int frame_num,
1501 struct ia_css_metadata *metadata)
1502 {
1503 unsigned int HIVE_ADDR_host_sp_com;
1504 unsigned int o;
1505
1506 /* MIPI buffers are dedicated to port, so now there are more of them. */
1507 assert(frame_num < (N_CSI_PORTS * NUM_MIPI_FRAMES_PER_STREAM));
1508
1509 /* Write new frame data into SP DMEM */
1510 HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1511 o = offsetof(struct host_sp_communication, host2sp_mipi_metadata)
1512 / sizeof(int);
1513 o += frame_num;
1514 store_sp_array_uint(host_sp_com, o,
1515 metadata ? metadata->address : 0);
1516 }
1517
1518 void
sh_css_update_host2sp_num_mipi_frames(unsigned int num_frames)1519 sh_css_update_host2sp_num_mipi_frames(unsigned int num_frames)
1520 {
1521 unsigned int HIVE_ADDR_host_sp_com;
1522 unsigned int offset;
1523
1524 /* Write new frame data into SP DMEM */
1525 HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1526 offset = (unsigned int)offsetof(struct host_sp_communication,
1527 host2sp_num_mipi_frames)
1528 / sizeof(int);
1529
1530 store_sp_array_uint(host_sp_com, offset, num_frames);
1531 }
1532
1533 void
sh_css_update_host2sp_cont_num_raw_frames(unsigned int num_frames,bool set_avail)1534 sh_css_update_host2sp_cont_num_raw_frames(unsigned int num_frames,
1535 bool set_avail)
1536 {
1537 const struct ia_css_fw_info *fw;
1538 unsigned int HIVE_ADDR_host_sp_com;
1539 unsigned int extra_num_frames, avail_num_frames;
1540 unsigned int offset, offset_extra;
1541
1542 /* Write new frame data into SP DMEM */
1543 fw = &sh_css_sp_fw;
1544 HIVE_ADDR_host_sp_com = fw->info.sp.host_sp_com;
1545 if (set_avail) {
1546 offset = (unsigned int)offsetof(struct host_sp_communication,
1547 host2sp_cont_avail_num_raw_frames)
1548 / sizeof(int);
1549 avail_num_frames = load_sp_array_uint(host_sp_com, offset);
1550 extra_num_frames = num_frames - avail_num_frames;
1551 offset_extra = (unsigned int)offsetof(struct host_sp_communication,
1552 host2sp_cont_extra_num_raw_frames)
1553 / sizeof(int);
1554 store_sp_array_uint(host_sp_com, offset_extra, extra_num_frames);
1555 } else
1556 offset = (unsigned int)offsetof(struct host_sp_communication,
1557 host2sp_cont_target_num_raw_frames)
1558 / sizeof(int);
1559
1560 store_sp_array_uint(host_sp_com, offset, num_frames);
1561 }
1562
1563 void
sh_css_event_init_irq_mask(void)1564 sh_css_event_init_irq_mask(void)
1565 {
1566 int i;
1567 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1568 unsigned int offset;
1569 struct sh_css_event_irq_mask event_irq_mask_init;
1570
1571 event_irq_mask_init.or_mask = IA_CSS_EVENT_TYPE_ALL;
1572 event_irq_mask_init.and_mask = IA_CSS_EVENT_TYPE_NONE;
1573 (void)HIVE_ADDR_host_sp_com; /* Suppress warnings in CRUN */
1574
1575 assert(sizeof(event_irq_mask_init) % HRT_BUS_BYTES == 0);
1576 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
1577 offset = (unsigned int)offsetof(struct host_sp_communication,
1578 host2sp_event_irq_mask[i]);
1579 assert(offset % HRT_BUS_BYTES == 0);
1580 sp_dmem_store(SP0_ID,
1581 (unsigned int)sp_address_of(host_sp_com) + offset,
1582 &event_irq_mask_init, sizeof(event_irq_mask_init));
1583 }
1584 }
1585
1586 int
ia_css_pipe_set_irq_mask(struct ia_css_pipe * pipe,unsigned int or_mask,unsigned int and_mask)1587 ia_css_pipe_set_irq_mask(struct ia_css_pipe *pipe,
1588 unsigned int or_mask,
1589 unsigned int and_mask) {
1590 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1591 unsigned int offset;
1592 struct sh_css_event_irq_mask event_irq_mask;
1593 unsigned int pipe_num;
1594
1595 assert(pipe);
1596
1597 assert(IA_CSS_PIPE_ID_NUM == NR_OF_PIPELINES);
1598 /* Linux kernel does not have UINT16_MAX
1599 * Therefore decided to comment out these 2 asserts for Linux
1600 * Alternatives that were not chosen:
1601 * - add a conditional #define for UINT16_MAX
1602 * - compare with (uint16_t)~0 or 0xffff
1603 * - different assert for Linux and Windows
1604 */
1605
1606 (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
1607
1608 IA_CSS_LOG("or_mask=%x, and_mask=%x", or_mask, and_mask);
1609 event_irq_mask.or_mask = (uint16_t)or_mask;
1610 event_irq_mask.and_mask = (uint16_t)and_mask;
1611
1612 pipe_num = ia_css_pipe_get_pipe_num(pipe);
1613 if (pipe_num >= IA_CSS_PIPE_ID_NUM)
1614 return -EINVAL;
1615 offset = (unsigned int)offsetof(struct host_sp_communication,
1616 host2sp_event_irq_mask[pipe_num]);
1617 assert(offset % HRT_BUS_BYTES == 0);
1618 sp_dmem_store(SP0_ID,
1619 (unsigned int)sp_address_of(host_sp_com) + offset,
1620 &event_irq_mask, sizeof(event_irq_mask));
1621
1622 return 0;
1623 }
1624
1625 int
ia_css_event_get_irq_mask(const struct ia_css_pipe * pipe,unsigned int * or_mask,unsigned int * and_mask)1626 ia_css_event_get_irq_mask(const struct ia_css_pipe *pipe,
1627 unsigned int *or_mask,
1628 unsigned int *and_mask) {
1629 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1630 unsigned int offset;
1631 struct sh_css_event_irq_mask event_irq_mask;
1632 unsigned int pipe_num;
1633
1634 (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
1635
1636 IA_CSS_ENTER_LEAVE("");
1637
1638 assert(pipe);
1639 assert(IA_CSS_PIPE_ID_NUM == NR_OF_PIPELINES);
1640
1641 pipe_num = ia_css_pipe_get_pipe_num(pipe);
1642 if (pipe_num >= IA_CSS_PIPE_ID_NUM)
1643 return -EINVAL;
1644 offset = (unsigned int)offsetof(struct host_sp_communication,
1645 host2sp_event_irq_mask[pipe_num]);
1646 assert(offset % HRT_BUS_BYTES == 0);
1647 sp_dmem_load(SP0_ID,
1648 (unsigned int)sp_address_of(host_sp_com) + offset,
1649 &event_irq_mask, sizeof(event_irq_mask));
1650
1651 if (or_mask)
1652 *or_mask = event_irq_mask.or_mask;
1653
1654 if (and_mask)
1655 *and_mask = event_irq_mask.and_mask;
1656
1657 return 0;
1658 }
1659
1660 void
sh_css_sp_set_sp_running(bool flag)1661 sh_css_sp_set_sp_running(bool flag)
1662 {
1663 sp_running = flag;
1664 }
1665
1666 bool
sh_css_sp_is_running(void)1667 sh_css_sp_is_running(void)
1668 {
1669 return sp_running;
1670 }
1671
1672 void
sh_css_sp_start_isp(void)1673 sh_css_sp_start_isp(void)
1674 {
1675 const struct ia_css_fw_info *fw;
1676 unsigned int HIVE_ADDR_sp_sw_state;
1677
1678 fw = &sh_css_sp_fw;
1679 HIVE_ADDR_sp_sw_state = fw->info.sp.sw_state;
1680
1681 if (sp_running)
1682 return;
1683
1684 (void)HIVE_ADDR_sp_sw_state; /* Suppres warnings in CRUN */
1685
1686 /* no longer here, sp started immediately */
1687 /*ia_css_debug_pipe_graph_dump_epilogue();*/
1688
1689 store_sp_group_data();
1690 store_sp_per_frame_data(fw);
1691
1692 sp_dmem_store_uint32(SP0_ID,
1693 (unsigned int)sp_address_of(sp_sw_state),
1694 (uint32_t)(IA_CSS_SP_SW_TERMINATED));
1695
1696 /* Note 1: The sp_start_isp function contains a wait till
1697 * the input network is configured by the SP.
1698 * Note 2: Not all SP binaries supports host2sp_commands.
1699 * In case a binary does support it, the host2sp_command
1700 * will have status cmd_ready after return of the function
1701 * sh_css_hrt_sp_start_isp. There is no race-condition here
1702 * because only after the process_frame command has been
1703 * received, the SP starts configuring the input network.
1704 */
1705
1706 /* we need to set sp_running before we call ia_css_mmu_invalidate_cache
1707 * as ia_css_mmu_invalidate_cache checks on sp_running to
1708 * avoid that it accesses dmem while the SP is not powered
1709 */
1710 sp_running = true;
1711 ia_css_mmu_invalidate_cache();
1712 /* Invalidate all MMU caches */
1713 mmu_invalidate_cache_all();
1714
1715 ia_css_spctrl_start(SP0_ID);
1716 }
1717
1718 bool
ia_css_isp_has_started(void)1719 ia_css_isp_has_started(void)
1720 {
1721 const struct ia_css_fw_info *fw = &sh_css_sp_fw;
1722 unsigned int HIVE_ADDR_ia_css_ispctrl_sp_isp_started = fw->info.sp.isp_started;
1723 (void)HIVE_ADDR_ia_css_ispctrl_sp_isp_started; /* Suppres warnings in CRUN */
1724
1725 return (bool)load_sp_uint(ia_css_ispctrl_sp_isp_started);
1726 }
1727
1728 /*
1729 * @brief Initialize the DMA software-mask in the debug mode.
1730 * Refer to "sh_css_sp.h" for more details.
1731 */
1732 bool
sh_css_sp_init_dma_sw_reg(int dma_id)1733 sh_css_sp_init_dma_sw_reg(int dma_id)
1734 {
1735 int i;
1736
1737 /* enable all the DMA channels */
1738 for (i = 0; i < N_DMA_CHANNEL_ID; i++) {
1739 /* enable the writing request */
1740 sh_css_sp_set_dma_sw_reg(dma_id,
1741 i,
1742 0,
1743 true);
1744 /* enable the reading request */
1745 sh_css_sp_set_dma_sw_reg(dma_id,
1746 i,
1747 1,
1748 true);
1749 }
1750
1751 return true;
1752 }
1753
1754 /*
1755 * @brief Set the DMA software-mask in the debug mode.
1756 * Refer to "sh_css_sp.h" for more details.
1757 */
1758 bool
sh_css_sp_set_dma_sw_reg(int dma_id,int channel_id,int request_type,bool enable)1759 sh_css_sp_set_dma_sw_reg(int dma_id,
1760 int channel_id,
1761 int request_type,
1762 bool enable)
1763 {
1764 u32 sw_reg;
1765 u32 bit_val;
1766 u32 bit_offset;
1767 u32 bit_mask;
1768
1769 (void)dma_id;
1770
1771 assert(channel_id >= 0 && channel_id < N_DMA_CHANNEL_ID);
1772 assert(request_type >= 0);
1773
1774 /* get the software-mask */
1775 sw_reg =
1776 sh_css_sp_group.debug.dma_sw_reg;
1777
1778 /* get the offest of the target bit */
1779 bit_offset = (8 * request_type) + channel_id;
1780
1781 /* clear the value of the target bit */
1782 bit_mask = ~(1 << bit_offset);
1783 sw_reg &= bit_mask;
1784
1785 /* set the value of the bit for the DMA channel */
1786 bit_val = enable ? 1 : 0;
1787 bit_val <<= bit_offset;
1788 sw_reg |= bit_val;
1789
1790 /* update the software status of DMA channels */
1791 sh_css_sp_group.debug.dma_sw_reg = sw_reg;
1792
1793 return true;
1794 }
1795
1796 void
sh_css_sp_reset_global_vars(void)1797 sh_css_sp_reset_global_vars(void)
1798 {
1799 memset(&sh_css_sp_group, 0, sizeof(struct sh_css_sp_group));
1800 memset(&sh_css_sp_stage, 0, sizeof(struct sh_css_sp_stage));
1801 memset(&sh_css_isp_stage, 0, sizeof(struct sh_css_isp_stage));
1802 memset(&sh_css_sp_output, 0, sizeof(struct sh_css_sp_output));
1803 memset(&per_frame_data, 0, sizeof(struct sh_css_sp_per_frame_data));
1804 }
1805