xref: /linux-6.15/sound/soc/sof/sof-client.c (revision cdd30ebb)
16955d951SPeter Ujfalusi // SPDX-License-Identifier: GPL-2.0-only
26955d951SPeter Ujfalusi //
3293ad281SPierre-Louis Bossart // Copyright(c) 2022 Intel Corporation
46955d951SPeter Ujfalusi //
56955d951SPeter Ujfalusi // Authors: Ranjani Sridharan <[email protected]>
66955d951SPeter Ujfalusi //	    Peter Ujfalusi <[email protected]>
76955d951SPeter Ujfalusi //
86955d951SPeter Ujfalusi 
96955d951SPeter Ujfalusi #include <linux/debugfs.h>
106955d951SPeter Ujfalusi #include <linux/errno.h>
116955d951SPeter Ujfalusi #include <linux/list.h>
126955d951SPeter Ujfalusi #include <linux/module.h>
136955d951SPeter Ujfalusi #include <linux/mutex.h>
146955d951SPeter Ujfalusi #include <linux/slab.h>
15100c9374SPeter Ujfalusi #include <sound/sof/ipc4/header.h>
166955d951SPeter Ujfalusi #include "ops.h"
176955d951SPeter Ujfalusi #include "sof-client.h"
186955d951SPeter Ujfalusi #include "sof-priv.h"
1970dad53dSCurtis Malainey #include "ipc3-priv.h"
207f0a3dffSJyri Sarha #include "ipc4-priv.h"
216955d951SPeter Ujfalusi 
226955d951SPeter Ujfalusi /**
236955d951SPeter Ujfalusi  * struct sof_ipc_event_entry - IPC client event description
246955d951SPeter Ujfalusi  * @ipc_msg_type:	IPC msg type of the event the client is interested
256955d951SPeter Ujfalusi  * @cdev:		sof_client_dev of the requesting client
266955d951SPeter Ujfalusi  * @callback:		Callback function of the client
276955d951SPeter Ujfalusi  * @list:		item in SOF core client event list
286955d951SPeter Ujfalusi  */
296955d951SPeter Ujfalusi struct sof_ipc_event_entry {
306955d951SPeter Ujfalusi 	u32 ipc_msg_type;
316955d951SPeter Ujfalusi 	struct sof_client_dev *cdev;
326955d951SPeter Ujfalusi 	sof_client_event_callback callback;
336955d951SPeter Ujfalusi 	struct list_head list;
346955d951SPeter Ujfalusi };
356955d951SPeter Ujfalusi 
366955d951SPeter Ujfalusi /**
376955d951SPeter Ujfalusi  * struct sof_state_event_entry - DSP panic event subscription entry
386955d951SPeter Ujfalusi  * @cdev:		sof_client_dev of the requesting client
396955d951SPeter Ujfalusi  * @callback:		Callback function of the client
406955d951SPeter Ujfalusi  * @list:		item in SOF core client event list
416955d951SPeter Ujfalusi  */
426955d951SPeter Ujfalusi struct sof_state_event_entry {
436955d951SPeter Ujfalusi 	struct sof_client_dev *cdev;
446955d951SPeter Ujfalusi 	sof_client_fw_state_callback callback;
456955d951SPeter Ujfalusi 	struct list_head list;
466955d951SPeter Ujfalusi };
476955d951SPeter Ujfalusi 
sof_client_auxdev_release(struct device * dev)486955d951SPeter Ujfalusi static void sof_client_auxdev_release(struct device *dev)
496955d951SPeter Ujfalusi {
506955d951SPeter Ujfalusi 	struct auxiliary_device *auxdev = to_auxiliary_dev(dev);
516955d951SPeter Ujfalusi 	struct sof_client_dev *cdev = auxiliary_dev_to_sof_client_dev(auxdev);
526955d951SPeter Ujfalusi 
536955d951SPeter Ujfalusi 	kfree(cdev->auxdev.dev.platform_data);
546955d951SPeter Ujfalusi 	kfree(cdev);
556955d951SPeter Ujfalusi }
566955d951SPeter Ujfalusi 
sof_client_dev_add_data(struct sof_client_dev * cdev,const void * data,size_t size)576955d951SPeter Ujfalusi static int sof_client_dev_add_data(struct sof_client_dev *cdev, const void *data,
586955d951SPeter Ujfalusi 				   size_t size)
596955d951SPeter Ujfalusi {
606955d951SPeter Ujfalusi 	void *d = NULL;
616955d951SPeter Ujfalusi 
626955d951SPeter Ujfalusi 	if (data) {
636955d951SPeter Ujfalusi 		d = kmemdup(data, size, GFP_KERNEL);
646955d951SPeter Ujfalusi 		if (!d)
656955d951SPeter Ujfalusi 			return -ENOMEM;
666955d951SPeter Ujfalusi 	}
676955d951SPeter Ujfalusi 
686955d951SPeter Ujfalusi 	cdev->auxdev.dev.platform_data = d;
696955d951SPeter Ujfalusi 	return 0;
706955d951SPeter Ujfalusi }
716955d951SPeter Ujfalusi 
726e9548cdSRanjani Sridharan #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST)
sof_register_ipc_flood_test(struct snd_sof_dev * sdev)736e9548cdSRanjani Sridharan static int sof_register_ipc_flood_test(struct snd_sof_dev *sdev)
746e9548cdSRanjani Sridharan {
756e9548cdSRanjani Sridharan 	int ret = 0;
766e9548cdSRanjani Sridharan 	int i;
776e9548cdSRanjani Sridharan 
78ebe18b15SPeter Ujfalusi 	if (sdev->pdata->ipc_type != SOF_IPC_TYPE_3)
795889ccddSPeter Ujfalusi 		return 0;
805889ccddSPeter Ujfalusi 
816e9548cdSRanjani Sridharan 	for (i = 0; i < CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST_NUM; i++) {
826e9548cdSRanjani Sridharan 		ret = sof_client_dev_register(sdev, "ipc_flood", i, NULL, 0);
836e9548cdSRanjani Sridharan 		if (ret < 0)
846e9548cdSRanjani Sridharan 			break;
856e9548cdSRanjani Sridharan 	}
866e9548cdSRanjani Sridharan 
876e9548cdSRanjani Sridharan 	if (ret) {
886e9548cdSRanjani Sridharan 		for (; i >= 0; --i)
896e9548cdSRanjani Sridharan 			sof_client_dev_unregister(sdev, "ipc_flood", i);
906e9548cdSRanjani Sridharan 	}
916e9548cdSRanjani Sridharan 
926e9548cdSRanjani Sridharan 	return ret;
936e9548cdSRanjani Sridharan }
946e9548cdSRanjani Sridharan 
sof_unregister_ipc_flood_test(struct snd_sof_dev * sdev)956e9548cdSRanjani Sridharan static void sof_unregister_ipc_flood_test(struct snd_sof_dev *sdev)
966e9548cdSRanjani Sridharan {
976e9548cdSRanjani Sridharan 	int i;
986e9548cdSRanjani Sridharan 
996e9548cdSRanjani Sridharan 	for (i = 0; i < CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST_NUM; i++)
1006e9548cdSRanjani Sridharan 		sof_client_dev_unregister(sdev, "ipc_flood", i);
1016e9548cdSRanjani Sridharan }
1026e9548cdSRanjani Sridharan #else
sof_register_ipc_flood_test(struct snd_sof_dev * sdev)1036e9548cdSRanjani Sridharan static inline int sof_register_ipc_flood_test(struct snd_sof_dev *sdev)
1046e9548cdSRanjani Sridharan {
1056e9548cdSRanjani Sridharan 	return 0;
1066e9548cdSRanjani Sridharan }
1076e9548cdSRanjani Sridharan 
sof_unregister_ipc_flood_test(struct snd_sof_dev * sdev)1086e9548cdSRanjani Sridharan static inline void sof_unregister_ipc_flood_test(struct snd_sof_dev *sdev) {}
1096e9548cdSRanjani Sridharan #endif /* CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST */
1106e9548cdSRanjani Sridharan 
111cac0b088SPeter Ujfalusi #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_MSG_INJECTOR)
sof_register_ipc_msg_injector(struct snd_sof_dev * sdev)112cac0b088SPeter Ujfalusi static int sof_register_ipc_msg_injector(struct snd_sof_dev *sdev)
113cac0b088SPeter Ujfalusi {
114cac0b088SPeter Ujfalusi 	return sof_client_dev_register(sdev, "msg_injector", 0, NULL, 0);
115cac0b088SPeter Ujfalusi }
116cac0b088SPeter Ujfalusi 
sof_unregister_ipc_msg_injector(struct snd_sof_dev * sdev)117cac0b088SPeter Ujfalusi static void sof_unregister_ipc_msg_injector(struct snd_sof_dev *sdev)
118cac0b088SPeter Ujfalusi {
119cac0b088SPeter Ujfalusi 	sof_client_dev_unregister(sdev, "msg_injector", 0);
120cac0b088SPeter Ujfalusi }
121cac0b088SPeter Ujfalusi #else
sof_register_ipc_msg_injector(struct snd_sof_dev * sdev)122cac0b088SPeter Ujfalusi static inline int sof_register_ipc_msg_injector(struct snd_sof_dev *sdev)
123cac0b088SPeter Ujfalusi {
124cac0b088SPeter Ujfalusi 	return 0;
125cac0b088SPeter Ujfalusi }
126cac0b088SPeter Ujfalusi 
sof_unregister_ipc_msg_injector(struct snd_sof_dev * sdev)127cac0b088SPeter Ujfalusi static inline void sof_unregister_ipc_msg_injector(struct snd_sof_dev *sdev) {}
128cac0b088SPeter Ujfalusi #endif /* CONFIG_SND_SOC_SOF_DEBUG_IPC_MSG_INJECTOR */
129cac0b088SPeter Ujfalusi 
13070dad53dSCurtis Malainey #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_KERNEL_INJECTOR)
sof_register_ipc_kernel_injector(struct snd_sof_dev * sdev)13170dad53dSCurtis Malainey static int sof_register_ipc_kernel_injector(struct snd_sof_dev *sdev)
13270dad53dSCurtis Malainey {
13370dad53dSCurtis Malainey 	/* Only IPC3 supported right now */
134ebe18b15SPeter Ujfalusi 	if (sdev->pdata->ipc_type != SOF_IPC_TYPE_3)
13570dad53dSCurtis Malainey 		return 0;
13670dad53dSCurtis Malainey 
13770dad53dSCurtis Malainey 	return sof_client_dev_register(sdev, "kernel_injector", 0, NULL, 0);
13870dad53dSCurtis Malainey }
13970dad53dSCurtis Malainey 
sof_unregister_ipc_kernel_injector(struct snd_sof_dev * sdev)14070dad53dSCurtis Malainey static void sof_unregister_ipc_kernel_injector(struct snd_sof_dev *sdev)
14170dad53dSCurtis Malainey {
14270dad53dSCurtis Malainey 	sof_client_dev_unregister(sdev, "kernel_injector", 0);
14370dad53dSCurtis Malainey }
14470dad53dSCurtis Malainey #else
sof_register_ipc_kernel_injector(struct snd_sof_dev * sdev)14570dad53dSCurtis Malainey static inline int sof_register_ipc_kernel_injector(struct snd_sof_dev *sdev)
14670dad53dSCurtis Malainey {
14770dad53dSCurtis Malainey 	return 0;
14870dad53dSCurtis Malainey }
14970dad53dSCurtis Malainey 
sof_unregister_ipc_kernel_injector(struct snd_sof_dev * sdev)15070dad53dSCurtis Malainey static inline void sof_unregister_ipc_kernel_injector(struct snd_sof_dev *sdev) {}
15170dad53dSCurtis Malainey #endif /* CONFIG_SND_SOC_SOF_DEBUG_IPC_KERNEL_INJECTOR */
15270dad53dSCurtis Malainey 
sof_register_clients(struct snd_sof_dev * sdev)1536955d951SPeter Ujfalusi int sof_register_clients(struct snd_sof_dev *sdev)
1546955d951SPeter Ujfalusi {
1556e9548cdSRanjani Sridharan 	int ret;
1566955d951SPeter Ujfalusi 
15728d40e7aSPeter Ujfalusi 	if (sdev->dspless_mode_selected)
15828d40e7aSPeter Ujfalusi 		return 0;
15928d40e7aSPeter Ujfalusi 
1606e9548cdSRanjani Sridharan 	/* Register platform independent client devices */
1616e9548cdSRanjani Sridharan 	ret = sof_register_ipc_flood_test(sdev);
1626e9548cdSRanjani Sridharan 	if (ret) {
1636e9548cdSRanjani Sridharan 		dev_err(sdev->dev, "IPC flood test client registration failed\n");
1646e9548cdSRanjani Sridharan 		return ret;
1656e9548cdSRanjani Sridharan 	}
1666e9548cdSRanjani Sridharan 
167cac0b088SPeter Ujfalusi 	ret = sof_register_ipc_msg_injector(sdev);
168cac0b088SPeter Ujfalusi 	if (ret) {
169cac0b088SPeter Ujfalusi 		dev_err(sdev->dev, "IPC message injector client registration failed\n");
170cac0b088SPeter Ujfalusi 		goto err_msg_injector;
171cac0b088SPeter Ujfalusi 	}
172cac0b088SPeter Ujfalusi 
17370dad53dSCurtis Malainey 	ret = sof_register_ipc_kernel_injector(sdev);
17470dad53dSCurtis Malainey 	if (ret) {
17570dad53dSCurtis Malainey 		dev_err(sdev->dev, "IPC kernel injector client registration failed\n");
17670dad53dSCurtis Malainey 		goto err_kernel_injector;
17770dad53dSCurtis Malainey 	}
17870dad53dSCurtis Malainey 
17945f2f28bSEugen Hristev 	/* Platform dependent client device registration */
1806e9548cdSRanjani Sridharan 
1816e9548cdSRanjani Sridharan 	if (sof_ops(sdev) && sof_ops(sdev)->register_ipc_clients)
1826e9548cdSRanjani Sridharan 		ret = sof_ops(sdev)->register_ipc_clients(sdev);
1836e9548cdSRanjani Sridharan 
184cac0b088SPeter Ujfalusi 	if (!ret)
185cac0b088SPeter Ujfalusi 		return 0;
186cac0b088SPeter Ujfalusi 
18770dad53dSCurtis Malainey 	sof_unregister_ipc_kernel_injector(sdev);
18870dad53dSCurtis Malainey 
18970dad53dSCurtis Malainey err_kernel_injector:
190cac0b088SPeter Ujfalusi 	sof_unregister_ipc_msg_injector(sdev);
191cac0b088SPeter Ujfalusi 
192cac0b088SPeter Ujfalusi err_msg_injector:
1936e9548cdSRanjani Sridharan 	sof_unregister_ipc_flood_test(sdev);
1946e9548cdSRanjani Sridharan 
1956e9548cdSRanjani Sridharan 	return ret;
1966955d951SPeter Ujfalusi }
1976955d951SPeter Ujfalusi 
sof_unregister_clients(struct snd_sof_dev * sdev)1986955d951SPeter Ujfalusi void sof_unregister_clients(struct snd_sof_dev *sdev)
1996955d951SPeter Ujfalusi {
2006955d951SPeter Ujfalusi 	if (sof_ops(sdev) && sof_ops(sdev)->unregister_ipc_clients)
2016955d951SPeter Ujfalusi 		sof_ops(sdev)->unregister_ipc_clients(sdev);
2026e9548cdSRanjani Sridharan 
20370dad53dSCurtis Malainey 	sof_unregister_ipc_kernel_injector(sdev);
204cac0b088SPeter Ujfalusi 	sof_unregister_ipc_msg_injector(sdev);
2056e9548cdSRanjani Sridharan 	sof_unregister_ipc_flood_test(sdev);
2066955d951SPeter Ujfalusi }
2076955d951SPeter Ujfalusi 
sof_client_dev_register(struct snd_sof_dev * sdev,const char * name,u32 id,const void * data,size_t size)2086955d951SPeter Ujfalusi int sof_client_dev_register(struct snd_sof_dev *sdev, const char *name, u32 id,
2096955d951SPeter Ujfalusi 			    const void *data, size_t size)
2106955d951SPeter Ujfalusi {
2116955d951SPeter Ujfalusi 	struct auxiliary_device *auxdev;
2126955d951SPeter Ujfalusi 	struct sof_client_dev *cdev;
2136955d951SPeter Ujfalusi 	int ret;
2146955d951SPeter Ujfalusi 
2156955d951SPeter Ujfalusi 	cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
2166955d951SPeter Ujfalusi 	if (!cdev)
2176955d951SPeter Ujfalusi 		return -ENOMEM;
2186955d951SPeter Ujfalusi 
2196955d951SPeter Ujfalusi 	cdev->sdev = sdev;
2206955d951SPeter Ujfalusi 	auxdev = &cdev->auxdev;
2216955d951SPeter Ujfalusi 	auxdev->name = name;
2226955d951SPeter Ujfalusi 	auxdev->dev.parent = sdev->dev;
2236955d951SPeter Ujfalusi 	auxdev->dev.release = sof_client_auxdev_release;
2246955d951SPeter Ujfalusi 	auxdev->id = id;
2256955d951SPeter Ujfalusi 
2266955d951SPeter Ujfalusi 	ret = sof_client_dev_add_data(cdev, data, size);
2276955d951SPeter Ujfalusi 	if (ret < 0)
2286955d951SPeter Ujfalusi 		goto err_dev_add_data;
2296955d951SPeter Ujfalusi 
2306955d951SPeter Ujfalusi 	ret = auxiliary_device_init(auxdev);
2316955d951SPeter Ujfalusi 	if (ret < 0) {
2326955d951SPeter Ujfalusi 		dev_err(sdev->dev, "failed to initialize client dev %s.%d\n", name, id);
2336955d951SPeter Ujfalusi 		goto err_dev_init;
2346955d951SPeter Ujfalusi 	}
2356955d951SPeter Ujfalusi 
2366955d951SPeter Ujfalusi 	ret = auxiliary_device_add(&cdev->auxdev);
2376955d951SPeter Ujfalusi 	if (ret < 0) {
2386955d951SPeter Ujfalusi 		dev_err(sdev->dev, "failed to add client dev %s.%d\n", name, id);
2396955d951SPeter Ujfalusi 		/*
2406955d951SPeter Ujfalusi 		 * sof_client_auxdev_release() will be invoked to free up memory
2416955d951SPeter Ujfalusi 		 * allocations through put_device()
2426955d951SPeter Ujfalusi 		 */
2436955d951SPeter Ujfalusi 		auxiliary_device_uninit(&cdev->auxdev);
2446955d951SPeter Ujfalusi 		return ret;
2456955d951SPeter Ujfalusi 	}
2466955d951SPeter Ujfalusi 
2476955d951SPeter Ujfalusi 	/* add to list of SOF client devices */
2486955d951SPeter Ujfalusi 	mutex_lock(&sdev->ipc_client_mutex);
2496955d951SPeter Ujfalusi 	list_add(&cdev->list, &sdev->ipc_client_list);
2506955d951SPeter Ujfalusi 	mutex_unlock(&sdev->ipc_client_mutex);
2516955d951SPeter Ujfalusi 
2526955d951SPeter Ujfalusi 	return 0;
2536955d951SPeter Ujfalusi 
2546955d951SPeter Ujfalusi err_dev_init:
2556955d951SPeter Ujfalusi 	kfree(cdev->auxdev.dev.platform_data);
2566955d951SPeter Ujfalusi 
2576955d951SPeter Ujfalusi err_dev_add_data:
2586955d951SPeter Ujfalusi 	kfree(cdev);
2596955d951SPeter Ujfalusi 
2606955d951SPeter Ujfalusi 	return ret;
2616955d951SPeter Ujfalusi }
262*cdd30ebbSPeter Zijlstra EXPORT_SYMBOL_NS_GPL(sof_client_dev_register, "SND_SOC_SOF_CLIENT");
2636955d951SPeter Ujfalusi 
sof_client_dev_unregister(struct snd_sof_dev * sdev,const char * name,u32 id)2646955d951SPeter Ujfalusi void sof_client_dev_unregister(struct snd_sof_dev *sdev, const char *name, u32 id)
2656955d951SPeter Ujfalusi {
2666955d951SPeter Ujfalusi 	struct sof_client_dev *cdev;
2676955d951SPeter Ujfalusi 
2686955d951SPeter Ujfalusi 	mutex_lock(&sdev->ipc_client_mutex);
2696955d951SPeter Ujfalusi 
2706955d951SPeter Ujfalusi 	/*
2716955d951SPeter Ujfalusi 	 * sof_client_auxdev_release() will be invoked to free up memory
2726955d951SPeter Ujfalusi 	 * allocations through put_device()
2736955d951SPeter Ujfalusi 	 */
2746955d951SPeter Ujfalusi 	list_for_each_entry(cdev, &sdev->ipc_client_list, list) {
2756955d951SPeter Ujfalusi 		if (!strcmp(cdev->auxdev.name, name) && cdev->auxdev.id == id) {
2766955d951SPeter Ujfalusi 			list_del(&cdev->list);
2776955d951SPeter Ujfalusi 			auxiliary_device_delete(&cdev->auxdev);
2786955d951SPeter Ujfalusi 			auxiliary_device_uninit(&cdev->auxdev);
2796955d951SPeter Ujfalusi 			break;
2806955d951SPeter Ujfalusi 		}
2816955d951SPeter Ujfalusi 	}
2826955d951SPeter Ujfalusi 
2836955d951SPeter Ujfalusi 	mutex_unlock(&sdev->ipc_client_mutex);
2846955d951SPeter Ujfalusi }
285*cdd30ebbSPeter Zijlstra EXPORT_SYMBOL_NS_GPL(sof_client_dev_unregister, "SND_SOC_SOF_CLIENT");
2866955d951SPeter Ujfalusi 
sof_client_ipc_tx_message(struct sof_client_dev * cdev,void * ipc_msg,void * reply_data,size_t reply_bytes)2876955d951SPeter Ujfalusi int sof_client_ipc_tx_message(struct sof_client_dev *cdev, void *ipc_msg,
2886955d951SPeter Ujfalusi 			      void *reply_data, size_t reply_bytes)
2896955d951SPeter Ujfalusi {
290ebe18b15SPeter Ujfalusi 	if (cdev->sdev->pdata->ipc_type == SOF_IPC_TYPE_3) {
2916955d951SPeter Ujfalusi 		struct sof_ipc_cmd_hdr *hdr = ipc_msg;
2926955d951SPeter Ujfalusi 
2932a51c0f8SPeter Ujfalusi 		return sof_ipc_tx_message(cdev->sdev->ipc, ipc_msg, hdr->size,
2946955d951SPeter Ujfalusi 					  reply_data, reply_bytes);
295ebe18b15SPeter Ujfalusi 	} else if (cdev->sdev->pdata->ipc_type == SOF_IPC_TYPE_4) {
296100c9374SPeter Ujfalusi 		struct sof_ipc4_msg *msg = ipc_msg;
297100c9374SPeter Ujfalusi 
298100c9374SPeter Ujfalusi 		return sof_ipc_tx_message(cdev->sdev->ipc, ipc_msg, msg->data_size,
299100c9374SPeter Ujfalusi 					  reply_data, reply_bytes);
300100c9374SPeter Ujfalusi 	}
301100c9374SPeter Ujfalusi 
302100c9374SPeter Ujfalusi 	return -EINVAL;
3036955d951SPeter Ujfalusi }
304*cdd30ebbSPeter Zijlstra EXPORT_SYMBOL_NS_GPL(sof_client_ipc_tx_message, "SND_SOC_SOF_CLIENT");
3056955d951SPeter Ujfalusi 
sof_client_ipc_rx_message(struct sof_client_dev * cdev,void * ipc_msg,void * msg_buf)30670dad53dSCurtis Malainey int sof_client_ipc_rx_message(struct sof_client_dev *cdev, void *ipc_msg, void *msg_buf)
30770dad53dSCurtis Malainey {
308d65d4a2cSPierre-Louis Bossart 	if (IS_ENABLED(CONFIG_SND_SOC_SOF_IPC3) &&
309d65d4a2cSPierre-Louis Bossart 	    cdev->sdev->pdata->ipc_type == SOF_IPC_TYPE_3) {
31070dad53dSCurtis Malainey 		struct sof_ipc_cmd_hdr *hdr = ipc_msg;
31170dad53dSCurtis Malainey 
31270dad53dSCurtis Malainey 		if (hdr->size < sizeof(hdr)) {
31370dad53dSCurtis Malainey 			dev_err(cdev->sdev->dev, "The received message size is invalid\n");
31470dad53dSCurtis Malainey 			return -EINVAL;
31570dad53dSCurtis Malainey 		}
31670dad53dSCurtis Malainey 
31770dad53dSCurtis Malainey 		sof_ipc3_do_rx_work(cdev->sdev, ipc_msg, msg_buf);
31870dad53dSCurtis Malainey 		return 0;
31970dad53dSCurtis Malainey 	}
32070dad53dSCurtis Malainey 
32170dad53dSCurtis Malainey 	return -EOPNOTSUPP;
32270dad53dSCurtis Malainey }
323*cdd30ebbSPeter Zijlstra EXPORT_SYMBOL_NS_GPL(sof_client_ipc_rx_message, "SND_SOC_SOF_CLIENT");
32470dad53dSCurtis Malainey 
sof_client_ipc_set_get_data(struct sof_client_dev * cdev,void * ipc_msg,bool set)325d8bc54a5SJyri Sarha int sof_client_ipc_set_get_data(struct sof_client_dev *cdev, void *ipc_msg,
326d8bc54a5SJyri Sarha 				bool set)
327d8bc54a5SJyri Sarha {
328ebe18b15SPeter Ujfalusi 	if (cdev->sdev->pdata->ipc_type == SOF_IPC_TYPE_3) {
329d8bc54a5SJyri Sarha 		struct sof_ipc_cmd_hdr *hdr = ipc_msg;
330d8bc54a5SJyri Sarha 
331d8bc54a5SJyri Sarha 		return sof_ipc_set_get_data(cdev->sdev->ipc, ipc_msg, hdr->size,
332d8bc54a5SJyri Sarha 					    set);
333ebe18b15SPeter Ujfalusi 	} else if (cdev->sdev->pdata->ipc_type == SOF_IPC_TYPE_4) {
334d8bc54a5SJyri Sarha 		struct sof_ipc4_msg *msg = ipc_msg;
335d8bc54a5SJyri Sarha 
336d8bc54a5SJyri Sarha 		return sof_ipc_set_get_data(cdev->sdev->ipc, ipc_msg,
337d8bc54a5SJyri Sarha 					    msg->data_size, set);
338d8bc54a5SJyri Sarha 	}
339d8bc54a5SJyri Sarha 
340d8bc54a5SJyri Sarha 	return -EINVAL;
341d8bc54a5SJyri Sarha }
342*cdd30ebbSPeter Zijlstra EXPORT_SYMBOL_NS_GPL(sof_client_ipc_set_get_data, "SND_SOC_SOF_CLIENT");
343d8bc54a5SJyri Sarha 
34482f4b383SPeter Ujfalusi #ifdef CONFIG_SND_SOC_SOF_IPC4
sof_client_ipc4_find_module(struct sof_client_dev * c,const guid_t * uuid)3457f0a3dffSJyri Sarha struct sof_ipc4_fw_module *sof_client_ipc4_find_module(struct sof_client_dev *c, const guid_t *uuid)
3467f0a3dffSJyri Sarha {
3477f0a3dffSJyri Sarha 	struct snd_sof_dev *sdev = c->sdev;
3487f0a3dffSJyri Sarha 
349ebe18b15SPeter Ujfalusi 	if (sdev->pdata->ipc_type == SOF_IPC_TYPE_4)
3507f0a3dffSJyri Sarha 		return sof_ipc4_find_module_by_uuid(sdev, uuid);
3517f0a3dffSJyri Sarha 	dev_err(sdev->dev, "Only supported with IPC4\n");
3527f0a3dffSJyri Sarha 
3537f0a3dffSJyri Sarha 	return NULL;
3547f0a3dffSJyri Sarha }
355*cdd30ebbSPeter Zijlstra EXPORT_SYMBOL_NS_GPL(sof_client_ipc4_find_module, "SND_SOC_SOF_CLIENT");
3567f0a3dffSJyri Sarha #endif
3577f0a3dffSJyri Sarha 
sof_suspend_clients(struct snd_sof_dev * sdev,pm_message_t state)3581069967aSPeter Ujfalusi int sof_suspend_clients(struct snd_sof_dev *sdev, pm_message_t state)
3591069967aSPeter Ujfalusi {
360ff985c75SGreg Kroah-Hartman 	const struct auxiliary_driver *adrv;
3611069967aSPeter Ujfalusi 	struct sof_client_dev *cdev;
3621069967aSPeter Ujfalusi 
3631069967aSPeter Ujfalusi 	mutex_lock(&sdev->ipc_client_mutex);
3641069967aSPeter Ujfalusi 
3651069967aSPeter Ujfalusi 	list_for_each_entry(cdev, &sdev->ipc_client_list, list) {
3661069967aSPeter Ujfalusi 		/* Skip devices without loaded driver */
3671069967aSPeter Ujfalusi 		if (!cdev->auxdev.dev.driver)
3681069967aSPeter Ujfalusi 			continue;
3691069967aSPeter Ujfalusi 
3701069967aSPeter Ujfalusi 		adrv = to_auxiliary_drv(cdev->auxdev.dev.driver);
3711069967aSPeter Ujfalusi 		if (adrv->suspend)
3721069967aSPeter Ujfalusi 			adrv->suspend(&cdev->auxdev, state);
3731069967aSPeter Ujfalusi 	}
3741069967aSPeter Ujfalusi 
3751069967aSPeter Ujfalusi 	mutex_unlock(&sdev->ipc_client_mutex);
3761069967aSPeter Ujfalusi 
3771069967aSPeter Ujfalusi 	return 0;
3781069967aSPeter Ujfalusi }
379*cdd30ebbSPeter Zijlstra EXPORT_SYMBOL_NS_GPL(sof_suspend_clients, "SND_SOC_SOF_CLIENT");
3801069967aSPeter Ujfalusi 
sof_resume_clients(struct snd_sof_dev * sdev)3811069967aSPeter Ujfalusi int sof_resume_clients(struct snd_sof_dev *sdev)
3821069967aSPeter Ujfalusi {
383ff985c75SGreg Kroah-Hartman 	const struct auxiliary_driver *adrv;
3841069967aSPeter Ujfalusi 	struct sof_client_dev *cdev;
3851069967aSPeter Ujfalusi 
3861069967aSPeter Ujfalusi 	mutex_lock(&sdev->ipc_client_mutex);
3871069967aSPeter Ujfalusi 
3881069967aSPeter Ujfalusi 	list_for_each_entry(cdev, &sdev->ipc_client_list, list) {
3891069967aSPeter Ujfalusi 		/* Skip devices without loaded driver */
3901069967aSPeter Ujfalusi 		if (!cdev->auxdev.dev.driver)
3911069967aSPeter Ujfalusi 			continue;
3921069967aSPeter Ujfalusi 
3931069967aSPeter Ujfalusi 		adrv = to_auxiliary_drv(cdev->auxdev.dev.driver);
3941069967aSPeter Ujfalusi 		if (adrv->resume)
3951069967aSPeter Ujfalusi 			adrv->resume(&cdev->auxdev);
3961069967aSPeter Ujfalusi 	}
3971069967aSPeter Ujfalusi 
3981069967aSPeter Ujfalusi 	mutex_unlock(&sdev->ipc_client_mutex);
3991069967aSPeter Ujfalusi 
4001069967aSPeter Ujfalusi 	return 0;
4011069967aSPeter Ujfalusi }
402*cdd30ebbSPeter Zijlstra EXPORT_SYMBOL_NS_GPL(sof_resume_clients, "SND_SOC_SOF_CLIENT");
4031069967aSPeter Ujfalusi 
sof_client_get_debugfs_root(struct sof_client_dev * cdev)4046955d951SPeter Ujfalusi struct dentry *sof_client_get_debugfs_root(struct sof_client_dev *cdev)
4056955d951SPeter Ujfalusi {
4066955d951SPeter Ujfalusi 	return cdev->sdev->debugfs_root;
4076955d951SPeter Ujfalusi }
408*cdd30ebbSPeter Zijlstra EXPORT_SYMBOL_NS_GPL(sof_client_get_debugfs_root, "SND_SOC_SOF_CLIENT");
4096955d951SPeter Ujfalusi 
4106955d951SPeter Ujfalusi /* DMA buffer allocation in client drivers must use the core SOF device */
sof_client_get_dma_dev(struct sof_client_dev * cdev)4116955d951SPeter Ujfalusi struct device *sof_client_get_dma_dev(struct sof_client_dev *cdev)
4126955d951SPeter Ujfalusi {
4136955d951SPeter Ujfalusi 	return cdev->sdev->dev;
4146955d951SPeter Ujfalusi }
415*cdd30ebbSPeter Zijlstra EXPORT_SYMBOL_NS_GPL(sof_client_get_dma_dev, "SND_SOC_SOF_CLIENT");
4166955d951SPeter Ujfalusi 
sof_client_get_fw_version(struct sof_client_dev * cdev)4176955d951SPeter Ujfalusi const struct sof_ipc_fw_version *sof_client_get_fw_version(struct sof_client_dev *cdev)
4186955d951SPeter Ujfalusi {
4196955d951SPeter Ujfalusi 	struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
4206955d951SPeter Ujfalusi 
4216955d951SPeter Ujfalusi 	return &sdev->fw_ready.version;
4226955d951SPeter Ujfalusi }
423*cdd30ebbSPeter Zijlstra EXPORT_SYMBOL_NS_GPL(sof_client_get_fw_version, "SND_SOC_SOF_CLIENT");
4246955d951SPeter Ujfalusi 
sof_client_get_ipc_max_payload_size(struct sof_client_dev * cdev)425a669ec5fSPeter Ujfalusi size_t sof_client_get_ipc_max_payload_size(struct sof_client_dev *cdev)
426a669ec5fSPeter Ujfalusi {
427a669ec5fSPeter Ujfalusi 	struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
428a669ec5fSPeter Ujfalusi 
429a669ec5fSPeter Ujfalusi 	return sdev->ipc->max_payload_size;
430a669ec5fSPeter Ujfalusi }
431*cdd30ebbSPeter Zijlstra EXPORT_SYMBOL_NS_GPL(sof_client_get_ipc_max_payload_size, "SND_SOC_SOF_CLIENT");
432a669ec5fSPeter Ujfalusi 
sof_client_get_ipc_type(struct sof_client_dev * cdev)433cdf8233dSPeter Ujfalusi enum sof_ipc_type sof_client_get_ipc_type(struct sof_client_dev *cdev)
434cdf8233dSPeter Ujfalusi {
435cdf8233dSPeter Ujfalusi 	struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
436cdf8233dSPeter Ujfalusi 
437cdf8233dSPeter Ujfalusi 	return sdev->pdata->ipc_type;
438cdf8233dSPeter Ujfalusi }
439*cdd30ebbSPeter Zijlstra EXPORT_SYMBOL_NS_GPL(sof_client_get_ipc_type, "SND_SOC_SOF_CLIENT");
440cdf8233dSPeter Ujfalusi 
4416955d951SPeter Ujfalusi /* module refcount management of SOF core */
sof_client_core_module_get(struct sof_client_dev * cdev)4426955d951SPeter Ujfalusi int sof_client_core_module_get(struct sof_client_dev *cdev)
4436955d951SPeter Ujfalusi {
4446955d951SPeter Ujfalusi 	struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
4456955d951SPeter Ujfalusi 
4466955d951SPeter Ujfalusi 	if (!try_module_get(sdev->dev->driver->owner))
4476955d951SPeter Ujfalusi 		return -ENODEV;
4486955d951SPeter Ujfalusi 
4496955d951SPeter Ujfalusi 	return 0;
4506955d951SPeter Ujfalusi }
451*cdd30ebbSPeter Zijlstra EXPORT_SYMBOL_NS_GPL(sof_client_core_module_get, "SND_SOC_SOF_CLIENT");
4526955d951SPeter Ujfalusi 
sof_client_core_module_put(struct sof_client_dev * cdev)4536955d951SPeter Ujfalusi void sof_client_core_module_put(struct sof_client_dev *cdev)
4546955d951SPeter Ujfalusi {
4556955d951SPeter Ujfalusi 	struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
4566955d951SPeter Ujfalusi 
4576955d951SPeter Ujfalusi 	module_put(sdev->dev->driver->owner);
4586955d951SPeter Ujfalusi }
459*cdd30ebbSPeter Zijlstra EXPORT_SYMBOL_NS_GPL(sof_client_core_module_put, "SND_SOC_SOF_CLIENT");
4606955d951SPeter Ujfalusi 
4616955d951SPeter Ujfalusi /* IPC event handling */
sof_client_ipc_rx_dispatcher(struct snd_sof_dev * sdev,void * msg_buf)4626955d951SPeter Ujfalusi void sof_client_ipc_rx_dispatcher(struct snd_sof_dev *sdev, void *msg_buf)
4636955d951SPeter Ujfalusi {
4646955d951SPeter Ujfalusi 	struct sof_ipc_event_entry *event;
465100c9374SPeter Ujfalusi 	u32 msg_type;
466100c9374SPeter Ujfalusi 
467ebe18b15SPeter Ujfalusi 	if (sdev->pdata->ipc_type == SOF_IPC_TYPE_3) {
468100c9374SPeter Ujfalusi 		struct sof_ipc_cmd_hdr *hdr = msg_buf;
469100c9374SPeter Ujfalusi 
470100c9374SPeter Ujfalusi 		msg_type = hdr->cmd & SOF_GLB_TYPE_MASK;
471ebe18b15SPeter Ujfalusi 	} else if (sdev->pdata->ipc_type == SOF_IPC_TYPE_4) {
472100c9374SPeter Ujfalusi 		struct sof_ipc4_msg *msg = msg_buf;
473100c9374SPeter Ujfalusi 
474100c9374SPeter Ujfalusi 		msg_type = SOF_IPC4_NOTIFICATION_TYPE_GET(msg->primary);
475100c9374SPeter Ujfalusi 	} else {
476298e3abaSPierre-Louis Bossart 		dev_dbg_once(sdev->dev, "Not supported IPC version: %d\n",
477298e3abaSPierre-Louis Bossart 			     sdev->pdata->ipc_type);
478100c9374SPeter Ujfalusi 		return;
479100c9374SPeter Ujfalusi 	}
4806955d951SPeter Ujfalusi 
4816955d951SPeter Ujfalusi 	mutex_lock(&sdev->client_event_handler_mutex);
4826955d951SPeter Ujfalusi 
4836955d951SPeter Ujfalusi 	list_for_each_entry(event, &sdev->ipc_rx_handler_list, list) {
4846955d951SPeter Ujfalusi 		if (event->ipc_msg_type == msg_type)
4856955d951SPeter Ujfalusi 			event->callback(event->cdev, msg_buf);
4866955d951SPeter Ujfalusi 	}
4876955d951SPeter Ujfalusi 
4886955d951SPeter Ujfalusi 	mutex_unlock(&sdev->client_event_handler_mutex);
4896955d951SPeter Ujfalusi }
4906955d951SPeter Ujfalusi 
sof_client_register_ipc_rx_handler(struct sof_client_dev * cdev,u32 ipc_msg_type,sof_client_event_callback callback)4916955d951SPeter Ujfalusi int sof_client_register_ipc_rx_handler(struct sof_client_dev *cdev,
4926955d951SPeter Ujfalusi 				       u32 ipc_msg_type,
4936955d951SPeter Ujfalusi 				       sof_client_event_callback callback)
4946955d951SPeter Ujfalusi {
4956955d951SPeter Ujfalusi 	struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
4966955d951SPeter Ujfalusi 	struct sof_ipc_event_entry *event;
4976955d951SPeter Ujfalusi 
498100c9374SPeter Ujfalusi 	if (!callback)
4996955d951SPeter Ujfalusi 		return -EINVAL;
5006955d951SPeter Ujfalusi 
501ebe18b15SPeter Ujfalusi 	if (cdev->sdev->pdata->ipc_type == SOF_IPC_TYPE_3) {
502100c9374SPeter Ujfalusi 		if (!(ipc_msg_type & SOF_GLB_TYPE_MASK))
503100c9374SPeter Ujfalusi 			return -EINVAL;
504ebe18b15SPeter Ujfalusi 	} else if (cdev->sdev->pdata->ipc_type == SOF_IPC_TYPE_4) {
505100c9374SPeter Ujfalusi 		if (!(ipc_msg_type & SOF_IPC4_NOTIFICATION_TYPE_MASK))
506100c9374SPeter Ujfalusi 			return -EINVAL;
507100c9374SPeter Ujfalusi 	} else {
508100c9374SPeter Ujfalusi 		dev_warn(sdev->dev, "%s: Not supported IPC version: %d\n",
509100c9374SPeter Ujfalusi 			 __func__, sdev->pdata->ipc_type);
510100c9374SPeter Ujfalusi 		return -EINVAL;
511100c9374SPeter Ujfalusi 	}
512100c9374SPeter Ujfalusi 
5136955d951SPeter Ujfalusi 	event = kmalloc(sizeof(*event), GFP_KERNEL);
5146955d951SPeter Ujfalusi 	if (!event)
5156955d951SPeter Ujfalusi 		return -ENOMEM;
5166955d951SPeter Ujfalusi 
5176955d951SPeter Ujfalusi 	event->ipc_msg_type = ipc_msg_type;
5186955d951SPeter Ujfalusi 	event->cdev = cdev;
5196955d951SPeter Ujfalusi 	event->callback = callback;
5206955d951SPeter Ujfalusi 
5216955d951SPeter Ujfalusi 	/* add to list of SOF client devices */
5226955d951SPeter Ujfalusi 	mutex_lock(&sdev->client_event_handler_mutex);
5236955d951SPeter Ujfalusi 	list_add(&event->list, &sdev->ipc_rx_handler_list);
5246955d951SPeter Ujfalusi 	mutex_unlock(&sdev->client_event_handler_mutex);
5256955d951SPeter Ujfalusi 
5266955d951SPeter Ujfalusi 	return 0;
5276955d951SPeter Ujfalusi }
528*cdd30ebbSPeter Zijlstra EXPORT_SYMBOL_NS_GPL(sof_client_register_ipc_rx_handler, "SND_SOC_SOF_CLIENT");
5296955d951SPeter Ujfalusi 
sof_client_unregister_ipc_rx_handler(struct sof_client_dev * cdev,u32 ipc_msg_type)5306955d951SPeter Ujfalusi void sof_client_unregister_ipc_rx_handler(struct sof_client_dev *cdev,
5316955d951SPeter Ujfalusi 					  u32 ipc_msg_type)
5326955d951SPeter Ujfalusi {
5336955d951SPeter Ujfalusi 	struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
5346955d951SPeter Ujfalusi 	struct sof_ipc_event_entry *event;
5356955d951SPeter Ujfalusi 
5366955d951SPeter Ujfalusi 	mutex_lock(&sdev->client_event_handler_mutex);
5376955d951SPeter Ujfalusi 
5386955d951SPeter Ujfalusi 	list_for_each_entry(event, &sdev->ipc_rx_handler_list, list) {
5396955d951SPeter Ujfalusi 		if (event->cdev == cdev && event->ipc_msg_type == ipc_msg_type) {
5406955d951SPeter Ujfalusi 			list_del(&event->list);
5416955d951SPeter Ujfalusi 			kfree(event);
5426955d951SPeter Ujfalusi 			break;
5436955d951SPeter Ujfalusi 		}
5446955d951SPeter Ujfalusi 	}
5456955d951SPeter Ujfalusi 
5466955d951SPeter Ujfalusi 	mutex_unlock(&sdev->client_event_handler_mutex);
5476955d951SPeter Ujfalusi }
548*cdd30ebbSPeter Zijlstra EXPORT_SYMBOL_NS_GPL(sof_client_unregister_ipc_rx_handler, "SND_SOC_SOF_CLIENT");
5496955d951SPeter Ujfalusi 
5506955d951SPeter Ujfalusi /*DSP state notification and query */
sof_client_fw_state_dispatcher(struct snd_sof_dev * sdev)5516955d951SPeter Ujfalusi void sof_client_fw_state_dispatcher(struct snd_sof_dev *sdev)
5526955d951SPeter Ujfalusi {
5536955d951SPeter Ujfalusi 	struct sof_state_event_entry *event;
5546955d951SPeter Ujfalusi 
5556955d951SPeter Ujfalusi 	mutex_lock(&sdev->client_event_handler_mutex);
5566955d951SPeter Ujfalusi 
5576955d951SPeter Ujfalusi 	list_for_each_entry(event, &sdev->fw_state_handler_list, list)
5586955d951SPeter Ujfalusi 		event->callback(event->cdev, sdev->fw_state);
5596955d951SPeter Ujfalusi 
5606955d951SPeter Ujfalusi 	mutex_unlock(&sdev->client_event_handler_mutex);
5616955d951SPeter Ujfalusi }
5626955d951SPeter Ujfalusi 
sof_client_register_fw_state_handler(struct sof_client_dev * cdev,sof_client_fw_state_callback callback)5636955d951SPeter Ujfalusi int sof_client_register_fw_state_handler(struct sof_client_dev *cdev,
5646955d951SPeter Ujfalusi 					 sof_client_fw_state_callback callback)
5656955d951SPeter Ujfalusi {
5666955d951SPeter Ujfalusi 	struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
5676955d951SPeter Ujfalusi 	struct sof_state_event_entry *event;
5686955d951SPeter Ujfalusi 
5696955d951SPeter Ujfalusi 	if (!callback)
5706955d951SPeter Ujfalusi 		return -EINVAL;
5716955d951SPeter Ujfalusi 
5726955d951SPeter Ujfalusi 	event = kmalloc(sizeof(*event), GFP_KERNEL);
5736955d951SPeter Ujfalusi 	if (!event)
5746955d951SPeter Ujfalusi 		return -ENOMEM;
5756955d951SPeter Ujfalusi 
5766955d951SPeter Ujfalusi 	event->cdev = cdev;
5776955d951SPeter Ujfalusi 	event->callback = callback;
5786955d951SPeter Ujfalusi 
5796955d951SPeter Ujfalusi 	/* add to list of SOF client devices */
5806955d951SPeter Ujfalusi 	mutex_lock(&sdev->client_event_handler_mutex);
5816955d951SPeter Ujfalusi 	list_add(&event->list, &sdev->fw_state_handler_list);
5826955d951SPeter Ujfalusi 	mutex_unlock(&sdev->client_event_handler_mutex);
5836955d951SPeter Ujfalusi 
5846955d951SPeter Ujfalusi 	return 0;
5856955d951SPeter Ujfalusi }
586*cdd30ebbSPeter Zijlstra EXPORT_SYMBOL_NS_GPL(sof_client_register_fw_state_handler, "SND_SOC_SOF_CLIENT");
5876955d951SPeter Ujfalusi 
sof_client_unregister_fw_state_handler(struct sof_client_dev * cdev)5886955d951SPeter Ujfalusi void sof_client_unregister_fw_state_handler(struct sof_client_dev *cdev)
5896955d951SPeter Ujfalusi {
5906955d951SPeter Ujfalusi 	struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
5916955d951SPeter Ujfalusi 	struct sof_state_event_entry *event;
5926955d951SPeter Ujfalusi 
5936955d951SPeter Ujfalusi 	mutex_lock(&sdev->client_event_handler_mutex);
5946955d951SPeter Ujfalusi 
5956955d951SPeter Ujfalusi 	list_for_each_entry(event, &sdev->fw_state_handler_list, list) {
5966955d951SPeter Ujfalusi 		if (event->cdev == cdev) {
5976955d951SPeter Ujfalusi 			list_del(&event->list);
5986955d951SPeter Ujfalusi 			kfree(event);
5996955d951SPeter Ujfalusi 			break;
6006955d951SPeter Ujfalusi 		}
6016955d951SPeter Ujfalusi 	}
6026955d951SPeter Ujfalusi 
6036955d951SPeter Ujfalusi 	mutex_unlock(&sdev->client_event_handler_mutex);
6046955d951SPeter Ujfalusi }
605*cdd30ebbSPeter Zijlstra EXPORT_SYMBOL_NS_GPL(sof_client_unregister_fw_state_handler, "SND_SOC_SOF_CLIENT");
6066955d951SPeter Ujfalusi 
sof_client_get_fw_state(struct sof_client_dev * cdev)6076955d951SPeter Ujfalusi enum sof_fw_state sof_client_get_fw_state(struct sof_client_dev *cdev)
6086955d951SPeter Ujfalusi {
6096955d951SPeter Ujfalusi 	struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
6106955d951SPeter Ujfalusi 
6116955d951SPeter Ujfalusi 	return sdev->fw_state;
6126955d951SPeter Ujfalusi }
613*cdd30ebbSPeter Zijlstra EXPORT_SYMBOL_NS_GPL(sof_client_get_fw_state, "SND_SOC_SOF_CLIENT");
614