ASoC: tegra-alt: fix dynamic pinmux config

Currently dynamic pinmux configuration for I2S, DMIC, DSPK modules
are present in runtime_resume() function which can be called even
without any audio usecase active on these modules. So this destroy
the purpose of programming pinmux only during stream active state.

This change has moved the dynamic pinmux code in these drivers to
dai ops callback of startup and shutdown which will ensure the
pinmux config happens only during the stream playback/capture.

Bug 200497486

Change-Id: I3c4e8a96d0d066b38c9aba5ffe530db5cf5246fc
Signed-off-by: Mohan Kumar <mkumard@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/2029745
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Dara Ramesh <dramesh@nvidia.com>
Reviewed-by: Ravindra Lokhande <rlokhande@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Mohan Kumar
2019-02-28 10:04:20 +05:30
committed by Sameer Pujar
parent 9050c3e455
commit 4a6ee45df7
4 changed files with 169 additions and 96 deletions

View File

@@ -1,7 +1,7 @@
/* /*
* tegra210_i2s_alt.h - Definitions for Tegra210 I2S driver * tegra210_i2s_alt.h - Definitions for Tegra210 I2S driver
* *
* Copyright (c) 2014-2018 NVIDIA CORPORATION. All rights reserved. * Copyright (c) 2014-2019 NVIDIA CORPORATION. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -232,7 +232,7 @@ struct tegra210_i2s {
unsigned int fsync_width; unsigned int fsync_width;
unsigned int tx_mask; unsigned int tx_mask;
unsigned int rx_mask; unsigned int rx_mask;
unsigned int loopback; bool loopback;
unsigned int format; unsigned int format;
bool enable_cya; bool enable_cya;
unsigned int rx_fifo_th; /* should be programmed interms of frames */ unsigned int rx_fifo_th; /* should be programmed interms of frames */

View File

@@ -1,7 +1,7 @@
/* /*
* tegra186_dspk_alt.c - Tegra186 DSPK driver * tegra186_dspk_alt.c - Tegra186 DSPK driver
* *
* Copyright (c) 2015-2018 NVIDIA CORPORATION. All rights reserved. * Copyright (c) 2015-2019 NVIDIA CORPORATION. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -94,21 +94,12 @@ static int tegra186_dspk_put_control(struct snd_kcontrol *kcontrol,
static int tegra186_dspk_runtime_suspend(struct device *dev) static int tegra186_dspk_runtime_suspend(struct device *dev)
{ {
struct tegra186_dspk *dspk = dev_get_drvdata(dev); struct tegra186_dspk *dspk = dev_get_drvdata(dev);
int ret;
regcache_cache_only(dspk->regmap, true); regcache_cache_only(dspk->regmap, true);
regcache_mark_dirty(dspk->regmap); regcache_mark_dirty(dspk->regmap);
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) { if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga()))
if (!IS_ERR(dspk->pin_idle_state) && dspk->is_pinctrl) {
ret = pinctrl_select_state(
dspk->pinctrl, dspk->pin_idle_state);
if (ret < 0)
dev_err(dev,
"setting dap pinctrl idle state failed\n");
}
clk_disable_unprepare(dspk->clk_dspk); clk_disable_unprepare(dspk->clk_dspk);
}
return 0; return 0;
} }
@@ -118,22 +109,7 @@ static int tegra186_dspk_runtime_resume(struct device *dev)
struct tegra186_dspk *dspk = dev_get_drvdata(dev); struct tegra186_dspk *dspk = dev_get_drvdata(dev);
int ret; int ret;
if (dspk->prod_name) {
ret = tegra_pinctrl_config_prod(dev, dspk->prod_name);
if (ret < 0)
dev_warn(dev, "Failed to set %s setting\n",
dspk->prod_name);
}
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) { if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
if (!IS_ERR(dspk->pin_active_state) && dspk->is_pinctrl) {
ret = pinctrl_select_state(dspk->pinctrl,
dspk->pin_active_state);
if (ret < 0)
dev_err(dev,
"setting dap pinctrl active state failed\n");
}
ret = clk_prepare_enable(dspk->clk_dspk); ret = clk_prepare_enable(dspk->clk_dspk);
if (ret) { if (ret) {
dev_err(dev, "clk_enable failed: %d\n", ret); dev_err(dev, "clk_enable failed: %d\n", ret);
@@ -214,6 +190,53 @@ static int tegra186_dspk_set_dai_bclk_ratio(struct snd_soc_dai *dai,
return 0; return 0;
} }
static int tegra186_dspk_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct device *dev = dai->dev;
struct tegra186_dspk *dspk = snd_soc_dai_get_drvdata(dai);
int ret;
if (dspk->prod_name != NULL) {
ret = tegra_pinctrl_config_prod(dev, dspk->prod_name);
if (ret < 0)
dev_warn(dev, "Failed to set %s setting\n",
dspk->prod_name);
}
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
if (!IS_ERR(dspk->pin_active_state) && dspk->is_pinctrl) {
ret = pinctrl_select_state(dspk->pinctrl,
dspk->pin_active_state);
if (ret < 0) {
dev_err(dev,
"setting dap pinctrl active state failed\n");
}
}
}
return 0;
}
static void tegra186_dspk_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct device *dev = dai->dev;
struct tegra186_dspk *dspk = snd_soc_dai_get_drvdata(dai);
int ret;
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
if (!IS_ERR(dspk->pin_idle_state) && dspk->is_pinctrl) {
ret = pinctrl_select_state(
dspk->pinctrl, dspk->pin_idle_state);
if (ret < 0) {
dev_err(dev,
"setting dap pinctrl idle state failed\n");
}
}
}
}
static int tegra186_dspk_hw_params(struct snd_pcm_substream *substream, static int tegra186_dspk_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
@@ -273,6 +296,8 @@ static int tegra186_dspk_codec_probe(struct snd_soc_codec *codec)
static struct snd_soc_dai_ops tegra186_dspk_dai_ops = { static struct snd_soc_dai_ops tegra186_dspk_dai_ops = {
.hw_params = tegra186_dspk_hw_params, .hw_params = tegra186_dspk_hw_params,
.set_bclk_ratio = tegra186_dspk_set_dai_bclk_ratio, .set_bclk_ratio = tegra186_dspk_set_dai_bclk_ratio,
.startup = tegra186_dspk_startup,
.shutdown = tegra186_dspk_shutdown,
}; };
static struct snd_soc_dai_driver tegra186_dspk_dais[] = { static struct snd_soc_dai_driver tegra186_dspk_dais[] = {

View File

@@ -75,22 +75,12 @@ static const struct reg_default tegra210_dmic_reg_defaults[] = {
static int tegra210_dmic_runtime_suspend(struct device *dev) static int tegra210_dmic_runtime_suspend(struct device *dev)
{ {
struct tegra210_dmic *dmic = dev_get_drvdata(dev); struct tegra210_dmic *dmic = dev_get_drvdata(dev);
int ret;
regcache_cache_only(dmic->regmap, true); regcache_cache_only(dmic->regmap, true);
regcache_mark_dirty(dmic->regmap); regcache_mark_dirty(dmic->regmap);
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) { if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga()))
if (!IS_ERR(dmic->pin_idle_state) && dmic->is_pinctrl) {
ret = pinctrl_select_state(
dmic->pinctrl, dmic->pin_idle_state);
if (ret < 0)
dev_err(dev,
"setting dap pinctrl idle state failed\n");
}
clk_disable_unprepare(dmic->clk_dmic); clk_disable_unprepare(dmic->clk_dmic);
}
return 0; return 0;
} }
@@ -100,22 +90,7 @@ static int tegra210_dmic_runtime_resume(struct device *dev)
struct tegra210_dmic *dmic = dev_get_drvdata(dev); struct tegra210_dmic *dmic = dev_get_drvdata(dev);
int ret; int ret;
if (dmic->prod_name) {
ret = tegra_pinctrl_config_prod(dev, dmic->prod_name);
if (ret < 0)
dev_warn(dev, "Failed to set %s setting\n",
dmic->prod_name);
}
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) { if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
if (!IS_ERR(dmic->pin_active_state) && dmic->is_pinctrl) {
ret = pinctrl_select_state(dmic->pinctrl,
dmic->pin_active_state);
if (ret < 0)
dev_err(dev,
"setting dap pinctrl active state failed\n");
}
ret = clk_prepare_enable(dmic->clk_dmic); ret = clk_prepare_enable(dmic->clk_dmic);
if (ret) { if (ret) {
dev_err(dev, "clk_enable failed: %d\n", ret); dev_err(dev, "clk_enable failed: %d\n", ret);
@@ -123,7 +98,6 @@ static int tegra210_dmic_runtime_resume(struct device *dev)
} }
} }
regcache_cache_only(dmic->regmap, false); regcache_cache_only(dmic->regmap, false);
if (!dmic->is_shutdown) if (!dmic->is_shutdown)
@@ -251,6 +225,52 @@ int tegra210_dmic_set_start_callback(int id, void (*callback)(void))
} }
EXPORT_SYMBOL_GPL(tegra210_dmic_set_start_callback); EXPORT_SYMBOL_GPL(tegra210_dmic_set_start_callback);
static int tegra210_dmic_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct device *dev = dai->dev;
struct tegra210_dmic *dmic = snd_soc_dai_get_drvdata(dai);
int ret;
if (dmic->prod_name != NULL) {
ret = tegra_pinctrl_config_prod(dev, dmic->prod_name);
if (ret < 0) {
dev_warn(dev, "Failed to set %s setting\n",
dmic->prod_name);
}
}
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
if (!IS_ERR(dmic->pin_active_state) && dmic->is_pinctrl) {
ret = pinctrl_select_state(dmic->pinctrl,
dmic->pin_active_state);
if (ret < 0) {
dev_err(dev,
"setting dap pinctrl active state failed\n");
}
}
}
return 0;
}
static void tegra210_dmic_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct device *dev = dai->dev;
struct tegra210_dmic *dmic = snd_soc_dai_get_drvdata(dai);
int ret;
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
if (!IS_ERR(dmic->pin_idle_state) && dmic->is_pinctrl) {
ret = pinctrl_select_state(
dmic->pinctrl, dmic->pin_idle_state);
if (ret < 0)
dev_err(dev,
"setting dap pinctrl idle state failed\n");
}
}
}
static int tegra210_dmic_hw_params(struct snd_pcm_substream *substream, static int tegra210_dmic_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
@@ -468,6 +488,8 @@ static int tegra210_dmic_codec_probe(struct snd_soc_codec *codec)
static struct snd_soc_dai_ops tegra210_dmic_dai_ops = { static struct snd_soc_dai_ops tegra210_dmic_dai_ops = {
.hw_params = tegra210_dmic_hw_params, .hw_params = tegra210_dmic_hw_params,
.set_bclk_ratio = tegra210_dmic_set_dai_bclk_ratio, .set_bclk_ratio = tegra210_dmic_set_dai_bclk_ratio,
.startup = tegra210_dmic_startup,
.shutdown = tegra210_dmic_shutdown,
}; };
static struct snd_soc_dai_driver tegra210_dmic_dais[] = { static struct snd_soc_dai_driver tegra210_dmic_dais[] = {

View File

@@ -220,29 +220,12 @@ static int tegra210_i2s_tx_stop(struct snd_soc_dapm_widget *w,
static int tegra210_i2s_runtime_suspend(struct device *dev) static int tegra210_i2s_runtime_suspend(struct device *dev)
{ {
struct tegra210_i2s *i2s = dev_get_drvdata(dev); struct tegra210_i2s *i2s = dev_get_drvdata(dev);
int ret;
regcache_cache_only(i2s->regmap, true);
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) { if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
if (!IS_ERR(i2s->pin_idle_state)) {
ret = pinctrl_select_state(
i2s->pinctrl, i2s->pin_idle_state);
if (ret < 0)
dev_err(dev, "setting dap pinctrl idle state failed\n");
}
if (i2s->num_supplies > 0) {
ret = regulator_bulk_disable(i2s->num_supplies,
i2s->supplies);
if (ret < 0)
dev_err(dev, "failed to disable i2s io regulator\n");
}
regcache_cache_only(i2s->regmap, true);
regcache_mark_dirty(i2s->regmap); regcache_mark_dirty(i2s->regmap);
clk_disable_unprepare(i2s->clk_i2s); clk_disable_unprepare(i2s->clk_i2s);
} else }
regcache_cache_only(i2s->regmap, true);
return 0; return 0;
} }
@@ -253,27 +236,6 @@ static int tegra210_i2s_runtime_resume(struct device *dev)
int ret; int ret;
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) { if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
if (i2s->prod_name) {
ret = tegra_pinctrl_config_prod(dev, i2s->prod_name);
if (ret < 0)
dev_warn(dev, "Failed to set %s setting\n",
i2s->prod_name);
}
if (!IS_ERR(i2s->pin_default_state)) {
ret = pinctrl_select_state(i2s->pinctrl,
i2s->pin_default_state);
if (ret < 0)
dev_err(dev, "setting dap pinctrl default state failed\n");
}
if (i2s->num_supplies > 0) {
ret = regulator_bulk_enable(i2s->num_supplies,
i2s->supplies);
if (ret < 0)
dev_err(dev, "failed to enable i2s io regulator\n");
}
ret = clk_prepare_enable(i2s->clk_i2s); ret = clk_prepare_enable(i2s->clk_i2s);
if (ret) { if (ret) {
dev_err(dev, "clk_enable failed: %d\n", ret); dev_err(dev, "clk_enable failed: %d\n", ret);
@@ -281,7 +243,6 @@ static int tegra210_i2s_runtime_resume(struct device *dev)
} }
} }
regcache_cache_only(i2s->regmap, false); regcache_cache_only(i2s->regmap, false);
if (!i2s->is_shutdown) if (!i2s->is_shutdown)
regcache_sync(i2s->regmap); regcache_sync(i2s->regmap);
@@ -536,6 +497,69 @@ static const struct soc_enum tegra210_i2s_format_enum =
ARRAY_SIZE(tegra210_i2s_format_text), ARRAY_SIZE(tegra210_i2s_format_text),
tegra210_i2s_format_text); tegra210_i2s_format_text);
static int tegra210_i2s_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct device *dev = dai->dev;
struct tegra210_i2s *i2s = dev_get_drvdata(dev);
int ret;
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga()) &&
!i2s->loopback) {
if (i2s->prod_name != NULL) {
ret = tegra_pinctrl_config_prod(dev, i2s->prod_name);
if (ret < 0) {
dev_warn(dev, "Failed to set %s setting\n",
i2s->prod_name);
}
}
if (!IS_ERR(i2s->pin_default_state)) {
ret = pinctrl_select_state(i2s->pinctrl,
i2s->pin_default_state);
if (ret < 0)
dev_err(dev, "setting dap pinctrl default state failed\n");
}
if (i2s->num_supplies > 0) {
ret = regulator_bulk_enable(i2s->num_supplies,
i2s->supplies);
if (ret < 0)
dev_err(dev, "failed to enable i2s io regulator\n");
}
}
return 0;
}
static void tegra210_i2s_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct device *dev = dai->dev;
struct tegra210_i2s *i2s = dev_get_drvdata(dev);
int ret;
if (!(tegra_platform_is_unit_fpga() || tegra_platform_is_fpga())) {
if (!IS_ERR(i2s->pin_idle_state)) {
ret = pinctrl_select_state(
i2s->pinctrl, i2s->pin_idle_state);
if (ret < 0) {
dev_err(dev,
"setting dap pinctrl idle state failed\n");
}
}
if (i2s->num_supplies > 0) {
ret = regulator_bulk_disable(i2s->num_supplies,
i2s->supplies);
if (ret < 0) {
dev_err(dev,
"failed to disable i2s io regulator\n");
}
}
}
}
static int tegra210_i2s_hw_params(struct snd_pcm_substream *substream, static int tegra210_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
@@ -717,6 +741,8 @@ static struct snd_soc_dai_ops tegra210_i2s_dai_ops = {
.hw_params = tegra210_i2s_hw_params, .hw_params = tegra210_i2s_hw_params,
.set_bclk_ratio = tegra210_i2s_set_dai_bclk_ratio, .set_bclk_ratio = tegra210_i2s_set_dai_bclk_ratio,
.set_tdm_slot = tegra210_i2s_set_tdm_slot, .set_tdm_slot = tegra210_i2s_set_tdm_slot,
.startup = tegra210_i2s_startup,
.shutdown = tegra210_i2s_shutdown,
}; };
static struct snd_soc_dai_driver tegra210_i2s_dais[] = { static struct snd_soc_dai_driver tegra210_i2s_dais[] = {