mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 09:11:26 +03:00
ASoC: tegra-alt: Improvement of t210 drivers
1. Add link name to platform data for unique
identification of the dai link
2. Remove set_sysclk from I2S and retreive
srate from params
3. Try to retrieve fsync-width from DT file,
if not default as 31
4. Add mono channel support in FSYNC mode
in machine driver
5. Fix dai_link_idx API to get link_idx
from unique name identifier
6. Add tdm_slot mask API for tx/rx mask settting
7. Initialize the DAPM dai link work struct for
non-pcm dai-links to avoid kernel crash
during powercycle in low power mode.
8. Add slot_size for AMX and ADX
9. Add clk_out_rate for 8kHz in automotive machine driver
Bug 1442940
Change-Id: Iaebdd7e12b8490021a9034afa351cdbc1d1d5d38
Signed-off-by: Arun Shamanna Lakshmi <aruns@nvidia.com>
Signed-off-by: Junghyun Kim <juskim@nvidia.com>
Reviewed-on: http://git-master/r/500553
This commit is contained in:
committed by
Sameer Pujar
parent
be0ba9e3e9
commit
8f48438124
@@ -119,9 +119,9 @@ static int tegra210_afc_set_thresholds(struct tegra210_afc *afc,
|
||||
if (tegra210_afc_get_sfc_id(afc_id)) {
|
||||
/* TODO program thresholds using SRC_BURST */
|
||||
} else {
|
||||
value = 8 << TEGRA210_AFC_FIFO_HIGH_THRESHOLD_SHIFT;
|
||||
value |= 7 << TEGRA210_AFC_FIFO_START_THRESHOLD_SHIFT;
|
||||
value |= 6;
|
||||
value = 4 << TEGRA210_AFC_FIFO_HIGH_THRESHOLD_SHIFT;
|
||||
value |= 3 << TEGRA210_AFC_FIFO_START_THRESHOLD_SHIFT;
|
||||
value |= 2;
|
||||
}
|
||||
regmap_write(afc->regmap, TEGRA210_AFC_TXCIF_FIFO_PARAMS, value);
|
||||
|
||||
|
||||
@@ -40,6 +40,18 @@
|
||||
|
||||
#define DRV_NAME "tegra210-i2s"
|
||||
|
||||
static void tegra210_i2s_set_slot_ctrl(struct regmap *regmap,
|
||||
unsigned int total_slots,
|
||||
unsigned int tx_slot_mask,
|
||||
unsigned int rx_slot_mask)
|
||||
{
|
||||
regmap_write(regmap, TEGRA210_I2S_SLOT_CTRL, total_slots - 1);
|
||||
regmap_write(regmap, TEGRA210_I2S_AXBAR_TX_SLOT_CTRL,
|
||||
tx_slot_mask);
|
||||
regmap_write(regmap, TEGRA210_I2S_AXBAR_RX_SLOT_CTRL,
|
||||
rx_slot_mask);
|
||||
}
|
||||
|
||||
static int tegra210_i2s_set_clock_rate(struct device *dev, int clock_rate)
|
||||
{
|
||||
unsigned int val;
|
||||
@@ -218,11 +230,27 @@ static int tegra210_i2s_set_fmt(struct snd_soc_dai *dai,
|
||||
regmap_update_bits(i2s->regmap, TEGRA210_I2S_AXBAR_RX_CTRL,
|
||||
TEGRA210_I2S_AXBAR_RX_CTRL_DATA_OFFSET_MASK,
|
||||
(data_offset << TEGRA210_I2S_AXBAR_RX_CTRL_DATA_OFFSET_SHIFT));
|
||||
regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL,
|
||||
TEGRA210_I2S_CTRL_FSYNC_WIDTH_MASK,
|
||||
i2s->fsync_width << TEGRA210_I2S_CTRL_FSYNC_WIDTH_SHIFT);
|
||||
pm_runtime_put(dai->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_i2s_set_tdm_slot(struct snd_soc_dai *dai,
|
||||
unsigned int tx_mask, unsigned int rx_mask,
|
||||
int slots, int slot_width)
|
||||
{
|
||||
struct tegra210_i2s *i2s = snd_soc_dai_get_drvdata(dai);
|
||||
|
||||
/* copy the required tx and rx mask */
|
||||
i2s->tx_mask = (tx_mask > 0xFFFF) ? 0xFFFF : tx_mask;
|
||||
i2s->rx_mask = (rx_mask > 0xFFFF) ? 0xFFFF : rx_mask;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_i2s_set_dai_bclk_ratio(struct snd_soc_dai *dai,
|
||||
unsigned int ratio)
|
||||
{
|
||||
@@ -249,17 +277,29 @@ static int tegra210_i2s_hw_params(struct snd_pcm_substream *substream,
|
||||
|
||||
mask = TEGRA210_I2S_CTRL_BIT_SIZE_MASK;
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S8:
|
||||
val = TEGRA210_I2S_CTRL_BIT_SIZE_8;
|
||||
sample_size = 8;
|
||||
cif_conf.audio_bits = TEGRA210_AUDIOCIF_BITS_8;
|
||||
cif_conf.client_bits = TEGRA210_AUDIOCIF_BITS_8;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
val = TEGRA210_I2S_CTRL_BIT_SIZE_16;
|
||||
sample_size = 16;
|
||||
cif_conf.audio_bits = TEGRA210_AUDIOCIF_BITS_16;
|
||||
cif_conf.client_bits = TEGRA210_AUDIOCIF_BITS_16;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S24_LE:
|
||||
val = TEGRA210_I2S_CTRL_BIT_SIZE_24;
|
||||
sample_size = 24;
|
||||
cif_conf.audio_bits = TEGRA210_AUDIOCIF_BITS_24;
|
||||
cif_conf.client_bits = TEGRA210_AUDIOCIF_BITS_24;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S32_LE:
|
||||
val = TEGRA210_I2S_CTRL_BIT_SIZE_32;
|
||||
sample_size = 32;
|
||||
cif_conf.audio_bits = TEGRA210_AUDIOCIF_BITS_32;
|
||||
cif_conf.client_bits = TEGRA210_AUDIOCIF_BITS_32;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "Wrong format!\n");
|
||||
@@ -275,19 +315,35 @@ static int tegra210_i2s_hw_params(struct snd_pcm_substream *substream,
|
||||
frame_format = val & TEGRA210_I2S_CTRL_FRAME_FORMAT_MASK;
|
||||
|
||||
if (frame_format == TEGRA210_I2S_CTRL_FRAME_FORMAT_FSYNC_MODE) {
|
||||
regmap_write(i2s->regmap, TEGRA210_I2S_SLOT_CTRL, channels - 1);
|
||||
regmap_write(i2s->regmap, TEGRA210_I2S_AXBAR_TX_SLOT_CTRL,
|
||||
((1 << channels) - 1));
|
||||
regmap_write(i2s->regmap, TEGRA210_I2S_AXBAR_RX_SLOT_CTRL,
|
||||
((1 << channels) - 1));
|
||||
i2s->soc_data->set_slot_ctrl(i2s->regmap, channels,
|
||||
i2s->tx_mask, i2s->rx_mask);
|
||||
/* FIXUP : I2S fifo threshold set to 3 when AFC is connected */
|
||||
cif_conf.threshold = 3;
|
||||
cif_conf.audio_channels = channels;
|
||||
cif_conf.client_channels = channels;
|
||||
cif_conf.expand = 0;
|
||||
cif_conf.stereo_conv = 0;
|
||||
cif_conf.replicate = 0;
|
||||
cif_conf.truncate = 0;
|
||||
cif_conf.mono_conv = 0;
|
||||
} else {
|
||||
cif_conf.threshold = 3;
|
||||
cif_conf.audio_channels = channels;
|
||||
cif_conf.client_channels = (channels == 1) ? 2 : channels;
|
||||
cif_conf.expand = 0;
|
||||
cif_conf.stereo_conv = 0;
|
||||
cif_conf.replicate = 0;
|
||||
cif_conf.truncate = 0;
|
||||
cif_conf.mono_conv = 0;
|
||||
}
|
||||
|
||||
i2sclock = srate * channels * sample_size;
|
||||
i2sclock = srate * sample_size * cif_conf.client_channels;
|
||||
|
||||
if (i2s->bclk_ratio != 0)
|
||||
i2sclock *= i2s->bclk_ratio;
|
||||
|
||||
bitcnt = (i2sclock / srate) - 1;
|
||||
|
||||
if ((bitcnt < 0) ||
|
||||
(bitcnt > TEGRA210_I2S_TIMING_CHANNEL_BIT_CNT_MASK)) {
|
||||
dev_err(dev, "Can't set channel bit count\n");
|
||||
@@ -311,24 +367,6 @@ static int tegra210_i2s_hw_params(struct snd_pcm_substream *substream,
|
||||
|
||||
regmap_write(i2s->regmap, TEGRA210_I2S_TIMING, val);
|
||||
|
||||
regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL,
|
||||
TEGRA210_I2S_CTRL_FSYNC_WIDTH_MASK,
|
||||
31 << TEGRA210_I2S_CTRL_FSYNC_WIDTH_SHIFT);
|
||||
|
||||
cif_conf.threshold = 0;
|
||||
cif_conf.audio_channels = channels;
|
||||
cif_conf.client_channels = channels;
|
||||
cif_conf.audio_bits = (sample_size == 16 ? TEGRA210_AUDIOCIF_BITS_16 :
|
||||
TEGRA210_AUDIOCIF_BITS_32);
|
||||
|
||||
cif_conf.client_bits = (sample_size == 16 ? TEGRA210_AUDIOCIF_BITS_16 :
|
||||
TEGRA210_AUDIOCIF_BITS_32);
|
||||
cif_conf.expand = 0;
|
||||
cif_conf.stereo_conv = 0;
|
||||
cif_conf.replicate = 0;
|
||||
cif_conf.truncate = 0;
|
||||
cif_conf.mono_conv = 0;
|
||||
|
||||
/* As a COCEC DAI, CAPTURE is transmit */
|
||||
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
|
||||
reg = TEGRA210_I2S_AXBAR_RX_CIF_CTRL;
|
||||
@@ -388,6 +426,7 @@ static struct snd_soc_dai_ops tegra210_i2s_dai_ops = {
|
||||
.set_fmt = tegra210_i2s_set_fmt,
|
||||
.hw_params = tegra210_i2s_hw_params,
|
||||
.set_bclk_ratio = tegra210_i2s_set_dai_bclk_ratio,
|
||||
.set_tdm_slot = tegra210_i2s_set_tdm_slot,
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver tegra210_i2s_dais[] = {
|
||||
@@ -577,6 +616,7 @@ static const struct regmap_config tegra210_i2s_regmap_config = {
|
||||
|
||||
static const struct tegra210_i2s_soc_data soc_data_tegra210 = {
|
||||
.set_audio_cif = tegra210_xbar_set_cif,
|
||||
.set_slot_ctrl = tegra210_i2s_set_slot_ctrl,
|
||||
};
|
||||
|
||||
static const struct of_device_id tegra210_i2s_of_match[] = {
|
||||
@@ -613,6 +653,7 @@ static int tegra210_i2s_platform_probe(struct platform_device *pdev)
|
||||
dev_set_drvdata(&pdev->dev, i2s);
|
||||
|
||||
i2s->soc_data = soc_data;
|
||||
i2s->tx_mask = i2s->rx_mask = 0xFFFF;
|
||||
i2s->bclk_ratio = 2;
|
||||
|
||||
i2s->clk_i2s = devm_clk_get(&pdev->dev, NULL);
|
||||
@@ -687,6 +728,19 @@ static int tegra210_i2s_platform_probe(struct platform_device *pdev)
|
||||
goto err_pll_a_out0_clk_put;
|
||||
}
|
||||
|
||||
if (of_property_read_u32(pdev->dev.of_node,
|
||||
"fsync-width", &i2s->fsync_width) < 0) {
|
||||
dev_warn(&pdev->dev, "Missing prop fsync-width for I2S%d\n",
|
||||
pdev->dev.id);
|
||||
i2s->fsync_width = 31;
|
||||
}
|
||||
|
||||
if (i2s->fsync_width > 255) {
|
||||
dev_warn(&pdev->dev, "Default fsync-width to 31 for I2S%d\n",
|
||||
pdev->dev.id);
|
||||
i2s->fsync_width = 31;
|
||||
}
|
||||
|
||||
num_supplies = of_property_count_strings(np, "regulator-supplies");
|
||||
if (num_supplies > 0) {
|
||||
i2s->num_supplies = num_supplies;
|
||||
|
||||
Reference in New Issue
Block a user