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:
Jon Hunter
2017-09-22 16:07:19 +01:00
committed by Sameer Pujar
parent 52b1047acc
commit 90ef4d49b0

View File

@@ -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 */