1 /*
2  * Support for Intel Camera Imaging ISP subsystem.
3  * Copyright (c) 2015, Intel Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  */
14 
15 #include "hmm.h"
16 
17 #include "sh_css_sp.h"
18 
19 #if !defined(HAS_NO_INPUT_FORMATTER)
20 #include "input_formatter.h"
21 #endif
22 
23 #include "dma.h"	/* N_DMA_CHANNEL_ID */
24 
25 #include "ia_css_buffer.h"
26 #include "ia_css_binary.h"
27 #include "sh_css_hrt.h"
28 #include "sh_css_defs.h"
29 #include "sh_css_internal.h"
30 #include "ia_css_control.h"
31 #include "ia_css_debug.h"
32 #include "ia_css_debug_pipe.h"
33 #include "ia_css_event_public.h"
34 #include "ia_css_mmu.h"
35 #include "ia_css_stream.h"
36 #include "ia_css_isp_param.h"
37 #include "sh_css_params.h"
38 #include "sh_css_legacy.h"
39 #include "ia_css_frame_comm.h"
40 #if !defined(HAS_NO_INPUT_SYSTEM)
41 #include "ia_css_isys.h"
42 #endif
43 
44 #include "gdc_device.h"				/* HRT_GDC_N */
45 
46 /*#include "sp.h"*/	/* host2sp_enqueue_frame_data() */
47 
48 
49 #include "assert_support.h"
50 #include "platform_support.h"	/* hrt_sleep() */
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 	strncpy(sh_css_isp_stage.binary_name, binary_name, SH_CSS_MAX_BINARY_NAME - 1);
994 	sh_css_isp_stage.binary_name[SH_CSS_MAX_BINARY_NAME - 1] = 0;
995 	sh_css_isp_stage.mem_initializers = *isp_mem_if;
996 
997 	/*
998 	 * Even when a stage does not need uds and does not params,
999 	 * ia_css_uds_sp_scale_params() seems to be called (needs
1000 	 * further investigation). This function can not deal with
1001 	 * dx, dy = {0, 0}
1002 	 */
1003 
1004 	err = sh_css_sp_write_frame_pointers(args);
1005 	/* TODO: move it to a better place */
1006 	if (binary->info->sp.enable.s3a)
1007 	{
1008 		ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_3A_STATISTICS, thread_id,
1009 					       &queue_id);
1010 		sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.s3a_buf, queue_id,
1011 						    mmgr_EXCEPTION,
1012 						    IA_CSS_BUFFER_TYPE_3A_STATISTICS);
1013 	}
1014 	if (binary->info->sp.enable.dis)
1015 	{
1016 		ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_DIS_STATISTICS, thread_id,
1017 					       &queue_id);
1018 		sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.dvs_buf, queue_id,
1019 						    mmgr_EXCEPTION,
1020 						    IA_CSS_BUFFER_TYPE_DIS_STATISTICS);
1021 	}
1022 #if defined SH_CSS_ENABLE_METADATA
1023 	ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_METADATA, thread_id, &queue_id);
1024 	sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.metadata_buf, queue_id, mmgr_EXCEPTION, IA_CSS_BUFFER_TYPE_METADATA);
1025 #endif
1026 	if (err)
1027 		return err;
1028 
1029 #ifdef USE_INPUT_SYSTEM_VERSION_2401
1030 	if (stage == 0) {
1031 		pipe = find_pipe_by_num(sh_css_sp_group.pipe[thread_id].pipe_num);
1032 		if (!pipe)
1033 			return -EINVAL;
1034 
1035 		if (args->in_frame)
1036 			ia_css_get_crop_offsets(pipe, &args->in_frame->info);
1037 		else
1038 			ia_css_get_crop_offsets(pipe, &binary->in_frame_info);
1039 	}
1040 #else
1041 	(void)pipe; /*avoid build warning*/
1042 #endif
1043 
1044 	err = configure_isp_from_args(&sh_css_sp_group.pipe[thread_id],
1045 				      binary, args, two_ppc, sh_css_sp_stage.deinterleaved);
1046 	if (err)
1047 		return err;
1048 
1049 	initialize_isp_states(binary);
1050 
1051 	/* we do this only for preview pipe because in fill_binary_info function
1052 	 * we assign vf_out res to out res, but for ISP internal processing, we need
1053 	 * the original out res. for video pipe, it has two output pins --- out and
1054 	 * vf_out, so it can keep these two resolutions already. */
1055 	if (binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_PREVIEW &&
1056 	    (binary->vf_downscale_log2 > 0))
1057 	{
1058 		/* TODO: Remove this after preview output decimation is fixed
1059 		 * by configuring out&vf info fiels properly */
1060 		sh_css_sp_stage.frames.out[0].info.padded_width
1061 		<<= binary->vf_downscale_log2;
1062 		sh_css_sp_stage.frames.out[0].info.res.width
1063 		<<= binary->vf_downscale_log2;
1064 		sh_css_sp_stage.frames.out[0].info.res.height
1065 		<<= binary->vf_downscale_log2;
1066 	}
1067 	err = copy_isp_mem_if_to_ddr(binary);
1068 	if (err)
1069 		return err;
1070 
1071 	return 0;
1072 }
1073 
1074 static int
1075 sp_init_stage(struct ia_css_pipeline_stage *stage,
1076 	      unsigned int pipe_num,
1077 	      bool xnr,
1078 	      unsigned int if_config_index,
1079 	      bool two_ppc) {
1080 	struct ia_css_binary *binary;
1081 	const struct ia_css_fw_info *firmware;
1082 	const struct sh_css_binary_args *args;
1083 	unsigned int stage_num;
1084 	/*
1085 	 * Initialiser required because of the "else" path below.
1086 	 * Is this a valid path ?
1087 	 */
1088 	const char *binary_name = "";
1089 	const struct ia_css_binary_xinfo *info = NULL;
1090 	/* note: the var below is made static as it is quite large;
1091 	   if it is not static it ends up on the stack which could
1092 	   cause issues for drivers
1093 	*/
1094 	static struct ia_css_binary tmp_binary;
1095 	const struct ia_css_blob_info *blob_info = NULL;
1096 	struct ia_css_isp_param_css_segments isp_mem_if;
1097 	/* LA: should be ia_css_data, should not contain host pointer.
1098 	   However, CSS/DDR pointer is not available yet.
1099 	   Hack is to store it in params->ddr_ptrs and then copy it late in the SP just before vmem init.
1100 	   TODO: Call this after CSS/DDR allocation and store that pointer.
1101 	   Best is to allocate it at stage creation time together with host pointer.
1102 	   Remove vmem from params.
1103 	*/
1104 	struct ia_css_isp_param_css_segments *mem_if = &isp_mem_if;
1105 
1106 	int err = 0;
1107 
1108 	assert(stage);
1109 
1110 	binary = stage->binary;
1111 	firmware = stage->firmware;
1112 	args = &stage->args;
1113 	stage_num = stage->stage_num;
1114 
1115 	if (binary)
1116 	{
1117 		info = binary->info;
1118 		binary_name = (const char *)(info->blob->name);
1119 		blob_info = &info->blob->header.blob;
1120 		ia_css_init_memory_interface(mem_if, &binary->mem_params, &binary->css_params);
1121 	} else if (firmware)
1122 	{
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]->info;
1127 		info = &firmware->info.isp;
1128 		ia_css_binary_fill_info(info, false, false,
1129 					ATOMISP_INPUT_FORMAT_RAW_10,
1130 					args->in_frame  ? &args->in_frame->info  : NULL,
1131 					NULL,
1132 					out_infos,
1133 					args->out_vf_frame ? &args->out_vf_frame->info
1134 					: NULL,
1135 					&tmp_binary,
1136 					NULL,
1137 					-1, true);
1138 		binary = &tmp_binary;
1139 		binary->info = info;
1140 		binary_name = IA_CSS_EXT_ISP_PROG_NAME(firmware);
1141 		blob_info = &firmware->blob;
1142 		mem_if = (struct ia_css_isp_param_css_segments *)&firmware->mem_initializers;
1143 	} else
1144 	{
1145 		/* SP stage */
1146 		assert(stage->sp_func != IA_CSS_PIPELINE_NO_FUNC);
1147 		/* binary and blob_info are now NULL.
1148 		   These will be passed to sh_css_sp_init_stage
1149 		   and dereferenced there, so passing a NULL
1150 		   pointer is no good. return an error */
1151 		return -EINVAL;
1152 	}
1153 
1154 	err = sh_css_sp_init_stage(binary,
1155 				   (const char *)binary_name,
1156 				   blob_info,
1157 				   args,
1158 				   pipe_num,
1159 				   stage_num,
1160 				   xnr,
1161 				   mem_if,
1162 				   if_config_index,
1163 				   two_ppc);
1164 	return err;
1165 }
1166 
1167 static void
1168 sp_init_sp_stage(struct ia_css_pipeline_stage *stage,
1169 		 unsigned int pipe_num,
1170 		 bool two_ppc,
1171 		 enum sh_css_pipe_config_override copy_ovrd,
1172 		 unsigned int if_config_index)
1173 {
1174 	const struct sh_css_binary_args *args = &stage->args;
1175 
1176 	assert(stage);
1177 	switch (stage->sp_func) {
1178 	case IA_CSS_PIPELINE_RAW_COPY:
1179 		sh_css_sp_start_raw_copy(args->out_frame[0],
1180 					 pipe_num, two_ppc,
1181 					 stage->max_input_width,
1182 					 copy_ovrd, if_config_index);
1183 		break;
1184 	case IA_CSS_PIPELINE_BIN_COPY:
1185 		assert(false); /* TBI */
1186 	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 	}
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 #if !defined(HAS_NO_INPUT_SYSTEM)
1209 			const enum mipi_port_id port_id,
1210 #endif
1211 			const struct ia_css_coordinate
1212 			*internal_frame_origin_bqs_on_sctbl, /* Origin of internal frame
1213 							positioned on shading table at shading correction in ISP. */
1214 			const struct ia_css_isp_parameters *params
1215 		       ) {
1216 	/* Get first stage */
1217 	struct ia_css_pipeline_stage *stage        = NULL;
1218 	struct ia_css_binary	     *first_binary = NULL;
1219 	struct ia_css_pipe *pipe = NULL;
1220 	unsigned int num;
1221 
1222 	enum ia_css_pipe_id pipe_id = id;
1223 	unsigned int thread_id;
1224 	u8 if_config_index, tmp_if_config_index;
1225 
1226 	assert(me);
1227 
1228 #if !defined(HAS_NO_INPUT_SYSTEM)
1229 	assert(me->stages);
1230 
1231 	first_binary = me->stages->binary;
1232 
1233 	if (input_mode == IA_CSS_INPUT_MODE_SENSOR ||
1234 	    input_mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
1235 	{
1236 		assert(port_id < N_MIPI_PORT_ID);
1237 		if (port_id >= N_MIPI_PORT_ID) /* should not happen but KW does not know */
1238 			return; /* we should be able to return an error */
1239 		if_config_index  = (uint8_t)(port_id - MIPI_PORT0_ID);
1240 	} else if (input_mode == IA_CSS_INPUT_MODE_MEMORY)
1241 	{
1242 		if_config_index = SH_CSS_IF_CONFIG_NOT_NEEDED;
1243 	} else
1244 	{
1245 		if_config_index = 0x0;
1246 	}
1247 #else
1248 	(void)input_mode;
1249 	if_config_index = SH_CSS_IF_CONFIG_NOT_NEEDED;
1250 #endif
1251 
1252 	ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
1253 	memset(&sh_css_sp_group.pipe[thread_id], 0, sizeof(struct sh_css_sp_pipeline));
1254 
1255 	/* Count stages */
1256 	for (stage = me->stages, num = 0; stage; stage = stage->next, num++)
1257 	{
1258 		stage->stage_num = num;
1259 		ia_css_debug_pipe_graph_dump_stage(stage, id);
1260 	}
1261 	me->num_stages = num;
1262 
1263 	if (first_binary)
1264 	{
1265 		/* Init pipeline data */
1266 		sh_css_sp_init_group(two_ppc, first_binary->input_format,
1267 				     offline, if_config_index);
1268 	} /* if (first_binary != NULL) */
1269 
1270 #if defined(USE_INPUT_SYSTEM_VERSION_2401) || defined(USE_INPUT_SYSTEM_VERSION_2)
1271 	/* Signal the host immediately after start for SP_ISYS_COPY only */
1272 	if ((me->num_stages == 1) && me->stages &&
1273 	    (me->stages->sp_func == IA_CSS_PIPELINE_ISYS_COPY))
1274 		sh_css_sp_group.config.no_isp_sync = true;
1275 #endif
1276 
1277 	/* Init stage data */
1278 	sh_css_init_host2sp_frame_data();
1279 
1280 	sh_css_sp_group.pipe[thread_id].num_stages = 0;
1281 	sh_css_sp_group.pipe[thread_id].pipe_id = pipe_id;
1282 	sh_css_sp_group.pipe[thread_id].thread_id = thread_id;
1283 	sh_css_sp_group.pipe[thread_id].pipe_num = pipe_num;
1284 	sh_css_sp_group.pipe[thread_id].num_execs = me->num_execs;
1285 	sh_css_sp_group.pipe[thread_id].pipe_qos_config = me->pipe_qos_config;
1286 	sh_css_sp_group.pipe[thread_id].required_bds_factor = required_bds_factor;
1287 #if !defined(HAS_NO_INPUT_SYSTEM)
1288 	sh_css_sp_group.pipe[thread_id].input_system_mode
1289 	= (uint32_t)input_mode;
1290 	sh_css_sp_group.pipe[thread_id].port_id = port_id;
1291 #endif
1292 	sh_css_sp_group.pipe[thread_id].dvs_frame_delay = (uint32_t)me->dvs_frame_delay;
1293 
1294 	/* TODO: next indicates from which queues parameters need to be
1295 		 sampled, needs checking/improvement */
1296 	if (ia_css_pipeline_uses_params(me))
1297 	{
1298 		sh_css_sp_group.pipe[thread_id].pipe_config =
1299 		SH_CSS_PIPE_CONFIG_SAMPLE_PARAMS << thread_id;
1300 	}
1301 
1302 	/* For continuous use-cases, SP copy is responsible for sampling the
1303 	 * parameters */
1304 	if (continuous)
1305 		sh_css_sp_group.pipe[thread_id].pipe_config = 0;
1306 
1307 	sh_css_sp_group.pipe[thread_id].inout_port_config = me->inout_port_config;
1308 
1309 	pipe = find_pipe_by_num(pipe_num);
1310 	assert(pipe);
1311 	if (!pipe)
1312 	{
1313 		return;
1314 	}
1315 	sh_css_sp_group.pipe[thread_id].scaler_pp_lut = sh_css_pipe_get_pp_gdc_lut(pipe);
1316 
1317 #if defined(SH_CSS_ENABLE_METADATA)
1318 	if (md_info && md_info->size > 0)
1319 	{
1320 		sh_css_sp_group.pipe[thread_id].metadata.width  = md_info->resolution.width;
1321 		sh_css_sp_group.pipe[thread_id].metadata.height = md_info->resolution.height;
1322 		sh_css_sp_group.pipe[thread_id].metadata.stride = md_info->stride;
1323 		sh_css_sp_group.pipe[thread_id].metadata.size   = md_info->size;
1324 		ia_css_isys_convert_stream_format_to_mipi_format(
1325 		    md_config->data_type, MIPI_PREDICTOR_NONE,
1326 		    &sh_css_sp_group.pipe[thread_id].metadata.format);
1327 	}
1328 #else
1329 	(void)md_config;
1330 	(void)md_info;
1331 #endif
1332 
1333 #if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS)
1334 	sh_css_sp_group.pipe[thread_id].output_frame_queue_id = (uint32_t)SH_CSS_INVALID_QUEUE_ID;
1335 	if (pipe_id != IA_CSS_PIPE_ID_COPY)
1336 	{
1337 		ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, thread_id,
1338 					       (enum sh_css_queue_id *)(
1339 						   &sh_css_sp_group.pipe[thread_id].output_frame_queue_id));
1340 	}
1341 #endif
1342 
1343 	if (atomisp_hw_is_isp2401) {
1344 		/* For the shading correction type 1 (the legacy shading table conversion in css is not used),
1345 		* the parameters are passed to the isp for the shading table centering.
1346 		*/
1347 		if (internal_frame_origin_bqs_on_sctbl &&
1348 		    params && params->shading_settings.enable_shading_table_conversion == 0)
1349 		{
1350 			sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_x_bqs_on_sctbl
1351 			= (uint32_t)internal_frame_origin_bqs_on_sctbl->x;
1352 			sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_y_bqs_on_sctbl
1353 			= (uint32_t)internal_frame_origin_bqs_on_sctbl->y;
1354 		} else
1355 		{
1356 			sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_x_bqs_on_sctbl =
1357 			0;
1358 			sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_y_bqs_on_sctbl =
1359 			0;
1360 		}
1361 	}
1362 
1363 	IA_CSS_LOG("pipe_id %d port_config %08x",
1364 		   pipe_id, sh_css_sp_group.pipe[thread_id].inout_port_config);
1365 
1366 	for (stage = me->stages, num = 0; stage; stage = stage->next, num++)
1367 	{
1368 		sh_css_sp_group.pipe[thread_id].num_stages++;
1369 		if (is_sp_stage(stage)) {
1370 			sp_init_sp_stage(stage, pipe_num, two_ppc,
1371 					 copy_ovrd, if_config_index);
1372 		} else {
1373 			if ((stage->stage_num != 0) ||
1374 			    SH_CSS_PIPE_PORT_CONFIG_IS_CONTINUOUS(me->inout_port_config))
1375 				tmp_if_config_index = SH_CSS_IF_CONFIG_NOT_NEEDED;
1376 			else
1377 				tmp_if_config_index = if_config_index;
1378 			sp_init_stage(stage, pipe_num,
1379 				      xnr, tmp_if_config_index, two_ppc);
1380 		}
1381 
1382 		store_sp_stage_data(pipe_id, pipe_num, num);
1383 	}
1384 	sh_css_sp_group.pipe[thread_id].pipe_config |= (uint32_t)
1385 		(me->acquire_isp_each_stage << IA_CSS_ACQUIRE_ISP_POS);
1386 	store_sp_group_data();
1387 }
1388 
1389 void
1390 sh_css_sp_uninit_pipeline(unsigned int pipe_num)
1391 {
1392 	unsigned int thread_id;
1393 
1394 	ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
1395 	/*memset(&sh_css_sp_group.pipe[thread_id], 0, sizeof(struct sh_css_sp_pipeline));*/
1396 	sh_css_sp_group.pipe[thread_id].num_stages = 0;
1397 }
1398 
1399 bool sh_css_write_host2sp_command(enum host2sp_commands host2sp_command)
1400 {
1401 	unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1402 	unsigned int offset = (unsigned int)offsetof(struct host_sp_communication,
1403 			      host2sp_command)
1404 			      / sizeof(int);
1405 	enum host2sp_commands last_cmd = host2sp_cmd_error;
1406 	(void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
1407 
1408 	/* Previous command must be handled by SP (by design) */
1409 	last_cmd = load_sp_array_uint(host_sp_com, offset);
1410 	if (last_cmd != host2sp_cmd_ready)
1411 		IA_CSS_ERROR("last host command not handled by SP(%d)", last_cmd);
1412 
1413 	store_sp_array_uint(host_sp_com, offset, host2sp_command);
1414 
1415 	return (last_cmd == host2sp_cmd_ready);
1416 }
1417 
1418 enum host2sp_commands
1419 sh_css_read_host2sp_command(void) {
1420 	unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1421 	unsigned int offset = (unsigned int)offsetof(struct host_sp_communication, host2sp_command)
1422 	/ sizeof(int);
1423 	(void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
1424 	return (enum host2sp_commands)load_sp_array_uint(host_sp_com, offset);
1425 }
1426 
1427 /*
1428  * Frame data is no longer part of the sp_stage structure but part of a
1429  * separate structure. The aim is to make the sp_data struct static
1430  * (it defines a pipeline) and that the dynamic (per frame) data is stored
1431  * separetly.
1432  *
1433  * This function must be called first every where were you start constructing
1434  * a new pipeline by defining one or more stages with use of variable
1435  * sh_css_sp_stage. Even the special cases like accelerator and copy_frame
1436  * These have a pipeline of just 1 stage.
1437  */
1438 void
1439 sh_css_init_host2sp_frame_data(void)
1440 {
1441 	/* Clean table */
1442 	unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1443 
1444 	(void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
1445 	/*
1446 	 * rvanimme: don't clean it to save static frame info line ref_in
1447 	 * ref_out, and tnr_frames. Once this static data is in a
1448 	 * separate data struct, this may be enable (but still, there is
1449 	 * no need for it)
1450 	 */
1451 }
1452 
1453 /*
1454  * @brief Update the offline frame information in host_sp_communication.
1455  * Refer to "sh_css_sp.h" for more details.
1456  */
1457 void
1458 sh_css_update_host2sp_offline_frame(
1459     unsigned int frame_num,
1460     struct ia_css_frame *frame,
1461     struct ia_css_metadata *metadata)
1462 {
1463 	unsigned int HIVE_ADDR_host_sp_com;
1464 	unsigned int offset;
1465 
1466 	assert(frame_num < NUM_CONTINUOUS_FRAMES);
1467 
1468 	/* Write new frame data into SP DMEM */
1469 	HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1470 	offset = (unsigned int)offsetof(struct host_sp_communication,
1471 					host2sp_offline_frames)
1472 		 / sizeof(int);
1473 	offset += frame_num;
1474 	store_sp_array_uint(host_sp_com, offset, frame ? frame->data : 0);
1475 
1476 	/* Write metadata buffer into SP DMEM */
1477 	offset = (unsigned int)offsetof(struct host_sp_communication,
1478 					host2sp_offline_metadata)
1479 		 / sizeof(int);
1480 	offset += frame_num;
1481 	store_sp_array_uint(host_sp_com, offset, metadata ? metadata->address : 0);
1482 }
1483 
1484 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
1485 /*
1486  * @brief Update the mipi frame information in host_sp_communication.
1487  * Refer to "sh_css_sp.h" for more details.
1488  */
1489 void
1490 sh_css_update_host2sp_mipi_frame(
1491     unsigned int frame_num,
1492     struct ia_css_frame *frame)
1493 {
1494 	unsigned int HIVE_ADDR_host_sp_com;
1495 	unsigned int offset;
1496 
1497 	/* MIPI buffers are dedicated to port, so now there are more of them. */
1498 	assert(frame_num < (N_CSI_PORTS * NUM_MIPI_FRAMES_PER_STREAM));
1499 
1500 	/* Write new frame data into SP DMEM */
1501 	HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1502 	offset = (unsigned int)offsetof(struct host_sp_communication,
1503 					host2sp_mipi_frames)
1504 		 / sizeof(int);
1505 	offset += frame_num;
1506 
1507 	store_sp_array_uint(host_sp_com, offset,
1508 			    frame ? frame->data : 0);
1509 }
1510 
1511 /*
1512  * @brief Update the mipi metadata information in host_sp_communication.
1513  * Refer to "sh_css_sp.h" for more details.
1514  */
1515 void
1516 sh_css_update_host2sp_mipi_metadata(
1517     unsigned int frame_num,
1518     struct ia_css_metadata *metadata)
1519 {
1520 	unsigned int HIVE_ADDR_host_sp_com;
1521 	unsigned int o;
1522 
1523 	/* MIPI buffers are dedicated to port, so now there are more of them. */
1524 	assert(frame_num < (N_CSI_PORTS * NUM_MIPI_FRAMES_PER_STREAM));
1525 
1526 	/* Write new frame data into SP DMEM */
1527 	HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1528 	o = offsetof(struct host_sp_communication, host2sp_mipi_metadata)
1529 	    / sizeof(int);
1530 	o += frame_num;
1531 	store_sp_array_uint(host_sp_com, o,
1532 			    metadata ? metadata->address : 0);
1533 }
1534 
1535 void
1536 sh_css_update_host2sp_num_mipi_frames(unsigned int num_frames)
1537 {
1538 	unsigned int HIVE_ADDR_host_sp_com;
1539 	unsigned int offset;
1540 
1541 	/* Write new frame data into SP DMEM */
1542 	HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1543 	offset = (unsigned int)offsetof(struct host_sp_communication,
1544 					host2sp_num_mipi_frames)
1545 		 / sizeof(int);
1546 
1547 	store_sp_array_uint(host_sp_com, offset, num_frames);
1548 }
1549 #endif
1550 
1551 void
1552 sh_css_update_host2sp_cont_num_raw_frames(unsigned int num_frames,
1553 	bool set_avail)
1554 {
1555 	const struct ia_css_fw_info *fw;
1556 	unsigned int HIVE_ADDR_host_sp_com;
1557 	unsigned int extra_num_frames, avail_num_frames;
1558 	unsigned int offset, offset_extra;
1559 
1560 	/* Write new frame data into SP DMEM */
1561 	fw = &sh_css_sp_fw;
1562 	HIVE_ADDR_host_sp_com = fw->info.sp.host_sp_com;
1563 	if (set_avail) {
1564 		offset = (unsigned int)offsetof(struct host_sp_communication,
1565 						host2sp_cont_avail_num_raw_frames)
1566 			 / sizeof(int);
1567 		avail_num_frames = load_sp_array_uint(host_sp_com, offset);
1568 		extra_num_frames = num_frames - avail_num_frames;
1569 		offset_extra = (unsigned int)offsetof(struct host_sp_communication,
1570 						      host2sp_cont_extra_num_raw_frames)
1571 			       / sizeof(int);
1572 		store_sp_array_uint(host_sp_com, offset_extra, extra_num_frames);
1573 	} else
1574 		offset = (unsigned int)offsetof(struct host_sp_communication,
1575 						host2sp_cont_target_num_raw_frames)
1576 			 / sizeof(int);
1577 
1578 	store_sp_array_uint(host_sp_com, offset, num_frames);
1579 }
1580 
1581 void
1582 sh_css_event_init_irq_mask(void)
1583 {
1584 	int i;
1585 	unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1586 	unsigned int offset;
1587 	struct sh_css_event_irq_mask event_irq_mask_init;
1588 
1589 	event_irq_mask_init.or_mask  = IA_CSS_EVENT_TYPE_ALL;
1590 	event_irq_mask_init.and_mask = IA_CSS_EVENT_TYPE_NONE;
1591 	(void)HIVE_ADDR_host_sp_com; /* Suppress warnings in CRUN */
1592 
1593 	assert(sizeof(event_irq_mask_init) % HRT_BUS_BYTES == 0);
1594 	for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
1595 		offset = (unsigned int)offsetof(struct host_sp_communication,
1596 						host2sp_event_irq_mask[i]);
1597 		assert(offset % HRT_BUS_BYTES == 0);
1598 		sp_dmem_store(SP0_ID,
1599 			      (unsigned int)sp_address_of(host_sp_com) + offset,
1600 			      &event_irq_mask_init, sizeof(event_irq_mask_init));
1601 	}
1602 }
1603 
1604 int
1605 ia_css_pipe_set_irq_mask(struct ia_css_pipe *pipe,
1606 			 unsigned int or_mask,
1607 			 unsigned int and_mask) {
1608 	unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1609 	unsigned int offset;
1610 	struct sh_css_event_irq_mask event_irq_mask;
1611 	unsigned int pipe_num;
1612 
1613 	assert(pipe);
1614 
1615 	assert(IA_CSS_PIPE_ID_NUM == NR_OF_PIPELINES);
1616 	/* Linux kernel does not have UINT16_MAX
1617 	 * Therefore decided to comment out these 2 asserts for Linux
1618 	 * Alternatives that were not chosen:
1619 	 * - add a conditional #define for UINT16_MAX
1620 	 * - compare with (uint16_t)~0 or 0xffff
1621 	 * - different assert for Linux and Windows
1622 	 */
1623 
1624 	(void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
1625 
1626 	IA_CSS_LOG("or_mask=%x, and_mask=%x", or_mask, and_mask);
1627 	event_irq_mask.or_mask  = (uint16_t)or_mask;
1628 	event_irq_mask.and_mask = (uint16_t)and_mask;
1629 
1630 	pipe_num = ia_css_pipe_get_pipe_num(pipe);
1631 	if (pipe_num >= IA_CSS_PIPE_ID_NUM)
1632 		return -EINVAL;
1633 	offset = (unsigned int)offsetof(struct host_sp_communication,
1634 					host2sp_event_irq_mask[pipe_num]);
1635 	assert(offset % HRT_BUS_BYTES == 0);
1636 	sp_dmem_store(SP0_ID,
1637 		      (unsigned int)sp_address_of(host_sp_com) + offset,
1638 		      &event_irq_mask, sizeof(event_irq_mask));
1639 
1640 	return 0;
1641 }
1642 
1643 int
1644 ia_css_event_get_irq_mask(const struct ia_css_pipe *pipe,
1645 			  unsigned int *or_mask,
1646 			  unsigned int *and_mask) {
1647 	unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1648 	unsigned int offset;
1649 	struct sh_css_event_irq_mask event_irq_mask;
1650 	unsigned int pipe_num;
1651 
1652 	(void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
1653 
1654 	IA_CSS_ENTER_LEAVE("");
1655 
1656 	assert(pipe);
1657 	assert(IA_CSS_PIPE_ID_NUM == NR_OF_PIPELINES);
1658 
1659 	pipe_num = ia_css_pipe_get_pipe_num(pipe);
1660 	if (pipe_num >= IA_CSS_PIPE_ID_NUM)
1661 		return -EINVAL;
1662 	offset = (unsigned int)offsetof(struct host_sp_communication,
1663 					host2sp_event_irq_mask[pipe_num]);
1664 	assert(offset % HRT_BUS_BYTES == 0);
1665 	sp_dmem_load(SP0_ID,
1666 		     (unsigned int)sp_address_of(host_sp_com) + offset,
1667 		     &event_irq_mask, sizeof(event_irq_mask));
1668 
1669 	if (or_mask)
1670 		*or_mask = event_irq_mask.or_mask;
1671 
1672 	if (and_mask)
1673 		*and_mask = event_irq_mask.and_mask;
1674 
1675 	return 0;
1676 }
1677 
1678 void
1679 sh_css_sp_set_sp_running(bool flag)
1680 {
1681 	sp_running = flag;
1682 }
1683 
1684 bool
1685 sh_css_sp_is_running(void)
1686 {
1687 	return sp_running;
1688 }
1689 
1690 void
1691 sh_css_sp_start_isp(void)
1692 {
1693 	const struct ia_css_fw_info *fw;
1694 	unsigned int HIVE_ADDR_sp_sw_state;
1695 
1696 	fw = &sh_css_sp_fw;
1697 	HIVE_ADDR_sp_sw_state = fw->info.sp.sw_state;
1698 
1699 	if (sp_running)
1700 		return;
1701 
1702 	(void)HIVE_ADDR_sp_sw_state; /* Suppres warnings in CRUN */
1703 
1704 	/* no longer here, sp started immediately */
1705 	/*ia_css_debug_pipe_graph_dump_epilogue();*/
1706 
1707 	store_sp_group_data();
1708 	store_sp_per_frame_data(fw);
1709 
1710 	sp_dmem_store_uint32(SP0_ID,
1711 			     (unsigned int)sp_address_of(sp_sw_state),
1712 			     (uint32_t)(IA_CSS_SP_SW_TERMINATED));
1713 
1714 	/* Note 1: The sp_start_isp function contains a wait till
1715 	 * the input network is configured by the SP.
1716 	 * Note 2: Not all SP binaries supports host2sp_commands.
1717 	 * In case a binary does support it, the host2sp_command
1718 	 * will have status cmd_ready after return of the function
1719 	 * sh_css_hrt_sp_start_isp. There is no race-condition here
1720 	 * because only after the process_frame command has been
1721 	 * received, the SP starts configuring the input network.
1722 	 */
1723 
1724 	/* we need to set sp_running before we call ia_css_mmu_invalidate_cache
1725 	 * as ia_css_mmu_invalidate_cache checks on sp_running to
1726 	 * avoid that it accesses dmem while the SP is not powered
1727 	 */
1728 	sp_running = true;
1729 	ia_css_mmu_invalidate_cache();
1730 	/* Invalidate all MMU caches */
1731 	mmu_invalidate_cache_all();
1732 
1733 	ia_css_spctrl_start(SP0_ID);
1734 }
1735 
1736 bool
1737 ia_css_isp_has_started(void)
1738 {
1739 	const struct ia_css_fw_info *fw = &sh_css_sp_fw;
1740 	unsigned int HIVE_ADDR_ia_css_ispctrl_sp_isp_started = fw->info.sp.isp_started;
1741 	(void)HIVE_ADDR_ia_css_ispctrl_sp_isp_started; /* Suppres warnings in CRUN */
1742 
1743 	return (bool)load_sp_uint(ia_css_ispctrl_sp_isp_started);
1744 }
1745 
1746 /*
1747  * @brief Initialize the DMA software-mask in the debug mode.
1748  * Refer to "sh_css_sp.h" for more details.
1749  */
1750 bool
1751 sh_css_sp_init_dma_sw_reg(int dma_id)
1752 {
1753 	int i;
1754 
1755 	/* enable all the DMA channels */
1756 	for (i = 0; i < N_DMA_CHANNEL_ID; i++) {
1757 		/* enable the writing request */
1758 		sh_css_sp_set_dma_sw_reg(dma_id,
1759 					 i,
1760 					 0,
1761 					 true);
1762 		/* enable the reading request */
1763 		sh_css_sp_set_dma_sw_reg(dma_id,
1764 					 i,
1765 					 1,
1766 					 true);
1767 	}
1768 
1769 	return true;
1770 }
1771 
1772 /*
1773  * @brief Set the DMA software-mask in the debug mode.
1774  * Refer to "sh_css_sp.h" for more details.
1775  */
1776 bool
1777 sh_css_sp_set_dma_sw_reg(int dma_id,
1778 			 int channel_id,
1779 			 int request_type,
1780 			 bool enable)
1781 {
1782 	u32 sw_reg;
1783 	u32 bit_val;
1784 	u32 bit_offset;
1785 	u32 bit_mask;
1786 
1787 	(void)dma_id;
1788 
1789 	assert(channel_id >= 0 && channel_id < N_DMA_CHANNEL_ID);
1790 	assert(request_type >= 0);
1791 
1792 	/* get the software-mask */
1793 	sw_reg =
1794 	    sh_css_sp_group.debug.dma_sw_reg;
1795 
1796 	/* get the offest of the target bit */
1797 	bit_offset = (8 * request_type) + channel_id;
1798 
1799 	/* clear the value of the target bit */
1800 	bit_mask = ~(1 << bit_offset);
1801 	sw_reg &= bit_mask;
1802 
1803 	/* set the value of the bit for the DMA channel */
1804 	bit_val = enable ? 1 : 0;
1805 	bit_val <<= bit_offset;
1806 	sw_reg |= bit_val;
1807 
1808 	/* update the software status of DMA channels */
1809 	sh_css_sp_group.debug.dma_sw_reg = sw_reg;
1810 
1811 	return true;
1812 }
1813 
1814 void
1815 sh_css_sp_reset_global_vars(void)
1816 {
1817 	memset(&sh_css_sp_group, 0, sizeof(struct sh_css_sp_group));
1818 	memset(&sh_css_sp_stage, 0, sizeof(struct sh_css_sp_stage));
1819 	memset(&sh_css_isp_stage, 0, sizeof(struct sh_css_isp_stage));
1820 	memset(&sh_css_sp_output, 0, sizeof(struct sh_css_sp_output));
1821 	memset(&per_frame_data, 0, sizeof(struct sh_css_sp_per_frame_data));
1822 }
1823