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