summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorNikesh Oswal <noswal@nvidia.com>2011-01-19 23:06:45 +0530
committerNiket Sirsi <nsirsi@nvidia.com>2011-01-25 15:27:22 -0800
commit7f31538897c8f1504f37bc837e7be9a356e2f863 (patch)
tree31314b65c996efc20f9e7dd3922ed1845896f8f1 /sound
parent92bf9f72fdf696de72de6186a1e1cd8818f3bb15 (diff)
sound: tegra: Enabled Recording and fixed volume
- Enabled Recording for WM8753. - Fixed low Volume in Play Back by enabling LDO7 - Fixed noise in PlayBack and Recording by using a bclk of 2.82 Mhz Bug 771506 Change-Id: I0c43adafa83969929cfdff700a71a68225ab4c22 Reviewed-on: http://git-master/r/16260 Tested-by: Nikesh Oswal <noswal@nvidia.com> Reviewed-by: Sachin Nikam <snikam@nvidia.com> Tested-by: Sachin Nikam <snikam@nvidia.com> Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/tegra/tegra_i2s.c16
-rw-r--r--sound/soc/tegra/tegra_soc_wm8753.c246
2 files changed, 228 insertions, 34 deletions
diff --git a/sound/soc/tegra/tegra_i2s.c b/sound/soc/tegra/tegra_i2s.c
index 92d4f4a2ca65..8d023d10d7f0 100644
--- a/sound/soc/tegra/tegra_i2s.c
+++ b/sound/soc/tegra/tegra_i2s.c
@@ -257,6 +257,22 @@ static int tegra_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
static int tegra_i2s_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
int clk_id, unsigned int freq, int dir)
{
+ struct tegra_i2s_info* info = cpu_dai->private_data;
+
+ if (info && info->i2s_clk) {
+ clk_set_rate(info->i2s_clk, freq);
+ if (clk_enable(info->i2s_clk)) {
+ pr_err("%s: failed to enable i2s-%d clock\n", __func__,
+ cpu_dai->id+1);
+ return -EIO;
+ }
+ }
+ else {
+ pr_err("%s: could not get i2s-%d clock\n", __func__,
+ cpu_dai->id+1);
+ return -EIO;
+ }
+
return 0;
}
diff --git a/sound/soc/tegra/tegra_soc_wm8753.c b/sound/soc/tegra/tegra_soc_wm8753.c
index 5a562f9e119d..103774e60639 100644
--- a/sound/soc/tegra/tegra_soc_wm8753.c
+++ b/sound/soc/tegra/tegra_soc_wm8753.c
@@ -26,93 +26,252 @@
#include "tegra_soc.h"
#include "../codecs/wm8753.h"
-
-#define WM8753_PWR1_VMIDSEL_EN 0x80 /* Vmid divider enable and select */
-#define WM8753_PWR1_VREF_EN 0x40 /* VREF Enable */
-#define WM8753_PWR1_DACL_EN 0x08 /* DAC Left Enable */
-#define WM8753_PWR1_DACR_EN 0x04 /* VREF Enable */
-
-#define WM8753_PWR3_LOU1_EN 0x100 /* LOUT1 Enable */
-#define WM8753_PWR3_ROU1_EN 0x70 /* ROUT1 Enable */
-
-#define WM8753_PWR4_RIGHTMIX_EN 0x02 /* Right mixer enable */
-#define WM8753_PWR4_LEFTMIX_EN 0x01 /* Left mixer enable */
-
-#define WM8753_LOUTM1_LD2LO 0x100 /* Left DAC to Left Mixer */
-#define WM8753_LOUTM1_LM2LO 0x80
-#define WM8753_LOUTM1_LM2LOVOL 0x70 /* LM Signal to Left Mixer Volume */
-
-#define WM8753_ROUTM1_RD2RO 0x100 /* Right DAC to Right Mixer */
-#define WM8753_ROUTM1_RM2RO 0x80
-#define WM8753_ROUTM1_RM2ROVOL 0x70 /* RM Signal to Right Mixer Volume */
+#include <linux/regulator/consumer.h>
+
+#define WM8753_PWR1_VMIDSEL_1 1<<8
+#define WM8753_PWR1_VMIDSEL_0 1<<7
+#define WM8753_PWR1_VREF 1<<6
+#define WM8753_PWR1_MICB 1<<5
+#define WM8753_PWR1_DACL 1<<3
+#define WM8753_PWR1_DACR 1<<2
+
+#define WM8753_PWR2_MICAMP1EN 1<<8
+#define WM8753_PWR2_MICAMP2EN 1<<7
+#define WM8753_PWR2_ALCMIX 1<<6
+#define WM8753_PWR2_PGAL 1<<5
+#define WM8753_PWR2_PGAR 1<<4
+#define WM8753_PWR2_ADCL 1<<3
+#define WM8753_PWR2_ADCR 1<<2
+#define WM8753_PWR2_RXMIX 1<<1
+#define WM8753_PWR2_LINEMIX 1<<0
+
+#define WM8753_PWR3_LOUT1 1<<8
+#define WM8753_PWR3_ROUT1 1<<7
+#define WM8753_PWR3_LOUT2 1<<6
+#define WM8753_PWR3_ROUT2 1<<5
+#define WM8753_PWR3_OUT3 1<<4
+#define WM8753_PWR3_OUT4 1<<3
+#define WM8753_PWR3_MONO1 1<<2
+#define WM8753_PWR3_MONO2 1<<1
+
+#define WM8753_PWR4_RECMIX 1<<3
+#define WM8753_PWR4_MONOMIX 1<<2
+#define WM8753_PWR4_RIGHTMIX 1<<1
+#define WM8753_PWR4_LEFTMIX 1<<0
+
+#define WM8753_IOCTL_VXCLKTRI 1<<7
+#define WM8753_IOCTL_BCCLKTRI 1<<6
+#define WM8753_IOCTL_VXDTRI 1<<5
+#define WM8753_IOCTL_ADCTRI 1<<4
+#define WM8753_IOCTL_IFMODE_1 1<<3
+#define WM8753_IOCTL_IFMODE_0 1<<2
+#define WM8753_IOCTL_VXFSOE 1<<1
+#define WM8753_IOCTL_LRCOE 1<<0
+
+#define WM8753_LOUTM1_LD2LO 1<<8
+
+#define WM8753_ROUTM1_RD2RO 1<<8
+
+#define WM8753_ADCIN_MONOMIX_1 1<<5
+#define WM8753_ADCIN_MONOMIX_0 1<<4
+#define WM8753_ADCIN_RADCSEL_1 1<<3
+#define WM8753_ADCIN_RADCSEL_0 1<<2
+#define WM8753_ADCIN_LADCSEL_1 1<<1
+#define WM8753_ADCIN_LADCSEL_0 1<<0
+
+#define WM8753_INCTL1_MIC2BOOST_1 1<<8
+#define WM8753_INCTL1_MIC2BOOST_0 1<<7
+
+#define WM8753_INCTL2_MICMUX_1 1<<5
+#define WM8753_INCTL2_MICMUX_0 1<<4
+
+#define WM8753_ADC_DATSEL_1 1<<8
+#define WM8753_ADC_DATSEL_0 1<<7
+#define WM8753_ADC_ADCPOL_1 1<<6
+#define WM8753_ADC_ADCPOL_0 1<<5
+#define WM8753_ADC_VXFILT 1<<4
+#define WM8753_ADC_HPMODE_1 1<<3
+#define WM8753_ADC_HPMODE_0 1<<2
+#define WM8753_ADC_HPOR 1<<1
+#define WM8753_ADC_ADCHPD 1<<0
+
+#define WM8753_LINVOL_MAX 0x11F
+
+#define WM8753_RINVOL_MAX 0x11F
static struct platform_device *tegra_snd_device;
+static struct regulator* wm8753_reg;
extern struct snd_soc_dai tegra_i2s_dai[];
extern struct snd_soc_platform tegra_soc_platform;
static int tegra_hifi_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
int err;
unsigned int value;
+ unsigned int channels, rate, bit_size = 16;
+ struct snd_soc_codec *codec = codec_dai->codec;
+
+ rate = params_rate(params); /* Sampling Rate in Hz */
+ channels = params_channels(params); /* Number of channels */
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ bit_size = 16;
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ bit_size = 20;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ bit_size = 24;
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ bit_size = 32;
+ break;
+ default:
+ pr_err(KERN_ERR "Invalid pcm format size\n");
+ return EINVAL;
+ }
err = snd_soc_dai_set_fmt(codec_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS);
+ SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS);
if (err < 0) {
- pr_err(KERN_ERR "codec_dai fmt not set \n");
+ pr_err(KERN_ERR "codec_dai fmt not set\n");
return err;
}
err = snd_soc_dai_set_fmt(cpu_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS);
+ SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS);
if (err < 0) {
- pr_err(KERN_ERR "cpu_dai fmt not set \n");
+ pr_err(KERN_ERR "cpu_dai fmt not set\n");
return err;
}
- err = snd_soc_dai_set_sysclk(codec_dai, 0, I2S_CLK, SND_SOC_CLOCK_IN);
+ err = snd_soc_dai_set_sysclk(codec_dai, 0, bit_size*rate*channels*2*4,
+ SND_SOC_CLOCK_IN);
if (err < 0) {
pr_err(KERN_ERR "codec_dai clock not set\n");
return err;
}
- err = snd_soc_dai_set_sysclk(cpu_dai, 0, I2S_CLK, SND_SOC_CLOCK_IN);
+ err = snd_soc_dai_set_sysclk(cpu_dai, 0, bit_size*rate*channels*2,
+ SND_SOC_CLOCK_IN);
if (err < 0) {
pr_err(KERN_ERR "cpu_dai clock not set\n");
return err;
}
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ /* Enables MICBIAS, VMIDSEL and VREF, DAC-L and DAC-R */
value = snd_soc_read(codec_dai->codec, WM8753_PWR1);
- value |= WM8753_PWR1_VMIDSEL_EN | WM8753_PWR1_VREF_EN |
- WM8753_PWR1_DACL_EN |WM8753_PWR1_DACR_EN;
+ value |= (WM8753_PWR1_VMIDSEL_0 | WM8753_PWR1_VREF |
+ WM8753_PWR1_MICB | WM8753_PWR1_DACL |
+ WM8753_PWR1_DACR);
+ value &= ~(WM8753_PWR1_VMIDSEL_1);
snd_soc_write(codec_dai->codec, WM8753_PWR1, value);
+ /* Enables Lout1 and Rout1 */
value = snd_soc_read(codec_dai->codec, WM8753_PWR3);
- value |= WM8753_PWR3_LOU1_EN | WM8753_PWR3_ROU1_EN;
+ value |= (WM8753_PWR3_LOUT1 | WM8753_PWR3_ROUT1);
snd_soc_write(codec_dai->codec, WM8753_PWR3, value);
+ /* Left and Right Mix Enabled */
value = snd_soc_read(codec_dai->codec, WM8753_PWR4);
- value |= WM8753_PWR4_RIGHTMIX_EN | WM8753_PWR4_LEFTMIX_EN;
+ value |= (WM8753_PWR4_RIGHTMIX | WM8753_PWR4_LEFTMIX);
snd_soc_write(codec_dai->codec, WM8753_PWR4, value);
+ /* Mode set to HiFi over HiFi interface and VXDOUT,ADCDAT,
+ VXCLK and BCLK pin enabled */
+ value = snd_soc_read(codec_dai->codec, WM8753_IOCTL);
+ value |= (WM8753_IOCTL_IFMODE_1);
+ value &= ~(WM8753_IOCTL_VXCLKTRI | WM8753_IOCTL_BCCLKTRI |
+ WM8753_IOCTL_VXDTRI | WM8753_IOCTL_ADCTRI |
+ WM8753_IOCTL_IFMODE_0 | WM8753_IOCTL_VXFSOE |
+ WM8753_IOCTL_LRCOE);
+ snd_soc_write(codec_dai->codec, WM8753_IOCTL, value);
+
+ /* L-DAC to L-Mix */
value = snd_soc_read(codec_dai->codec, WM8753_LOUTM1);
value |= WM8753_LOUTM1_LD2LO;
snd_soc_write(codec_dai->codec, WM8753_LOUTM1, value);
+ /* R-DAC to R-Mix */
value = snd_soc_read(codec_dai->codec, WM8753_ROUTM1);
value |= WM8753_ROUTM1_RD2RO;
snd_soc_write(codec_dai->codec, WM8753_ROUTM1, value);
}
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+ /* PGA i/p's to L and R ADC and operation in stero mode */
+ value = snd_soc_read(codec_dai->codec, WM8753_ADCIN);
+ value &= ~(WM8753_ADCIN_MONOMIX_1 | WM8753_ADCIN_MONOMIX_0 |
+ WM8753_ADCIN_RADCSEL_1 | WM8753_ADCIN_RADCSEL_0 |
+ WM8753_ADCIN_LADCSEL_1 | WM8753_ADCIN_LADCSEL_0);
+ snd_soc_write(codec_dai->codec, WM8753_ADCIN, value);
+
+ /* 24 db boost for Mic2 */
+ value = snd_soc_read(codec_dai->codec, WM8753_INCTL1);
+ value |= (WM8753_INCTL1_MIC2BOOST_1);
+ value &= ~(WM8753_INCTL1_MIC2BOOST_0);
+ snd_soc_write(codec_dai->codec, WM8753_INCTL1, value);
+
+ /* Side-Tone-Mic2 preamp o/p */
+ value = snd_soc_read(codec_dai->codec, WM8753_INCTL2);
+ value |= (WM8753_INCTL2_MICMUX_1);
+ value &= ~(WM8753_INCTL2_MICMUX_0);
+ snd_soc_write(codec_dai->codec, WM8753_INCTL2, value);
+
+ /* L and R data from R-ADC */
+ value = snd_soc_read(codec_dai->codec, WM8753_ADC);
+ value |= (WM8753_ADC_DATSEL_1);
+ value &= ~(WM8753_ADC_DATSEL_0 | WM8753_ADC_ADCPOL_1 |
+ WM8753_ADC_ADCPOL_0 | WM8753_ADC_VXFILT |
+ WM8753_ADC_HPMODE_1 | WM8753_ADC_HPMODE_0 |
+ WM8753_ADC_HPOR | WM8753_ADC_ADCHPD);
+ snd_soc_write(codec_dai->codec, WM8753_ADC, value);
+
+ /* Disable Mute and set L-PGA Vol to max */
+ snd_soc_write(codec, WM8753_LINVOL, WM8753_LINVOL_MAX);
+
+ /* Disable Mute and set R-PGA Vol to max */
+ snd_soc_write(codec, WM8753_RINVOL, WM8753_RINVOL_MAX);
+
+ /* Enables MICBIAS, VMIDSEL and VREF */
+ value = snd_soc_read(codec_dai->codec, WM8753_PWR1);
+ value |= (WM8753_PWR1_VMIDSEL_0|WM8753_PWR1_VREF|
+ WM8753_PWR1_MICB);
+ value &= ~(WM8753_PWR1_VMIDSEL_1);
+ snd_soc_write(codec_dai->codec, WM8753_PWR1, value);
+
+ /* Enable Mic2 preamp, PGA-R and ADC-R (Mic1 preamp,ALC Mix,
+ PGA-L , ADC-L, RXMIX and LINEMIX disabled) */
+ value = snd_soc_read(codec_dai->codec, WM8753_PWR2);
+ value |= (WM8753_PWR2_MICAMP2EN | WM8753_PWR2_PGAR|
+ WM8753_PWR2_ADCR);
+ value &= ~(WM8753_PWR2_MICAMP1EN | WM8753_PWR2_ALCMIX |
+ WM8753_PWR2_PGAL | WM8753_PWR2_ADCL |
+ WM8753_PWR2_RXMIX | WM8753_PWR2_LINEMIX);
+ snd_soc_write(codec, WM8753_PWR2, value);
+
+ /* Mode set to HiFi over HiFi interface and VXDOUT,ADCDAT,
+ VXCLK and BCLK pin enabled */
+ value = snd_soc_read(codec_dai->codec, WM8753_IOCTL);
+ value |= (WM8753_IOCTL_IFMODE_1);
+ value &= ~(WM8753_IOCTL_VXCLKTRI | WM8753_IOCTL_BCCLKTRI |
+ WM8753_IOCTL_VXDTRI | WM8753_IOCTL_ADCTRI |
+ WM8753_IOCTL_IFMODE_0 | WM8753_IOCTL_VXFSOE |
+ WM8753_IOCTL_LRCOE);
+ snd_soc_write(codec_dai->codec, WM8753_IOCTL, value);
+ }
+
return 0;
}
@@ -198,6 +357,19 @@ static int __init tegra_init(void)
goto fail;
}
+ wm8753_reg = regulator_get(NULL, "avddio_audio");
+ if (IS_ERR(wm8753_reg)) {
+ ret = PTR_ERR(wm8753_reg);
+ pr_err("unable to get wm8753 regulator\n");
+ goto fail;
+ }
+
+ ret = regulator_enable(wm8753_reg);
+ if (ret) {
+ pr_err("wm8753 regulator enable failed\n");
+ goto err_put_regulator;
+ }
+
return 0;
fail:
@@ -207,12 +379,18 @@ fail:
}
return ret;
+
+err_put_regulator:
+ regulator_put(wm8753_reg);
+ return ret;
}
static void __exit tegra_exit(void)
{
tegra_controls_exit();
platform_device_unregister(tegra_snd_device);
+ regulator_disable(wm8753_reg);
+ regulator_put(wm8753_reg);
}
module_init(tegra_init);