linux-stable/sound/soc/sof/sof-client.c

558 lines
14 KiB
C
Raw Normal View History

ASoC: SOF: Introduce IPC SOF client support A client in the SOF (Sound Open Firmware) context is a driver that needs to communicate with the DSP via IPC messages. The SOF core is responsible for serializing the IPC messages to the DSP from the different clients. One example of an SOF client would be an IPC test client that floods the DSP with test IPC messages to validate if the serialization works as expected. Multi-client support will also add the ability to split the existing audio cards into multiple ones, so as to e.g. to deal with HDMI with a dedicated client instead of adding HDMI to all cards. This patch introduces descriptors for SOF client driver and SOF client device along with APIs for registering and unregistering a SOF client driver, sending IPCs from a client device and accessing the SOF core debugfs root entry. Along with this, add a couple of new members to struct snd_sof_dev that will be used for maintaining the list of clients. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Co-developed-by: Fred Oh <fred.oh@linux.intel.com> Signed-off-by: Fred Oh <fred.oh@linux.intel.com> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Link: https://lore.kernel.org/r/20220210150525.30756-6-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
2022-02-10 15:05:21 +00:00
// SPDX-License-Identifier: GPL-2.0-only
//
// Copyright(c) 2022 Intel Corporation. All rights reserved.
//
// Authors: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
// Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
//
#include <linux/debugfs.h>
#include <linux/errno.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <sound/sof/ipc4/header.h>
ASoC: SOF: Introduce IPC SOF client support A client in the SOF (Sound Open Firmware) context is a driver that needs to communicate with the DSP via IPC messages. The SOF core is responsible for serializing the IPC messages to the DSP from the different clients. One example of an SOF client would be an IPC test client that floods the DSP with test IPC messages to validate if the serialization works as expected. Multi-client support will also add the ability to split the existing audio cards into multiple ones, so as to e.g. to deal with HDMI with a dedicated client instead of adding HDMI to all cards. This patch introduces descriptors for SOF client driver and SOF client device along with APIs for registering and unregistering a SOF client driver, sending IPCs from a client device and accessing the SOF core debugfs root entry. Along with this, add a couple of new members to struct snd_sof_dev that will be used for maintaining the list of clients. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Co-developed-by: Fred Oh <fred.oh@linux.intel.com> Signed-off-by: Fred Oh <fred.oh@linux.intel.com> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Link: https://lore.kernel.org/r/20220210150525.30756-6-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
2022-02-10 15:05:21 +00:00
#include "ops.h"
#include "sof-client.h"
#include "sof-priv.h"
#include "ipc4-priv.h"
ASoC: SOF: Introduce IPC SOF client support A client in the SOF (Sound Open Firmware) context is a driver that needs to communicate with the DSP via IPC messages. The SOF core is responsible for serializing the IPC messages to the DSP from the different clients. One example of an SOF client would be an IPC test client that floods the DSP with test IPC messages to validate if the serialization works as expected. Multi-client support will also add the ability to split the existing audio cards into multiple ones, so as to e.g. to deal with HDMI with a dedicated client instead of adding HDMI to all cards. This patch introduces descriptors for SOF client driver and SOF client device along with APIs for registering and unregistering a SOF client driver, sending IPCs from a client device and accessing the SOF core debugfs root entry. Along with this, add a couple of new members to struct snd_sof_dev that will be used for maintaining the list of clients. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Co-developed-by: Fred Oh <fred.oh@linux.intel.com> Signed-off-by: Fred Oh <fred.oh@linux.intel.com> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Link: https://lore.kernel.org/r/20220210150525.30756-6-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
2022-02-10 15:05:21 +00:00
/**
* struct sof_ipc_event_entry - IPC client event description
* @ipc_msg_type: IPC msg type of the event the client is interested
* @cdev: sof_client_dev of the requesting client
* @callback: Callback function of the client
* @list: item in SOF core client event list
*/
struct sof_ipc_event_entry {
u32 ipc_msg_type;
struct sof_client_dev *cdev;
sof_client_event_callback callback;
struct list_head list;
};
/**
* struct sof_state_event_entry - DSP panic event subscription entry
* @cdev: sof_client_dev of the requesting client
* @callback: Callback function of the client
* @list: item in SOF core client event list
*/
struct sof_state_event_entry {
struct sof_client_dev *cdev;
sof_client_fw_state_callback callback;
struct list_head list;
};
static void sof_client_auxdev_release(struct device *dev)
{
struct auxiliary_device *auxdev = to_auxiliary_dev(dev);
struct sof_client_dev *cdev = auxiliary_dev_to_sof_client_dev(auxdev);
kfree(cdev->auxdev.dev.platform_data);
kfree(cdev);
}
static int sof_client_dev_add_data(struct sof_client_dev *cdev, const void *data,
size_t size)
{
void *d = NULL;
if (data) {
d = kmemdup(data, size, GFP_KERNEL);
if (!d)
return -ENOMEM;
}
cdev->auxdev.dev.platform_data = d;
return 0;
}
#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST)
static int sof_register_ipc_flood_test(struct snd_sof_dev *sdev)
{
int ret = 0;
int i;
if (sdev->pdata->ipc_type != SOF_IPC)
return 0;
for (i = 0; i < CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST_NUM; i++) {
ret = sof_client_dev_register(sdev, "ipc_flood", i, NULL, 0);
if (ret < 0)
break;
}
if (ret) {
for (; i >= 0; --i)
sof_client_dev_unregister(sdev, "ipc_flood", i);
}
return ret;
}
static void sof_unregister_ipc_flood_test(struct snd_sof_dev *sdev)
{
int i;
for (i = 0; i < CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST_NUM; i++)
sof_client_dev_unregister(sdev, "ipc_flood", i);
}
#else
static inline int sof_register_ipc_flood_test(struct snd_sof_dev *sdev)
{
return 0;
}
static inline void sof_unregister_ipc_flood_test(struct snd_sof_dev *sdev) {}
#endif /* CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST */
#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_MSG_INJECTOR)
static int sof_register_ipc_msg_injector(struct snd_sof_dev *sdev)
{
return sof_client_dev_register(sdev, "msg_injector", 0, NULL, 0);
}
static void sof_unregister_ipc_msg_injector(struct snd_sof_dev *sdev)
{
sof_client_dev_unregister(sdev, "msg_injector", 0);
}
#else
static inline int sof_register_ipc_msg_injector(struct snd_sof_dev *sdev)
{
return 0;
}
static inline void sof_unregister_ipc_msg_injector(struct snd_sof_dev *sdev) {}
#endif /* CONFIG_SND_SOC_SOF_DEBUG_IPC_MSG_INJECTOR */
ASoC: SOF: Introduce IPC SOF client support A client in the SOF (Sound Open Firmware) context is a driver that needs to communicate with the DSP via IPC messages. The SOF core is responsible for serializing the IPC messages to the DSP from the different clients. One example of an SOF client would be an IPC test client that floods the DSP with test IPC messages to validate if the serialization works as expected. Multi-client support will also add the ability to split the existing audio cards into multiple ones, so as to e.g. to deal with HDMI with a dedicated client instead of adding HDMI to all cards. This patch introduces descriptors for SOF client driver and SOF client device along with APIs for registering and unregistering a SOF client driver, sending IPCs from a client device and accessing the SOF core debugfs root entry. Along with this, add a couple of new members to struct snd_sof_dev that will be used for maintaining the list of clients. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Co-developed-by: Fred Oh <fred.oh@linux.intel.com> Signed-off-by: Fred Oh <fred.oh@linux.intel.com> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Link: https://lore.kernel.org/r/20220210150525.30756-6-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
2022-02-10 15:05:21 +00:00
int sof_register_clients(struct snd_sof_dev *sdev)
{
int ret;
/* Register platform independent client devices */
ret = sof_register_ipc_flood_test(sdev);
if (ret) {
dev_err(sdev->dev, "IPC flood test client registration failed\n");
return ret;
}
ret = sof_register_ipc_msg_injector(sdev);
if (ret) {
dev_err(sdev->dev, "IPC message injector client registration failed\n");
goto err_msg_injector;
}
/* Platform depndent client device registration */
ASoC: SOF: Introduce IPC SOF client support A client in the SOF (Sound Open Firmware) context is a driver that needs to communicate with the DSP via IPC messages. The SOF core is responsible for serializing the IPC messages to the DSP from the different clients. One example of an SOF client would be an IPC test client that floods the DSP with test IPC messages to validate if the serialization works as expected. Multi-client support will also add the ability to split the existing audio cards into multiple ones, so as to e.g. to deal with HDMI with a dedicated client instead of adding HDMI to all cards. This patch introduces descriptors for SOF client driver and SOF client device along with APIs for registering and unregistering a SOF client driver, sending IPCs from a client device and accessing the SOF core debugfs root entry. Along with this, add a couple of new members to struct snd_sof_dev that will be used for maintaining the list of clients. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Co-developed-by: Fred Oh <fred.oh@linux.intel.com> Signed-off-by: Fred Oh <fred.oh@linux.intel.com> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Link: https://lore.kernel.org/r/20220210150525.30756-6-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
2022-02-10 15:05:21 +00:00
if (sof_ops(sdev) && sof_ops(sdev)->register_ipc_clients)
ret = sof_ops(sdev)->register_ipc_clients(sdev);
ASoC: SOF: Introduce IPC SOF client support A client in the SOF (Sound Open Firmware) context is a driver that needs to communicate with the DSP via IPC messages. The SOF core is responsible for serializing the IPC messages to the DSP from the different clients. One example of an SOF client would be an IPC test client that floods the DSP with test IPC messages to validate if the serialization works as expected. Multi-client support will also add the ability to split the existing audio cards into multiple ones, so as to e.g. to deal with HDMI with a dedicated client instead of adding HDMI to all cards. This patch introduces descriptors for SOF client driver and SOF client device along with APIs for registering and unregistering a SOF client driver, sending IPCs from a client device and accessing the SOF core debugfs root entry. Along with this, add a couple of new members to struct snd_sof_dev that will be used for maintaining the list of clients. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Co-developed-by: Fred Oh <fred.oh@linux.intel.com> Signed-off-by: Fred Oh <fred.oh@linux.intel.com> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Link: https://lore.kernel.org/r/20220210150525.30756-6-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
2022-02-10 15:05:21 +00:00
if (!ret)
return 0;
sof_unregister_ipc_msg_injector(sdev);
err_msg_injector:
sof_unregister_ipc_flood_test(sdev);
return ret;
ASoC: SOF: Introduce IPC SOF client support A client in the SOF (Sound Open Firmware) context is a driver that needs to communicate with the DSP via IPC messages. The SOF core is responsible for serializing the IPC messages to the DSP from the different clients. One example of an SOF client would be an IPC test client that floods the DSP with test IPC messages to validate if the serialization works as expected. Multi-client support will also add the ability to split the existing audio cards into multiple ones, so as to e.g. to deal with HDMI with a dedicated client instead of adding HDMI to all cards. This patch introduces descriptors for SOF client driver and SOF client device along with APIs for registering and unregistering a SOF client driver, sending IPCs from a client device and accessing the SOF core debugfs root entry. Along with this, add a couple of new members to struct snd_sof_dev that will be used for maintaining the list of clients. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Co-developed-by: Fred Oh <fred.oh@linux.intel.com> Signed-off-by: Fred Oh <fred.oh@linux.intel.com> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Link: https://lore.kernel.org/r/20220210150525.30756-6-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
2022-02-10 15:05:21 +00:00
}
void sof_unregister_clients(struct snd_sof_dev *sdev)
{
if (sof_ops(sdev) && sof_ops(sdev)->unregister_ipc_clients)
sof_ops(sdev)->unregister_ipc_clients(sdev);
sof_unregister_ipc_msg_injector(sdev);
sof_unregister_ipc_flood_test(sdev);
ASoC: SOF: Introduce IPC SOF client support A client in the SOF (Sound Open Firmware) context is a driver that needs to communicate with the DSP via IPC messages. The SOF core is responsible for serializing the IPC messages to the DSP from the different clients. One example of an SOF client would be an IPC test client that floods the DSP with test IPC messages to validate if the serialization works as expected. Multi-client support will also add the ability to split the existing audio cards into multiple ones, so as to e.g. to deal with HDMI with a dedicated client instead of adding HDMI to all cards. This patch introduces descriptors for SOF client driver and SOF client device along with APIs for registering and unregistering a SOF client driver, sending IPCs from a client device and accessing the SOF core debugfs root entry. Along with this, add a couple of new members to struct snd_sof_dev that will be used for maintaining the list of clients. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Co-developed-by: Fred Oh <fred.oh@linux.intel.com> Signed-off-by: Fred Oh <fred.oh@linux.intel.com> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Link: https://lore.kernel.org/r/20220210150525.30756-6-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
2022-02-10 15:05:21 +00:00
}
int sof_client_dev_register(struct snd_sof_dev *sdev, const char *name, u32 id,
const void *data, size_t size)
{
struct auxiliary_device *auxdev;
struct sof_client_dev *cdev;
int ret;
cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
if (!cdev)
return -ENOMEM;
cdev->sdev = sdev;
auxdev = &cdev->auxdev;
auxdev->name = name;
auxdev->dev.parent = sdev->dev;
auxdev->dev.release = sof_client_auxdev_release;
auxdev->id = id;
ret = sof_client_dev_add_data(cdev, data, size);
if (ret < 0)
goto err_dev_add_data;
ret = auxiliary_device_init(auxdev);
if (ret < 0) {
dev_err(sdev->dev, "failed to initialize client dev %s.%d\n", name, id);
goto err_dev_init;
}
ret = auxiliary_device_add(&cdev->auxdev);
if (ret < 0) {
dev_err(sdev->dev, "failed to add client dev %s.%d\n", name, id);
/*
* sof_client_auxdev_release() will be invoked to free up memory
* allocations through put_device()
*/
auxiliary_device_uninit(&cdev->auxdev);
return ret;
}
/* add to list of SOF client devices */
mutex_lock(&sdev->ipc_client_mutex);
list_add(&cdev->list, &sdev->ipc_client_list);
mutex_unlock(&sdev->ipc_client_mutex);
return 0;
err_dev_init:
kfree(cdev->auxdev.dev.platform_data);
err_dev_add_data:
kfree(cdev);
return ret;
}
EXPORT_SYMBOL_NS_GPL(sof_client_dev_register, SND_SOC_SOF_CLIENT);
void sof_client_dev_unregister(struct snd_sof_dev *sdev, const char *name, u32 id)
{
struct sof_client_dev *cdev;
mutex_lock(&sdev->ipc_client_mutex);
/*
* sof_client_auxdev_release() will be invoked to free up memory
* allocations through put_device()
*/
list_for_each_entry(cdev, &sdev->ipc_client_list, list) {
if (!strcmp(cdev->auxdev.name, name) && cdev->auxdev.id == id) {
list_del(&cdev->list);
auxiliary_device_delete(&cdev->auxdev);
auxiliary_device_uninit(&cdev->auxdev);
break;
}
}
mutex_unlock(&sdev->ipc_client_mutex);
}
EXPORT_SYMBOL_NS_GPL(sof_client_dev_unregister, SND_SOC_SOF_CLIENT);
int sof_client_ipc_tx_message(struct sof_client_dev *cdev, void *ipc_msg,
void *reply_data, size_t reply_bytes)
{
if (cdev->sdev->pdata->ipc_type == SOF_IPC) {
struct sof_ipc_cmd_hdr *hdr = ipc_msg;
ASoC: SOF: Introduce IPC SOF client support A client in the SOF (Sound Open Firmware) context is a driver that needs to communicate with the DSP via IPC messages. The SOF core is responsible for serializing the IPC messages to the DSP from the different clients. One example of an SOF client would be an IPC test client that floods the DSP with test IPC messages to validate if the serialization works as expected. Multi-client support will also add the ability to split the existing audio cards into multiple ones, so as to e.g. to deal with HDMI with a dedicated client instead of adding HDMI to all cards. This patch introduces descriptors for SOF client driver and SOF client device along with APIs for registering and unregistering a SOF client driver, sending IPCs from a client device and accessing the SOF core debugfs root entry. Along with this, add a couple of new members to struct snd_sof_dev that will be used for maintaining the list of clients. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Co-developed-by: Fred Oh <fred.oh@linux.intel.com> Signed-off-by: Fred Oh <fred.oh@linux.intel.com> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Link: https://lore.kernel.org/r/20220210150525.30756-6-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
2022-02-10 15:05:21 +00:00
return sof_ipc_tx_message(cdev->sdev->ipc, ipc_msg, hdr->size,
reply_data, reply_bytes);
} else if (cdev->sdev->pdata->ipc_type == SOF_INTEL_IPC4) {
struct sof_ipc4_msg *msg = ipc_msg;
return sof_ipc_tx_message(cdev->sdev->ipc, ipc_msg, msg->data_size,
reply_data, reply_bytes);
}
return -EINVAL;
ASoC: SOF: Introduce IPC SOF client support A client in the SOF (Sound Open Firmware) context is a driver that needs to communicate with the DSP via IPC messages. The SOF core is responsible for serializing the IPC messages to the DSP from the different clients. One example of an SOF client would be an IPC test client that floods the DSP with test IPC messages to validate if the serialization works as expected. Multi-client support will also add the ability to split the existing audio cards into multiple ones, so as to e.g. to deal with HDMI with a dedicated client instead of adding HDMI to all cards. This patch introduces descriptors for SOF client driver and SOF client device along with APIs for registering and unregistering a SOF client driver, sending IPCs from a client device and accessing the SOF core debugfs root entry. Along with this, add a couple of new members to struct snd_sof_dev that will be used for maintaining the list of clients. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Co-developed-by: Fred Oh <fred.oh@linux.intel.com> Signed-off-by: Fred Oh <fred.oh@linux.intel.com> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Link: https://lore.kernel.org/r/20220210150525.30756-6-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
2022-02-10 15:05:21 +00:00
}
EXPORT_SYMBOL_NS_GPL(sof_client_ipc_tx_message, SND_SOC_SOF_CLIENT);
int sof_client_ipc_set_get_data(struct sof_client_dev *cdev, void *ipc_msg,
bool set)
{
if (cdev->sdev->pdata->ipc_type == SOF_IPC) {
struct sof_ipc_cmd_hdr *hdr = ipc_msg;
return sof_ipc_set_get_data(cdev->sdev->ipc, ipc_msg, hdr->size,
set);
} else if (cdev->sdev->pdata->ipc_type == SOF_INTEL_IPC4) {
struct sof_ipc4_msg *msg = ipc_msg;
return sof_ipc_set_get_data(cdev->sdev->ipc, ipc_msg,
msg->data_size, set);
}
return -EINVAL;
}
EXPORT_SYMBOL_NS_GPL(sof_client_ipc_set_get_data, SND_SOC_SOF_CLIENT);
#ifdef CONFIG_SND_SOC_SOF_INTEL_IPC4
struct sof_ipc4_fw_module *sof_client_ipc4_find_module(struct sof_client_dev *c, const guid_t *uuid)
{
struct snd_sof_dev *sdev = c->sdev;
if (sdev->pdata->ipc_type == SOF_INTEL_IPC4)
return sof_ipc4_find_module_by_uuid(sdev, uuid);
dev_err(sdev->dev, "Only supported with IPC4\n");
return NULL;
}
EXPORT_SYMBOL_NS_GPL(sof_client_ipc4_find_module, SND_SOC_SOF_CLIENT);
#endif
int sof_suspend_clients(struct snd_sof_dev *sdev, pm_message_t state)
{
struct auxiliary_driver *adrv;
struct sof_client_dev *cdev;
mutex_lock(&sdev->ipc_client_mutex);
list_for_each_entry(cdev, &sdev->ipc_client_list, list) {
/* Skip devices without loaded driver */
if (!cdev->auxdev.dev.driver)
continue;
adrv = to_auxiliary_drv(cdev->auxdev.dev.driver);
if (adrv->suspend)
adrv->suspend(&cdev->auxdev, state);
}
mutex_unlock(&sdev->ipc_client_mutex);
return 0;
}
EXPORT_SYMBOL_NS_GPL(sof_suspend_clients, SND_SOC_SOF_CLIENT);
int sof_resume_clients(struct snd_sof_dev *sdev)
{
struct auxiliary_driver *adrv;
struct sof_client_dev *cdev;
mutex_lock(&sdev->ipc_client_mutex);
list_for_each_entry(cdev, &sdev->ipc_client_list, list) {
/* Skip devices without loaded driver */
if (!cdev->auxdev.dev.driver)
continue;
adrv = to_auxiliary_drv(cdev->auxdev.dev.driver);
if (adrv->resume)
adrv->resume(&cdev->auxdev);
}
mutex_unlock(&sdev->ipc_client_mutex);
return 0;
}
EXPORT_SYMBOL_NS_GPL(sof_resume_clients, SND_SOC_SOF_CLIENT);
ASoC: SOF: Introduce IPC SOF client support A client in the SOF (Sound Open Firmware) context is a driver that needs to communicate with the DSP via IPC messages. The SOF core is responsible for serializing the IPC messages to the DSP from the different clients. One example of an SOF client would be an IPC test client that floods the DSP with test IPC messages to validate if the serialization works as expected. Multi-client support will also add the ability to split the existing audio cards into multiple ones, so as to e.g. to deal with HDMI with a dedicated client instead of adding HDMI to all cards. This patch introduces descriptors for SOF client driver and SOF client device along with APIs for registering and unregistering a SOF client driver, sending IPCs from a client device and accessing the SOF core debugfs root entry. Along with this, add a couple of new members to struct snd_sof_dev that will be used for maintaining the list of clients. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Co-developed-by: Fred Oh <fred.oh@linux.intel.com> Signed-off-by: Fred Oh <fred.oh@linux.intel.com> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Link: https://lore.kernel.org/r/20220210150525.30756-6-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
2022-02-10 15:05:21 +00:00
struct dentry *sof_client_get_debugfs_root(struct sof_client_dev *cdev)
{
return cdev->sdev->debugfs_root;
}
EXPORT_SYMBOL_NS_GPL(sof_client_get_debugfs_root, SND_SOC_SOF_CLIENT);
/* DMA buffer allocation in client drivers must use the core SOF device */
struct device *sof_client_get_dma_dev(struct sof_client_dev *cdev)
{
return cdev->sdev->dev;
}
EXPORT_SYMBOL_NS_GPL(sof_client_get_dma_dev, SND_SOC_SOF_CLIENT);
const struct sof_ipc_fw_version *sof_client_get_fw_version(struct sof_client_dev *cdev)
{
struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
return &sdev->fw_ready.version;
}
EXPORT_SYMBOL_NS_GPL(sof_client_get_fw_version, SND_SOC_SOF_CLIENT);
size_t sof_client_get_ipc_max_payload_size(struct sof_client_dev *cdev)
{
struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
return sdev->ipc->max_payload_size;
}
EXPORT_SYMBOL_NS_GPL(sof_client_get_ipc_max_payload_size, SND_SOC_SOF_CLIENT);
enum sof_ipc_type sof_client_get_ipc_type(struct sof_client_dev *cdev)
{
struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
return sdev->pdata->ipc_type;
}
EXPORT_SYMBOL_NS_GPL(sof_client_get_ipc_type, SND_SOC_SOF_CLIENT);
ASoC: SOF: Introduce IPC SOF client support A client in the SOF (Sound Open Firmware) context is a driver that needs to communicate with the DSP via IPC messages. The SOF core is responsible for serializing the IPC messages to the DSP from the different clients. One example of an SOF client would be an IPC test client that floods the DSP with test IPC messages to validate if the serialization works as expected. Multi-client support will also add the ability to split the existing audio cards into multiple ones, so as to e.g. to deal with HDMI with a dedicated client instead of adding HDMI to all cards. This patch introduces descriptors for SOF client driver and SOF client device along with APIs for registering and unregistering a SOF client driver, sending IPCs from a client device and accessing the SOF core debugfs root entry. Along with this, add a couple of new members to struct snd_sof_dev that will be used for maintaining the list of clients. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Co-developed-by: Fred Oh <fred.oh@linux.intel.com> Signed-off-by: Fred Oh <fred.oh@linux.intel.com> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Link: https://lore.kernel.org/r/20220210150525.30756-6-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
2022-02-10 15:05:21 +00:00
/* module refcount management of SOF core */
int sof_client_core_module_get(struct sof_client_dev *cdev)
{
struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
if (!try_module_get(sdev->dev->driver->owner))
return -ENODEV;
return 0;
}
EXPORT_SYMBOL_NS_GPL(sof_client_core_module_get, SND_SOC_SOF_CLIENT);
void sof_client_core_module_put(struct sof_client_dev *cdev)
{
struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
module_put(sdev->dev->driver->owner);
}
EXPORT_SYMBOL_NS_GPL(sof_client_core_module_put, SND_SOC_SOF_CLIENT);
/* IPC event handling */
void sof_client_ipc_rx_dispatcher(struct snd_sof_dev *sdev, void *msg_buf)
{
struct sof_ipc_event_entry *event;
u32 msg_type;
if (sdev->pdata->ipc_type == SOF_IPC) {
struct sof_ipc_cmd_hdr *hdr = msg_buf;
msg_type = hdr->cmd & SOF_GLB_TYPE_MASK;
} else if (sdev->pdata->ipc_type == SOF_INTEL_IPC4) {
struct sof_ipc4_msg *msg = msg_buf;
msg_type = SOF_IPC4_NOTIFICATION_TYPE_GET(msg->primary);
} else {
dev_dbg_once(sdev->dev, "Not supported IPC version: %d\n",
sdev->pdata->ipc_type);
return;
}
ASoC: SOF: Introduce IPC SOF client support A client in the SOF (Sound Open Firmware) context is a driver that needs to communicate with the DSP via IPC messages. The SOF core is responsible for serializing the IPC messages to the DSP from the different clients. One example of an SOF client would be an IPC test client that floods the DSP with test IPC messages to validate if the serialization works as expected. Multi-client support will also add the ability to split the existing audio cards into multiple ones, so as to e.g. to deal with HDMI with a dedicated client instead of adding HDMI to all cards. This patch introduces descriptors for SOF client driver and SOF client device along with APIs for registering and unregistering a SOF client driver, sending IPCs from a client device and accessing the SOF core debugfs root entry. Along with this, add a couple of new members to struct snd_sof_dev that will be used for maintaining the list of clients. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Co-developed-by: Fred Oh <fred.oh@linux.intel.com> Signed-off-by: Fred Oh <fred.oh@linux.intel.com> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Link: https://lore.kernel.org/r/20220210150525.30756-6-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
2022-02-10 15:05:21 +00:00
mutex_lock(&sdev->client_event_handler_mutex);
list_for_each_entry(event, &sdev->ipc_rx_handler_list, list) {
if (event->ipc_msg_type == msg_type)
event->callback(event->cdev, msg_buf);
}
mutex_unlock(&sdev->client_event_handler_mutex);
}
int sof_client_register_ipc_rx_handler(struct sof_client_dev *cdev,
u32 ipc_msg_type,
sof_client_event_callback callback)
{
struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
struct sof_ipc_event_entry *event;
if (!callback)
ASoC: SOF: Introduce IPC SOF client support A client in the SOF (Sound Open Firmware) context is a driver that needs to communicate with the DSP via IPC messages. The SOF core is responsible for serializing the IPC messages to the DSP from the different clients. One example of an SOF client would be an IPC test client that floods the DSP with test IPC messages to validate if the serialization works as expected. Multi-client support will also add the ability to split the existing audio cards into multiple ones, so as to e.g. to deal with HDMI with a dedicated client instead of adding HDMI to all cards. This patch introduces descriptors for SOF client driver and SOF client device along with APIs for registering and unregistering a SOF client driver, sending IPCs from a client device and accessing the SOF core debugfs root entry. Along with this, add a couple of new members to struct snd_sof_dev that will be used for maintaining the list of clients. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Co-developed-by: Fred Oh <fred.oh@linux.intel.com> Signed-off-by: Fred Oh <fred.oh@linux.intel.com> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Link: https://lore.kernel.org/r/20220210150525.30756-6-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
2022-02-10 15:05:21 +00:00
return -EINVAL;
if (cdev->sdev->pdata->ipc_type == SOF_IPC) {
if (!(ipc_msg_type & SOF_GLB_TYPE_MASK))
return -EINVAL;
} else if (cdev->sdev->pdata->ipc_type == SOF_INTEL_IPC4) {
if (!(ipc_msg_type & SOF_IPC4_NOTIFICATION_TYPE_MASK))
return -EINVAL;
} else {
dev_warn(sdev->dev, "%s: Not supported IPC version: %d\n",
__func__, sdev->pdata->ipc_type);
return -EINVAL;
}
ASoC: SOF: Introduce IPC SOF client support A client in the SOF (Sound Open Firmware) context is a driver that needs to communicate with the DSP via IPC messages. The SOF core is responsible for serializing the IPC messages to the DSP from the different clients. One example of an SOF client would be an IPC test client that floods the DSP with test IPC messages to validate if the serialization works as expected. Multi-client support will also add the ability to split the existing audio cards into multiple ones, so as to e.g. to deal with HDMI with a dedicated client instead of adding HDMI to all cards. This patch introduces descriptors for SOF client driver and SOF client device along with APIs for registering and unregistering a SOF client driver, sending IPCs from a client device and accessing the SOF core debugfs root entry. Along with this, add a couple of new members to struct snd_sof_dev that will be used for maintaining the list of clients. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Co-developed-by: Fred Oh <fred.oh@linux.intel.com> Signed-off-by: Fred Oh <fred.oh@linux.intel.com> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Link: https://lore.kernel.org/r/20220210150525.30756-6-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
2022-02-10 15:05:21 +00:00
event = kmalloc(sizeof(*event), GFP_KERNEL);
if (!event)
return -ENOMEM;
event->ipc_msg_type = ipc_msg_type;
event->cdev = cdev;
event->callback = callback;
/* add to list of SOF client devices */
mutex_lock(&sdev->client_event_handler_mutex);
list_add(&event->list, &sdev->ipc_rx_handler_list);
mutex_unlock(&sdev->client_event_handler_mutex);
return 0;
}
EXPORT_SYMBOL_NS_GPL(sof_client_register_ipc_rx_handler, SND_SOC_SOF_CLIENT);
void sof_client_unregister_ipc_rx_handler(struct sof_client_dev *cdev,
u32 ipc_msg_type)
{
struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
struct sof_ipc_event_entry *event;
mutex_lock(&sdev->client_event_handler_mutex);
list_for_each_entry(event, &sdev->ipc_rx_handler_list, list) {
if (event->cdev == cdev && event->ipc_msg_type == ipc_msg_type) {
list_del(&event->list);
kfree(event);
break;
}
}
mutex_unlock(&sdev->client_event_handler_mutex);
}
EXPORT_SYMBOL_NS_GPL(sof_client_unregister_ipc_rx_handler, SND_SOC_SOF_CLIENT);
/*DSP state notification and query */
void sof_client_fw_state_dispatcher(struct snd_sof_dev *sdev)
{
struct sof_state_event_entry *event;
mutex_lock(&sdev->client_event_handler_mutex);
list_for_each_entry(event, &sdev->fw_state_handler_list, list)
event->callback(event->cdev, sdev->fw_state);
mutex_unlock(&sdev->client_event_handler_mutex);
}
int sof_client_register_fw_state_handler(struct sof_client_dev *cdev,
sof_client_fw_state_callback callback)
{
struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
struct sof_state_event_entry *event;
if (!callback)
return -EINVAL;
event = kmalloc(sizeof(*event), GFP_KERNEL);
if (!event)
return -ENOMEM;
event->cdev = cdev;
event->callback = callback;
/* add to list of SOF client devices */
mutex_lock(&sdev->client_event_handler_mutex);
list_add(&event->list, &sdev->fw_state_handler_list);
mutex_unlock(&sdev->client_event_handler_mutex);
return 0;
}
EXPORT_SYMBOL_NS_GPL(sof_client_register_fw_state_handler, SND_SOC_SOF_CLIENT);
void sof_client_unregister_fw_state_handler(struct sof_client_dev *cdev)
{
struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
struct sof_state_event_entry *event;
mutex_lock(&sdev->client_event_handler_mutex);
list_for_each_entry(event, &sdev->fw_state_handler_list, list) {
if (event->cdev == cdev) {
list_del(&event->list);
kfree(event);
break;
}
}
mutex_unlock(&sdev->client_event_handler_mutex);
}
EXPORT_SYMBOL_NS_GPL(sof_client_unregister_fw_state_handler, SND_SOC_SOF_CLIENT);
enum sof_fw_state sof_client_get_fw_state(struct sof_client_dev *cdev)
{
struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
return sdev->fw_state;
}
EXPORT_SYMBOL_NS_GPL(sof_client_get_fw_state, SND_SOC_SOF_CLIENT);