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