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 	enum sh_css_queue_id queue_id;
334 
335 	assert(out_frame);
336 
337 	{
338 		/*
339 		 * Clear sh_css_sp_stage for easy debugging.
340 		 * program_input_circuit must be saved as it is set outside
341 		 * this function.
342 		 */
343 		u8 program_input_circuit;
344 
345 		program_input_circuit = sh_css_sp_stage.program_input_circuit;
346 		memset(&sh_css_sp_stage, 0, sizeof(sh_css_sp_stage));
347 		sh_css_sp_stage.program_input_circuit = program_input_circuit;
348 	}
349 
350 	pipe_id = IA_CSS_PIPE_ID_COPY;
351 	ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
352 	pipe = &sh_css_sp_group.pipe[thread_id];
353 
354 	pipe->copy.raw.height		= out_frame->info.res.height;
355 	pipe->copy.raw.width		= out_frame->info.res.width;
356 	pipe->copy.raw.padded_width	= out_frame->info.padded_width;
357 	pipe->copy.raw.raw_bit_depth	= out_frame->info.raw_bit_depth;
358 	pipe->copy.raw.max_input_width	= max_input_width;
359 	pipe->num_stages		= 1;
360 	pipe->pipe_id			= pipe_id;
361 	pipe->pipe_config		= 0x0;	/* No parameters */
362 	pipe->pipe_qos_config		= QOS_INVALID;
363 
364 	initialize_stage_frames(&sh_css_sp_stage.frames);
365 	sh_css_sp_stage.num = stage_num;
366 	sh_css_sp_stage.xmem_bin_addr = 0x0;
367 	sh_css_sp_stage.stage_type = SH_CSS_SP_STAGE_TYPE;
368 	sh_css_sp_stage.func = (unsigned int)IA_CSS_PIPELINE_ISYS_COPY;
369 	sh_css_sp_stage.if_config_index = (uint8_t)if_config_index;
370 
371 	set_output_frame_buffer(out_frame, 0);
372 
373 	if (pipe->metadata.height > 0) {
374 		ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_METADATA, thread_id,
375 					       &queue_id);
376 		sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.metadata_buf,
377 						    queue_id, mmgr_EXCEPTION,
378 						    IA_CSS_BUFFER_TYPE_METADATA);
379 	}
380 
381 	ia_css_debug_pipe_graph_dump_sp_raw_copy(out_frame);
382 }
383 
384 unsigned int
385 sh_css_sp_get_binary_copy_size(void)
386 {
387 	const struct ia_css_fw_info *fw = &sh_css_sp_fw;
388 	unsigned int HIVE_ADDR_sp_output = fw->info.sp.output;
389 	unsigned int offset = (unsigned int)offsetof(struct sh_css_sp_output,
390 			      bin_copy_bytes_copied) / sizeof(int);
391 	(void)HIVE_ADDR_sp_output; /* To get rid of warning in CRUN */
392 	return load_sp_array_uint(sp_output, offset);
393 }
394 
395 unsigned int
396 sh_css_sp_get_sw_interrupt_value(unsigned int irq)
397 {
398 	const struct ia_css_fw_info *fw = &sh_css_sp_fw;
399 	unsigned int HIVE_ADDR_sp_output = fw->info.sp.output;
400 	unsigned int offset = (unsigned int)offsetof(struct sh_css_sp_output,
401 			      sw_interrupt_value)
402 			      / sizeof(int);
403 	(void)HIVE_ADDR_sp_output; /* To get rid of warning in CRUN */
404 	return load_sp_array_uint(sp_output, offset + irq);
405 }
406 
407 static void
408 sh_css_copy_buffer_attr_to_spbuffer(struct ia_css_buffer_sp *dest_buf,
409 				    const enum sh_css_queue_id queue_id,
410 				    const ia_css_ptr xmem_addr,
411 				    const enum ia_css_buffer_type buf_type)
412 {
413 	assert(buf_type < IA_CSS_NUM_BUFFER_TYPE);
414 	if (queue_id > SH_CSS_INVALID_QUEUE_ID) {
415 		/*
416 		 * value >=0 indicates that function init_frame_pointers()
417 		 * should use the dynamic data address
418 		 */
419 		assert(queue_id < SH_CSS_MAX_NUM_QUEUES);
420 
421 		/* Klocwork assumes assert can be disabled;
422 		   Since we can get there with any type, and it does not
423 		   know that frame_in->dynamic_data_index can only be set
424 		   for one of the types in the assert) it has to assume we
425 		   can get here for any type. however this could lead to an
426 		   out of bounds reference when indexing buf_type about 10
427 		   lines below. In order to satisfy KW an additional if
428 		   has been added. This one will always yield true.
429 		 */
430 		if ((queue_id < SH_CSS_MAX_NUM_QUEUES)) {
431 			dest_buf->buf_src.queue_id = queue_id;
432 		}
433 	} else {
434 		assert(xmem_addr != mmgr_EXCEPTION);
435 		dest_buf->buf_src.xmem_addr = xmem_addr;
436 	}
437 	dest_buf->buf_type = buf_type;
438 }
439 
440 static void
441 sh_css_copy_frame_to_spframe(struct ia_css_frame_sp *sp_frame_out,
442 			     const struct ia_css_frame *frame_in)
443 {
444 	assert(frame_in);
445 
446 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
447 			    "sh_css_copy_frame_to_spframe():\n");
448 
449 	sh_css_copy_buffer_attr_to_spbuffer(&sp_frame_out->buf_attr,
450 					    frame_in->dynamic_queue_id,
451 					    frame_in->data,
452 					    frame_in->buf_type);
453 
454 	ia_css_frame_info_to_frame_sp_info(&sp_frame_out->info, &frame_in->info);
455 
456 	switch (frame_in->info.format) {
457 	case IA_CSS_FRAME_FORMAT_RAW_PACKED:
458 	case IA_CSS_FRAME_FORMAT_RAW:
459 		sp_frame_out->planes.raw.offset = frame_in->planes.raw.offset;
460 		break;
461 	case IA_CSS_FRAME_FORMAT_RGB565:
462 	case IA_CSS_FRAME_FORMAT_RGBA888:
463 		sp_frame_out->planes.rgb.offset = frame_in->planes.rgb.offset;
464 		break;
465 	case IA_CSS_FRAME_FORMAT_PLANAR_RGB888:
466 		sp_frame_out->planes.planar_rgb.r.offset =
467 		    frame_in->planes.planar_rgb.r.offset;
468 		sp_frame_out->planes.planar_rgb.g.offset =
469 		    frame_in->planes.planar_rgb.g.offset;
470 		sp_frame_out->planes.planar_rgb.b.offset =
471 		    frame_in->planes.planar_rgb.b.offset;
472 		break;
473 	case IA_CSS_FRAME_FORMAT_YUYV:
474 	case IA_CSS_FRAME_FORMAT_UYVY:
475 	case IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8:
476 	case IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8:
477 	case IA_CSS_FRAME_FORMAT_YUV_LINE:
478 		sp_frame_out->planes.yuyv.offset = frame_in->planes.yuyv.offset;
479 		break;
480 	case IA_CSS_FRAME_FORMAT_NV11:
481 	case IA_CSS_FRAME_FORMAT_NV12:
482 	case IA_CSS_FRAME_FORMAT_NV12_16:
483 	case IA_CSS_FRAME_FORMAT_NV12_TILEY:
484 	case IA_CSS_FRAME_FORMAT_NV21:
485 	case IA_CSS_FRAME_FORMAT_NV16:
486 	case IA_CSS_FRAME_FORMAT_NV61:
487 		sp_frame_out->planes.nv.y.offset =
488 		    frame_in->planes.nv.y.offset;
489 		sp_frame_out->planes.nv.uv.offset =
490 		    frame_in->planes.nv.uv.offset;
491 		break;
492 	case IA_CSS_FRAME_FORMAT_YUV420:
493 	case IA_CSS_FRAME_FORMAT_YUV422:
494 	case IA_CSS_FRAME_FORMAT_YUV444:
495 	case IA_CSS_FRAME_FORMAT_YUV420_16:
496 	case IA_CSS_FRAME_FORMAT_YUV422_16:
497 	case IA_CSS_FRAME_FORMAT_YV12:
498 	case IA_CSS_FRAME_FORMAT_YV16:
499 		sp_frame_out->planes.yuv.y.offset =
500 		    frame_in->planes.yuv.y.offset;
501 		sp_frame_out->planes.yuv.u.offset =
502 		    frame_in->planes.yuv.u.offset;
503 		sp_frame_out->planes.yuv.v.offset =
504 		    frame_in->planes.yuv.v.offset;
505 		break;
506 	case IA_CSS_FRAME_FORMAT_QPLANE6:
507 		sp_frame_out->planes.plane6.r.offset =
508 		    frame_in->planes.plane6.r.offset;
509 		sp_frame_out->planes.plane6.r_at_b.offset =
510 		    frame_in->planes.plane6.r_at_b.offset;
511 		sp_frame_out->planes.plane6.gr.offset =
512 		    frame_in->planes.plane6.gr.offset;
513 		sp_frame_out->planes.plane6.gb.offset =
514 		    frame_in->planes.plane6.gb.offset;
515 		sp_frame_out->planes.plane6.b.offset =
516 		    frame_in->planes.plane6.b.offset;
517 		sp_frame_out->planes.plane6.b_at_r.offset =
518 		    frame_in->planes.plane6.b_at_r.offset;
519 		break;
520 	case IA_CSS_FRAME_FORMAT_BINARY_8:
521 		sp_frame_out->planes.binary.data.offset =
522 		    frame_in->planes.binary.data.offset;
523 		break;
524 	default:
525 		/* This should not happen, but in case it does,
526 		 * nullify the planes
527 		 */
528 		memset(&sp_frame_out->planes, 0, sizeof(sp_frame_out->planes));
529 		break;
530 	}
531 }
532 
533 static int
534 set_input_frame_buffer(const struct ia_css_frame *frame)
535 {
536 	if (!frame)
537 		return -EINVAL;
538 
539 	switch (frame->info.format) {
540 	case IA_CSS_FRAME_FORMAT_QPLANE6:
541 	case IA_CSS_FRAME_FORMAT_YUV420_16:
542 	case IA_CSS_FRAME_FORMAT_RAW_PACKED:
543 	case IA_CSS_FRAME_FORMAT_RAW:
544 	case IA_CSS_FRAME_FORMAT_YUV420:
545 	case IA_CSS_FRAME_FORMAT_YUYV:
546 	case IA_CSS_FRAME_FORMAT_YUV_LINE:
547 	case IA_CSS_FRAME_FORMAT_NV12:
548 	case IA_CSS_FRAME_FORMAT_NV12_16:
549 	case IA_CSS_FRAME_FORMAT_NV12_TILEY:
550 	case IA_CSS_FRAME_FORMAT_NV21:
551 	case IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8:
552 	case IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8:
553 	case IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_10:
554 		break;
555 	default:
556 		return -EINVAL;
557 	}
558 	sh_css_copy_frame_to_spframe(&sh_css_sp_stage.frames.in, frame);
559 
560 	return 0;
561 }
562 
563 static int
564 set_output_frame_buffer(const struct ia_css_frame *frame,
565 			unsigned int idx)
566 {
567 	if (!frame)
568 		return -EINVAL;
569 
570 	switch (frame->info.format) {
571 	case IA_CSS_FRAME_FORMAT_YUV420:
572 	case IA_CSS_FRAME_FORMAT_YUV422:
573 	case IA_CSS_FRAME_FORMAT_YUV444:
574 	case IA_CSS_FRAME_FORMAT_YV12:
575 	case IA_CSS_FRAME_FORMAT_YV16:
576 	case IA_CSS_FRAME_FORMAT_YUV420_16:
577 	case IA_CSS_FRAME_FORMAT_YUV422_16:
578 	case IA_CSS_FRAME_FORMAT_NV11:
579 	case IA_CSS_FRAME_FORMAT_NV12:
580 	case IA_CSS_FRAME_FORMAT_NV12_16:
581 	case IA_CSS_FRAME_FORMAT_NV12_TILEY:
582 	case IA_CSS_FRAME_FORMAT_NV16:
583 	case IA_CSS_FRAME_FORMAT_NV21:
584 	case IA_CSS_FRAME_FORMAT_NV61:
585 	case IA_CSS_FRAME_FORMAT_YUYV:
586 	case IA_CSS_FRAME_FORMAT_UYVY:
587 	case IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8:
588 	case IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8:
589 	case IA_CSS_FRAME_FORMAT_YUV_LINE:
590 	case IA_CSS_FRAME_FORMAT_RGB565:
591 	case IA_CSS_FRAME_FORMAT_RGBA888:
592 	case IA_CSS_FRAME_FORMAT_PLANAR_RGB888:
593 	case IA_CSS_FRAME_FORMAT_RAW:
594 	case IA_CSS_FRAME_FORMAT_RAW_PACKED:
595 	case IA_CSS_FRAME_FORMAT_QPLANE6:
596 	case IA_CSS_FRAME_FORMAT_BINARY_8:
597 		break;
598 	default:
599 		return -EINVAL;
600 	}
601 	sh_css_copy_frame_to_spframe(&sh_css_sp_stage.frames.out[idx], frame);
602 	return 0;
603 }
604 
605 static int
606 set_view_finder_buffer(const struct ia_css_frame *frame)
607 {
608 	if (!frame)
609 		return -EINVAL;
610 
611 	switch (frame->info.format) {
612 	/* the dual output pin */
613 	case IA_CSS_FRAME_FORMAT_NV12:
614 	case IA_CSS_FRAME_FORMAT_NV12_16:
615 	case IA_CSS_FRAME_FORMAT_NV21:
616 	case IA_CSS_FRAME_FORMAT_YUYV:
617 	case IA_CSS_FRAME_FORMAT_UYVY:
618 	case IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8:
619 	case IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8:
620 	case IA_CSS_FRAME_FORMAT_YUV420:
621 	case IA_CSS_FRAME_FORMAT_YV12:
622 	case IA_CSS_FRAME_FORMAT_NV12_TILEY:
623 
624 	/* for vf_veceven */
625 	case IA_CSS_FRAME_FORMAT_YUV_LINE:
626 		break;
627 	default:
628 		return -EINVAL;
629 	}
630 
631 	sh_css_copy_frame_to_spframe(&sh_css_sp_stage.frames.out_vf, frame);
632 	return 0;
633 }
634 
635 #if !defined(ISP2401)
636 void sh_css_sp_set_if_configs(
637     const input_formatter_cfg_t	*config_a,
638     const input_formatter_cfg_t	*config_b,
639     const uint8_t		if_config_index
640 )
641 {
642 	assert(if_config_index < SH_CSS_MAX_IF_CONFIGS);
643 	assert(config_a);
644 
645 	sh_css_sp_group.config.input_formatter.set[if_config_index].config_a =
646 	    *config_a;
647 	sh_css_sp_group.config.input_formatter.a_changed = true;
648 
649 	if (config_b) {
650 		sh_css_sp_group.config.input_formatter.set[if_config_index].config_b =
651 		    *config_b;
652 		sh_css_sp_group.config.input_formatter.b_changed = true;
653 	}
654 
655 	return;
656 }
657 #endif
658 
659 #if !defined(ISP2401)
660 void
661 sh_css_sp_program_input_circuit(int fmt_type,
662 				int ch_id,
663 				enum ia_css_input_mode input_mode)
664 {
665 	sh_css_sp_group.config.input_circuit.no_side_band = false;
666 	sh_css_sp_group.config.input_circuit.fmt_type     = fmt_type;
667 	sh_css_sp_group.config.input_circuit.ch_id	      = ch_id;
668 	sh_css_sp_group.config.input_circuit.input_mode   = input_mode;
669 	/*
670 	 * The SP group is only loaded at SP boot time and is read once
671 	 * change flags as "input_circuit_cfg_changed" must be reset on the SP
672 	 */
673 	sh_css_sp_group.config.input_circuit_cfg_changed = true;
674 	sh_css_sp_stage.program_input_circuit = true;
675 }
676 #endif
677 
678 #if !defined(ISP2401)
679 void
680 sh_css_sp_configure_sync_gen(int width, int height,
681 			     int hblank_cycles,
682 			     int vblank_cycles)
683 {
684 	sh_css_sp_group.config.sync_gen.width	       = width;
685 	sh_css_sp_group.config.sync_gen.height	       = height;
686 	sh_css_sp_group.config.sync_gen.hblank_cycles = hblank_cycles;
687 	sh_css_sp_group.config.sync_gen.vblank_cycles = vblank_cycles;
688 }
689 
690 void
691 sh_css_sp_configure_tpg(int x_mask,
692 			int y_mask,
693 			int x_delta,
694 			int y_delta,
695 			int xy_mask)
696 {
697 	sh_css_sp_group.config.tpg.x_mask  = x_mask;
698 	sh_css_sp_group.config.tpg.y_mask  = y_mask;
699 	sh_css_sp_group.config.tpg.x_delta = x_delta;
700 	sh_css_sp_group.config.tpg.y_delta = y_delta;
701 	sh_css_sp_group.config.tpg.xy_mask = xy_mask;
702 }
703 
704 void
705 sh_css_sp_configure_prbs(int seed)
706 {
707 	sh_css_sp_group.config.prbs.seed = seed;
708 }
709 #endif
710 
711 void
712 sh_css_sp_configure_enable_raw_pool_locking(bool lock_all)
713 {
714 	sh_css_sp_group.config.enable_raw_pool_locking = true;
715 	sh_css_sp_group.config.lock_all = lock_all;
716 }
717 
718 void
719 sh_css_sp_enable_isys_event_queue(bool enable)
720 {
721 	sh_css_sp_group.config.enable_isys_event_queue = enable;
722 }
723 
724 void
725 sh_css_sp_set_disable_continuous_viewfinder(bool flag)
726 {
727 	sh_css_sp_group.config.disable_cont_vf = flag;
728 }
729 
730 static int
731 sh_css_sp_write_frame_pointers(const struct sh_css_binary_args *args)
732 {
733 	int err = 0;
734 	int i;
735 
736 	assert(args);
737 
738 	if (args->in_frame)
739 		err = set_input_frame_buffer(args->in_frame);
740 	if (!err && args->out_vf_frame)
741 		err = set_view_finder_buffer(args->out_vf_frame);
742 	for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) {
743 		if (!err && args->out_frame[i])
744 			err = set_output_frame_buffer(args->out_frame[i], i);
745 	}
746 
747 	/* we don't pass this error back to the upper layer, so we add a assert here
748 	   because we actually hit the error here but it still works by accident... */
749 	if (err) assert(false);
750 	return err;
751 }
752 
753 static void
754 sh_css_sp_init_group(bool two_ppc,
755 		     enum atomisp_input_format input_format,
756 		     bool no_isp_sync,
757 		     uint8_t if_config_index)
758 {
759 #if !defined(ISP2401)
760 	sh_css_sp_group.config.input_formatter.isp_2ppc = two_ppc;
761 #else
762 	(void)two_ppc;
763 #endif
764 
765 	sh_css_sp_group.config.no_isp_sync = (uint8_t)no_isp_sync;
766 	/* decide whether the frame is processed online or offline */
767 	if (if_config_index == SH_CSS_IF_CONFIG_NOT_NEEDED) return;
768 #if !defined(ISP2401)
769 	assert(if_config_index < SH_CSS_MAX_IF_CONFIGS);
770 	sh_css_sp_group.config.input_formatter.set[if_config_index].stream_format =
771 	    input_format;
772 #else
773 	(void)input_format;
774 #endif
775 }
776 
777 void
778 sh_css_stage_write_binary_info(struct ia_css_binary_info *info)
779 {
780 	assert(info);
781 	sh_css_isp_stage.binary_info = *info;
782 }
783 
784 static int
785 copy_isp_mem_if_to_ddr(struct ia_css_binary *binary)
786 {
787 	int err;
788 
789 	err = ia_css_isp_param_copy_isp_mem_if_to_ddr(
790 	    &binary->css_params,
791 	    &binary->mem_params,
792 	    IA_CSS_PARAM_CLASS_CONFIG);
793 	if (err)
794 		return err;
795 	err = ia_css_isp_param_copy_isp_mem_if_to_ddr(
796 	    &binary->css_params,
797 	    &binary->mem_params,
798 	    IA_CSS_PARAM_CLASS_STATE);
799 	if (err)
800 		return err;
801 	return 0;
802 }
803 
804 static bool
805 is_sp_stage(struct ia_css_pipeline_stage *stage)
806 {
807 	assert(stage);
808 	return stage->sp_func != IA_CSS_PIPELINE_NO_FUNC;
809 }
810 
811 static int configure_isp_from_args(const struct sh_css_sp_pipeline *pipeline,
812 				   const struct ia_css_binary      *binary,
813 				   const struct sh_css_binary_args *args,
814 				   bool				   two_ppc,
815 				   bool				   deinterleaved)
816 {
817 	int ret;
818 
819 	ret = ia_css_fpn_configure(binary,  &binary->in_frame_info);
820 	if (ret)
821 		return ret;
822 	ret = ia_css_crop_configure(binary, &args->delay_frames[0]->info);
823 	if (ret)
824 		return ret;
825 	ret = ia_css_qplane_configure(pipeline, binary, &binary->in_frame_info);
826 	if (ret)
827 		return ret;
828 	ret = ia_css_output0_configure(binary, &args->out_frame[0]->info);
829 	if (ret)
830 		return ret;
831 	ret = ia_css_output1_configure(binary, &args->out_vf_frame->info);
832 	if (ret)
833 		return ret;
834 	ret = ia_css_copy_output_configure(binary, args->copy_output);
835 	if (ret)
836 		return ret;
837 	ret = ia_css_output0_configure(binary, &args->out_frame[0]->info);
838 	if (ret)
839 		return ret;
840 	ret = ia_css_iterator_configure(binary, &args->in_frame->info);
841 	if (ret)
842 		return ret;
843 	ret = ia_css_dvs_configure(binary, &args->out_frame[0]->info);
844 	if (ret)
845 		return ret;
846 	ret = ia_css_output_configure(binary, &args->out_frame[0]->info);
847 	if (ret)
848 		return ret;
849 	ret = ia_css_raw_configure(pipeline, binary, &args->in_frame->info, &binary->in_frame_info, two_ppc, deinterleaved);
850 	if (ret)
851 		return ret;
852 
853 	/*
854 	 * FIXME: args->delay_frames can be NULL here
855 	 *
856 	 * Somehow, the driver at the Intel Atom Yocto tree doesn't seem to
857 	 * suffer from the same issue.
858 	 *
859 	 * Anyway, the function below should now handle a NULL delay_frames
860 	 * without crashing, but the pipeline should likely be built without
861 	 * adding it at the first place (or there are a hidden bug somewhere)
862 	 */
863 	ret = ia_css_ref_configure(binary, args->delay_frames, pipeline->dvs_frame_delay);
864 	if (ret)
865 		return ret;
866 	ret = ia_css_tnr_configure(binary, args->tnr_frames);
867 	if (ret)
868 		return ret;
869 	return ia_css_bayer_io_config(binary, args);
870 }
871 
872 static void
873 initialize_isp_states(const struct ia_css_binary *binary)
874 {
875 	unsigned int i;
876 
877 	if (!binary->info->mem_offsets.offsets.state)
878 		return;
879 	for (i = 0; i < IA_CSS_NUM_STATE_IDS; i++) {
880 		ia_css_kernel_init_state[i](binary);
881 	}
882 }
883 
884 static void
885 initialize_frame_buffer_attribute(struct ia_css_buffer_sp *buf_attr)
886 {
887 	buf_attr->buf_src.queue_id = SH_CSS_INVALID_QUEUE_ID;
888 	buf_attr->buf_type = IA_CSS_BUFFER_TYPE_INVALID;
889 }
890 
891 static void
892 initialize_stage_frames(struct ia_css_frames_sp *frames)
893 {
894 	unsigned int i;
895 
896 	initialize_frame_buffer_attribute(&frames->in.buf_attr);
897 	for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) {
898 		initialize_frame_buffer_attribute(&frames->out[i].buf_attr);
899 	}
900 	initialize_frame_buffer_attribute(&frames->out_vf.buf_attr);
901 	initialize_frame_buffer_attribute(&frames->s3a_buf);
902 	initialize_frame_buffer_attribute(&frames->dvs_buf);
903 	initialize_frame_buffer_attribute(&frames->metadata_buf);
904 }
905 
906 static int
907 sh_css_sp_init_stage(struct ia_css_binary *binary,
908 		     const char *binary_name,
909 		     const struct ia_css_blob_info *blob_info,
910 		     const struct sh_css_binary_args *args,
911 		     unsigned int pipe_num,
912 		     unsigned int stage,
913 		     bool xnr,
914 		     const struct ia_css_isp_param_css_segments *isp_mem_if,
915 		     unsigned int if_config_index,
916 		     bool two_ppc)
917 {
918 	const struct ia_css_binary_xinfo *xinfo;
919 	const struct ia_css_binary_info  *info;
920 	int err = 0;
921 	int i;
922 	struct ia_css_pipe *pipe = NULL;
923 	unsigned int thread_id;
924 	enum sh_css_queue_id queue_id;
925 	bool continuous = sh_css_continuous_is_enabled((uint8_t)pipe_num);
926 
927 	assert(binary);
928 	assert(blob_info);
929 	assert(args);
930 	assert(isp_mem_if);
931 
932 	xinfo = binary->info;
933 	info  = &xinfo->sp;
934 	{
935 		/*
936 		 * Clear sh_css_sp_stage for easy debugging.
937 		 * program_input_circuit must be saved as it is set outside
938 		 * this function.
939 		 */
940 		u8 program_input_circuit;
941 
942 		program_input_circuit = sh_css_sp_stage.program_input_circuit;
943 		memset(&sh_css_sp_stage, 0, sizeof(sh_css_sp_stage));
944 		sh_css_sp_stage.program_input_circuit = (uint8_t)program_input_circuit;
945 	}
946 
947 	ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
948 
949 	if (!info) {
950 		sh_css_sp_group.pipe[thread_id].sp_stage_addr[stage] = mmgr_NULL;
951 		return 0;
952 	}
953 
954 #if defined(ISP2401)
955 	(void)continuous;
956 	sh_css_sp_stage.deinterleaved = 0;
957 #else
958 	sh_css_sp_stage.deinterleaved = ((stage == 0) && continuous);
959 #endif
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->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
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]->info;
1128 		info = &firmware->info.isp;
1129 		ia_css_binary_fill_info(info, false, false,
1130 					ATOMISP_INPUT_FORMAT_RAW_10,
1131 					args->in_frame  ? &args->in_frame->info  : NULL,
1132 					NULL,
1133 					out_infos,
1134 					args->out_vf_frame ? &args->out_vf_frame->info
1135 					: NULL,
1136 					&tmp_binary,
1137 					NULL,
1138 					-1, true);
1139 		binary = &tmp_binary;
1140 		binary->info = info;
1141 		binary_name = IA_CSS_EXT_ISP_PROG_NAME(firmware);
1142 		blob_info = &firmware->blob;
1143 		mem_if = (struct ia_css_isp_param_css_segments *)&firmware->mem_initializers;
1144 	} else {
1145 		/* SP stage */
1146 		assert(stage->sp_func != IA_CSS_PIPELINE_NO_FUNC);
1147 		/* binary and blob_info are now NULL.
1148 		   These will be passed to sh_css_sp_init_stage
1149 		   and dereferenced there, so passing a NULL
1150 		   pointer is no good. return an error */
1151 		return -EINVAL;
1152 	}
1153 
1154 	err = sh_css_sp_init_stage(binary,
1155 				   (const char *)binary_name,
1156 				   blob_info,
1157 				   args,
1158 				   pipe_num,
1159 				   stage_num,
1160 				   xnr,
1161 				   mem_if,
1162 				   if_config_index,
1163 				   two_ppc);
1164 	return err;
1165 }
1166 
1167 static void
1168 sp_init_sp_stage(struct ia_css_pipeline_stage *stage,
1169 		 unsigned int pipe_num,
1170 		 bool two_ppc,
1171 		 enum sh_css_pipe_config_override copy_ovrd,
1172 		 unsigned int if_config_index)
1173 {
1174 	const struct sh_css_binary_args *args = &stage->args;
1175 
1176 	assert(stage);
1177 	switch (stage->sp_func) {
1178 	case IA_CSS_PIPELINE_RAW_COPY:
1179 		sh_css_sp_start_raw_copy(args->out_frame[0],
1180 					 pipe_num, two_ppc,
1181 					 stage->max_input_width,
1182 					 copy_ovrd, if_config_index);
1183 		break;
1184 	case IA_CSS_PIPELINE_BIN_COPY:
1185 		assert(false); /* TBI */
1186 		break;
1187 	case IA_CSS_PIPELINE_ISYS_COPY:
1188 		sh_css_sp_start_isys_copy(args->out_frame[0],
1189 					  pipe_num, stage->max_input_width, if_config_index);
1190 		break;
1191 	case IA_CSS_PIPELINE_NO_FUNC:
1192 		assert(false);
1193 		break;
1194 	}
1195 }
1196 
1197 void
1198 sh_css_sp_init_pipeline(struct ia_css_pipeline *me,
1199 			enum ia_css_pipe_id id,
1200 			u8 pipe_num,
1201 			bool xnr,
1202 			bool two_ppc,
1203 			bool continuous,
1204 			bool offline,
1205 			unsigned int required_bds_factor,
1206 			enum sh_css_pipe_config_override copy_ovrd,
1207 			enum ia_css_input_mode input_mode,
1208 			const struct ia_css_metadata_config *md_config,
1209 			const struct ia_css_metadata_info *md_info,
1210 			const enum mipi_port_id port_id)
1211 {
1212 	/* Get first stage */
1213 	struct ia_css_pipeline_stage *stage        = NULL;
1214 	struct ia_css_binary	     *first_binary = NULL;
1215 	struct ia_css_pipe *pipe = NULL;
1216 	unsigned int num;
1217 
1218 	enum ia_css_pipe_id pipe_id = id;
1219 	unsigned int thread_id;
1220 	u8 if_config_index, tmp_if_config_index;
1221 
1222 	assert(me);
1223 
1224 	assert(me->stages);
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) && me->stages &&
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 = me->pipe_qos_config;
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
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 
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
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
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
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
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
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
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
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
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
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
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
1630 sh_css_sp_set_sp_running(bool flag)
1631 {
1632 	sp_running = flag;
1633 }
1634 
1635 bool
1636 sh_css_sp_is_running(void)
1637 {
1638 	return sp_running;
1639 }
1640 
1641 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
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
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
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
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