aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/qcom
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/qcom')
-rw-r--r--sound/soc/qcom/Kconfig4
-rw-r--r--sound/soc/qcom/apq8016_sbc.c21
-rw-r--r--sound/soc/qcom/apq8096.c71
-rw-r--r--sound/soc/qcom/common.c10
-rw-r--r--sound/soc/qcom/qdsp6/q6asm-dai.c17
-rw-r--r--sound/soc/qcom/sdm845.c33
6 files changed, 133 insertions, 23 deletions
diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig
index 804ae0d93058..75ceb04d8bf0 100644
--- a/sound/soc/qcom/Kconfig
+++ b/sound/soc/qcom/Kconfig
@@ -98,10 +98,12 @@ config SND_SOC_MSM8996
config SND_SOC_SDM845
tristate "SoC Machine driver for SDM845 boards"
- depends on QCOM_APR
+ depends on QCOM_APR && MFD_CROS_EC
select SND_SOC_QDSP6
select SND_SOC_QCOM_COMMON
select SND_SOC_RT5663
+ select SND_SOC_MAX98927
+ select SND_SOC_CROS_EC_CODEC
help
To add support for audio on Qualcomm Technologies Inc.
SDM845 SoC-based systems.
diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c
index 1dd23bba1bed..4b559932adc3 100644
--- a/sound/soc/qcom/apq8016_sbc.c
+++ b/sound/soc/qcom/apq8016_sbc.c
@@ -164,41 +164,52 @@ static struct apq8016_sbc_data *apq8016_sbc_parse_of(struct snd_soc_card *card)
if (!cpu || !codec) {
dev_err(dev, "Can't find cpu/codec DT node\n");
- return ERR_PTR(-EINVAL);
+ ret = -EINVAL;
+ goto error;
}
link->cpu_of_node = of_parse_phandle(cpu, "sound-dai", 0);
if (!link->cpu_of_node) {
dev_err(card->dev, "error getting cpu phandle\n");
- return ERR_PTR(-EINVAL);
+ ret = -EINVAL;
+ goto error;
}
ret = snd_soc_of_get_dai_name(cpu, &link->cpu_dai_name);
if (ret) {
dev_err(card->dev, "error getting cpu dai name\n");
- return ERR_PTR(ret);
+ goto error;
}
ret = snd_soc_of_get_dai_link_codecs(dev, codec, link);
if (ret < 0) {
dev_err(card->dev, "error getting codec dai name\n");
- return ERR_PTR(ret);
+ goto error;
}
link->platform_of_node = link->cpu_of_node;
ret = of_property_read_string(np, "link-name", &link->name);
if (ret) {
dev_err(card->dev, "error getting codec dai_link name\n");
- return ERR_PTR(ret);
+ goto error;
}
link->stream_name = link->name;
link->init = apq8016_sbc_dai_init;
link++;
+
+ of_node_put(cpu);
+ of_node_put(codec);
}
return data;
+
+ error:
+ of_node_put(np);
+ of_node_put(cpu);
+ of_node_put(codec);
+ return ERR_PTR(ret);
}
static const struct snd_soc_dapm_widget apq8016_sbc_dapm_widgets[] = {
diff --git a/sound/soc/qcom/apq8096.c b/sound/soc/qcom/apq8096.c
index fb45f396ab4a..94363fd6846a 100644
--- a/sound/soc/qcom/apq8096.c
+++ b/sound/soc/qcom/apq8096.c
@@ -9,6 +9,10 @@
#include <sound/pcm.h>
#include "common.h"
+#define SLIM_MAX_TX_PORTS 16
+#define SLIM_MAX_RX_PORTS 16
+#define WCD9335_DEFAULT_MCLK_RATE 9600000
+
static int apq8096_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
@@ -23,14 +27,79 @@ static int apq8096_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
return 0;
}
+static int msm_snd_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ u32 rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
+ u32 rx_ch_cnt = 0, tx_ch_cnt = 0;
+ int ret = 0;
+
+ ret = snd_soc_dai_get_channel_map(codec_dai,
+ &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
+ if (ret != 0 && ret != -ENOTSUPP) {
+ pr_err("failed to get codec chan map, err:%d\n", ret);
+ goto end;
+ } else if (ret == -ENOTSUPP) {
+ return 0;
+ }
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ ret = snd_soc_dai_set_channel_map(cpu_dai, 0, NULL,
+ rx_ch_cnt, rx_ch);
+ else
+ ret = snd_soc_dai_set_channel_map(cpu_dai, tx_ch_cnt, tx_ch,
+ 0, NULL);
+ if (ret != 0 && ret != -ENOTSUPP)
+ pr_err("Failed to set cpu chan map, err:%d\n", ret);
+ else if (ret == -ENOTSUPP)
+ ret = 0;
+end:
+ return ret;
+}
+
+static struct snd_soc_ops apq8096_ops = {
+ .hw_params = msm_snd_hw_params,
+};
+
+static int apq8096_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+
+ /*
+ * Codec SLIMBUS configuration
+ * RX1, RX2, RX3, RX4, RX5, RX6, RX7, RX8, RX9, RX10, RX11, RX12, RX13
+ * TX1, TX2, TX3, TX4, TX5, TX6, TX7, TX8, TX9, TX10, TX11, TX12, TX13
+ * TX14, TX15, TX16
+ */
+ unsigned int rx_ch[SLIM_MAX_RX_PORTS] = {144, 145, 146, 147, 148, 149,
+ 150, 151, 152, 153, 154, 155, 156};
+ unsigned int tx_ch[SLIM_MAX_TX_PORTS] = {128, 129, 130, 131, 132, 133,
+ 134, 135, 136, 137, 138, 139,
+ 140, 141, 142, 143};
+
+ snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch),
+ tx_ch, ARRAY_SIZE(rx_ch), rx_ch);
+
+ snd_soc_dai_set_sysclk(codec_dai, 0, WCD9335_DEFAULT_MCLK_RATE,
+ SNDRV_PCM_STREAM_PLAYBACK);
+
+ return 0;
+}
+
static void apq8096_add_be_ops(struct snd_soc_card *card)
{
struct snd_soc_dai_link *link;
int i;
for_each_card_prelinks(card, i, link) {
- if (link->no_pcm == 1)
+ if (link->no_pcm == 1) {
link->be_hw_params_fixup = apq8096_be_hw_params_fixup;
+ link->init = apq8096_init;
+ link->ops = &apq8096_ops;
+ }
}
}
diff --git a/sound/soc/qcom/common.c b/sound/soc/qcom/common.c
index 4715527054e5..5661025e8cec 100644
--- a/sound/soc/qcom/common.c
+++ b/sound/soc/qcom/common.c
@@ -42,6 +42,9 @@ int qcom_snd_parse_of(struct snd_soc_card *card)
link = card->dai_link;
for_each_child_of_node(dev->of_node, np) {
cpu = of_get_child_by_name(np, "cpu");
+ platform = of_get_child_by_name(np, "platform");
+ codec = of_get_child_by_name(np, "codec");
+
if (!cpu) {
dev_err(dev, "Can't find cpu DT node\n");
ret = -EINVAL;
@@ -63,8 +66,6 @@ int qcom_snd_parse_of(struct snd_soc_card *card)
goto err;
}
- platform = of_get_child_by_name(np, "platform");
- codec = of_get_child_by_name(np, "codec");
if (codec && platform) {
link->platform_of_node = of_parse_phandle(platform,
"sound-dai",
@@ -100,10 +101,15 @@ int qcom_snd_parse_of(struct snd_soc_card *card)
link->dpcm_capture = 1;
link->stream_name = link->name;
link++;
+
+ of_node_put(cpu);
+ of_node_put(codec);
+ of_node_put(platform);
}
return 0;
err:
+ of_node_put(np);
of_node_put(cpu);
of_node_put(codec);
of_node_put(platform);
diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c
index 5b986b74dd36..548eb4fa2da6 100644
--- a/sound/soc/qcom/qdsp6/q6asm-dai.c
+++ b/sound/soc/qcom/qdsp6/q6asm-dai.c
@@ -570,10 +570,10 @@ static int q6asm_dai_compr_open(struct snd_compr_stream *stream)
prtd->audio_client = q6asm_audio_client_alloc(dev,
(q6asm_cb)compress_event_handler,
prtd, stream_id, LEGACY_PCM_MODE);
- if (!prtd->audio_client) {
+ if (IS_ERR(prtd->audio_client)) {
dev_err(dev, "Could not allocate memory\n");
- kfree(prtd);
- return -ENOMEM;
+ ret = PTR_ERR(prtd->audio_client);
+ goto free_prtd;
}
size = COMPR_PLAYBACK_MAX_FRAGMENT_SIZE *
@@ -582,7 +582,7 @@ static int q6asm_dai_compr_open(struct snd_compr_stream *stream)
&prtd->dma_buffer);
if (ret) {
dev_err(dev, "Cannot allocate buffer(s)\n");
- return ret;
+ goto free_client;
}
if (pdata->sid < 0)
@@ -595,6 +595,13 @@ static int q6asm_dai_compr_open(struct snd_compr_stream *stream)
runtime->private_data = prtd;
return 0;
+
+free_client:
+ q6asm_audio_client_free(prtd->audio_client);
+free_prtd:
+ kfree(prtd);
+
+ return ret;
}
static int q6asm_dai_compr_free(struct snd_compr_stream *stream)
@@ -874,7 +881,7 @@ static int of_q6asm_parse_dai_data(struct device *dev,
for_each_child_of_node(dev->of_node, node) {
ret = of_property_read_u32(node, "reg", &id);
- if (ret || id > MAX_SESSIONS || id < 0) {
+ if (ret || id >= MAX_SESSIONS || id < 0) {
dev_err(dev, "valid dai id not found:%d\n", ret);
continue;
}
diff --git a/sound/soc/qcom/sdm845.c b/sound/soc/qcom/sdm845.c
index 1db8ef668223..882f52ed8231 100644
--- a/sound/soc/qcom/sdm845.c
+++ b/sound/soc/qcom/sdm845.c
@@ -158,17 +158,24 @@ static int sdm845_snd_hw_params(struct snd_pcm_substream *substream,
return ret;
}
+static void sdm845_jack_free(struct snd_jack *jack)
+{
+ struct snd_soc_component *component = jack->private_data;
+
+ snd_soc_component_set_jack(component, NULL, NULL);
+}
+
static int sdm845_dai_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_component *component;
- struct snd_soc_dai_link *dai_link = rtd->dai_link;
struct snd_soc_card *card = rtd->card;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct sdm845_snd_data *pdata = snd_soc_card_get_drvdata(card);
- int i, rval;
+ struct snd_jack *jack;
+ int rval;
if (!pdata->jack_setup) {
- struct snd_jack *jack;
-
rval = snd_soc_card_jack_new(card, "Headset Jack",
SND_JACK_HEADSET |
SND_JACK_HEADPHONE |
@@ -190,16 +197,22 @@ static int sdm845_dai_init(struct snd_soc_pcm_runtime *rtd)
pdata->jack_setup = true;
}
- for (i = 0 ; i < dai_link->num_codecs; i++) {
- struct snd_soc_dai *dai = rtd->codec_dais[i];
+ switch (cpu_dai->id) {
+ case PRIMARY_MI2S_RX:
+ jack = pdata->jack.jack;
+ component = codec_dai->component;
- component = dai->component;
- rval = snd_soc_component_set_jack(
- component, &pdata->jack, NULL);
+ jack->private_data = component;
+ jack->private_free = sdm845_jack_free;
+ rval = snd_soc_component_set_jack(component,
+ &pdata->jack, NULL);
if (rval != 0 && rval != -ENOTSUPP) {
dev_warn(card->dev, "Failed to set jack: %d\n", rval);
return rval;
}
+ break;
+ default:
+ break;
}
return 0;
@@ -235,12 +248,14 @@ static int sdm845_snd_startup(struct snd_pcm_substream *substream)
break;
case SECONDARY_MI2S_TX:
+ codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S;
if (++(data->sec_mi2s_clk_count) == 1) {
snd_soc_dai_set_sysclk(cpu_dai,
Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT,
MI2S_BCLK_RATE, SNDRV_PCM_STREAM_CAPTURE);
}
snd_soc_dai_set_fmt(cpu_dai, fmt);
+ snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt);
break;
case QUATERNARY_TDM_RX_0: