mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 17:25:35 +03:00
ASoC: tegra-alt: use regmap macros for timeout
Following print is seen while using regmap_read_poll_timeout() macro in snd_soc_dai_ops trigger() callback in ADMAIF driver, *** BUG: scheduling while atomic *** and kernel panic happens there after. This happens because above macro is not atomic safe and trigger() is called in atomic context. Earlier this addressed by using readx_poll_timeout_atomic() macro. Though this works fine driver needs to keep a reference to base address. To avoid this new macro was pushed and is accepted in upstream and following is the commit - https://lkml.org/lkml/2020/1/9/985 This patch makes use of regmap macros where there is a need of timeout functionality. Following is the guideline that can be followed. * use regmap_read_poll_timeout_atomic() where the caller is in atomic context. ex: trigger() etc., * use regmap_read_poll_timeout() when the caller is known to be running in non-atomic context. ex: hw_param(), prepare() etc., Based on this audio drivers are updated. ASRC and ARAD drivers will be taken up in a separate change. Bug 200566596 Change-Id: Iea88adc60de5919e456a36a30152212652a8ecd3 Signed-off-by: Sameer Pujar <spujar@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2274874 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Sharad Gupta <sharadg@nvidia.com> GVS: Gerrit_Virtual_Submit Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
@@ -209,7 +209,6 @@ struct tegra210_i2s {
|
||||
bool loopback;
|
||||
unsigned int format;
|
||||
unsigned int rx_fifo_th; /* should be programmed interms of frames */
|
||||
void __iomem *base_addr;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -16,10 +16,8 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
@@ -431,7 +429,7 @@ static int tegra_admaif_stop(struct snd_soc_dai *dai, int direction)
|
||||
regmap_update_bits(admaif->regmap, enable_reg, mask, ~enable);
|
||||
|
||||
/* wait until ADMAIF TX/RX status is disabled */
|
||||
ret = readl_poll_timeout_atomic(REG_IOVA(status_reg), val,
|
||||
ret = regmap_read_poll_timeout_atomic(admaif->regmap, status_reg, val,
|
||||
!(val & enable), 10, 10000);
|
||||
|
||||
/* Timeout may be hit if sink gets closed/blocked ahead of source */
|
||||
@@ -443,7 +441,7 @@ static int tegra_admaif_stop(struct snd_soc_dai *dai, int direction)
|
||||
regmap_update_bits(admaif->regmap, reset_reg, SW_RESET_MASK, SW_RESET);
|
||||
|
||||
/* wait till SW reset is complete */
|
||||
ret = readl_poll_timeout_atomic(REG_IOVA(reset_reg), val,
|
||||
ret = regmap_read_poll_timeout_atomic(admaif->regmap, reset_reg, val,
|
||||
!(val & SW_RESET_MASK & SW_RESET),
|
||||
10, 10000);
|
||||
if (ret < 0) {
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/io.h>
|
||||
@@ -155,22 +154,34 @@ static void tegra210_adx_update_map_ram(struct tegra210_adx *adx)
|
||||
tegra210_adx_write_map_ram(adx, i, adx->map[i]);
|
||||
}
|
||||
|
||||
static int tegra210_adx_sw_reset(struct tegra210_adx *adx,
|
||||
int timeout)
|
||||
static int tegra210_adx_stop(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
|
||||
struct device *dev = codec->dev;
|
||||
struct tegra210_adx *adx = dev_get_drvdata(dev);
|
||||
unsigned int val;
|
||||
int wait = timeout;
|
||||
int ret;
|
||||
|
||||
/* ensure if ADX status is disabled */
|
||||
ret = regmap_read_poll_timeout_atomic(adx->regmap, TEGRA210_ADX_STATUS,
|
||||
val, !(val & 0x1), 10, 10000);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to stop ADX, err = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* SW reset */
|
||||
regmap_update_bits(adx->regmap, TEGRA210_ADX_SOFT_RESET,
|
||||
TEGRA210_ADX_SOFT_RESET_SOFT_RESET_MASK,
|
||||
TEGRA210_ADX_SOFT_RESET_SOFT_EN);
|
||||
|
||||
do {
|
||||
regmap_read(adx->regmap, TEGRA210_ADX_SOFT_RESET, &val);
|
||||
wait--;
|
||||
if (!wait)
|
||||
return -EINVAL;
|
||||
} while (val & 0x00000001);
|
||||
ret = regmap_read_poll_timeout(adx->regmap, TEGRA210_ADX_SOFT_RESET,
|
||||
val, !(val & 0x1), 10, 10000);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to reset ADX, err = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
regmap_update_bits(adx->regmap, TEGRA210_ADX_SOFT_RESET,
|
||||
TEGRA210_ADX_SOFT_RESET_SOFT_RESET_MASK,
|
||||
@@ -179,44 +190,11 @@ static int tegra210_adx_sw_reset(struct tegra210_adx *adx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_adx_get_status(struct tegra210_adx *adx)
|
||||
static unsigned int __maybe_unused
|
||||
tegra210_adx_read_map_ram(struct tegra210_adx *adx, unsigned int addr)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
regmap_read(adx->regmap, TEGRA210_ADX_STATUS, &val);
|
||||
val = (val & 0x00000001);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static int tegra210_adx_stop(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
|
||||
struct device *dev = codec->dev;
|
||||
struct tegra210_adx *adx = dev_get_drvdata(dev);
|
||||
int dcnt = 10, ret = 0;
|
||||
|
||||
/* wait until ADX status is disabled */
|
||||
while (tegra210_adx_get_status(adx) && dcnt--)
|
||||
udelay(100);
|
||||
|
||||
/* HW needs sw reset to make sure previous transaction be clean */
|
||||
ret = tegra210_adx_sw_reset(adx, 0xffff);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed at ADX%d sw reset\n", dev->id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return (dcnt < 0) ? -ETIMEDOUT : 0;
|
||||
}
|
||||
|
||||
static unsigned int __maybe_unused tegra210_adx_read_map_ram(
|
||||
struct tegra210_adx *adx,
|
||||
unsigned int addr)
|
||||
{
|
||||
unsigned int val, wait;
|
||||
wait = 0xffff;
|
||||
int ret;
|
||||
|
||||
regmap_write(adx->regmap, TEGRA210_ADX_AHUBRAMCTL_ADX_CTRL,
|
||||
(addr << TEGRA210_ADX_AHUBRAMCTL_ADX_CTRL_RAM_ADDR_SHIFT));
|
||||
@@ -228,12 +206,11 @@ static unsigned int __maybe_unused tegra210_adx_read_map_ram(
|
||||
val &= ~(TEGRA210_ADX_AHUBRAMCTL_ADX_CTRL_RW_WRITE);
|
||||
regmap_write(adx->regmap, TEGRA210_ADX_AHUBRAMCTL_ADX_CTRL, val);
|
||||
|
||||
do {
|
||||
regmap_read(adx->regmap, TEGRA210_ADX_AHUBRAMCTL_ADX_CTRL, &val);
|
||||
wait--;
|
||||
if (!wait)
|
||||
return -EINVAL;
|
||||
} while (val & 0x80000000);
|
||||
ret = regmap_read_poll_timeout(adx->regmap,
|
||||
TEGRA210_ADX_AHUBRAMCTL_ADX_CTRL,
|
||||
val, !(val & 0x80000000), 10, 10000);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
regmap_read(adx->regmap, TEGRA210_ADX_AHUBRAMCTL_ADX_DATA, &val);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* tegra210_afc_alt.c - Tegra210 AFC driver
|
||||
*
|
||||
* Copyright (c) 2014-2019 NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2014-2020 NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -15,7 +15,6 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <linux/delay.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/io.h>
|
||||
@@ -179,60 +178,40 @@ static void tegra210_amx_update_map_ram(struct tegra210_amx *amx)
|
||||
tegra210_amx_write_map_ram(amx, i, amx->map[i]);
|
||||
}
|
||||
|
||||
static int tegra210_amx_sw_reset(struct tegra210_amx *amx,
|
||||
int timeout)
|
||||
{
|
||||
unsigned int val;
|
||||
int wait = timeout;
|
||||
|
||||
regmap_update_bits(amx->regmap, TEGRA210_AMX_SOFT_RESET,
|
||||
TEGRA210_AMX_SOFT_RESET_SOFT_RESET_MASK,
|
||||
TEGRA210_AMX_SOFT_RESET_SOFT_EN);
|
||||
|
||||
do {
|
||||
regmap_read(amx->regmap, TEGRA210_AMX_SOFT_RESET, &val);
|
||||
wait--;
|
||||
if (!wait)
|
||||
return -EINVAL;
|
||||
} while (val & 0x00000001);
|
||||
|
||||
regmap_update_bits(amx->regmap, TEGRA210_AMX_SOFT_RESET,
|
||||
TEGRA210_AMX_SOFT_RESET_SOFT_RESET_MASK,
|
||||
TEGRA210_AMX_SOFT_RESET_SOFT_DEFAULT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_amx_get_status(struct tegra210_amx *amx)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
regmap_read(amx->regmap, TEGRA210_AMX_STATUS, &val);
|
||||
val = (val & 0x00000001);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static int tegra210_amx_stop(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
|
||||
struct device *dev = codec->dev;
|
||||
struct tegra210_amx *amx = dev_get_drvdata(dev);
|
||||
int dcnt = 10, ret = 0;
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
/* wait until AMX status is disabled */
|
||||
while (tegra210_amx_get_status(amx) && dcnt--)
|
||||
udelay(100);
|
||||
|
||||
/* HW needs sw reset to make sure previous transaction be clean */
|
||||
ret = tegra210_amx_sw_reset(amx, 0xffff);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed at AMX%d sw reset\n", dev->id);
|
||||
/* Ensure if AMX is disabled */
|
||||
ret = regmap_read_poll_timeout(amx->regmap, TEGRA210_AMX_STATUS, val,
|
||||
!(val & 0x1), 10, 10000);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to stop AMX, err = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return (dcnt < 0) ? -ETIMEDOUT : 0;
|
||||
/* SW reset */
|
||||
regmap_update_bits(amx->regmap, TEGRA210_AMX_SOFT_RESET,
|
||||
TEGRA210_AMX_SOFT_RESET_SOFT_RESET_MASK,
|
||||
TEGRA210_AMX_SOFT_RESET_SOFT_EN);
|
||||
|
||||
ret = regmap_read_poll_timeout(amx->regmap, TEGRA210_AMX_SOFT_RESET,
|
||||
val, !(val & 0x1), 10, 10000);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to reset AMX, err = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
regmap_update_bits(amx->regmap, TEGRA210_AMX_SOFT_RESET,
|
||||
TEGRA210_AMX_SOFT_RESET_SOFT_RESET_MASK,
|
||||
TEGRA210_AMX_SOFT_RESET_SOFT_DEFAULT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_amx_runtime_suspend(struct device *dev)
|
||||
@@ -245,12 +224,11 @@ static int tegra210_amx_runtime_suspend(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int __maybe_unused tegra210_amx_read_map_ram(
|
||||
struct tegra210_amx *amx,
|
||||
unsigned int addr)
|
||||
static unsigned int __maybe_unused
|
||||
tegra210_amx_read_map_ram(struct tegra210_amx *amx, unsigned int addr)
|
||||
{
|
||||
unsigned int val, wait;
|
||||
wait = 0xffff;
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
regmap_write(amx->regmap, TEGRA210_AMX_AHUBRAMCTL_AMX_CTRL,
|
||||
(addr << TEGRA210_AMX_AHUBRAMCTL_AMX_CTRL_RAM_ADDR_SHIFT));
|
||||
@@ -262,13 +240,11 @@ static unsigned int __maybe_unused tegra210_amx_read_map_ram(
|
||||
val &= ~(TEGRA210_AMX_AHUBRAMCTL_AMX_CTRL_RW_WRITE);
|
||||
regmap_write(amx->regmap, TEGRA210_AMX_AHUBRAMCTL_AMX_CTRL, val);
|
||||
|
||||
do {
|
||||
regmap_read(amx->regmap,
|
||||
TEGRA210_AMX_AHUBRAMCTL_AMX_CTRL, &val);
|
||||
wait--;
|
||||
if (!wait)
|
||||
return -EINVAL;
|
||||
} while (val & 0x80000000);
|
||||
ret = regmap_read_poll_timeout(amx->regmap,
|
||||
TEGRA210_AMX_AHUBRAMCTL_AMX_CTRL,
|
||||
val, !(val & 0x80000000), 10, 10000);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
regmap_read(amx->regmap, TEGRA210_AMX_AHUBRAMCTL_AMX_DATA, &val);
|
||||
|
||||
|
||||
@@ -16,11 +16,9 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
@@ -33,7 +31,6 @@
|
||||
#include <linux/pinctrl/pinconf-tegra.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/tegra-powergate.h>
|
||||
#include <soc/tegra/chip-id.h>
|
||||
#include <linux/pm_domain.h>
|
||||
@@ -43,8 +40,6 @@
|
||||
|
||||
#define DRV_NAME "tegra210-i2s"
|
||||
|
||||
#define REG_IOVA(reg) (i2s->base_addr + (reg))
|
||||
|
||||
static const struct reg_default tegra210_i2s_reg_defaults[] = {
|
||||
{ TEGRA210_I2S_AXBAR_RX_INT_MASK, 0x00000003},
|
||||
{ TEGRA210_I2S_AXBAR_RX_CIF_CTRL, 0x00007700},
|
||||
@@ -144,7 +139,7 @@ static int tegra210_i2s_sw_reset(struct snd_soc_codec *codec, bool is_playback)
|
||||
/* SW reset */
|
||||
regmap_update_bits(i2s->regmap, reset_reg, reset_mask, reset_en);
|
||||
|
||||
ret = readl_poll_timeout_atomic(REG_IOVA(reset_reg), val,
|
||||
ret = regmap_read_poll_timeout(i2s->regmap, reset_reg, val,
|
||||
!(val & reset_mask & reset_en),
|
||||
10, 10000);
|
||||
if (ret < 0) {
|
||||
@@ -185,7 +180,7 @@ static int tegra210_i2s_init(struct snd_soc_dapm_widget *w,
|
||||
}
|
||||
|
||||
/* ensure I2S is in disabled state before new session */
|
||||
ret = readl_poll_timeout_atomic(REG_IOVA(status_reg), val,
|
||||
ret = regmap_read_poll_timeout(i2s->regmap, status_reg, val,
|
||||
!(val & TEGRA210_I2S_EN_MASK & TEGRA210_I2S_EN),
|
||||
10, 10000);
|
||||
if (ret < 0) {
|
||||
@@ -1100,8 +1095,6 @@ static int tegra210_i2s_platform_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(regs))
|
||||
return PTR_ERR(regs);
|
||||
|
||||
i2s->base_addr = regs;
|
||||
|
||||
i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
|
||||
&tegra210_i2s_regmap_config);
|
||||
if (IS_ERR(i2s->regmap)) {
|
||||
|
||||
@@ -96,19 +96,17 @@ static int tegra210_mixer_runtime_resume(struct device *dev)
|
||||
|
||||
static int tegra210_mixer_write_ram(struct tegra210_mixer *mixer,
|
||||
unsigned int addr,
|
||||
unsigned int val)
|
||||
unsigned int coef)
|
||||
{
|
||||
unsigned int reg, value, wait = 0xffff;
|
||||
unsigned int reg, val;
|
||||
int ret;
|
||||
|
||||
/* check if busy */
|
||||
do {
|
||||
regmap_read(mixer->regmap,
|
||||
TEGRA210_MIXER_AHUBRAMCTL_GAIN_CONFIG_RAM_CTRL, &value);
|
||||
wait--;
|
||||
if (!wait)
|
||||
return -EINVAL;
|
||||
} while (value & 0x80000000);
|
||||
value = 0;
|
||||
ret = regmap_read_poll_timeout(mixer->regmap,
|
||||
TEGRA210_MIXER_AHUBRAMCTL_GAIN_CONFIG_RAM_CTRL,
|
||||
val, !(val & 0x80000000), 10, 10000);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
reg = (addr << TEGRA210_MIXER_AHUBRAMCTL_GAIN_CONFIG_RAM_CTRL_RAM_ADDR_SHIFT) &
|
||||
TEGRA210_MIXER_AHUBRAMCTL_GAIN_CONFIG_RAM_CTRL_RAM_ADDR_MASK;
|
||||
@@ -117,9 +115,11 @@ static int tegra210_mixer_write_ram(struct tegra210_mixer *mixer,
|
||||
reg |= TEGRA210_MIXER_AHUBRAMCTL_GAIN_CONFIG_RAM_CTRL_SEQ_ACCESS_EN;
|
||||
|
||||
regmap_write(mixer->regmap,
|
||||
TEGRA210_MIXER_AHUBRAMCTL_GAIN_CONFIG_RAM_CTRL, reg);
|
||||
TEGRA210_MIXER_AHUBRAMCTL_GAIN_CONFIG_RAM_CTRL,
|
||||
reg);
|
||||
regmap_write(mixer->regmap,
|
||||
TEGRA210_MIXER_AHUBRAMCTL_GAIN_CONFIG_RAM_DATA, val);
|
||||
TEGRA210_MIXER_AHUBRAMCTL_GAIN_CONFIG_RAM_DATA,
|
||||
coef);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "tegra210_xbar_alt.h"
|
||||
#include "tegra210_mvc_alt.h"
|
||||
@@ -75,40 +74,17 @@ static int tegra210_mvc_runtime_resume(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_mvc_soft_reset(struct tegra210_mvc *mvc)
|
||||
{
|
||||
int value;
|
||||
int dcnt = 10;
|
||||
/* issue soft reset */
|
||||
regmap_write(mvc->regmap, TEGRA210_MVC_SOFT_RESET, 1);
|
||||
/* wait for soft reset bit to clear */
|
||||
do {
|
||||
udelay(10);
|
||||
regmap_read(mvc->regmap, TEGRA210_MVC_SOFT_RESET, &value);
|
||||
dcnt--;
|
||||
if (dcnt < 0)
|
||||
return -EINVAL;
|
||||
} while (value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_mvc_write_ram(struct tegra210_mvc *mvc,
|
||||
unsigned int addr,
|
||||
unsigned int val)
|
||||
unsigned int addr, unsigned int coef)
|
||||
{
|
||||
unsigned int reg, value, wait = 0xffff;
|
||||
unsigned int reg, val;
|
||||
int ret;
|
||||
|
||||
/* check if busy */
|
||||
do {
|
||||
regmap_read(mvc->regmap,
|
||||
ret = regmap_read_poll_timeout(mvc->regmap,
|
||||
TEGRA210_MVC_AHUBRAMCTL_CONFIG_RAM_CTRL,
|
||||
&value);
|
||||
wait--;
|
||||
if (!wait)
|
||||
return -EINVAL;
|
||||
} while (value & 0x80000000);
|
||||
value = 0;
|
||||
val, !(val & 0x80000000), 10, 10000);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
reg = (addr << TEGRA210_MVC_AHUBRAMCTL_CONFIG_RAM_CTRL_RAM_ADDR_SHIFT) &
|
||||
TEGRA210_MVC_AHUBRAMCTL_CONFIG_RAM_CTRL_RAM_ADDR_MASK;
|
||||
@@ -116,10 +92,9 @@ static int tegra210_mvc_write_ram(struct tegra210_mvc *mvc,
|
||||
reg |= TEGRA210_MVC_AHUBRAMCTL_CONFIG_RAM_CTRL_RW_WRITE;
|
||||
reg |= TEGRA210_MVC_AHUBRAMCTL_CONFIG_RAM_CTRL_SEQ_ACCESS_EN;
|
||||
|
||||
regmap_write(mvc->regmap,
|
||||
TEGRA210_MVC_AHUBRAMCTL_CONFIG_RAM_CTRL, reg);
|
||||
regmap_write(mvc->regmap,
|
||||
TEGRA210_MVC_AHUBRAMCTL_CONFIG_RAM_DATA, val);
|
||||
regmap_write(mvc->regmap, TEGRA210_MVC_AHUBRAMCTL_CONFIG_RAM_CTRL, reg);
|
||||
regmap_write(mvc->regmap, TEGRA210_MVC_AHUBRAMCTL_CONFIG_RAM_DATA,
|
||||
coef);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -161,21 +136,18 @@ static int tegra210_mvc_put_vol(struct snd_kcontrol *kcontrol,
|
||||
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
|
||||
struct tegra210_mvc *mvc = snd_soc_codec_get_drvdata(codec);
|
||||
unsigned int reg = mc->reg;
|
||||
unsigned int value, wait = 0xffff;
|
||||
unsigned int value;
|
||||
int ret = 0;
|
||||
s32 val;
|
||||
|
||||
pm_runtime_get_sync(codec->dev);
|
||||
|
||||
/* check if VOLUME_SWITCH is triggered */
|
||||
do {
|
||||
regmap_read(mvc->regmap,
|
||||
TEGRA210_MVC_SWITCH, &value);
|
||||
wait--;
|
||||
if (!wait) {
|
||||
ret = -EINVAL;
|
||||
ret = regmap_read_poll_timeout(mvc->regmap, TEGRA210_MVC_SWITCH,
|
||||
value, !(value & TEGRA210_MVC_VOLUME_SWITCH_MASK),
|
||||
10, 10000);
|
||||
if (ret < 0)
|
||||
goto end;
|
||||
}
|
||||
} while (value & TEGRA210_MVC_VOLUME_SWITCH_MASK);
|
||||
|
||||
if (reg == TEGRA210_MVC_TARGET_VOL) {
|
||||
/* Volume control read from mixer ctl is with */
|
||||
@@ -357,11 +329,15 @@ static int tegra210_mvc_hw_params(struct snd_pcm_substream *substream,
|
||||
{
|
||||
struct device *dev = dai->dev;
|
||||
struct tegra210_mvc *mvc = snd_soc_dai_get_drvdata(dai);
|
||||
int i, ret;
|
||||
int i, ret, val;
|
||||
|
||||
ret = tegra210_mvc_soft_reset(mvc);
|
||||
/* SW reset */
|
||||
regmap_write(mvc->regmap, TEGRA210_MVC_SOFT_RESET, 1);
|
||||
|
||||
ret = regmap_read_poll_timeout(mvc->regmap, TEGRA210_MVC_SOFT_RESET,
|
||||
val, !val, 10, 10000);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "SOFT_RESET error: %d\n", ret);
|
||||
dev_err(dev, "SW reset failed, err = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -396,8 +372,14 @@ static int tegra210_mvc_hw_params(struct snd_pcm_substream *substream,
|
||||
regmap_write(mvc->regmap, TEGRA210_MVC_TARGET_VOL, mvc->volume);
|
||||
|
||||
/* program the poly coefficients */
|
||||
for (i = 0; i < 9; i++)
|
||||
tegra210_mvc_write_ram(mvc, i, mvc->poly_coeff[i]);
|
||||
for (i = 0; i < 9; i++) {
|
||||
ret = tegra210_mvc_write_ram(mvc, i, mvc->poly_coeff[i]);
|
||||
if (ret < 0) {
|
||||
dev_err(dai->dev, "failed to write coefs, err = %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* program poly_n1, poly_n2, duration */
|
||||
regmap_write(mvc->regmap, TEGRA210_MVC_POLY_N1, mvc->poly_n1);
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "tegra210_xbar_alt.h"
|
||||
#include "tegra210_sfc_alt.h"
|
||||
@@ -3015,20 +3014,19 @@ static int tegra210_sfc_set_audio_cif(struct tegra210_sfc *sfc,
|
||||
static int tegra210_sfc_soft_reset(struct tegra210_sfc *sfc)
|
||||
{
|
||||
u32 val;
|
||||
int cnt = 10;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
regmap_update_bits(sfc->regmap,
|
||||
TEGRA210_SFC_SOFT_RESET,
|
||||
TEGRA210_SFC_SOFT_RESET_EN,
|
||||
1);
|
||||
do {
|
||||
udelay(100);
|
||||
regmap_read(sfc->regmap, TEGRA210_SFC_SOFT_RESET, &val);
|
||||
} while ((val & TEGRA210_SFC_SOFT_RESET_EN) && cnt--);
|
||||
if (!cnt)
|
||||
ret = -ETIMEDOUT;
|
||||
/* SW reset */
|
||||
regmap_update_bits(sfc->regmap, TEGRA210_SFC_SOFT_RESET,
|
||||
TEGRA210_SFC_SOFT_RESET_EN, 1);
|
||||
|
||||
ret = regmap_read_poll_timeout(sfc->regmap, TEGRA210_SFC_SOFT_RESET,
|
||||
val, !(val & TEGRA210_SFC_SOFT_RESET_EN),
|
||||
10, 10000);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_sfc_in_hw_params(struct snd_pcm_substream *substream,
|
||||
@@ -3045,8 +3043,10 @@ static int tegra210_sfc_in_hw_params(struct snd_pcm_substream *substream,
|
||||
0);
|
||||
|
||||
ret = tegra210_sfc_soft_reset(sfc);
|
||||
if (ret) {
|
||||
dev_err(dev, "SOFT_RESET error: %d\n", ret);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to reset SFC in %s, err = %d\n",
|
||||
__func__, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -3200,27 +3200,28 @@ static int tegra210_sfc_init_put(struct snd_kcontrol *kcontrol,
|
||||
|
||||
if (is_enabled) {
|
||||
u32 val;
|
||||
int cnt = 100;
|
||||
|
||||
regmap_write(sfc->regmap, TEGRA210_SFC_ENABLE, 0);
|
||||
|
||||
regmap_read(sfc->regmap, TEGRA210_SFC_STATUS, &val);
|
||||
while ((val & 1) && cnt--) {
|
||||
udelay(100);
|
||||
regmap_read(sfc->regmap, TEGRA210_SFC_STATUS, &val);
|
||||
ret = regmap_read_poll_timeout(sfc->regmap,
|
||||
TEGRA210_SFC_STATUS, val,
|
||||
!(val & 0x1), 10, 10000);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev,
|
||||
"failed to disable SFC, err = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!cnt)
|
||||
dev_warn(codec->dev, "SFC disable timeout\n");
|
||||
|
||||
regmap_update_bits(sfc->regmap,
|
||||
TEGRA210_SFC_COEF_RAM,
|
||||
TEGRA210_SFC_COEF_RAM_COEF_RAM_EN,
|
||||
0);
|
||||
|
||||
ret = tegra210_sfc_soft_reset(sfc);
|
||||
if (ret) {
|
||||
dev_err(codec->dev, "SOFT_RESET error: %d\n", ret);
|
||||
if (ret < 0) {
|
||||
dev_err(codec->dev,
|
||||
"failed to reset SFC in %s, err = %d\n",
|
||||
__func__, ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user