summaryrefslogtreecommitdiff
path: root/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/qcom/qdsp6/q6apm-lpass-dais.c')
-rw-r--r--sound/soc/qcom/qdsp6/q6apm-lpass-dais.c61
1 files changed, 39 insertions, 22 deletions
diff --git a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
index 7ad604b80e25..528756f1332b 100644
--- a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
+++ b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2021, Linaro Limited
+#include <dt-bindings/sound/qcom,q6dsp-lpass-ports.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/module.h>
@@ -24,13 +25,15 @@ struct q6apm_lpass_dai_data {
};
static int q6dma_set_channel_map(struct snd_soc_dai *dai,
- unsigned int tx_num, unsigned int *tx_ch_mask,
- unsigned int rx_num, unsigned int *rx_ch_mask)
+ unsigned int tx_num,
+ const unsigned int *tx_ch_mask,
+ unsigned int rx_num,
+ const unsigned int *rx_ch_mask)
{
struct q6apm_lpass_dai_data *dai_data = dev_get_drvdata(dai->dev);
struct audioreach_module_config *cfg = &dai_data->module_config[dai->id];
- int ch_mask;
+ int i;
switch (dai->id) {
case WSA_CODEC_DMA_TX_0:
@@ -55,7 +58,8 @@ static int q6dma_set_channel_map(struct snd_soc_dai *dai,
tx_num);
return -EINVAL;
}
- ch_mask = *tx_ch_mask;
+ for (i = 0; i < tx_num; i++)
+ cfg->channel_map[i] = tx_ch_mask[i];
break;
case WSA_CODEC_DMA_RX_0:
@@ -78,7 +82,8 @@ static int q6dma_set_channel_map(struct snd_soc_dai *dai,
rx_num);
return -EINVAL;
}
- ch_mask = *rx_ch_mask;
+ for (i = 0; i < rx_num; i++)
+ cfg->channel_map[i] = rx_ch_mask[i];
break;
default:
@@ -87,8 +92,6 @@ static int q6dma_set_channel_map(struct snd_soc_dai *dai,
return -EINVAL;
}
- cfg->active_channels_mask = ch_mask;
-
return 0;
}
@@ -97,12 +100,13 @@ static int q6hdmi_hw_params(struct snd_pcm_substream *substream,
{
struct q6apm_lpass_dai_data *dai_data = dev_get_drvdata(dai->dev);
struct audioreach_module_config *cfg = &dai_data->module_config[dai->id];
- int channels = params_channels(params);
+ int channels = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS)->max;
int ret;
cfg->bit_width = params_width(params);
cfg->sample_rate = params_rate(params);
cfg->num_channels = channels;
+ audioreach_set_default_channel_mapping(cfg->channel_map, channels);
switch (dai->id) {
case DISPLAY_PORT_RX_0:
@@ -127,10 +131,12 @@ static int q6dma_hw_params(struct snd_pcm_substream *substream,
{
struct q6apm_lpass_dai_data *dai_data = dev_get_drvdata(dai->dev);
struct audioreach_module_config *cfg = &dai_data->module_config[dai->id];
+ int channels = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS)->max;
cfg->bit_width = params_width(params);
cfg->sample_rate = params_rate(params);
- cfg->num_channels = params_channels(params);
+ cfg->num_channels = channels;
+ audioreach_set_default_channel_mapping(cfg->channel_map, channels);
return 0;
}
@@ -140,14 +146,17 @@ static void q6apm_lpass_dai_shutdown(struct snd_pcm_substream *substream, struct
struct q6apm_lpass_dai_data *dai_data = dev_get_drvdata(dai->dev);
int rc;
- if (!dai_data->is_port_started[dai->id])
- return;
- rc = q6apm_graph_stop(dai_data->graph[dai->id]);
- if (rc < 0)
- dev_err(dai->dev, "fail to close APM port (%d)\n", rc);
+ if (dai_data->is_port_started[dai->id]) {
+ rc = q6apm_graph_stop(dai_data->graph[dai->id]);
+ dai_data->is_port_started[dai->id] = false;
+ if (rc < 0)
+ dev_err(dai->dev, "fail to close APM port (%d)\n", rc);
+ }
- q6apm_graph_close(dai_data->graph[dai->id]);
- dai_data->is_port_started[dai->id] = false;
+ if (dai_data->graph[dai->id]) {
+ q6apm_graph_close(dai_data->graph[dai->id]);
+ dai_data->graph[dai->id] = NULL;
+ }
}
static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
@@ -162,8 +171,10 @@ static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct s
q6apm_graph_stop(dai_data->graph[dai->id]);
dai_data->is_port_started[dai->id] = false;
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
q6apm_graph_close(dai_data->graph[dai->id]);
+ dai_data->graph[dai->id] = NULL;
+ }
}
/**
@@ -182,26 +193,31 @@ static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct s
cfg->direction = substream->stream;
rc = q6apm_graph_media_format_pcm(dai_data->graph[dai->id], cfg);
-
if (rc) {
dev_err(dai->dev, "Failed to set media format %d\n", rc);
- return rc;
+ goto err;
}
rc = q6apm_graph_prepare(dai_data->graph[dai->id]);
if (rc) {
dev_err(dai->dev, "Failed to prepare Graph %d\n", rc);
- return rc;
+ goto err;
}
rc = q6apm_graph_start(dai_data->graph[dai->id]);
if (rc < 0) {
- dev_err(dai->dev, "fail to start APM port %x\n", dai->id);
- return rc;
+ dev_err(dai->dev, "Failed to start APM port %d\n", dai->id);
+ goto err;
}
dai_data->is_port_started[dai->id] = true;
return 0;
+err:
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ q6apm_graph_close(dai_data->graph[dai->id]);
+ dai_data->graph[dai->id] = NULL;
+ }
+ return rc;
}
static int q6apm_lpass_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
@@ -246,6 +262,7 @@ static const struct snd_soc_dai_ops q6i2s_ops = {
.shutdown = q6apm_lpass_dai_shutdown,
.set_channel_map = q6dma_set_channel_map,
.hw_params = q6dma_hw_params,
+ .set_fmt = q6i2s_set_fmt,
};
static const struct snd_soc_dai_ops q6hdmi_ops = {