diff --git a/sound/soc/qcom/qdsp6/audioreach.c b/sound/soc/qcom/qdsp6/audioreach.c
index c655f0213723..8175678d8843 100644
--- a/sound/soc/qcom/qdsp6/audioreach.c
+++ b/sound/soc/qcom/qdsp6/audioreach.c
@@ -267,7 +267,7 @@ void *audioreach_alloc_apm_cmd_pkt(int pkt_size, uint32_t opcode, uint32_t token
}
EXPORT_SYMBOL_GPL(audioreach_alloc_apm_cmd_pkt);
-static void audioreach_set_channel_mapping(u8 *ch_map, int num_channels)
+void audioreach_set_channel_mapping(u8 *ch_map, int num_channels)
{
if (num_channels == 1) {
ch_map[0] = PCM_CHANNEL_FL;
diff --git a/sound/soc/qcom/qdsp6/audioreach.h b/sound/soc/qcom/qdsp6/audioreach.h
index 2c82917b7162..cef9a9015dcc 100644
--- a/sound/soc/qcom/qdsp6/audioreach.h
+++ b/sound/soc/qcom/qdsp6/audioreach.h
@@ -767,6 +767,7 @@ struct audioreach_module_config {
/* Packet Allocation routines */
void *audioreach_alloc_apm_cmd_pkt(int pkt_size, uint32_t opcode, uint32_t
token);
+void audioreach_set_channel_mapping(u8 *ch_map, int num_channels);
void *audioreach_alloc_cmd_pkt(int payload_size, uint32_t opcode,
uint32_t token, uint32_t src_port,
uint32_t dest_port);
diff --git a/sound/soc/qcom/qdsp6/q6apm.c b/sound/soc/qcom/qdsp6/q6apm.c
index 2a2a5bd98110..c29a2dd36992 100644
--- a/sound/soc/qcom/qdsp6/q6apm.c
+++ b/sound/soc/qcom/qdsp6/q6apm.c
@@ -13,6 +13,7 @@
#include <linux/soc/qcom/apr.h>
#include <linux/wait.h>
#include <sound/soc.h>
+#include <sound/soc-dai.h>
#include <sound/soc-dapm.h>
#include <sound/pcm.h>
#include "audioreach.h"
@@ -29,6 +30,29 @@ struct apm_graph_mgmt_cmd {
static struct q6apm *g_apm;
+static int q6apm_dai_set_channel_map(struct snd_soc_dai *dai,
+ unsigned int tx_num,
+ const unsigned int *tx_ch_mask,
+ unsigned int rx_num,
+ const unsigned int *rx_ch_mask)
+{
+ struct q6apm *apm = dev_get_drvdata(dai->dev);
+ int i;
+
+ if (dai->id >= ARRAY_SIZE(apm->dai_config))
+ return -EINVAL;
+
+ apm->dai_config[dai->id].num_channels = rx_num;
+ for (i = 0; i < rx_num; i++)
+ apm->dai_config[dai->id].channel_map[i] = rx_ch_mask[i];
+
+ return 0;
+}
+
+const struct snd_soc_dai_ops q6apm_dai_ops = {
+ .set_channel_map = q6apm_dai_set_channel_map,
+};
+
int q6apm_send_cmd_sync(struct q6apm *apm, struct gpr_pkt *pkt, uint32_t rsp_opcode)
{
gpr_device_t *gdev = apm->gdev;
@@ -722,7 +746,7 @@ static int apm_probe(gpr_device_t *gdev)
{
struct device *dev = &gdev->dev;
struct q6apm *apm;
- int ret;
+ int ret, i;
apm = devm_kzalloc(dev, sizeof(*apm), GFP_KERNEL);
if (!apm)
@@ -733,6 +757,8 @@ static int apm_probe(gpr_device_t *gdev)
mutex_init(&apm->lock);
apm->dev = dev;
apm->gdev = gdev;
+ for (i = 0; i < ARRAY_SIZE(apm->dai_config); i++)
+ audioreach_set_channel_mapping(apm->dai_config[i].channel_map, 4);
init_waitqueue_head(&apm->wait);
INIT_LIST_HEAD(&apm->widget_list);
diff --git a/sound/soc/qcom/qdsp6/q6apm.h b/sound/soc/qcom/qdsp6/q6apm.h
index c248c8d2b1ab..0e2e7b6cd6c1 100644
--- a/sound/soc/qcom/qdsp6/q6apm.h
+++ b/sound/soc/qcom/qdsp6/q6apm.h
@@ -47,6 +47,11 @@
#define APM_LAST_BUFFER_FLAG BIT(30)
#define NO_TIMESTAMP 0xFF00
+struct q6apm_dai_config {
+ unsigned int num_channels;
+ u8 channel_map[AR_PCM_MAX_NUM_CHANNEL];
+};
+
struct q6apm {
struct device *dev;
gpr_port_t *port;
@@ -65,6 +70,7 @@ struct q6apm {
struct idr sub_graphs_idr;
struct idr containers_idr;
struct idr modules_idr;
+ struct q6apm_dai_config dai_config[4];
};
struct audio_buffer {
@@ -108,6 +114,8 @@ struct q6apm_graph {
struct audioreach_graph_info *info;
};
+extern const struct snd_soc_dai_ops q6apm_dai_ops;
+
/* Graph Operations */
struct q6apm_graph *q6apm_graph_open(struct device *dev, q6apm_cb cb,
void *priv, int graph_id);
diff --git a/sound/soc/qcom/qdsp6/topology.c b/sound/soc/qcom/qdsp6/topology.c
index 70572c83e101..9708d200568d 100644
--- a/sound/soc/qcom/qdsp6/topology.c
+++ b/sound/soc/qcom/qdsp6/topology.c
@@ -1034,6 +1034,17 @@ static int audioreach_tplg_complete(struct snd_soc_component *component)
return 0;
}
+static int audioreach_dai_load(struct snd_soc_component *cmp, int index,
+ struct snd_soc_dai_driver *dai_drv,
+ struct snd_soc_tplg_pcm *pcm,
+ struct snd_soc_dai *dai)
+{
+ if (pcm)
+ dai_drv->ops = &q6apm_dai_ops;
+
+ return 0;
+}
+
/* DAI link - used for any driver specific init */
static int audioreach_link_load(struct snd_soc_component *component, int index,
struct snd_soc_dai_link *link,
@@ -1251,6 +1262,7 @@ static struct snd_soc_tplg_ops audioreach_tplg_ops = {
.widget_unload = audioreach_widget_unload,
.complete = audioreach_tplg_complete,
+ .dai_load = audioreach_dai_load,
.link_load = audioreach_link_load,
.dapm_route_load = audioreach_route_load,