mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 09:11:26 +03:00
sound: soc: tegra: Fix Tegra210 I2S Fsync Polarity
The 'normal' polarity of the fsync is dependent on the audio format. For example, for I2S the 'normal' polarity for the fsync is falling-edge/low, where as for r/l-justified or dsp modes A/B it is rising-edge/high. This is detailed in the Tegra210 TRM in the table titled "Programming I2S to Operate in Various Modes" and also in the Linux kernel header file for include/sound/soc-dai.h. The Tegra210 i2s driver always assumes that the fsync is low for 'normal' polarity and high for 'inverted' polarity and does not account for the audio format. Correct the Tegra210 I2S driver to set the polarity according the the audio format. Bug 1788838 Bug 1993738 Change-Id: I5c7395f225ff8c25e2bb277c35e3ecb7a86f36cb Signed-off-by: Jon Hunter <jonathanh@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1567742 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: svccoveritychecker <svccoveritychecker@nvidia.com> Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com> Reviewed-by: Ravindra Lokhande <rlokhande@nvidia.com> Reviewed-by: Mohan Kumar D <mkumard@nvidia.com> Reviewed-by: Sameer Pujar <spujar@nvidia.com> Reviewed-by: Bibek Basu <bbasu@nvidia.com> Tested-by: Bibek Basu <bbasu@nvidia.com> GVS: Gerrit_Virtual_Submit
This commit is contained in:
@@ -313,35 +313,13 @@ static int tegra210_i2s_set_fmt(struct snd_soc_dai *dai,
|
||||
struct tegra210_i2s *i2s = snd_soc_dai_get_drvdata(dai);
|
||||
unsigned int mask, val, data_offset;
|
||||
|
||||
mask = TEGRA210_I2S_CTRL_EDGE_CTRL_MASK;
|
||||
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
|
||||
case SND_SOC_DAIFMT_NB_NF:
|
||||
val = TEGRA210_I2S_CTRL_EDGE_CTRL_POS_EDGE;
|
||||
val |= TEGRA210_I2S_CTRL_LRCK_POLARITY_LOW;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_NB_IF:
|
||||
val = TEGRA210_I2S_CTRL_EDGE_CTRL_POS_EDGE;
|
||||
val |= TEGRA210_I2S_CTRL_LRCK_POLARITY_HIGH;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_IB_NF:
|
||||
val = TEGRA210_I2S_CTRL_EDGE_CTRL_NEG_EDGE;
|
||||
val |= TEGRA210_I2S_CTRL_LRCK_POLARITY_LOW;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_IB_IF:
|
||||
val = TEGRA210_I2S_CTRL_EDGE_CTRL_NEG_EDGE;
|
||||
val |= TEGRA210_I2S_CTRL_LRCK_POLARITY_HIGH;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mask |= TEGRA210_I2S_CTRL_MASTER_EN_MASK;
|
||||
mask = TEGRA210_I2S_CTRL_MASTER_EN_MASK;
|
||||
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
|
||||
case SND_SOC_DAIFMT_CBS_CFS:
|
||||
val &= ~(TEGRA210_I2S_CTRL_MASTER_EN);
|
||||
val = 0;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_CBM_CFM:
|
||||
val |= TEGRA210_I2S_CTRL_MASTER_EN;
|
||||
val = TEGRA210_I2S_CTRL_MASTER_EN;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@@ -352,30 +330,55 @@ static int tegra210_i2s_set_fmt(struct snd_soc_dai *dai,
|
||||
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
case SND_SOC_DAIFMT_DSP_A:
|
||||
val |= TEGRA210_I2S_CTRL_FRAME_FORMAT_FSYNC_MODE;
|
||||
val |= TEGRA210_I2S_CTRL_LRCK_POLARITY_HIGH;
|
||||
data_offset = 1;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_DSP_B:
|
||||
val |= TEGRA210_I2S_CTRL_FRAME_FORMAT_FSYNC_MODE;
|
||||
val |= TEGRA210_I2S_CTRL_LRCK_POLARITY_HIGH;
|
||||
data_offset = 0;
|
||||
break;
|
||||
/* I2S mode has data offset of 1 */
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
val |= TEGRA210_I2S_CTRL_FRAME_FORMAT_LRCK_MODE;
|
||||
val |= TEGRA210_I2S_CTRL_LRCK_POLARITY_LOW;
|
||||
data_offset = 1;
|
||||
break;
|
||||
/* LJ/RJ mode assumed to operate at bclk = 64fs */
|
||||
case SND_SOC_DAIFMT_RIGHT_J:
|
||||
val |= TEGRA210_I2S_CTRL_FRAME_FORMAT_LRCK_MODE;
|
||||
val |= TEGRA210_I2S_CTRL_LRCK_POLARITY_HIGH;
|
||||
data_offset = 16;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_LEFT_J:
|
||||
val |= TEGRA210_I2S_CTRL_FRAME_FORMAT_LRCK_MODE;
|
||||
val |= TEGRA210_I2S_CTRL_LRCK_POLARITY_HIGH;
|
||||
data_offset = 0;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mask |= TEGRA210_I2S_CTRL_EDGE_CTRL_MASK;
|
||||
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
|
||||
case SND_SOC_DAIFMT_NB_NF:
|
||||
val |= TEGRA210_I2S_CTRL_EDGE_CTRL_POS_EDGE;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_NB_IF:
|
||||
val |= TEGRA210_I2S_CTRL_EDGE_CTRL_POS_EDGE;
|
||||
val ^= TEGRA210_I2S_CTRL_LRCK_POLARITY_MASK;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_IB_NF:
|
||||
val |= TEGRA210_I2S_CTRL_EDGE_CTRL_NEG_EDGE;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_IB_IF:
|
||||
val |= TEGRA210_I2S_CTRL_EDGE_CTRL_NEG_EDGE;
|
||||
val ^= TEGRA210_I2S_CTRL_LRCK_POLARITY_MASK;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pm_runtime_get_sync(dai->dev);
|
||||
regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, mask, val);
|
||||
/* FIXME: global enabling */
|
||||
|
||||
Reference in New Issue
Block a user