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