diff options
author | Nikesh Oswal <noswal@nvidia.com> | 2013-06-10 21:18:40 +0530 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2013-09-14 13:28:24 -0700 |
commit | a153870f0bd6e78652d7a61d764d221bedee1d0e (patch) | |
tree | de8becef4e4c8a37339447918a47498769929ea5 /sound | |
parent | 6c72d0a328df007132678788dca532d8f330f804 (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.c | 53 |
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; |