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