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