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