xref: /openbmc/linux/sound/soc/sof/sof-client-ipc-msg-injector.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1cac0b088SPeter Ujfalusi // SPDX-License-Identifier: GPL-2.0-only
2cac0b088SPeter Ujfalusi //
3cac0b088SPeter Ujfalusi // Copyright(c) 2022 Intel Corporation. All rights reserved.
4cac0b088SPeter Ujfalusi //
5cac0b088SPeter Ujfalusi // Author: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
6cac0b088SPeter Ujfalusi //
7cac0b088SPeter Ujfalusi 
8cac0b088SPeter Ujfalusi #include <linux/auxiliary_bus.h>
9cac0b088SPeter Ujfalusi #include <linux/completion.h>
10cac0b088SPeter Ujfalusi #include <linux/debugfs.h>
11cac0b088SPeter Ujfalusi #include <linux/ktime.h>
12cac0b088SPeter Ujfalusi #include <linux/mod_devicetable.h>
13cac0b088SPeter Ujfalusi #include <linux/module.h>
14cac0b088SPeter Ujfalusi #include <linux/pm_runtime.h>
15cac0b088SPeter Ujfalusi #include <linux/slab.h>
16cac0b088SPeter Ujfalusi #include <linux/uaccess.h>
17cac0b088SPeter Ujfalusi #include <sound/sof/header.h>
18066c6762SPeter Ujfalusi #include <sound/sof/ipc4/header.h>
19cac0b088SPeter Ujfalusi 
20cac0b088SPeter Ujfalusi #include "sof-client.h"
21cac0b088SPeter Ujfalusi 
22cac0b088SPeter Ujfalusi #define SOF_IPC_CLIENT_SUSPEND_DELAY_MS	3000
23cac0b088SPeter Ujfalusi 
24cac0b088SPeter Ujfalusi struct sof_msg_inject_priv {
25cac0b088SPeter Ujfalusi 	struct dentry *dfs_file;
26ef368c33SPeter Ujfalusi 	size_t max_msg_size;
27066c6762SPeter Ujfalusi 	enum sof_ipc_type ipc_type;
28cac0b088SPeter Ujfalusi 
29cac0b088SPeter Ujfalusi 	void *tx_buffer;
30cac0b088SPeter Ujfalusi 	void *rx_buffer;
31cac0b088SPeter Ujfalusi };
32cac0b088SPeter Ujfalusi 
sof_msg_inject_dfs_open(struct inode * inode,struct file * file)33cac0b088SPeter Ujfalusi static int sof_msg_inject_dfs_open(struct inode *inode, struct file *file)
34cac0b088SPeter Ujfalusi {
35cac0b088SPeter Ujfalusi 	struct sof_client_dev *cdev = inode->i_private;
36cac0b088SPeter Ujfalusi 	int ret;
37cac0b088SPeter Ujfalusi 
38cac0b088SPeter Ujfalusi 	if (sof_client_get_fw_state(cdev) == SOF_FW_CRASHED)
39cac0b088SPeter Ujfalusi 		return -ENODEV;
40cac0b088SPeter Ujfalusi 
41cac0b088SPeter Ujfalusi 	ret = debugfs_file_get(file->f_path.dentry);
42cac0b088SPeter Ujfalusi 	if (unlikely(ret))
43cac0b088SPeter Ujfalusi 		return ret;
44cac0b088SPeter Ujfalusi 
45cac0b088SPeter Ujfalusi 	ret = simple_open(inode, file);
46cac0b088SPeter Ujfalusi 	if (ret)
47cac0b088SPeter Ujfalusi 		debugfs_file_put(file->f_path.dentry);
48cac0b088SPeter Ujfalusi 
49cac0b088SPeter Ujfalusi 	return ret;
50cac0b088SPeter Ujfalusi }
51cac0b088SPeter Ujfalusi 
sof_msg_inject_dfs_read(struct file * file,char __user * buffer,size_t count,loff_t * ppos)52cac0b088SPeter Ujfalusi static ssize_t sof_msg_inject_dfs_read(struct file *file, char __user *buffer,
53cac0b088SPeter Ujfalusi 				       size_t count, loff_t *ppos)
54cac0b088SPeter Ujfalusi {
55cac0b088SPeter Ujfalusi 	struct sof_client_dev *cdev = file->private_data;
56cac0b088SPeter Ujfalusi 	struct sof_msg_inject_priv *priv = cdev->data;
57cac0b088SPeter Ujfalusi 	struct sof_ipc_reply *rhdr = priv->rx_buffer;
58cac0b088SPeter Ujfalusi 
59cac0b088SPeter Ujfalusi 	if (!rhdr->hdr.size || !count || *ppos)
60cac0b088SPeter Ujfalusi 		return 0;
61cac0b088SPeter Ujfalusi 
62cac0b088SPeter Ujfalusi 	if (count > rhdr->hdr.size)
63cac0b088SPeter Ujfalusi 		count = rhdr->hdr.size;
64cac0b088SPeter Ujfalusi 
65cac0b088SPeter Ujfalusi 	if (copy_to_user(buffer, priv->rx_buffer, count))
66cac0b088SPeter Ujfalusi 		return -EFAULT;
67cac0b088SPeter Ujfalusi 
68cac0b088SPeter Ujfalusi 	*ppos += count;
69cac0b088SPeter Ujfalusi 	return count;
70cac0b088SPeter Ujfalusi }
71cac0b088SPeter Ujfalusi 
sof_msg_inject_ipc4_dfs_read(struct file * file,char __user * buffer,size_t count,loff_t * ppos)72066c6762SPeter Ujfalusi static ssize_t sof_msg_inject_ipc4_dfs_read(struct file *file,
73066c6762SPeter Ujfalusi 					    char __user *buffer,
74066c6762SPeter Ujfalusi 					    size_t count, loff_t *ppos)
75066c6762SPeter Ujfalusi {
76066c6762SPeter Ujfalusi 	struct sof_client_dev *cdev = file->private_data;
77066c6762SPeter Ujfalusi 	struct sof_msg_inject_priv *priv = cdev->data;
78066c6762SPeter Ujfalusi 	struct sof_ipc4_msg *ipc4_msg = priv->rx_buffer;
79c5003f08SPeter Ujfalusi 	size_t header_size = sizeof(ipc4_msg->header_u64);
80066c6762SPeter Ujfalusi 	size_t remaining;
81066c6762SPeter Ujfalusi 
82066c6762SPeter Ujfalusi 	if (!ipc4_msg->header_u64 || !count || *ppos)
83066c6762SPeter Ujfalusi 		return 0;
84066c6762SPeter Ujfalusi 
85c5003f08SPeter Ujfalusi 	/* we need space for the header at minimum (u64) */
86c5003f08SPeter Ujfalusi 	if (count < header_size)
87c5003f08SPeter Ujfalusi 		return -ENOSPC;
88c5003f08SPeter Ujfalusi 
89c5003f08SPeter Ujfalusi 	remaining = header_size;
90066c6762SPeter Ujfalusi 
91066c6762SPeter Ujfalusi 	/* Only get large config have payload */
92066c6762SPeter Ujfalusi 	if (SOF_IPC4_MSG_IS_MODULE_MSG(ipc4_msg->primary) &&
93066c6762SPeter Ujfalusi 	    (SOF_IPC4_MSG_TYPE_GET(ipc4_msg->primary) == SOF_IPC4_MOD_LARGE_CONFIG_GET))
94066c6762SPeter Ujfalusi 		remaining += ipc4_msg->data_size;
95066c6762SPeter Ujfalusi 
96066c6762SPeter Ujfalusi 	if (count > remaining)
97066c6762SPeter Ujfalusi 		count = remaining;
98c5003f08SPeter Ujfalusi 	else if (count < remaining)
99c5003f08SPeter Ujfalusi 		remaining = count;
100066c6762SPeter Ujfalusi 
101066c6762SPeter Ujfalusi 	/* copy the header first */
102c5003f08SPeter Ujfalusi 	if (copy_to_user(buffer, &ipc4_msg->header_u64, header_size))
103066c6762SPeter Ujfalusi 		return -EFAULT;
104066c6762SPeter Ujfalusi 
105c5003f08SPeter Ujfalusi 	*ppos += header_size;
106c5003f08SPeter Ujfalusi 	remaining -= header_size;
107066c6762SPeter Ujfalusi 
108066c6762SPeter Ujfalusi 	if (!remaining)
109066c6762SPeter Ujfalusi 		return count;
110066c6762SPeter Ujfalusi 
111066c6762SPeter Ujfalusi 	if (remaining > ipc4_msg->data_size)
112066c6762SPeter Ujfalusi 		remaining = ipc4_msg->data_size;
113066c6762SPeter Ujfalusi 
114066c6762SPeter Ujfalusi 	/* Copy the payload */
115066c6762SPeter Ujfalusi 	if (copy_to_user(buffer + *ppos, ipc4_msg->data_ptr, remaining))
116066c6762SPeter Ujfalusi 		return -EFAULT;
117066c6762SPeter Ujfalusi 
118066c6762SPeter Ujfalusi 	*ppos += remaining;
119066c6762SPeter Ujfalusi 	return count;
120066c6762SPeter Ujfalusi }
121066c6762SPeter Ujfalusi 
sof_msg_inject_send_message(struct sof_client_dev * cdev)122a9aa3381SPeter Ujfalusi static int sof_msg_inject_send_message(struct sof_client_dev *cdev)
123a9aa3381SPeter Ujfalusi {
124a9aa3381SPeter Ujfalusi 	struct sof_msg_inject_priv *priv = cdev->data;
125a9aa3381SPeter Ujfalusi 	struct device *dev = &cdev->auxdev.dev;
126a9aa3381SPeter Ujfalusi 	int ret, err;
127a9aa3381SPeter Ujfalusi 
128a9aa3381SPeter Ujfalusi 	ret = pm_runtime_resume_and_get(dev);
129a9aa3381SPeter Ujfalusi 	if (ret < 0 && ret != -EACCES) {
130a9aa3381SPeter Ujfalusi 		dev_err_ratelimited(dev, "debugfs write failed to resume %d\n", ret);
131a9aa3381SPeter Ujfalusi 		return ret;
132a9aa3381SPeter Ujfalusi 	}
133a9aa3381SPeter Ujfalusi 
134a9aa3381SPeter Ujfalusi 	/* send the message */
135a9aa3381SPeter Ujfalusi 	ret = sof_client_ipc_tx_message(cdev, priv->tx_buffer, priv->rx_buffer,
136a9aa3381SPeter Ujfalusi 					priv->max_msg_size);
137a9aa3381SPeter Ujfalusi 	if (ret)
138a9aa3381SPeter Ujfalusi 		dev_err(dev, "IPC message send failed: %d\n", ret);
139a9aa3381SPeter Ujfalusi 
140a9aa3381SPeter Ujfalusi 	pm_runtime_mark_last_busy(dev);
141a9aa3381SPeter Ujfalusi 	err = pm_runtime_put_autosuspend(dev);
142a9aa3381SPeter Ujfalusi 	if (err < 0)
143a9aa3381SPeter Ujfalusi 		dev_err_ratelimited(dev, "debugfs write failed to idle %d\n", err);
144a9aa3381SPeter Ujfalusi 
145a9aa3381SPeter Ujfalusi 	return ret;
146a9aa3381SPeter Ujfalusi }
147a9aa3381SPeter Ujfalusi 
sof_msg_inject_dfs_write(struct file * file,const char __user * buffer,size_t count,loff_t * ppos)148cac0b088SPeter Ujfalusi static ssize_t sof_msg_inject_dfs_write(struct file *file, const char __user *buffer,
149cac0b088SPeter Ujfalusi 					size_t count, loff_t *ppos)
150cac0b088SPeter Ujfalusi {
151cac0b088SPeter Ujfalusi 	struct sof_client_dev *cdev = file->private_data;
152cac0b088SPeter Ujfalusi 	struct sof_msg_inject_priv *priv = cdev->data;
153d9a251a0SDan Carpenter 	ssize_t size;
154a9aa3381SPeter Ujfalusi 	int ret;
155cac0b088SPeter Ujfalusi 
156cac0b088SPeter Ujfalusi 	if (*ppos)
157cac0b088SPeter Ujfalusi 		return 0;
158cac0b088SPeter Ujfalusi 
159ef368c33SPeter Ujfalusi 	size = simple_write_to_buffer(priv->tx_buffer, priv->max_msg_size,
160cac0b088SPeter Ujfalusi 				      ppos, buffer, count);
161d9a251a0SDan Carpenter 	if (size < 0)
162d9a251a0SDan Carpenter 		return size;
163cac0b088SPeter Ujfalusi 	if (size != count)
164d9a251a0SDan Carpenter 		return -EFAULT;
165cac0b088SPeter Ujfalusi 
166ef368c33SPeter Ujfalusi 	memset(priv->rx_buffer, 0, priv->max_msg_size);
167cac0b088SPeter Ujfalusi 
168a9aa3381SPeter Ujfalusi 	ret = sof_msg_inject_send_message(cdev);
169cac0b088SPeter Ujfalusi 
170a9aa3381SPeter Ujfalusi 	/* return the error code if test failed */
171a9aa3381SPeter Ujfalusi 	if (ret < 0)
172a9aa3381SPeter Ujfalusi 		size = ret;
173a9aa3381SPeter Ujfalusi 
174a9aa3381SPeter Ujfalusi 	return size;
175cac0b088SPeter Ujfalusi };
176cac0b088SPeter Ujfalusi 
sof_msg_inject_ipc4_dfs_write(struct file * file,const char __user * buffer,size_t count,loff_t * ppos)177066c6762SPeter Ujfalusi static ssize_t sof_msg_inject_ipc4_dfs_write(struct file *file,
178066c6762SPeter Ujfalusi 					     const char __user *buffer,
179066c6762SPeter Ujfalusi 					     size_t count, loff_t *ppos)
180066c6762SPeter Ujfalusi {
181066c6762SPeter Ujfalusi 	struct sof_client_dev *cdev = file->private_data;
182066c6762SPeter Ujfalusi 	struct sof_msg_inject_priv *priv = cdev->data;
183066c6762SPeter Ujfalusi 	struct sof_ipc4_msg *ipc4_msg = priv->tx_buffer;
184*fa9b878fSDan Carpenter 	size_t data_size;
185066c6762SPeter Ujfalusi 	int ret;
186066c6762SPeter Ujfalusi 
187066c6762SPeter Ujfalusi 	if (*ppos)
188066c6762SPeter Ujfalusi 		return 0;
189066c6762SPeter Ujfalusi 
190066c6762SPeter Ujfalusi 	if (count < sizeof(ipc4_msg->header_u64))
191066c6762SPeter Ujfalusi 		return -EINVAL;
192066c6762SPeter Ujfalusi 
193066c6762SPeter Ujfalusi 	/* copy the header first */
194*fa9b878fSDan Carpenter 	if (copy_from_user(&ipc4_msg->header_u64, buffer,
195*fa9b878fSDan Carpenter 			   sizeof(ipc4_msg->header_u64)))
196d9a251a0SDan Carpenter 		return -EFAULT;
197066c6762SPeter Ujfalusi 
198*fa9b878fSDan Carpenter 	data_size = count - sizeof(ipc4_msg->header_u64);
199*fa9b878fSDan Carpenter 	if (data_size > priv->max_msg_size)
200*fa9b878fSDan Carpenter 		return -EINVAL;
201*fa9b878fSDan Carpenter 
202066c6762SPeter Ujfalusi 	/* Copy the payload */
203*fa9b878fSDan Carpenter 	if (copy_from_user(ipc4_msg->data_ptr,
204*fa9b878fSDan Carpenter 			   buffer + sizeof(ipc4_msg->header_u64), data_size))
205d9a251a0SDan Carpenter 		return -EFAULT;
206066c6762SPeter Ujfalusi 
207*fa9b878fSDan Carpenter 	ipc4_msg->data_size = data_size;
208066c6762SPeter Ujfalusi 
209066c6762SPeter Ujfalusi 	/* Initialize the reply storage */
210066c6762SPeter Ujfalusi 	ipc4_msg = priv->rx_buffer;
211066c6762SPeter Ujfalusi 	ipc4_msg->header_u64 = 0;
212066c6762SPeter Ujfalusi 	ipc4_msg->data_size = priv->max_msg_size;
213066c6762SPeter Ujfalusi 	memset(ipc4_msg->data_ptr, 0, priv->max_msg_size);
214066c6762SPeter Ujfalusi 
215066c6762SPeter Ujfalusi 	ret = sof_msg_inject_send_message(cdev);
216066c6762SPeter Ujfalusi 
217066c6762SPeter Ujfalusi 	/* return the error code if test failed */
218066c6762SPeter Ujfalusi 	if (ret < 0)
219*fa9b878fSDan Carpenter 		return ret;
220066c6762SPeter Ujfalusi 
221*fa9b878fSDan Carpenter 	return count;
222066c6762SPeter Ujfalusi };
223066c6762SPeter Ujfalusi 
sof_msg_inject_dfs_release(struct inode * inode,struct file * file)224cac0b088SPeter Ujfalusi static int sof_msg_inject_dfs_release(struct inode *inode, struct file *file)
225cac0b088SPeter Ujfalusi {
226cac0b088SPeter Ujfalusi 	debugfs_file_put(file->f_path.dentry);
227cac0b088SPeter Ujfalusi 
228cac0b088SPeter Ujfalusi 	return 0;
229cac0b088SPeter Ujfalusi }
230cac0b088SPeter Ujfalusi 
231cac0b088SPeter Ujfalusi static const struct file_operations sof_msg_inject_fops = {
232cac0b088SPeter Ujfalusi 	.open = sof_msg_inject_dfs_open,
233cac0b088SPeter Ujfalusi 	.read = sof_msg_inject_dfs_read,
234cac0b088SPeter Ujfalusi 	.write = sof_msg_inject_dfs_write,
235cac0b088SPeter Ujfalusi 	.llseek = default_llseek,
236cac0b088SPeter Ujfalusi 	.release = sof_msg_inject_dfs_release,
237cac0b088SPeter Ujfalusi 
238cac0b088SPeter Ujfalusi 	.owner = THIS_MODULE,
239cac0b088SPeter Ujfalusi };
240cac0b088SPeter Ujfalusi 
241066c6762SPeter Ujfalusi static const struct file_operations sof_msg_inject_ipc4_fops = {
242066c6762SPeter Ujfalusi 	.open = sof_msg_inject_dfs_open,
243066c6762SPeter Ujfalusi 	.read = sof_msg_inject_ipc4_dfs_read,
244066c6762SPeter Ujfalusi 	.write = sof_msg_inject_ipc4_dfs_write,
245066c6762SPeter Ujfalusi 	.llseek = default_llseek,
246066c6762SPeter Ujfalusi 	.release = sof_msg_inject_dfs_release,
247066c6762SPeter Ujfalusi 
248066c6762SPeter Ujfalusi 	.owner = THIS_MODULE,
249066c6762SPeter Ujfalusi };
250066c6762SPeter Ujfalusi 
sof_msg_inject_probe(struct auxiliary_device * auxdev,const struct auxiliary_device_id * id)251cac0b088SPeter Ujfalusi static int sof_msg_inject_probe(struct auxiliary_device *auxdev,
252cac0b088SPeter Ujfalusi 				const struct auxiliary_device_id *id)
253cac0b088SPeter Ujfalusi {
254cac0b088SPeter Ujfalusi 	struct sof_client_dev *cdev = auxiliary_dev_to_sof_client_dev(auxdev);
255cac0b088SPeter Ujfalusi 	struct dentry *debugfs_root = sof_client_get_debugfs_root(cdev);
256066c6762SPeter Ujfalusi 	static const struct file_operations *fops;
257cac0b088SPeter Ujfalusi 	struct device *dev = &auxdev->dev;
258cac0b088SPeter Ujfalusi 	struct sof_msg_inject_priv *priv;
259066c6762SPeter Ujfalusi 	size_t alloc_size;
260cac0b088SPeter Ujfalusi 
261cac0b088SPeter Ujfalusi 	/* allocate memory for client data */
262cac0b088SPeter Ujfalusi 	priv = devm_kzalloc(&auxdev->dev, sizeof(*priv), GFP_KERNEL);
263cac0b088SPeter Ujfalusi 	if (!priv)
264cac0b088SPeter Ujfalusi 		return -ENOMEM;
265cac0b088SPeter Ujfalusi 
266066c6762SPeter Ujfalusi 	priv->ipc_type = sof_client_get_ipc_type(cdev);
267ef368c33SPeter Ujfalusi 	priv->max_msg_size = sof_client_get_ipc_max_payload_size(cdev);
268066c6762SPeter Ujfalusi 	alloc_size = priv->max_msg_size;
269066c6762SPeter Ujfalusi 
270066c6762SPeter Ujfalusi 	if (priv->ipc_type == SOF_INTEL_IPC4)
271066c6762SPeter Ujfalusi 		alloc_size += sizeof(struct sof_ipc4_msg);
272066c6762SPeter Ujfalusi 
273066c6762SPeter Ujfalusi 	priv->tx_buffer = devm_kmalloc(dev, alloc_size, GFP_KERNEL);
274066c6762SPeter Ujfalusi 	priv->rx_buffer = devm_kzalloc(dev, alloc_size, GFP_KERNEL);
275cac0b088SPeter Ujfalusi 	if (!priv->tx_buffer || !priv->rx_buffer)
276cac0b088SPeter Ujfalusi 		return -ENOMEM;
277cac0b088SPeter Ujfalusi 
278066c6762SPeter Ujfalusi 	if (priv->ipc_type == SOF_INTEL_IPC4) {
279066c6762SPeter Ujfalusi 		struct sof_ipc4_msg *ipc4_msg;
280066c6762SPeter Ujfalusi 
281066c6762SPeter Ujfalusi 		ipc4_msg = priv->tx_buffer;
282066c6762SPeter Ujfalusi 		ipc4_msg->data_ptr = priv->tx_buffer + sizeof(struct sof_ipc4_msg);
283066c6762SPeter Ujfalusi 
284066c6762SPeter Ujfalusi 		ipc4_msg = priv->rx_buffer;
285066c6762SPeter Ujfalusi 		ipc4_msg->data_ptr = priv->rx_buffer + sizeof(struct sof_ipc4_msg);
286066c6762SPeter Ujfalusi 
287066c6762SPeter Ujfalusi 		fops = &sof_msg_inject_ipc4_fops;
288066c6762SPeter Ujfalusi 	} else {
289066c6762SPeter Ujfalusi 		fops = &sof_msg_inject_fops;
290066c6762SPeter Ujfalusi 	}
291066c6762SPeter Ujfalusi 
292cac0b088SPeter Ujfalusi 	cdev->data = priv;
293cac0b088SPeter Ujfalusi 
294cac0b088SPeter Ujfalusi 	priv->dfs_file = debugfs_create_file("ipc_msg_inject", 0644, debugfs_root,
295066c6762SPeter Ujfalusi 					     cdev, fops);
296cac0b088SPeter Ujfalusi 
297cac0b088SPeter Ujfalusi 	/* enable runtime PM */
298cac0b088SPeter Ujfalusi 	pm_runtime_set_autosuspend_delay(dev, SOF_IPC_CLIENT_SUSPEND_DELAY_MS);
299cac0b088SPeter Ujfalusi 	pm_runtime_use_autosuspend(dev);
300cac0b088SPeter Ujfalusi 	pm_runtime_enable(dev);
301cac0b088SPeter Ujfalusi 	pm_runtime_mark_last_busy(dev);
302cac0b088SPeter Ujfalusi 	pm_runtime_idle(dev);
303cac0b088SPeter Ujfalusi 
304cac0b088SPeter Ujfalusi 	return 0;
305cac0b088SPeter Ujfalusi }
306cac0b088SPeter Ujfalusi 
sof_msg_inject_remove(struct auxiliary_device * auxdev)307cac0b088SPeter Ujfalusi static void sof_msg_inject_remove(struct auxiliary_device *auxdev)
308cac0b088SPeter Ujfalusi {
309cac0b088SPeter Ujfalusi 	struct sof_client_dev *cdev = auxiliary_dev_to_sof_client_dev(auxdev);
310cac0b088SPeter Ujfalusi 	struct sof_msg_inject_priv *priv = cdev->data;
311cac0b088SPeter Ujfalusi 
312cac0b088SPeter Ujfalusi 	pm_runtime_disable(&auxdev->dev);
313cac0b088SPeter Ujfalusi 
314cac0b088SPeter Ujfalusi 	debugfs_remove(priv->dfs_file);
315cac0b088SPeter Ujfalusi }
316cac0b088SPeter Ujfalusi 
317cac0b088SPeter Ujfalusi static const struct auxiliary_device_id sof_msg_inject_client_id_table[] = {
318cac0b088SPeter Ujfalusi 	{ .name = "snd_sof.msg_injector" },
319cac0b088SPeter Ujfalusi 	{},
320cac0b088SPeter Ujfalusi };
321cac0b088SPeter Ujfalusi MODULE_DEVICE_TABLE(auxiliary, sof_msg_inject_client_id_table);
322cac0b088SPeter Ujfalusi 
323cac0b088SPeter Ujfalusi /*
324cac0b088SPeter Ujfalusi  * No need for driver pm_ops as the generic pm callbacks in the auxiliary bus
325cac0b088SPeter Ujfalusi  * type are enough to ensure that the parent SOF device resumes to bring the DSP
326cac0b088SPeter Ujfalusi  * back to D0.
327cac0b088SPeter Ujfalusi  * Driver name will be set based on KBUILD_MODNAME.
328cac0b088SPeter Ujfalusi  */
329cac0b088SPeter Ujfalusi static struct auxiliary_driver sof_msg_inject_client_drv = {
330cac0b088SPeter Ujfalusi 	.probe = sof_msg_inject_probe,
331cac0b088SPeter Ujfalusi 	.remove = sof_msg_inject_remove,
332cac0b088SPeter Ujfalusi 
333cac0b088SPeter Ujfalusi 	.id_table = sof_msg_inject_client_id_table,
334cac0b088SPeter Ujfalusi };
335cac0b088SPeter Ujfalusi 
336cac0b088SPeter Ujfalusi module_auxiliary_driver(sof_msg_inject_client_drv);
337cac0b088SPeter Ujfalusi 
338cac0b088SPeter Ujfalusi MODULE_DESCRIPTION("SOF IPC Message Injector Client Driver");
339cac0b088SPeter Ujfalusi MODULE_LICENSE("GPL");
340cac0b088SPeter Ujfalusi MODULE_IMPORT_NS(SND_SOC_SOF_CLIENT);
341