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