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