|
@@ -20,16 +20,12 @@
|
|
|
#include <linux/of.h>
|
|
|
#include <linux/of_address.h>
|
|
|
#include <linux/pm_runtime.h>
|
|
|
-#include <sound/soc.h>
|
|
|
|
|
|
#include "mt2701-afe-common.h"
|
|
|
-
|
|
|
#include "mt2701-afe-clock-ctrl.h"
|
|
|
#include "../common/mtk-afe-platform-driver.h"
|
|
|
#include "../common/mtk-afe-fe-dai.h"
|
|
|
|
|
|
-#define AFE_IRQ_STATUS_BITS 0xff
|
|
|
-
|
|
|
static const struct snd_pcm_hardware mt2701_afe_hardware = {
|
|
|
.info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED
|
|
|
| SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID,
|
|
@@ -107,21 +103,16 @@ static int mt2701_afe_i2s_startup(struct snd_pcm_substream *substream,
|
|
|
|
|
|
static int mt2701_afe_i2s_path_shutdown(struct snd_pcm_substream *substream,
|
|
|
struct snd_soc_dai *dai,
|
|
|
+ int i2s_num,
|
|
|
int dir_invert)
|
|
|
{
|
|
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
|
|
struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
|
|
|
struct mt2701_afe_private *afe_priv = afe->platform_priv;
|
|
|
- int i2s_num = mt2701_dai_num_to_i2s(afe, dai->id);
|
|
|
- struct mt2701_i2s_path *i2s_path;
|
|
|
+ struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[i2s_num];
|
|
|
const struct mt2701_i2s_data *i2s_data;
|
|
|
int stream_dir = substream->stream;
|
|
|
|
|
|
- if (i2s_num < 0)
|
|
|
- return i2s_num;
|
|
|
-
|
|
|
- i2s_path = &afe_priv->i2s_path[i2s_num];
|
|
|
-
|
|
|
if (dir_invert) {
|
|
|
if (stream_dir == SNDRV_PCM_STREAM_PLAYBACK)
|
|
|
stream_dir = SNDRV_PCM_STREAM_CAPTURE;
|
|
@@ -167,11 +158,11 @@ static void mt2701_afe_i2s_shutdown(struct snd_pcm_substream *substream,
|
|
|
else
|
|
|
goto I2S_UNSTART;
|
|
|
|
|
|
- mt2701_afe_i2s_path_shutdown(substream, dai, 0);
|
|
|
+ mt2701_afe_i2s_path_shutdown(substream, dai, i2s_num, 0);
|
|
|
|
|
|
/* need to disable i2s-out path when disable i2s-in */
|
|
|
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
|
|
|
- mt2701_afe_i2s_path_shutdown(substream, dai, 1);
|
|
|
+ mt2701_afe_i2s_path_shutdown(substream, dai, i2s_num, 1);
|
|
|
|
|
|
I2S_UNSTART:
|
|
|
/* disable mclk */
|
|
@@ -180,24 +171,19 @@ I2S_UNSTART:
|
|
|
|
|
|
static int mt2701_i2s_path_prepare_enable(struct snd_pcm_substream *substream,
|
|
|
struct snd_soc_dai *dai,
|
|
|
+ int i2s_num,
|
|
|
int dir_invert)
|
|
|
{
|
|
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
|
|
struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
|
|
|
struct mt2701_afe_private *afe_priv = afe->platform_priv;
|
|
|
- int i2s_num = mt2701_dai_num_to_i2s(afe, dai->id);
|
|
|
- struct mt2701_i2s_path *i2s_path;
|
|
|
+ struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[i2s_num];
|
|
|
const struct mt2701_i2s_data *i2s_data;
|
|
|
struct snd_pcm_runtime * const runtime = substream->runtime;
|
|
|
int reg, fs, w_len = 1; /* now we support bck 64bits only */
|
|
|
int stream_dir = substream->stream;
|
|
|
unsigned int mask = 0, val = 0;
|
|
|
|
|
|
- if (i2s_num < 0)
|
|
|
- return i2s_num;
|
|
|
-
|
|
|
- i2s_path = &afe_priv->i2s_path[i2s_num];
|
|
|
-
|
|
|
if (dir_invert) {
|
|
|
if (stream_dir == SNDRV_PCM_STREAM_PLAYBACK)
|
|
|
stream_dir = SNDRV_PCM_STREAM_CAPTURE;
|
|
@@ -288,13 +274,13 @@ static int mt2701_afe_i2s_prepare(struct snd_pcm_substream *substream,
|
|
|
mt2701_mclk_configuration(afe, i2s_num, clk_domain, mclk_rate);
|
|
|
|
|
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
|
|
- mt2701_i2s_path_prepare_enable(substream, dai, 0);
|
|
|
+ mt2701_i2s_path_prepare_enable(substream, dai, i2s_num, 0);
|
|
|
} else {
|
|
|
/* need to enable i2s-out path when enable i2s-in */
|
|
|
/* prepare for another direction "out" */
|
|
|
- mt2701_i2s_path_prepare_enable(substream, dai, 1);
|
|
|
+ mt2701_i2s_path_prepare_enable(substream, dai, i2s_num, 1);
|
|
|
/* prepare for "in" */
|
|
|
- mt2701_i2s_path_prepare_enable(substream, dai, 0);
|
|
|
+ mt2701_i2s_path_prepare_enable(substream, dai, i2s_num, 0);
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
@@ -562,7 +548,6 @@ static const struct snd_soc_dai_ops mt2701_single_memif_dai_ops = {
|
|
|
.hw_free = mtk_afe_fe_hw_free,
|
|
|
.prepare = mtk_afe_fe_prepare,
|
|
|
.trigger = mtk_afe_fe_trigger,
|
|
|
-
|
|
|
};
|
|
|
|
|
|
static const struct snd_soc_dai_ops mt2701_dlm_memif_dai_ops = {
|
|
@@ -903,31 +888,6 @@ static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_i2s4[] = {
|
|
|
PWR2_TOP_CON, 19, 1, 0),
|
|
|
};
|
|
|
|
|
|
-static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_asrc0[] = {
|
|
|
- SOC_DAPM_SINGLE_AUTODISABLE("Asrc0 out Switch", AUDIO_TOP_CON4, 14, 1,
|
|
|
- 1),
|
|
|
-};
|
|
|
-
|
|
|
-static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_asrc1[] = {
|
|
|
- SOC_DAPM_SINGLE_AUTODISABLE("Asrc1 out Switch", AUDIO_TOP_CON4, 15, 1,
|
|
|
- 1),
|
|
|
-};
|
|
|
-
|
|
|
-static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_asrc2[] = {
|
|
|
- SOC_DAPM_SINGLE_AUTODISABLE("Asrc2 out Switch", PWR2_TOP_CON, 6, 1,
|
|
|
- 1),
|
|
|
-};
|
|
|
-
|
|
|
-static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_asrc3[] = {
|
|
|
- SOC_DAPM_SINGLE_AUTODISABLE("Asrc3 out Switch", PWR2_TOP_CON, 7, 1,
|
|
|
- 1),
|
|
|
-};
|
|
|
-
|
|
|
-static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_asrc4[] = {
|
|
|
- SOC_DAPM_SINGLE_AUTODISABLE("Asrc4 out Switch", PWR2_TOP_CON, 8, 1,
|
|
|
- 1),
|
|
|
-};
|
|
|
-
|
|
|
static const struct snd_soc_dapm_widget mt2701_afe_pcm_widgets[] = {
|
|
|
/* inter-connections */
|
|
|
SND_SOC_DAPM_MIXER("I00", SND_SOC_NOPM, 0, 0, NULL, 0),
|
|
@@ -987,19 +947,6 @@ static const struct snd_soc_dapm_widget mt2701_afe_pcm_widgets[] = {
|
|
|
SND_SOC_DAPM_MIXER("I18I19", SND_SOC_NOPM, 0, 0,
|
|
|
mt2701_afe_multi_ch_out_i2s3,
|
|
|
ARRAY_SIZE(mt2701_afe_multi_ch_out_i2s3)),
|
|
|
-
|
|
|
- SND_SOC_DAPM_MIXER("ASRC_O0", SND_SOC_NOPM, 0, 0,
|
|
|
- mt2701_afe_multi_ch_out_asrc0,
|
|
|
- ARRAY_SIZE(mt2701_afe_multi_ch_out_asrc0)),
|
|
|
- SND_SOC_DAPM_MIXER("ASRC_O1", SND_SOC_NOPM, 0, 0,
|
|
|
- mt2701_afe_multi_ch_out_asrc1,
|
|
|
- ARRAY_SIZE(mt2701_afe_multi_ch_out_asrc1)),
|
|
|
- SND_SOC_DAPM_MIXER("ASRC_O2", SND_SOC_NOPM, 0, 0,
|
|
|
- mt2701_afe_multi_ch_out_asrc2,
|
|
|
- ARRAY_SIZE(mt2701_afe_multi_ch_out_asrc2)),
|
|
|
- SND_SOC_DAPM_MIXER("ASRC_O3", SND_SOC_NOPM, 0, 0,
|
|
|
- mt2701_afe_multi_ch_out_asrc3,
|
|
|
- ARRAY_SIZE(mt2701_afe_multi_ch_out_asrc3)),
|
|
|
};
|
|
|
|
|
|
static const struct snd_soc_dapm_route mt2701_afe_pcm_routes[] = {
|
|
@@ -1009,7 +956,6 @@ static const struct snd_soc_dapm_route mt2701_afe_pcm_routes[] = {
|
|
|
|
|
|
{"I2S0 Playback", NULL, "O15"},
|
|
|
{"I2S0 Playback", NULL, "O16"},
|
|
|
-
|
|
|
{"I2S1 Playback", NULL, "O17"},
|
|
|
{"I2S1 Playback", NULL, "O18"},
|
|
|
{"I2S2 Playback", NULL, "O19"},
|
|
@@ -1026,7 +972,6 @@ static const struct snd_soc_dapm_route mt2701_afe_pcm_routes[] = {
|
|
|
|
|
|
{"I00", NULL, "I2S0 Capture"},
|
|
|
{"I01", NULL, "I2S0 Capture"},
|
|
|
-
|
|
|
{"I02", NULL, "I2S1 Capture"},
|
|
|
{"I03", NULL, "I2S1 Capture"},
|
|
|
/* I02,03 link to UL2, also need to open I2S0 */
|
|
@@ -1034,15 +979,10 @@ static const struct snd_soc_dapm_route mt2701_afe_pcm_routes[] = {
|
|
|
|
|
|
{"I26", NULL, "BT Capture"},
|
|
|
|
|
|
- {"ASRC_O0", "Asrc0 out Switch", "DLM"},
|
|
|
- {"ASRC_O1", "Asrc1 out Switch", "DLM"},
|
|
|
- {"ASRC_O2", "Asrc2 out Switch", "DLM"},
|
|
|
- {"ASRC_O3", "Asrc3 out Switch", "DLM"},
|
|
|
-
|
|
|
- {"I12I13", "Multich I2S0 Out Switch", "ASRC_O0"},
|
|
|
- {"I14I15", "Multich I2S1 Out Switch", "ASRC_O1"},
|
|
|
- {"I16I17", "Multich I2S2 Out Switch", "ASRC_O2"},
|
|
|
- {"I18I19", "Multich I2S3 Out Switch", "ASRC_O3"},
|
|
|
+ {"I12I13", "Multich I2S0 Out Switch", "DLM"},
|
|
|
+ {"I14I15", "Multich I2S1 Out Switch", "DLM"},
|
|
|
+ {"I16I17", "Multich I2S2 Out Switch", "DLM"},
|
|
|
+ {"I18I19", "Multich I2S3 Out Switch", "DLM"},
|
|
|
|
|
|
{ "I12", NULL, "I12I13" },
|
|
|
{ "I13", NULL, "I12I13" },
|
|
@@ -1067,7 +1007,6 @@ static const struct snd_soc_dapm_route mt2701_afe_pcm_routes[] = {
|
|
|
{ "O21", "I18 Switch", "I18" },
|
|
|
{ "O22", "I19 Switch", "I19" },
|
|
|
{ "O31", "I35 Switch", "I35" },
|
|
|
-
|
|
|
};
|
|
|
|
|
|
static const struct snd_soc_component_driver mt2701_afe_pcm_dai_component = {
|
|
@@ -1484,12 +1423,13 @@ static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev)
|
|
|
afe = devm_kzalloc(&pdev->dev, sizeof(*afe), GFP_KERNEL);
|
|
|
if (!afe)
|
|
|
return -ENOMEM;
|
|
|
+
|
|
|
afe->platform_priv = devm_kzalloc(&pdev->dev, sizeof(*afe_priv),
|
|
|
GFP_KERNEL);
|
|
|
if (!afe->platform_priv)
|
|
|
return -ENOMEM;
|
|
|
- afe_priv = afe->platform_priv;
|
|
|
|
|
|
+ afe_priv = afe->platform_priv;
|
|
|
afe->dev = &pdev->dev;
|
|
|
dev = afe->dev;
|
|
|
|
|
@@ -1524,7 +1464,6 @@ static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev)
|
|
|
afe->memif_size = MT2701_MEMIF_NUM;
|
|
|
afe->memif = devm_kcalloc(dev, afe->memif_size, sizeof(*afe->memif),
|
|
|
GFP_KERNEL);
|
|
|
-
|
|
|
if (!afe->memif)
|
|
|
return -ENOMEM;
|
|
|
|
|
@@ -1537,7 +1476,6 @@ static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev)
|
|
|
afe->irqs_size = MT2701_IRQ_ASYS_END;
|
|
|
afe->irqs = devm_kcalloc(dev, afe->irqs_size, sizeof(*afe->irqs),
|
|
|
GFP_KERNEL);
|
|
|
-
|
|
|
if (!afe->irqs)
|
|
|
return -ENOMEM;
|
|
|
|
|
@@ -1555,7 +1493,6 @@ static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev)
|
|
|
afe->mtk_afe_hardware = &mt2701_afe_hardware;
|
|
|
afe->memif_fs = mt2701_memif_fs;
|
|
|
afe->irq_fs = mt2701_irq_fs;
|
|
|
-
|
|
|
afe->reg_back_up_list = mt2701_afe_backup_list;
|
|
|
afe->reg_back_up_list_num = ARRAY_SIZE(mt2701_afe_backup_list);
|
|
|
afe->runtime_resume = mt2701_afe_runtime_resume;
|
|
@@ -1646,4 +1583,3 @@ module_platform_driver(mt2701_afe_pcm_driver);
|
|
|
MODULE_DESCRIPTION("Mediatek ALSA SoC AFE platform driver for 2701");
|
|
|
MODULE_AUTHOR("Garlic Tseng <garlic.tseng@mediatek.com>");
|
|
|
MODULE_LICENSE("GPL v2");
|
|
|
-
|