summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorNikesh Oswal <noswal@nvidia.com>2013-06-10 21:18:40 +0530
committerDan Willemsen <dwillemsen@nvidia.com>2013-09-14 13:28:24 -0700
commita153870f0bd6e78652d7a61d764d221bedee1d0e (patch)
treede8becef4e4c8a37339447918a47498769929ea5 /sound
parent6c72d0a328df007132678788dca532d8f330f804 (diff)
asoc: tegra: rt5645: set clk for 24 bit audio
Change-Id: Iffccb194ca75699f305cfe59493c2a3c71e79456 Signed-off-by: Nikesh Oswal <noswal@nvidia.com> Reviewed-on: http://git-master/r/241913 Reviewed-by: Seema Khowala <seemaj@nvidia.com> Tested-by: Seema Khowala <seemaj@nvidia.com>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/tegra/tegra_rt5645.c53
1 files changed, 50 insertions, 3 deletions
diff --git a/sound/soc/tegra/tegra_rt5645.c b/sound/soc/tegra/tegra_rt5645.c
index c110c7c966ba..75d77efa9873 100644
--- a/sound/soc/tegra/tegra_rt5645.c
+++ b/sound/soc/tegra/tegra_rt5645.c
@@ -95,8 +95,9 @@ static int tegra_rt5645_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_card *card = codec->card;
struct tegra_rt5645 *machine = snd_soc_card_get_drvdata(card);
struct tegra_asoc_platform_data *pdata = machine->pdata;
- int srate, mclk, i2s_daifmt;
- int err, rate;
+ int srate, mclk, i2s_daifmt, codec_daifmt;
+ int err, rate, sample_size;
+ unsigned int i2sclock;
srate = params_rate(params);
mclk = 256 * srate;
@@ -105,6 +106,23 @@ static int tegra_rt5645_hw_params(struct snd_pcm_substream *substream,
i2s_daifmt |= pdata->i2s_param[HIFI_CODEC].is_i2s_master ?
SND_SOC_DAIFMT_CBS_CFS : SND_SOC_DAIFMT_CBM_CFM;
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S8:
+ sample_size = 8;
+ break;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ sample_size = 16;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ sample_size = 24;
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ sample_size = 32;
+ break;
+ default:
+ return -EINVAL;
+ }
+
switch (pdata->i2s_param[HIFI_CODEC].i2s_mode) {
case TEGRA_DAIFMT_I2S:
i2s_daifmt |= SND_SOC_DAIFMT_I2S;
@@ -162,7 +180,36 @@ static int tegra_rt5645_hw_params(struct snd_pcm_substream *substream,
}
}
- err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt);
+ /*for 24 bit audio we support only S24_LE (S24_3LE is not supported)
+ which is rendered on bus in 32 bits packet so consider as 32 bit
+ depth in clock calculations, extra 4 is required by codec,
+ God knows why ?*/
+ if (sample_size == 24)
+ i2sclock = srate * params_channels(params) * 32 * 4;
+ else
+ i2sclock = 0;
+
+ err = snd_soc_dai_set_sysclk(cpu_dai, 0,
+ i2sclock, SND_SOC_CLOCK_OUT);
+ if (err < 0) {
+ dev_err(card->dev, "cpu_dai clock not set\n");
+ return err;
+ }
+
+ codec_daifmt = i2s_daifmt;
+
+ /*invert the codec bclk polarity when codec is master
+ in DSP mode this is done to match with the negative
+ edge settings of tegra i2s*/
+ if (((i2s_daifmt & SND_SOC_DAIFMT_FORMAT_MASK)
+ == SND_SOC_DAIFMT_DSP_A) &&
+ ((i2s_daifmt & SND_SOC_DAIFMT_MASTER_MASK)
+ == SND_SOC_DAIFMT_CBM_CFM)) {
+ codec_daifmt &= ~(SND_SOC_DAIFMT_INV_MASK);
+ codec_daifmt |= SND_SOC_DAIFMT_IB_NF;
+ }
+
+ err = snd_soc_dai_set_fmt(codec_dai, codec_daifmt);
if (err < 0) {
dev_err(card->dev, "codec_dai fmt not set\n");
return err;