xref: /openbmc/linux/sound/soc/sof/ipc.c (revision 015044e9)
1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2 //
3 // This file is provided under a dual BSD/GPLv2 license.  When using or
4 // redistributing this file, you may do so under either license.
5 //
6 // Copyright(c) 2018 Intel Corporation. All rights reserved.
7 //
8 // Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
9 //
10 // Generic IPC layer that can work over MMIO and SPI/I2C. PHY layer provided
11 // by platform driver code.
12 //
13 
14 #include <linux/mutex.h>
15 #include <linux/types.h>
16 
17 #include "sof-priv.h"
18 #include "sof-audio.h"
19 #include "ops.h"
20 
21 typedef void (*ipc_rx_callback)(struct snd_sof_dev *sdev, void *msg_buf);
22 
23 static void ipc_trace_message(struct snd_sof_dev *sdev, void *msg_buf);
24 static void ipc_stream_message(struct snd_sof_dev *sdev, void *msg_buf);
25 
26 /*
27  * IPC message Tx/Rx message handling.
28  */
29 
30 /* SOF generic IPC data */
31 struct snd_sof_ipc {
32 	struct snd_sof_dev *sdev;
33 
34 	/* protects messages and the disable flag */
35 	struct mutex tx_mutex;
36 	/* disables further sending of ipc's */
37 	bool disable_ipc_tx;
38 
39 	struct snd_sof_ipc_msg msg;
40 };
41 
42 struct sof_ipc_ctrl_data_params {
43 	size_t msg_bytes;
44 	size_t hdr_bytes;
45 	size_t pl_size;
46 	size_t elems;
47 	u32 num_msg;
48 	u8 *src;
49 	u8 *dst;
50 };
51 
52 #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_VERBOSE_IPC)
53 static void ipc_log_header(struct device *dev, u8 *text, u32 cmd)
54 {
55 	u8 *str;
56 	u8 *str2 = NULL;
57 	u32 glb;
58 	u32 type;
59 	bool vdbg = false;
60 
61 	glb = cmd & SOF_GLB_TYPE_MASK;
62 	type = cmd & SOF_CMD_TYPE_MASK;
63 
64 	switch (glb) {
65 	case SOF_IPC_GLB_REPLY:
66 		str = "GLB_REPLY"; break;
67 	case SOF_IPC_GLB_COMPOUND:
68 		str = "GLB_COMPOUND"; break;
69 	case SOF_IPC_GLB_TPLG_MSG:
70 		str = "GLB_TPLG_MSG";
71 		switch (type) {
72 		case SOF_IPC_TPLG_COMP_NEW:
73 			str2 = "COMP_NEW"; break;
74 		case SOF_IPC_TPLG_COMP_FREE:
75 			str2 = "COMP_FREE"; break;
76 		case SOF_IPC_TPLG_COMP_CONNECT:
77 			str2 = "COMP_CONNECT"; break;
78 		case SOF_IPC_TPLG_PIPE_NEW:
79 			str2 = "PIPE_NEW"; break;
80 		case SOF_IPC_TPLG_PIPE_FREE:
81 			str2 = "PIPE_FREE"; break;
82 		case SOF_IPC_TPLG_PIPE_CONNECT:
83 			str2 = "PIPE_CONNECT"; break;
84 		case SOF_IPC_TPLG_PIPE_COMPLETE:
85 			str2 = "PIPE_COMPLETE"; break;
86 		case SOF_IPC_TPLG_BUFFER_NEW:
87 			str2 = "BUFFER_NEW"; break;
88 		case SOF_IPC_TPLG_BUFFER_FREE:
89 			str2 = "BUFFER_FREE"; break;
90 		default:
91 			str2 = "unknown type"; break;
92 		}
93 		break;
94 	case SOF_IPC_GLB_PM_MSG:
95 		str = "GLB_PM_MSG";
96 		switch (type) {
97 		case SOF_IPC_PM_CTX_SAVE:
98 			str2 = "CTX_SAVE"; break;
99 		case SOF_IPC_PM_CTX_RESTORE:
100 			str2 = "CTX_RESTORE"; break;
101 		case SOF_IPC_PM_CTX_SIZE:
102 			str2 = "CTX_SIZE"; break;
103 		case SOF_IPC_PM_CLK_SET:
104 			str2 = "CLK_SET"; break;
105 		case SOF_IPC_PM_CLK_GET:
106 			str2 = "CLK_GET"; break;
107 		case SOF_IPC_PM_CLK_REQ:
108 			str2 = "CLK_REQ"; break;
109 		case SOF_IPC_PM_CORE_ENABLE:
110 			str2 = "CORE_ENABLE"; break;
111 		case SOF_IPC_PM_GATE:
112 			str2 = "GATE"; break;
113 		default:
114 			str2 = "unknown type"; break;
115 		}
116 		break;
117 	case SOF_IPC_GLB_COMP_MSG:
118 		str = "GLB_COMP_MSG";
119 		switch (type) {
120 		case SOF_IPC_COMP_SET_VALUE:
121 			str2 = "SET_VALUE"; break;
122 		case SOF_IPC_COMP_GET_VALUE:
123 			str2 = "GET_VALUE"; break;
124 		case SOF_IPC_COMP_SET_DATA:
125 			str2 = "SET_DATA"; break;
126 		case SOF_IPC_COMP_GET_DATA:
127 			str2 = "GET_DATA"; break;
128 		default:
129 			str2 = "unknown type"; break;
130 		}
131 		break;
132 	case SOF_IPC_GLB_STREAM_MSG:
133 		str = "GLB_STREAM_MSG";
134 		switch (type) {
135 		case SOF_IPC_STREAM_PCM_PARAMS:
136 			str2 = "PCM_PARAMS"; break;
137 		case SOF_IPC_STREAM_PCM_PARAMS_REPLY:
138 			str2 = "PCM_REPLY"; break;
139 		case SOF_IPC_STREAM_PCM_FREE:
140 			str2 = "PCM_FREE"; break;
141 		case SOF_IPC_STREAM_TRIG_START:
142 			str2 = "TRIG_START"; break;
143 		case SOF_IPC_STREAM_TRIG_STOP:
144 			str2 = "TRIG_STOP"; break;
145 		case SOF_IPC_STREAM_TRIG_PAUSE:
146 			str2 = "TRIG_PAUSE"; break;
147 		case SOF_IPC_STREAM_TRIG_RELEASE:
148 			str2 = "TRIG_RELEASE"; break;
149 		case SOF_IPC_STREAM_TRIG_DRAIN:
150 			str2 = "TRIG_DRAIN"; break;
151 		case SOF_IPC_STREAM_TRIG_XRUN:
152 			str2 = "TRIG_XRUN"; break;
153 		case SOF_IPC_STREAM_POSITION:
154 			vdbg = true;
155 			str2 = "POSITION"; break;
156 		case SOF_IPC_STREAM_VORBIS_PARAMS:
157 			str2 = "VORBIS_PARAMS"; break;
158 		case SOF_IPC_STREAM_VORBIS_FREE:
159 			str2 = "VORBIS_FREE"; break;
160 		default:
161 			str2 = "unknown type"; break;
162 		}
163 		break;
164 	case SOF_IPC_FW_READY:
165 		str = "FW_READY"; break;
166 	case SOF_IPC_GLB_DAI_MSG:
167 		str = "GLB_DAI_MSG";
168 		switch (type) {
169 		case SOF_IPC_DAI_CONFIG:
170 			str2 = "CONFIG"; break;
171 		case SOF_IPC_DAI_LOOPBACK:
172 			str2 = "LOOPBACK"; break;
173 		default:
174 			str2 = "unknown type"; break;
175 		}
176 		break;
177 	case SOF_IPC_GLB_TRACE_MSG:
178 		str = "GLB_TRACE_MSG";
179 		switch (type) {
180 		case SOF_IPC_TRACE_DMA_PARAMS:
181 			str2 = "DMA_PARAMS"; break;
182 		case SOF_IPC_TRACE_DMA_POSITION:
183 			str2 = "DMA_POSITION"; break;
184 		case SOF_IPC_TRACE_DMA_PARAMS_EXT:
185 			str2 = "DMA_PARAMS_EXT"; break;
186 		case SOF_IPC_TRACE_FILTER_UPDATE:
187 			str2 = "FILTER_UPDATE"; break;
188 		case SOF_IPC_TRACE_DMA_FREE:
189 			str2 = "DMA_FREE"; break;
190 		default:
191 			str2 = "unknown type"; break;
192 		}
193 		break;
194 	case SOF_IPC_GLB_TEST_MSG:
195 		str = "GLB_TEST_MSG";
196 		switch (type) {
197 		case SOF_IPC_TEST_IPC_FLOOD:
198 			str2 = "IPC_FLOOD"; break;
199 		default:
200 			str2 = "unknown type"; break;
201 		}
202 		break;
203 	case SOF_IPC_GLB_DEBUG:
204 		str = "GLB_DEBUG";
205 		switch (type) {
206 		case SOF_IPC_DEBUG_MEM_USAGE:
207 			str2 = "MEM_USAGE"; break;
208 		default:
209 			str2 = "unknown type"; break;
210 		}
211 		break;
212 	case SOF_IPC_GLB_PROBE:
213 		str = "GLB_PROBE";
214 		switch (type) {
215 		case SOF_IPC_PROBE_INIT:
216 			str2 = "INIT"; break;
217 		case SOF_IPC_PROBE_DEINIT:
218 			str2 = "DEINIT"; break;
219 		case SOF_IPC_PROBE_DMA_ADD:
220 			str2 = "DMA_ADD"; break;
221 		case SOF_IPC_PROBE_DMA_INFO:
222 			str2 = "DMA_INFO"; break;
223 		case SOF_IPC_PROBE_DMA_REMOVE:
224 			str2 = "DMA_REMOVE"; break;
225 		case SOF_IPC_PROBE_POINT_ADD:
226 			str2 = "POINT_ADD"; break;
227 		case SOF_IPC_PROBE_POINT_INFO:
228 			str2 = "POINT_INFO"; break;
229 		case SOF_IPC_PROBE_POINT_REMOVE:
230 			str2 = "POINT_REMOVE"; break;
231 		default:
232 			str2 = "unknown type"; break;
233 		}
234 		break;
235 	default:
236 		str = "unknown GLB command"; break;
237 	}
238 
239 	if (str2) {
240 		if (vdbg)
241 			dev_vdbg(dev, "%s: 0x%x: %s: %s\n", text, cmd, str, str2);
242 		else
243 			dev_dbg(dev, "%s: 0x%x: %s: %s\n", text, cmd, str, str2);
244 	} else {
245 		dev_dbg(dev, "%s: 0x%x: %s\n", text, cmd, str);
246 	}
247 }
248 #else
249 static inline void ipc_log_header(struct device *dev, u8 *text, u32 cmd)
250 {
251 	if ((cmd & SOF_GLB_TYPE_MASK) != SOF_IPC_GLB_TRACE_MSG)
252 		dev_dbg(dev, "%s: 0x%x\n", text, cmd);
253 }
254 #endif
255 
256 /* wait for IPC message reply */
257 static int tx_wait_done(struct snd_sof_ipc *ipc, struct snd_sof_ipc_msg *msg,
258 			void *reply_data)
259 {
260 	struct snd_sof_dev *sdev = ipc->sdev;
261 	struct sof_ipc_cmd_hdr *hdr = msg->msg_data;
262 	int ret;
263 
264 	/* wait for DSP IPC completion */
265 	ret = wait_event_timeout(msg->waitq, msg->ipc_complete,
266 				 msecs_to_jiffies(sdev->ipc_timeout));
267 
268 	if (ret == 0) {
269 		dev_err(sdev->dev,
270 			"ipc tx timed out for %#x (msg/reply size: %d/%zu)\n",
271 			hdr->cmd, hdr->size, msg->reply_size);
272 		snd_sof_handle_fw_exception(ipc->sdev);
273 		ret = -ETIMEDOUT;
274 	} else {
275 		ret = msg->reply_error;
276 		if (ret < 0) {
277 			dev_err(sdev->dev,
278 				"ipc tx error for %#x (msg/reply size: %d/%zu): %d\n",
279 				hdr->cmd, hdr->size, msg->reply_size, ret);
280 		} else {
281 			ipc_log_header(sdev->dev, "ipc tx succeeded", hdr->cmd);
282 			if (msg->reply_size)
283 				/* copy the data returned from DSP */
284 				memcpy(reply_data, msg->reply_data,
285 				       msg->reply_size);
286 		}
287 
288 		/* re-enable dumps after successful IPC tx */
289 		if (sdev->ipc_dump_printed) {
290 			sdev->dbg_dump_printed = false;
291 			sdev->ipc_dump_printed = false;
292 		}
293 	}
294 
295 	return ret;
296 }
297 
298 /* send IPC message from host to DSP */
299 static int sof_ipc_tx_message_unlocked(struct snd_sof_ipc *ipc,
300 				       void *msg_data, size_t msg_bytes,
301 				       void *reply_data, size_t reply_bytes)
302 {
303 	struct sof_ipc_cmd_hdr *hdr = msg_data;
304 	struct snd_sof_dev *sdev = ipc->sdev;
305 	struct snd_sof_ipc_msg *msg;
306 	int ret;
307 
308 	if (!msg_data || msg_bytes < sizeof(*hdr)) {
309 		dev_err_ratelimited(sdev->dev, "No IPC message to send\n");
310 		return -EINVAL;
311 	}
312 
313 	if (ipc->disable_ipc_tx || sdev->fw_state != SOF_FW_BOOT_COMPLETE)
314 		return -ENODEV;
315 
316 	/*
317 	 * The spin-lock is also still needed to protect message objects against
318 	 * other atomic contexts.
319 	 */
320 	spin_lock_irq(&sdev->ipc_lock);
321 
322 	/* initialise the message */
323 	msg = &ipc->msg;
324 
325 	/* attach message data */
326 	msg->msg_data = msg_data;
327 	msg->msg_size = msg_bytes;
328 
329 	msg->reply_size = reply_bytes;
330 	msg->reply_error = 0;
331 
332 	sdev->msg = msg;
333 
334 	ret = snd_sof_dsp_send_msg(sdev, msg);
335 	/* Next reply that we receive will be related to this message */
336 	if (!ret)
337 		msg->ipc_complete = false;
338 
339 	spin_unlock_irq(&sdev->ipc_lock);
340 
341 	if (ret) {
342 		dev_err_ratelimited(sdev->dev,
343 				    "error: ipc tx failed with error %d\n",
344 				    ret);
345 		return ret;
346 	}
347 
348 	ipc_log_header(sdev->dev, "ipc tx", hdr->cmd);
349 
350 	/* now wait for completion */
351 	return tx_wait_done(ipc, msg, reply_data);
352 }
353 
354 /* send IPC message from host to DSP */
355 int sof_ipc_tx_message(struct snd_sof_ipc *ipc, u32 header,
356 		       void *msg_data, size_t msg_bytes, void *reply_data,
357 		       size_t reply_bytes)
358 {
359 	const struct sof_dsp_power_state target_state = {
360 		.state = SOF_DSP_PM_D0,
361 	};
362 	int ret;
363 
364 	/* ensure the DSP is in D0 before sending a new IPC */
365 	ret = snd_sof_dsp_set_power_state(ipc->sdev, &target_state);
366 	if (ret < 0) {
367 		dev_err(ipc->sdev->dev, "error: resuming DSP %d\n", ret);
368 		return ret;
369 	}
370 
371 	return sof_ipc_tx_message_no_pm(ipc, header, msg_data, msg_bytes,
372 					reply_data, reply_bytes);
373 }
374 EXPORT_SYMBOL(sof_ipc_tx_message);
375 
376 /*
377  * send IPC message from host to DSP without modifying the DSP state.
378  * This will be used for IPC's that can be handled by the DSP
379  * even in a low-power D0 substate.
380  */
381 int sof_ipc_tx_message_no_pm(struct snd_sof_ipc *ipc, u32 header,
382 			     void *msg_data, size_t msg_bytes,
383 			     void *reply_data, size_t reply_bytes)
384 {
385 	int ret;
386 
387 	if (msg_bytes > SOF_IPC_MSG_MAX_SIZE ||
388 	    reply_bytes > SOF_IPC_MSG_MAX_SIZE)
389 		return -ENOBUFS;
390 
391 	/* Serialise IPC TX */
392 	mutex_lock(&ipc->tx_mutex);
393 
394 	ret = sof_ipc_tx_message_unlocked(ipc, msg_data, msg_bytes,
395 					  reply_data, reply_bytes);
396 
397 	mutex_unlock(&ipc->tx_mutex);
398 
399 	return ret;
400 }
401 EXPORT_SYMBOL(sof_ipc_tx_message_no_pm);
402 
403 /* Generic helper function to retrieve the reply */
404 void snd_sof_ipc_get_reply(struct snd_sof_dev *sdev)
405 {
406 	struct snd_sof_ipc_msg *msg = sdev->msg;
407 	struct sof_ipc_reply reply;
408 	int ret = 0;
409 
410 	/*
411 	 * Sometimes, there is unexpected reply ipc arriving. The reply
412 	 * ipc belongs to none of the ipcs sent from driver.
413 	 * In this case, the driver must ignore the ipc.
414 	 */
415 	if (!msg) {
416 		dev_warn(sdev->dev, "unexpected ipc interrupt raised!\n");
417 		return;
418 	}
419 
420 	/* get the generic reply */
421 	snd_sof_dsp_mailbox_read(sdev, sdev->host_box.offset, &reply,
422 				 sizeof(reply));
423 
424 	if (reply.error < 0) {
425 		memcpy(msg->reply_data, &reply, sizeof(reply));
426 		ret = reply.error;
427 	} else if (!reply.hdr.size) {
428 		/* Reply should always be >= sizeof(struct sof_ipc_reply) */
429 		if (msg->reply_size)
430 			dev_err(sdev->dev,
431 				"empty reply received, expected %zu bytes\n",
432 				msg->reply_size);
433 		else
434 			dev_err(sdev->dev, "empty reply received\n");
435 
436 		ret = -EINVAL;
437 	} else if (msg->reply_size > 0) {
438 		if (reply.hdr.size == msg->reply_size) {
439 			ret = 0;
440 		} else if (reply.hdr.size < msg->reply_size) {
441 			dev_dbg(sdev->dev,
442 				"reply size (%u) is less than expected (%zu)\n",
443 				reply.hdr.size, msg->reply_size);
444 
445 			msg->reply_size = reply.hdr.size;
446 			ret = 0;
447 		} else {
448 			dev_err(sdev->dev,
449 				"reply size (%u) exceeds the buffer size (%zu)\n",
450 				reply.hdr.size, msg->reply_size);
451 			ret = -EINVAL;
452 		}
453 
454 		/* get the full message if reply.hdr.size <= msg->reply_size */
455 		if (!ret)
456 			snd_sof_dsp_mailbox_read(sdev, sdev->host_box.offset,
457 						 msg->reply_data, msg->reply_size);
458 	}
459 
460 	msg->reply_error = ret;
461 }
462 EXPORT_SYMBOL(snd_sof_ipc_get_reply);
463 
464 /* handle reply message from DSP */
465 void snd_sof_ipc_reply(struct snd_sof_dev *sdev, u32 msg_id)
466 {
467 	struct snd_sof_ipc_msg *msg = &sdev->ipc->msg;
468 
469 	if (msg->ipc_complete) {
470 		dev_dbg(sdev->dev,
471 			"no reply expected, received 0x%x, will be ignored",
472 			msg_id);
473 		return;
474 	}
475 
476 	/* wake up and return the error if we have waiters on this message ? */
477 	msg->ipc_complete = true;
478 	wake_up(&msg->waitq);
479 }
480 EXPORT_SYMBOL(snd_sof_ipc_reply);
481 
482 static void ipc_comp_notification(struct snd_sof_dev *sdev, void *msg_buf)
483 {
484 	struct sof_ipc_cmd_hdr *hdr = msg_buf;
485 	u32 msg_type = hdr->cmd & SOF_CMD_TYPE_MASK;
486 
487 	switch (msg_type) {
488 	case SOF_IPC_COMP_GET_VALUE:
489 	case SOF_IPC_COMP_GET_DATA:
490 		break;
491 	default:
492 		dev_err(sdev->dev, "error: unhandled component message %#x\n", msg_type);
493 		return;
494 	}
495 
496 	snd_sof_control_notify(sdev, msg_buf);
497 }
498 
499 /* DSP firmware has sent host a message  */
500 void snd_sof_ipc_msgs_rx(struct snd_sof_dev *sdev)
501 {
502 	ipc_rx_callback rx_callback = NULL;
503 	struct sof_ipc_cmd_hdr hdr;
504 	void *msg_buf;
505 	u32 cmd;
506 	int err;
507 
508 	/* read back header */
509 	err = snd_sof_ipc_msg_data(sdev, NULL, &hdr, sizeof(hdr));
510 	if (err < 0) {
511 		dev_warn(sdev->dev, "failed to read IPC header: %d\n", err);
512 		return;
513 	}
514 
515 	if (hdr.size < sizeof(hdr)) {
516 		dev_err(sdev->dev, "The received message size is invalid\n");
517 		return;
518 	}
519 
520 	ipc_log_header(sdev->dev, "ipc rx", hdr.cmd);
521 
522 	cmd = hdr.cmd & SOF_GLB_TYPE_MASK;
523 
524 	/* check message type */
525 	switch (cmd) {
526 	case SOF_IPC_GLB_REPLY:
527 		dev_err(sdev->dev, "error: ipc reply unknown\n");
528 		break;
529 	case SOF_IPC_FW_READY:
530 		/* check for FW boot completion */
531 		if (sdev->fw_state == SOF_FW_BOOT_IN_PROGRESS) {
532 			err = sof_ops(sdev)->fw_ready(sdev, cmd);
533 			if (err < 0)
534 				sof_set_fw_state(sdev, SOF_FW_BOOT_READY_FAILED);
535 			else
536 				sof_set_fw_state(sdev, SOF_FW_BOOT_READY_OK);
537 
538 			/* wake up firmware loader */
539 			wake_up(&sdev->boot_wait);
540 		}
541 		break;
542 	case SOF_IPC_GLB_COMPOUND:
543 	case SOF_IPC_GLB_TPLG_MSG:
544 	case SOF_IPC_GLB_PM_MSG:
545 		break;
546 	case SOF_IPC_GLB_COMP_MSG:
547 		rx_callback = ipc_comp_notification;
548 		break;
549 	case SOF_IPC_GLB_STREAM_MSG:
550 		rx_callback = ipc_stream_message;
551 		break;
552 	case SOF_IPC_GLB_TRACE_MSG:
553 		rx_callback = ipc_trace_message;
554 		break;
555 	default:
556 		dev_err(sdev->dev, "%s: Unknown DSP message: 0x%x\n", __func__, cmd);
557 		break;
558 	}
559 
560 	/* read the full message */
561 	msg_buf = kmalloc(hdr.size, GFP_KERNEL);
562 	if (!msg_buf)
563 		return;
564 
565 	err = snd_sof_ipc_msg_data(sdev, NULL, msg_buf, hdr.size);
566 	if (err < 0) {
567 		dev_err(sdev->dev, "%s: Failed to read message: %d\n", __func__, err);
568 	} else {
569 		/* Call local handler for the message */
570 		if (rx_callback)
571 			rx_callback(sdev, msg_buf);
572 
573 		/* Notify registered clients */
574 		sof_client_ipc_rx_dispatcher(sdev, msg_buf);
575 	}
576 
577 	kfree(msg_buf);
578 
579 	ipc_log_header(sdev->dev, "ipc rx done", hdr.cmd);
580 }
581 EXPORT_SYMBOL(snd_sof_ipc_msgs_rx);
582 
583 /*
584  * IPC trace mechanism.
585  */
586 
587 static void ipc_trace_message(struct snd_sof_dev *sdev, void *msg_buf)
588 {
589 	struct sof_ipc_cmd_hdr *hdr = msg_buf;
590 	u32 msg_type = hdr->cmd & SOF_CMD_TYPE_MASK;
591 
592 	switch (msg_type) {
593 	case SOF_IPC_TRACE_DMA_POSITION:
594 		snd_sof_trace_update_pos(sdev, msg_buf);
595 		break;
596 	default:
597 		dev_err(sdev->dev, "error: unhandled trace message %#x\n", msg_type);
598 		break;
599 	}
600 }
601 
602 /*
603  * IPC stream position.
604  */
605 
606 static void ipc_period_elapsed(struct snd_sof_dev *sdev, u32 msg_id)
607 {
608 	struct snd_soc_component *scomp = sdev->component;
609 	struct snd_sof_pcm_stream *stream;
610 	struct sof_ipc_stream_posn posn;
611 	struct snd_sof_pcm *spcm;
612 	int direction, ret;
613 
614 	spcm = snd_sof_find_spcm_comp(scomp, msg_id, &direction);
615 	if (!spcm) {
616 		dev_err(sdev->dev,
617 			"error: period elapsed for unknown stream, msg_id %d\n",
618 			msg_id);
619 		return;
620 	}
621 
622 	stream = &spcm->stream[direction];
623 	ret = snd_sof_ipc_msg_data(sdev, stream->substream, &posn, sizeof(posn));
624 	if (ret < 0) {
625 		dev_warn(sdev->dev, "failed to read stream position: %d\n", ret);
626 		return;
627 	}
628 
629 	dev_vdbg(sdev->dev, "posn : host 0x%llx dai 0x%llx wall 0x%llx\n",
630 		 posn.host_posn, posn.dai_posn, posn.wallclock);
631 
632 	memcpy(&stream->posn, &posn, sizeof(posn));
633 
634 	if (spcm->pcm.compress)
635 		snd_sof_compr_fragment_elapsed(stream->cstream);
636 	else if (stream->substream->runtime &&
637 		 !stream->substream->runtime->no_period_wakeup)
638 		/* only inform ALSA for period_wakeup mode */
639 		snd_sof_pcm_period_elapsed(stream->substream);
640 }
641 
642 /* DSP notifies host of an XRUN within FW */
643 static void ipc_xrun(struct snd_sof_dev *sdev, u32 msg_id)
644 {
645 	struct snd_soc_component *scomp = sdev->component;
646 	struct snd_sof_pcm_stream *stream;
647 	struct sof_ipc_stream_posn posn;
648 	struct snd_sof_pcm *spcm;
649 	int direction, ret;
650 
651 	spcm = snd_sof_find_spcm_comp(scomp, msg_id, &direction);
652 	if (!spcm) {
653 		dev_err(sdev->dev, "error: XRUN for unknown stream, msg_id %d\n",
654 			msg_id);
655 		return;
656 	}
657 
658 	stream = &spcm->stream[direction];
659 	ret = snd_sof_ipc_msg_data(sdev, stream->substream, &posn, sizeof(posn));
660 	if (ret < 0) {
661 		dev_warn(sdev->dev, "failed to read overrun position: %d\n", ret);
662 		return;
663 	}
664 
665 	dev_dbg(sdev->dev,  "posn XRUN: host %llx comp %d size %d\n",
666 		posn.host_posn, posn.xrun_comp_id, posn.xrun_size);
667 
668 #if defined(CONFIG_SND_SOC_SOF_DEBUG_XRUN_STOP)
669 	/* stop PCM on XRUN - used for pipeline debug */
670 	memcpy(&stream->posn, &posn, sizeof(posn));
671 	snd_pcm_stop_xrun(stream->substream);
672 #endif
673 }
674 
675 /* stream notifications from DSP FW */
676 static void ipc_stream_message(struct snd_sof_dev *sdev, void *msg_buf)
677 {
678 	struct sof_ipc_cmd_hdr *hdr = msg_buf;
679 	u32 msg_type = hdr->cmd & SOF_CMD_TYPE_MASK;
680 	u32 msg_id = SOF_IPC_MESSAGE_ID(hdr->cmd);
681 
682 	switch (msg_type) {
683 	case SOF_IPC_STREAM_POSITION:
684 		ipc_period_elapsed(sdev, msg_id);
685 		break;
686 	case SOF_IPC_STREAM_TRIG_XRUN:
687 		ipc_xrun(sdev, msg_id);
688 		break;
689 	default:
690 		dev_err(sdev->dev, "error: unhandled stream message %#x\n",
691 			msg_id);
692 		break;
693 	}
694 }
695 
696 /* get stream position IPC - use faster MMIO method if available on platform */
697 int snd_sof_ipc_stream_posn(struct snd_soc_component *scomp,
698 			    struct snd_sof_pcm *spcm, int direction,
699 			    struct sof_ipc_stream_posn *posn)
700 {
701 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
702 	struct sof_ipc_stream stream;
703 	int err;
704 
705 	/* read position via slower IPC */
706 	stream.hdr.size = sizeof(stream);
707 	stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_POSITION;
708 	stream.comp_id = spcm->stream[direction].comp_id;
709 
710 	/* send IPC to the DSP */
711 	err = sof_ipc_tx_message(sdev->ipc,
712 				 stream.hdr.cmd, &stream, sizeof(stream), posn,
713 				 sizeof(*posn));
714 	if (err < 0) {
715 		dev_err(sdev->dev, "error: failed to get stream %d position\n",
716 			stream.comp_id);
717 		return err;
718 	}
719 
720 	return 0;
721 }
722 EXPORT_SYMBOL(snd_sof_ipc_stream_posn);
723 
724 static int sof_get_ctrl_copy_params(enum sof_ipc_ctrl_type ctrl_type,
725 				    struct sof_ipc_ctrl_data *src,
726 				    struct sof_ipc_ctrl_data *dst,
727 				    struct sof_ipc_ctrl_data_params *sparams)
728 {
729 	switch (ctrl_type) {
730 	case SOF_CTRL_TYPE_VALUE_CHAN_GET:
731 	case SOF_CTRL_TYPE_VALUE_CHAN_SET:
732 		sparams->src = (u8 *)src->chanv;
733 		sparams->dst = (u8 *)dst->chanv;
734 		break;
735 	case SOF_CTRL_TYPE_DATA_GET:
736 	case SOF_CTRL_TYPE_DATA_SET:
737 		sparams->src = (u8 *)src->data->data;
738 		sparams->dst = (u8 *)dst->data->data;
739 		break;
740 	default:
741 		return -EINVAL;
742 	}
743 
744 	/* calculate payload size and number of messages */
745 	sparams->pl_size = SOF_IPC_MSG_MAX_SIZE - sparams->hdr_bytes;
746 	sparams->num_msg = DIV_ROUND_UP(sparams->msg_bytes, sparams->pl_size);
747 
748 	return 0;
749 }
750 
751 static int sof_set_get_large_ctrl_data(struct snd_sof_dev *sdev,
752 				       struct sof_ipc_ctrl_data *cdata,
753 				       struct sof_ipc_ctrl_data_params *sparams,
754 				       bool set)
755 {
756 	struct sof_ipc_ctrl_data *partdata;
757 	size_t send_bytes;
758 	size_t offset = 0;
759 	size_t msg_bytes;
760 	size_t pl_size;
761 	int err;
762 	int i;
763 
764 	/* allocate max ipc size because we have at least one */
765 	partdata = kzalloc(SOF_IPC_MSG_MAX_SIZE, GFP_KERNEL);
766 	if (!partdata)
767 		return -ENOMEM;
768 
769 	if (set)
770 		err = sof_get_ctrl_copy_params(cdata->type, cdata, partdata,
771 					       sparams);
772 	else
773 		err = sof_get_ctrl_copy_params(cdata->type, partdata, cdata,
774 					       sparams);
775 	if (err < 0) {
776 		kfree(partdata);
777 		return err;
778 	}
779 
780 	msg_bytes = sparams->msg_bytes;
781 	pl_size = sparams->pl_size;
782 
783 	/* copy the header data */
784 	memcpy(partdata, cdata, sparams->hdr_bytes);
785 
786 	/* Serialise IPC TX */
787 	mutex_lock(&sdev->ipc->tx_mutex);
788 
789 	/* copy the payload data in a loop */
790 	for (i = 0; i < sparams->num_msg; i++) {
791 		send_bytes = min(msg_bytes, pl_size);
792 		partdata->num_elems = send_bytes;
793 		partdata->rhdr.hdr.size = sparams->hdr_bytes + send_bytes;
794 		partdata->msg_index = i;
795 		msg_bytes -= send_bytes;
796 		partdata->elems_remaining = msg_bytes;
797 
798 		if (set)
799 			memcpy(sparams->dst, sparams->src + offset, send_bytes);
800 
801 		err = sof_ipc_tx_message_unlocked(sdev->ipc,
802 						  partdata,
803 						  partdata->rhdr.hdr.size,
804 						  partdata,
805 						  partdata->rhdr.hdr.size);
806 		if (err < 0)
807 			break;
808 
809 		if (!set)
810 			memcpy(sparams->dst + offset, sparams->src, send_bytes);
811 
812 		offset += pl_size;
813 	}
814 
815 	mutex_unlock(&sdev->ipc->tx_mutex);
816 
817 	kfree(partdata);
818 	return err;
819 }
820 
821 /*
822  * IPC get()/set() for kcontrols.
823  */
824 int snd_sof_ipc_set_get_comp_data(struct snd_sof_control *scontrol, bool set)
825 {
826 	struct snd_soc_component *scomp = scontrol->scomp;
827 	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
828 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
829 	struct sof_ipc_fw_ready *ready = &sdev->fw_ready;
830 	struct sof_ipc_fw_version *v = &ready->version;
831 	struct sof_ipc_ctrl_data_params sparams;
832 	enum sof_ipc_ctrl_type ctrl_type;
833 	struct snd_sof_widget *swidget;
834 	bool widget_found = false;
835 	size_t send_bytes;
836 	u32 ipc_cmd;
837 	int err;
838 
839 	list_for_each_entry(swidget, &sdev->widget_list, list) {
840 		if (swidget->comp_id == scontrol->comp_id) {
841 			widget_found = true;
842 			break;
843 		}
844 	}
845 
846 	if (!widget_found) {
847 		dev_err(sdev->dev, "error: can't find widget with id %d\n", scontrol->comp_id);
848 		return -EINVAL;
849 	}
850 
851 	/*
852 	 * Volatile controls should always be part of static pipelines and the widget use_count
853 	 * would always be > 0 in this case. For the others, just return the cached value if the
854 	 * widget is not set up.
855 	 */
856 	if (!swidget->use_count)
857 		return 0;
858 
859 	/* read or write firmware volume */
860 	if (scontrol->readback_offset != 0) {
861 		/* write/read value header via mmaped region */
862 		send_bytes = sizeof(struct sof_ipc_ctrl_value_chan) *
863 		cdata->num_elems;
864 		if (set)
865 			err = snd_sof_dsp_block_write(sdev, SOF_FW_BLK_TYPE_IRAM,
866 						      scontrol->readback_offset,
867 						      cdata->chanv, send_bytes);
868 
869 		else
870 			err = snd_sof_dsp_block_read(sdev, SOF_FW_BLK_TYPE_IRAM,
871 						     scontrol->readback_offset,
872 						     cdata->chanv, send_bytes);
873 
874 		if (err)
875 			dev_err_once(sdev->dev, "error: %s TYPE_IRAM failed\n",
876 				     set ? "write to" :  "read from");
877 		return err;
878 	}
879 
880 	/*
881 	 * Select the IPC cmd and the ctrl_type based on the ctrl_cmd and the
882 	 * direction
883 	 * Note: SOF_CTRL_TYPE_VALUE_COMP_* is not used and supported currently
884 	 *	 for ctrl_type
885 	 */
886 	if (cdata->cmd == SOF_CTRL_CMD_BINARY) {
887 		ipc_cmd = set ? SOF_IPC_COMP_SET_DATA : SOF_IPC_COMP_GET_DATA;
888 		ctrl_type = set ? SOF_CTRL_TYPE_DATA_SET : SOF_CTRL_TYPE_DATA_GET;
889 	} else {
890 		ipc_cmd = set ? SOF_IPC_COMP_SET_VALUE : SOF_IPC_COMP_GET_VALUE;
891 		ctrl_type = set ? SOF_CTRL_TYPE_VALUE_CHAN_SET : SOF_CTRL_TYPE_VALUE_CHAN_GET;
892 	}
893 
894 	cdata->rhdr.hdr.cmd = SOF_IPC_GLB_COMP_MSG | ipc_cmd;
895 	cdata->type = ctrl_type;
896 	cdata->comp_id = scontrol->comp_id;
897 	cdata->msg_index = 0;
898 
899 	/* calculate header and data size */
900 	switch (cdata->type) {
901 	case SOF_CTRL_TYPE_VALUE_CHAN_GET:
902 	case SOF_CTRL_TYPE_VALUE_CHAN_SET:
903 		sparams.msg_bytes = scontrol->num_channels *
904 			sizeof(struct sof_ipc_ctrl_value_chan);
905 		sparams.hdr_bytes = sizeof(struct sof_ipc_ctrl_data);
906 		sparams.elems = scontrol->num_channels;
907 		break;
908 	case SOF_CTRL_TYPE_DATA_GET:
909 	case SOF_CTRL_TYPE_DATA_SET:
910 		sparams.msg_bytes = cdata->data->size;
911 		sparams.hdr_bytes = sizeof(struct sof_ipc_ctrl_data) +
912 			sizeof(struct sof_abi_hdr);
913 		sparams.elems = cdata->data->size;
914 		break;
915 	default:
916 		return -EINVAL;
917 	}
918 
919 	cdata->rhdr.hdr.size = sparams.msg_bytes + sparams.hdr_bytes;
920 	cdata->num_elems = sparams.elems;
921 	cdata->elems_remaining = 0;
922 
923 	/* send normal size ipc in one part */
924 	if (cdata->rhdr.hdr.size <= SOF_IPC_MSG_MAX_SIZE) {
925 		err = sof_ipc_tx_message(sdev->ipc, cdata->rhdr.hdr.cmd, cdata,
926 					 cdata->rhdr.hdr.size, cdata,
927 					 cdata->rhdr.hdr.size);
928 
929 		if (err < 0)
930 			dev_err(sdev->dev, "error: set/get ctrl ipc comp %d\n",
931 				cdata->comp_id);
932 
933 		return err;
934 	}
935 
936 	/* data is bigger than max ipc size, chop into smaller pieces */
937 	dev_dbg(sdev->dev, "large ipc size %u, control size %u\n",
938 		cdata->rhdr.hdr.size, scontrol->size);
939 
940 	/* large messages is only supported from ABI 3.3.0 onwards */
941 	if (v->abi_version < SOF_ABI_VER(3, 3, 0)) {
942 		dev_err(sdev->dev, "error: incompatible FW ABI version\n");
943 		return -EINVAL;
944 	}
945 
946 	err = sof_set_get_large_ctrl_data(sdev, cdata, &sparams, set);
947 
948 	if (err < 0)
949 		dev_err(sdev->dev, "error: set/get large ctrl ipc comp %d\n",
950 			cdata->comp_id);
951 
952 	return err;
953 }
954 EXPORT_SYMBOL(snd_sof_ipc_set_get_comp_data);
955 
956 int snd_sof_ipc_valid(struct snd_sof_dev *sdev)
957 {
958 	struct sof_ipc_fw_ready *ready = &sdev->fw_ready;
959 	struct sof_ipc_fw_version *v = &ready->version;
960 
961 	dev_info(sdev->dev,
962 		 "Firmware info: version %d:%d:%d-%s\n",  v->major, v->minor,
963 		 v->micro, v->tag);
964 	dev_info(sdev->dev,
965 		 "Firmware: ABI %d:%d:%d Kernel ABI %d:%d:%d\n",
966 		 SOF_ABI_VERSION_MAJOR(v->abi_version),
967 		 SOF_ABI_VERSION_MINOR(v->abi_version),
968 		 SOF_ABI_VERSION_PATCH(v->abi_version),
969 		 SOF_ABI_MAJOR, SOF_ABI_MINOR, SOF_ABI_PATCH);
970 
971 	if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, v->abi_version)) {
972 		dev_err(sdev->dev, "error: incompatible FW ABI version\n");
973 		return -EINVAL;
974 	}
975 
976 	if (SOF_ABI_VERSION_MINOR(v->abi_version) > SOF_ABI_MINOR) {
977 		if (!IS_ENABLED(CONFIG_SND_SOC_SOF_STRICT_ABI_CHECKS)) {
978 			dev_warn(sdev->dev, "warn: FW ABI is more recent than kernel\n");
979 		} else {
980 			dev_err(sdev->dev, "error: FW ABI is more recent than kernel\n");
981 			return -EINVAL;
982 		}
983 	}
984 
985 	if (ready->flags & SOF_IPC_INFO_BUILD) {
986 		dev_info(sdev->dev,
987 			 "Firmware debug build %d on %s-%s - options:\n"
988 			 " GDB: %s\n"
989 			 " lock debug: %s\n"
990 			 " lock vdebug: %s\n",
991 			 v->build, v->date, v->time,
992 			 (ready->flags & SOF_IPC_INFO_GDB) ?
993 				"enabled" : "disabled",
994 			 (ready->flags & SOF_IPC_INFO_LOCKS) ?
995 				"enabled" : "disabled",
996 			 (ready->flags & SOF_IPC_INFO_LOCKSV) ?
997 				"enabled" : "disabled");
998 	}
999 
1000 	/* copy the fw_version into debugfs at first boot */
1001 	memcpy(&sdev->fw_version, v, sizeof(*v));
1002 
1003 	return 0;
1004 }
1005 EXPORT_SYMBOL(snd_sof_ipc_valid);
1006 
1007 int sof_ipc_init_msg_memory(struct snd_sof_dev *sdev)
1008 {
1009 	struct snd_sof_ipc_msg *msg;
1010 
1011 	msg = &sdev->ipc->msg;
1012 
1013 	msg->reply_data = devm_kzalloc(sdev->dev, SOF_IPC_MSG_MAX_SIZE, GFP_KERNEL);
1014 	if (!msg->reply_data)
1015 		return -ENOMEM;
1016 
1017 	return 0;
1018 }
1019 
1020 struct snd_sof_ipc *snd_sof_ipc_init(struct snd_sof_dev *sdev)
1021 {
1022 	struct snd_sof_ipc *ipc;
1023 	struct snd_sof_ipc_msg *msg;
1024 
1025 	ipc = devm_kzalloc(sdev->dev, sizeof(*ipc), GFP_KERNEL);
1026 	if (!ipc)
1027 		return NULL;
1028 
1029 	mutex_init(&ipc->tx_mutex);
1030 	ipc->sdev = sdev;
1031 	msg = &ipc->msg;
1032 
1033 	/* indicate that we aren't sending a message ATM */
1034 	msg->ipc_complete = true;
1035 
1036 	init_waitqueue_head(&msg->waitq);
1037 
1038 	return ipc;
1039 }
1040 EXPORT_SYMBOL(snd_sof_ipc_init);
1041 
1042 void snd_sof_ipc_free(struct snd_sof_dev *sdev)
1043 {
1044 	struct snd_sof_ipc *ipc = sdev->ipc;
1045 
1046 	if (!ipc)
1047 		return;
1048 
1049 	/* disable sending of ipc's */
1050 	mutex_lock(&ipc->tx_mutex);
1051 	ipc->disable_ipc_tx = true;
1052 	mutex_unlock(&ipc->tx_mutex);
1053 }
1054 EXPORT_SYMBOL(snd_sof_ipc_free);
1055