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