mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 17:25:35 +03:00
ASoC: tegra-alt: fix dspk driver issues
- Make the primary dais to be in sync with other ahub drivers by renaming it to DAP/CIF, this would remove the dependency on the link name dspk-playback-l/r for dspk and can use any generic name. - The second dais which was used for dual mono codec path can avoid using the dai_ops callback, as there is no need of calling hw_params, set_bclk etc.. multiple times per pcm_open. Only the primary dai with name DAP will be used for callbacks. - Support S32_LE format support for the dais. - Change SND_SOC_DAPM_AIF_IN to SND_SOC_DAPM_AIF_OUT as the dspk is audio output interface. - Add proper DAPM route entry to machine driver and remove any check with dspk-playback-l to make it more generic usage. - Cleanup aud_mclk parent configuration Bug 200525217 Change-Id: I3a718f72ea0b442a7cf1716540e79d69a05a220a Signed-off-by: Mohan Kumar <mkumard@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/2133518 (cherry picked from commit a3233ef7bc78953a264c2729ace9ea0a0da59814) Reviewed-on: https://git-master.nvidia.com/r/2145942 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Sameer Pujar <spujar@nvidia.com> GVS: Gerrit_Virtual_Submit Reviewed-by: Dara Ramesh <dramesh@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
committed by
Sameer Pujar
parent
bb5f984534
commit
f1e0181664
@@ -54,7 +54,6 @@ struct tegra_asoc_audio_clock_info {
|
|||||||
struct clk *clk_cdev1;
|
struct clk *clk_cdev1;
|
||||||
struct clk *clk_ahub;
|
struct clk *clk_ahub;
|
||||||
struct reset_control *clk_cdev1_rst;
|
struct reset_control *clk_cdev1_rst;
|
||||||
struct clk *clk_m;
|
|
||||||
struct clk *clk_pll_p_out1;
|
struct clk *clk_pll_p_out1;
|
||||||
int set_mclk;
|
int set_mclk;
|
||||||
int lock_count;
|
int lock_count;
|
||||||
@@ -76,9 +75,6 @@ void tegra_alt_asoc_utils_lock_clk_rate(
|
|||||||
int lock);
|
int lock);
|
||||||
int tegra_alt_asoc_utils_init(struct tegra_asoc_audio_clock_info *data,
|
int tegra_alt_asoc_utils_init(struct tegra_asoc_audio_clock_info *data,
|
||||||
struct device *dev, struct snd_soc_card *card);
|
struct device *dev, struct snd_soc_card *card);
|
||||||
|
|
||||||
int tegra_alt_asoc_utils_set_extern_parent(
|
|
||||||
struct tegra_asoc_audio_clock_info *data, const char *parent);
|
|
||||||
int tegra_alt_asoc_utils_clk_enable(struct tegra_asoc_audio_clock_info *data);
|
int tegra_alt_asoc_utils_clk_enable(struct tegra_asoc_audio_clock_info *data);
|
||||||
int tegra_alt_asoc_utils_clk_disable(struct tegra_asoc_audio_clock_info *data);
|
int tegra_alt_asoc_utils_clk_disable(struct tegra_asoc_audio_clock_info *data);
|
||||||
int tegra_alt_asoc_utils_register_ctls(struct tegra_asoc_audio_clock_info *data);
|
int tegra_alt_asoc_utils_register_ctls(struct tegra_asoc_audio_clock_info *data);
|
||||||
|
|||||||
@@ -245,6 +245,7 @@ static const struct snd_soc_dapm_widget tegra_machine_dapm_widgets[] = {
|
|||||||
|
|
||||||
SND_SOC_DAPM_SPK("d1 Headphone", NULL),
|
SND_SOC_DAPM_SPK("d1 Headphone", NULL),
|
||||||
SND_SOC_DAPM_SPK("d2 Headphone", NULL),
|
SND_SOC_DAPM_SPK("d2 Headphone", NULL),
|
||||||
|
SND_SOC_DAPM_SPK("d3 Headphone", NULL),
|
||||||
|
|
||||||
SND_SOC_DAPM_HP("w Headphone", NULL),
|
SND_SOC_DAPM_HP("w Headphone", NULL),
|
||||||
SND_SOC_DAPM_HP("x Headphone", NULL),
|
SND_SOC_DAPM_HP("x Headphone", NULL),
|
||||||
@@ -730,22 +731,6 @@ static int tegra_machine_suspend_pre(struct snd_soc_card *card)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tegra_machine_dspk_init(struct snd_soc_pcm_runtime *rtd)
|
|
||||||
{
|
|
||||||
struct snd_soc_card *card = rtd->card;
|
|
||||||
struct snd_soc_dapm_context *dapm = &card->dapm;
|
|
||||||
struct tegra_machine *machine = snd_soc_card_get_drvdata(card);
|
|
||||||
int err;
|
|
||||||
|
|
||||||
err = tegra_alt_asoc_utils_set_extern_parent(&machine->audio_clock,
|
|
||||||
"pll_a_out0");
|
|
||||||
if (err < 0)
|
|
||||||
dev_err(card->dev, "Failed to set extern clk parent\n");
|
|
||||||
|
|
||||||
snd_soc_dapm_sync(dapm);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_SND_SOC_TEGRA210_ADSP_ALT)
|
#if IS_ENABLED(CONFIG_SND_SOC_TEGRA210_ADSP_ALT)
|
||||||
static int tegra_machine_compr_startup(struct snd_compr_stream *cstream)
|
static int tegra_machine_compr_startup(struct snd_compr_stream *cstream)
|
||||||
{
|
{
|
||||||
@@ -824,17 +809,9 @@ static int tegra_machine_fepi_init(struct snd_soc_pcm_runtime *rtd)
|
|||||||
static int tegra_machine_rt565x_init(struct snd_soc_pcm_runtime *rtd)
|
static int tegra_machine_rt565x_init(struct snd_soc_pcm_runtime *rtd)
|
||||||
{
|
{
|
||||||
struct snd_soc_card *card = rtd->card;
|
struct snd_soc_card *card = rtd->card;
|
||||||
struct tegra_machine *machine = snd_soc_card_get_drvdata(card);
|
|
||||||
struct snd_soc_jack *jack;
|
struct snd_soc_jack *jack;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = tegra_alt_asoc_utils_set_extern_parent(&machine->audio_clock,
|
|
||||||
"pll_a_out0");
|
|
||||||
if (err < 0) {
|
|
||||||
dev_err(card->dev, "Failed to set extern clk parent\n");
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
jack = devm_kzalloc(card->dev, sizeof(struct snd_soc_jack), GFP_KERNEL);
|
jack = devm_kzalloc(card->dev, sizeof(struct snd_soc_jack), GFP_KERNEL);
|
||||||
if (!jack)
|
if (!jack)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@@ -923,14 +900,6 @@ static void dai_link_setup(struct platform_device *pdev)
|
|||||||
tegra_machine_codec_links[i].init =
|
tegra_machine_codec_links[i].init =
|
||||||
tegra_machine_rt565x_init;
|
tegra_machine_rt565x_init;
|
||||||
}
|
}
|
||||||
} else if (strstr(tegra_machine_codec_links[i].name,
|
|
||||||
"dspk-playback-r")) {
|
|
||||||
tegra_machine_codec_links[i].init =
|
|
||||||
tegra_machine_dspk_init;
|
|
||||||
} else if (strstr(tegra_machine_codec_links[i].name,
|
|
||||||
"dspk-playback-l")) {
|
|
||||||
tegra_machine_codec_links[i].init =
|
|
||||||
tegra_machine_dspk_init;
|
|
||||||
} else if (strstr(tegra_machine_codec_links[i].name,
|
} else if (strstr(tegra_machine_codec_links[i].name,
|
||||||
"fe-pi-audio-z-v2")) {
|
"fe-pi-audio-z-v2")) {
|
||||||
tegra_machine_codec_links[i].init =
|
tegra_machine_codec_links[i].init =
|
||||||
|
|||||||
@@ -271,70 +271,75 @@ static struct snd_soc_dai_ops tegra186_dspk_dai_ops = {
|
|||||||
.shutdown = tegra186_dspk_shutdown,
|
.shutdown = tegra186_dspk_shutdown,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct snd_soc_dai_driver tegra186_dspk_dais[] = {
|
static struct snd_soc_dai_ops tegra186_dspk_dai_ops2 = {
|
||||||
/* for left channel audio */
|
.set_bclk_ratio = tegra186_dspk_set_dai_bclk_ratio,
|
||||||
{
|
};
|
||||||
.name = "DAP Left",
|
|
||||||
.capture = {
|
|
||||||
.stream_name = "DSPK Left Transmit",
|
|
||||||
.channels_min = 1,
|
|
||||||
.channels_max = 2,
|
|
||||||
.rates = SNDRV_PCM_RATE_8000_48000,
|
|
||||||
.formats = SNDRV_PCM_FMTBIT_S16_LE,
|
|
||||||
},
|
|
||||||
.ops = &tegra186_dspk_dai_ops,
|
|
||||||
.symmetric_rates = 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = "CIF Right",
|
|
||||||
.playback = {
|
|
||||||
.stream_name = "DSPK Receive Right",
|
|
||||||
.channels_min = 1,
|
|
||||||
.channels_max = 2,
|
|
||||||
.rates = SNDRV_PCM_RATE_8000_48000,
|
|
||||||
.formats = SNDRV_PCM_FMTBIT_S16_LE,
|
|
||||||
},
|
|
||||||
.ops = &tegra186_dspk_dai_ops,
|
|
||||||
.symmetric_rates = 1,
|
|
||||||
},
|
|
||||||
|
|
||||||
/* for right channel audio */
|
static struct snd_soc_dai_driver tegra186_dspk_dais[] = {
|
||||||
{
|
{
|
||||||
.name = "DAP Right",
|
.name = "DAP",
|
||||||
.capture = {
|
.capture = {
|
||||||
.stream_name = "DSPK Right Transmit",
|
.stream_name = "DAP Transmit",
|
||||||
.channels_min = 1,
|
.channels_min = 1,
|
||||||
.channels_max = 2,
|
.channels_max = 2,
|
||||||
.rates = SNDRV_PCM_RATE_8000_48000,
|
.rates = SNDRV_PCM_RATE_8000_48000,
|
||||||
.formats = SNDRV_PCM_FMTBIT_S16_LE,
|
.formats = SNDRV_PCM_FMTBIT_S16_LE |
|
||||||
|
SNDRV_PCM_FMTBIT_S32_LE,
|
||||||
},
|
},
|
||||||
.ops = &tegra186_dspk_dai_ops,
|
.ops = &tegra186_dspk_dai_ops,
|
||||||
.symmetric_rates = 1,
|
.symmetric_rates = 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "CIF Left",
|
.name = "CIF",
|
||||||
.playback = {
|
.playback = {
|
||||||
.stream_name = "DSPK Receive Left",
|
.stream_name = "CIF Receive",
|
||||||
.channels_min = 1,
|
.channels_min = 1,
|
||||||
.channels_max = 2,
|
.channels_max = 2,
|
||||||
.rates = SNDRV_PCM_RATE_8000_48000,
|
.rates = SNDRV_PCM_RATE_8000_48000,
|
||||||
.formats = SNDRV_PCM_FMTBIT_S16_LE,
|
.formats = SNDRV_PCM_FMTBIT_S16_LE |
|
||||||
|
SNDRV_PCM_FMTBIT_S32_LE,
|
||||||
},
|
},
|
||||||
.ops = &tegra186_dspk_dai_ops,
|
},
|
||||||
|
/* The second DAI is used when the output of the DSPK is connected
|
||||||
|
* to two mono codecs. When the output of the DSPK is connected to
|
||||||
|
* a single stereo codec, then only the first DAI should be used.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
.name = "DAP2",
|
||||||
|
.capture = {
|
||||||
|
.stream_name = "DAP2 Transmit",
|
||||||
|
.channels_min = 1,
|
||||||
|
.channels_max = 2,
|
||||||
|
.rates = SNDRV_PCM_RATE_8000_48000,
|
||||||
|
.formats = SNDRV_PCM_FMTBIT_S16_LE |
|
||||||
|
SNDRV_PCM_FMTBIT_S32_LE,
|
||||||
|
},
|
||||||
|
.ops = &tegra186_dspk_dai_ops2,
|
||||||
.symmetric_rates = 1,
|
.symmetric_rates = 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "CIF2",
|
||||||
|
.playback = {
|
||||||
|
.stream_name = "CIF2 Receive",
|
||||||
|
.channels_min = 1,
|
||||||
|
.channels_max = 2,
|
||||||
|
.rates = SNDRV_PCM_RATE_8000_48000,
|
||||||
|
.formats = SNDRV_PCM_FMTBIT_S16_LE |
|
||||||
|
SNDRV_PCM_FMTBIT_S32_LE,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct snd_soc_dapm_widget tegra186_dspk_widgets[] = {
|
static const struct snd_soc_dapm_widget tegra186_dspk_widgets[] = {
|
||||||
SND_SOC_DAPM_AIF_IN("DSPK TX1", NULL, 0, TEGRA186_DSPK_ENABLE, 0, 0),
|
SND_SOC_DAPM_AIF_OUT("DAP TX", NULL, 0, TEGRA186_DSPK_ENABLE, 0, 0),
|
||||||
SND_SOC_DAPM_AIF_IN("DSPK TX2", NULL, 0, TEGRA186_DSPK_ENABLE, 0, 0),
|
SND_SOC_DAPM_AIF_OUT("DAP2 TX", NULL, 0, 0, 0, 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct snd_soc_dapm_route tegra186_dspk_routes[] = {
|
static const struct snd_soc_dapm_route tegra186_dspk_routes[] = {
|
||||||
{ "DSPK TX1", NULL, "DSPK Receive Left" },
|
{ "DAP TX", NULL, "CIF Receive" },
|
||||||
{ "DSPK Left Transmit", NULL, "DSPK TX1" },
|
{ "DAP Transmit", NULL, "DAP TX" },
|
||||||
{ "DSPK TX2", NULL, "DSPK Receive Right" },
|
{ "DAP2 TX", NULL, "CIF2 Receive" },
|
||||||
{ "DSPK Right Transmit", NULL, "DSPK TX2" },
|
{ "DAP2 Transmit", NULL, "DAP2 TX" },
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char * const tegra186_dspk_osr_text[] = {
|
static const char * const tegra186_dspk_osr_text[] = {
|
||||||
|
|||||||
@@ -3221,9 +3221,7 @@ struct snd_soc_dai_link *tegra_machine_new_codec_links(
|
|||||||
/* special case to handle specifically for dspk, connected to
|
/* special case to handle specifically for dspk, connected to
|
||||||
two mono amplifiers */
|
two mono amplifiers */
|
||||||
if (!strcmp(tegra_codec_links[i].name, "dspk-playback-r"))
|
if (!strcmp(tegra_codec_links[i].name, "dspk-playback-r"))
|
||||||
tegra_codec_links[i].cpu_dai_name = "DAP Right";
|
tegra_codec_links[i].cpu_dai_name = "DAP2";
|
||||||
else if (!strcmp(tegra_codec_links[i].name, "dspk-playback-l"))
|
|
||||||
tegra_codec_links[i].cpu_dai_name = "DAP Left";
|
|
||||||
else
|
else
|
||||||
tegra_codec_links[i].cpu_dai_name = "DAP";
|
tegra_codec_links[i].cpu_dai_name = "DAP";
|
||||||
|
|
||||||
@@ -3289,9 +3287,7 @@ struct snd_soc_dai_link *tegra_machine_new_codec_links(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(tegra_codec_links[i].name, "dspk-playback-r"))
|
if (!strcmp(tegra_codec_links[i].name, "dspk-playback-r"))
|
||||||
tegra_codec_links[j].codec_dai_name = "CIF Right";
|
tegra_codec_links[j].codec_dai_name = "CIF2";
|
||||||
else if (!strcmp(tegra_codec_links[i].name, "dspk-playback-l"))
|
|
||||||
tegra_codec_links[j].codec_dai_name = "CIF Left";
|
|
||||||
else
|
else
|
||||||
tegra_codec_links[j].codec_dai_name = "CIF";
|
tegra_codec_links[j].codec_dai_name = "CIF";
|
||||||
|
|
||||||
|
|||||||
@@ -187,6 +187,8 @@ EXPORT_SYMBOL_GPL(tegra_alt_asoc_utils_clk_disable);
|
|||||||
int tegra_alt_asoc_utils_init(struct tegra_asoc_audio_clock_info *data,
|
int tegra_alt_asoc_utils_init(struct tegra_asoc_audio_clock_info *data,
|
||||||
struct device *dev, struct snd_soc_card *card)
|
struct device *dev, struct snd_soc_card *card)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
data->dev = dev;
|
data->dev = dev;
|
||||||
data->card = card;
|
data->card = card;
|
||||||
|
|
||||||
@@ -201,12 +203,6 @@ int tegra_alt_asoc_utils_init(struct tegra_asoc_audio_clock_info *data,
|
|||||||
/* DT boot, but unknown SoC */
|
/* DT boot, but unknown SoC */
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
data->clk_m = devm_clk_get(dev, "clk_m");
|
|
||||||
if (IS_ERR(data->clk_m)) {
|
|
||||||
dev_err(data->dev, "Can't retrieve clk clk_m\n");
|
|
||||||
return PTR_ERR(data->clk_m);
|
|
||||||
}
|
|
||||||
|
|
||||||
data->clk_pll_a = devm_clk_get(dev, "pll_a");
|
data->clk_pll_a = devm_clk_get(dev, "pll_a");
|
||||||
if (IS_ERR(data->clk_pll_a)) {
|
if (IS_ERR(data->clk_pll_a)) {
|
||||||
dev_err(data->dev, "Can't retrieve clk pll_a\n");
|
dev_err(data->dev, "Can't retrieve clk pll_a\n");
|
||||||
@@ -231,7 +227,7 @@ int tegra_alt_asoc_utils_init(struct tegra_asoc_audio_clock_info *data,
|
|||||||
*/
|
*/
|
||||||
data->clk_mclk_parent = devm_clk_get(dev, "mclk_parent");
|
data->clk_mclk_parent = devm_clk_get(dev, "mclk_parent");
|
||||||
if (IS_ERR(data->clk_mclk_parent))
|
if (IS_ERR(data->clk_mclk_parent))
|
||||||
dev_dbg(data->dev, "Can't retrieve mclk parent clk\n");
|
data->clk_mclk_parent = data->clk_pll_a_out0;
|
||||||
|
|
||||||
if (data->soc > TEGRA_ASOC_UTILS_SOC_TEGRA210) {
|
if (data->soc > TEGRA_ASOC_UTILS_SOC_TEGRA210) {
|
||||||
data->clk_ahub = devm_clk_get(dev, "ahub");
|
data->clk_ahub = devm_clk_get(dev, "ahub");
|
||||||
@@ -252,39 +248,16 @@ int tegra_alt_asoc_utils_init(struct tegra_asoc_audio_clock_info *data,
|
|||||||
reset_control_reset(data->clk_cdev1_rst);
|
reset_control_reset(data->clk_cdev1_rst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = clk_set_parent(data->clk_cdev1, data->clk_mclk_parent);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(card->dev, "Failed to set extern clk parent\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(tegra_alt_asoc_utils_init);
|
EXPORT_SYMBOL_GPL(tegra_alt_asoc_utils_init);
|
||||||
|
|
||||||
int tegra_alt_asoc_utils_set_extern_parent(
|
|
||||||
struct tegra_asoc_audio_clock_info *data, const char *parent)
|
|
||||||
{
|
|
||||||
unsigned long rate;
|
|
||||||
int err = 0;
|
|
||||||
|
|
||||||
rate = clk_get_rate(data->clk_cdev1);
|
|
||||||
if (!IS_ERR(data->clk_mclk_parent))
|
|
||||||
err = clk_set_parent(data->clk_cdev1, data->clk_mclk_parent);
|
|
||||||
else if (!strcmp(parent, "clk_m"))
|
|
||||||
err = clk_set_parent(data->clk_cdev1, data->clk_m);
|
|
||||||
else if (!strcmp(parent, "pll_a_out0"))
|
|
||||||
err = clk_set_parent(data->clk_cdev1, data->clk_pll_a_out0);
|
|
||||||
|
|
||||||
if (err) {
|
|
||||||
dev_err(data->dev, "Can't set aud mclk clock parent");
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = clk_set_rate(data->clk_cdev1, rate);
|
|
||||||
if (err) {
|
|
||||||
dev_err(data->dev, "Can't set clk rate");
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(tegra_alt_asoc_utils_set_extern_parent);
|
|
||||||
|
|
||||||
MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
|
MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
|
||||||
MODULE_DESCRIPTION("Tegra ASoC utility code");
|
MODULE_DESCRIPTION("Tegra ASoC utility code");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|||||||
Reference in New Issue
Block a user