diff options
author | Ravindra Lokhande <rlokhande@nvidia.com> | 2011-01-12 17:20:38 +0530 |
---|---|---|
committer | Bharat Nihalani <bnihalani@nvidia.com> | 2011-01-12 21:51:38 -0800 |
commit | 1503bf380cf05df14cf477245ee21228d75dbff9 (patch) | |
tree | 4e8e5933d14ffcddf57ebbf9632047df6244d5fc | |
parent | 6b27d35c0ccb5193691282feef2e1d5abfdd1ce2 (diff) |
[tegra ALSA] separated codec and control code
- separated codec and control code
- codec specific code is added to tegra_soc_xxx
- alsa controls code added to tegra_soc_controls
Fixes bug 759167
Change-Id: Ib8cd19364b3d4a0cb726d20b4eb1a7fab4017bf1
Reviewed-on: http://git-master/r/15637
Tested-by: Ravindra Lokhande <rlokhande@nvidia.com>
Reviewed-by: Sachin Nikam <snikam@nvidia.com>
Reviewed-by: Scott Peterson <speterson@nvidia.com>
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
-rw-r--r-- | sound/soc/tegra/Makefile | 9 | ||||
-rw-r--r-- | sound/soc/tegra/tegra_soc.h | 3 | ||||
-rw-r--r-- | sound/soc/tegra/tegra_soc_controls.c (renamed from sound/soc/tegra/tegra_soc.c) | 277 | ||||
-rw-r--r-- | sound/soc/tegra/tegra_soc_wm8903.c | 227 |
4 files changed, 271 insertions, 245 deletions
diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile index b1bc3d02109c..afd353f62f9e 100644 --- a/sound/soc/tegra/Makefile +++ b/sound/soc/tegra/Makefile @@ -1,6 +1,7 @@ -ccflags-y += -DNV_DEBUG=0 -obj-$(CONFIG_TEGRA_PCM) += tegra_pcm.o -obj-$(CONFIG_TEGRA_I2S) += tegra_i2s.o -obj-$(CONFIG_TEGRA_ALSA) += tegra_soc.o +ccflags-y += -DNV_DEBUG=0 +obj-$(CONFIG_TEGRA_PCM) += tegra_pcm.o +obj-$(CONFIG_TEGRA_I2S) += tegra_i2s.o +obj-$(CONFIG_TEGRA_ALSA) += tegra_soc_controls.o +obj-${CONFIG_SND_SOC_WM8903} += tegra_soc_wm8903.o diff --git a/sound/soc/tegra/tegra_soc.h b/sound/soc/tegra/tegra_soc.h index 5aeedc9fd0d4..c9ef76acebc0 100644 --- a/sound/soc/tegra/tegra_soc.h +++ b/sound/soc/tegra/tegra_soc.h @@ -106,4 +106,7 @@ struct tegra_audio_data { bool is_call_mode; }; +int tegra_controls_init(struct snd_soc_codec *codec); +void tegra_controls_exit(void); + #endif diff --git a/sound/soc/tegra/tegra_soc.c b/sound/soc/tegra/tegra_soc_controls.c index afb3d1c761a2..a090740a3f7d 100644 --- a/sound/soc/tegra/tegra_soc.c +++ b/sound/soc/tegra/tegra_soc_controls.c @@ -1,25 +1,27 @@ /* - * tegra_soc.c -- SoC audio for tegra + * tegra_soc_controls.c -- alsa controls for tegra SoC * - * (c) 2010 Nvidia Graphics Pvt. Ltd. - * http://www.nvidia.com + * Copyright (c) 2010, NVIDIA Corporation. * - * Copyright 2007 Wolfson Microelectronics PLC. - * Author: Graeme Gregory - * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + #include "tegra_soc.h" #include <mach/audio.h> -#include "../codecs/wm8903.h" -static struct platform_device *tegra_snd_device; static struct tegra_audio_data *audio_data; static int tegra_jack_func; static int tegra_spk_func; @@ -32,38 +34,6 @@ static int tegra_spk_func; #define TEGRA_SPK_ON 0 #define TEGRA_SPK_OFF 1 -/* codec register values */ -#define B07_INEMUTE 7 -#define B06_VOL_M3DB 6 -#define B00_IN_VOL 0 -#define B00_INR_ENA 0 -#define B01_INL_ENA 1 -#define R06_MICBIAS_CTRL_0 6 -#define B07_MICDET_HYST_ENA 7 -#define B04_MICDET_THR 4 -#define B02_MICSHORT_THR 2 -#define B01_MICDET_ENA 1 -#define B00_MICBIAS_ENA 0 -#define B15_DRC_ENA 15 -#define B03_DACL_ENA 3 -#define B02_DACR_ENA 2 -#define B01_ADCL_ENA 1 -#define B00_ADCR_ENA 0 -#define B06_IN_CM_ENA 6 -#define B04_IP_SEL_N 4 -#define B02_IP_SEL_P 2 -#define B00_MODE 0 -#define B06_AIF_ADCL 7 -#define B06_AIF_ADCR 6 -#define B05_ADC_HPF_CUT 5 -#define B04_ADC_HPF_ENA 4 -#define B01_ADCL_DATINV 1 -#define B00_ADCR_DATINV 0 -#define R20_SIDETONE_CTRL 32 -#define R29_DRC_1 41 -#define SET_REG_VAL(r,m,l,v) (((r)&(~((m)<<(l))))|(((v)&(m))<<(l))) - - static void tegra_ext_control(struct snd_soc_codec *codec) { /* set up jack connection */ @@ -105,109 +75,6 @@ static void tegra_ext_control(struct snd_soc_codec *codec) snd_soc_dapm_sync(codec); } -static int tegra_hifi_hw_params(struct snd_pcm_substream *substream, - 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; - struct snd_soc_codec *codec = codec_dai->codec; - int CtrlReg = 0; - int VolumeCtrlReg = 0; - int SidetoneCtrlReg = 0; - int SideToneAtenuation = 0; - - err = snd_soc_dai_set_fmt(codec_dai, - SND_SOC_DAIFMT_I2S | \ - SND_SOC_DAIFMT_NB_NF | \ - SND_SOC_DAIFMT_CBS_CFS); - if (err < 0) { - printk(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); - if (err < 0) { - printk(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); - - if (err<0) { - printk(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); - - if (err<0) { - printk(KERN_ERR "cpu_dai clock not set\n"); - return err; - } - - if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) { - snd_soc_write(codec, WM8903_ANALOGUE_LEFT_INPUT_0, 0X7); - snd_soc_write(codec, WM8903_ANALOGUE_RIGHT_INPUT_0, 0X7); - // Mic Bias enable - CtrlReg = (0x1<<B00_MICBIAS_ENA) | (0x1<<B01_MICDET_ENA); - snd_soc_write(codec, WM8903_MIC_BIAS_CONTROL_0, CtrlReg); - // Enable DRC - CtrlReg = snd_soc_read(codec, WM8903_DRC_0); - CtrlReg |= (1<<B15_DRC_ENA); - snd_soc_write(codec, WM8903_DRC_0, CtrlReg); - // Single Ended Mic - CtrlReg = (0x0<<B06_IN_CM_ENA) | - (0x0<<B00_MODE) | (0x0<<B04_IP_SEL_N) - | (0x1<<B02_IP_SEL_P); - VolumeCtrlReg = (0x5 << B00_IN_VOL); - // Mic Setting - snd_soc_write(codec, WM8903_ANALOGUE_LEFT_INPUT_1, CtrlReg); - snd_soc_write(codec, WM8903_ANALOGUE_RIGHT_INPUT_1, CtrlReg); - // voulme for single ended mic - snd_soc_write(codec, WM8903_ANALOGUE_LEFT_INPUT_0, - VolumeCtrlReg); - snd_soc_write(codec, WM8903_ANALOGUE_RIGHT_INPUT_0, - VolumeCtrlReg); - // replicate mic setting on both channels - CtrlReg = snd_soc_read(codec, WM8903_AUDIO_INTERFACE_0); - CtrlReg = SET_REG_VAL(CtrlReg, 0x1, B06_AIF_ADCR, 0x0); - CtrlReg = SET_REG_VAL(CtrlReg, 0x1, B06_AIF_ADCL, 0x0); - snd_soc_write(codec, WM8903_AUDIO_INTERFACE_0, CtrlReg); - // Enable analog inputs - CtrlReg = (0x1<<B01_INL_ENA) | (0x1<<B00_INR_ENA); - snd_soc_write(codec, WM8903_POWER_MANAGEMENT_0, CtrlReg); - // ADC Settings - CtrlReg = snd_soc_read(codec, WM8903_ADC_DIGITAL_0); - CtrlReg |= (0x1<<B04_ADC_HPF_ENA); - snd_soc_write(codec, WM8903_ADC_DIGITAL_0, CtrlReg); - SidetoneCtrlReg = 0; - snd_soc_write(codec, R20_SIDETONE_CTRL, SidetoneCtrlReg); - // Enable ADC - CtrlReg = snd_soc_read(codec, WM8903_POWER_MANAGEMENT_6); - CtrlReg |= (0x1<<B00_ADCR_ENA)|(0x1<<B01_ADCL_ENA); - snd_soc_write(codec, WM8903_POWER_MANAGEMENT_6, CtrlReg); - // Enable Sidetone - SidetoneCtrlReg = (0x1<<2) | (0x2<<0); - SideToneAtenuation = 12 ; // sidetone 0 db - SidetoneCtrlReg |= (SideToneAtenuation<<8) - | (SideToneAtenuation<<4); - snd_soc_write(codec, R20_SIDETONE_CTRL, SidetoneCtrlReg); - CtrlReg = snd_soc_read(codec, R29_DRC_1); - CtrlReg |= 0x3; //mic volume 18 db - snd_soc_write(codec, R29_DRC_1, CtrlReg); - } - - return 0; -} - -static struct snd_soc_ops tegra_hifi_ops = { - .hw_params = tegra_hifi_hw_params, -}; - - static int tegra_get_jack(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -250,7 +117,7 @@ static int tegra_set_spk(struct snd_kcontrol *kcontrol, } /*tegra machine dapm widgets */ -static const struct snd_soc_dapm_widget wm8903_dapm_widgets[] = { +static const struct snd_soc_dapm_widget tegra_dapm_widgets[] = { SND_SOC_DAPM_HP("Headphone Jack", NULL), SND_SOC_DAPM_MIC("Mic Jack", NULL), SND_SOC_DAPM_SPK("Ext Spk", NULL), @@ -286,7 +153,7 @@ static const struct soc_enum tegra_enum[] = { SOC_ENUM_SINGLE_EXT(2, spk_function), }; -static const struct snd_kcontrol_new wm8903_tegra_controls[] = { +static const struct snd_kcontrol_new tegra_controls[] = { SOC_ENUM_EXT("Jack Function", tegra_enum[0], tegra_get_jack, tegra_set_jack), SOC_ENUM_EXT("Speaker Function", tegra_enum[1], tegra_get_spk, @@ -408,8 +275,7 @@ static int tegra_play_route_put(struct snd_kcontrol *kcontrol, return -EINVAL; } -struct snd_kcontrol_new tegra_play_route_control = -{ +struct snd_kcontrol_new tegra_play_route_control = { .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Pcm Playback Route", @@ -458,8 +324,7 @@ static int tegra_capture_route_put(struct snd_kcontrol *kcontrol, return -EINVAL; } -struct snd_kcontrol_new tegra_capture_route_control = -{ +struct snd_kcontrol_new tegra_capture_route_control = { .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Pcm Capture Route", @@ -508,8 +373,7 @@ static int tegra_call_mode_put(struct snd_kcontrol *kcontrol, return -EINVAL; } -struct snd_kcontrol_new tegra_call_mode_control = -{ +struct snd_kcontrol_new tegra_call_mode_control = { .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Call Mode Switch", @@ -519,19 +383,25 @@ struct snd_kcontrol_new tegra_call_mode_control = .put = tegra_call_mode_put }; -static int tegra_codec_init(struct snd_soc_codec *codec) +int tegra_controls_init(struct snd_soc_codec *codec) { int err; + audio_data = kzalloc(sizeof(*audio_data), GFP_KERNEL); + if (!audio_data) { + pr_err("failed to allocate tegra_audio_data \n"); + return -ENOMEM; + } + /* Add tegra specific controls */ - err = snd_soc_add_controls(codec, wm8903_tegra_controls, - ARRAY_SIZE(wm8903_tegra_controls)); + err = snd_soc_add_controls(codec, tegra_controls, + ARRAY_SIZE(tegra_controls)); if (err < 0) - return err; + goto fail; /* Add tegra specific widgets */ - snd_soc_dapm_new_controls(codec, wm8903_dapm_widgets, - ARRAY_SIZE(wm8903_dapm_widgets)); + snd_soc_dapm_new_controls(codec, tegra_dapm_widgets, + ARRAY_SIZE(tegra_dapm_widgets)); /* Set up tegra specific audio path audio_map */ snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); @@ -541,19 +411,19 @@ static int tegra_codec_init(struct snd_soc_codec *codec) err = snd_ctl_add(codec->card, snd_ctl_new1(&tegra_play_route_control, NULL)); if (err < 0) - return err; + goto fail; /* Add capture route control */ err = snd_ctl_add(codec->card, snd_ctl_new1(&tegra_capture_route_control, NULL)); if (err < 0) - return err; + goto fail; /* Add call mode switch control */ err = snd_ctl_add(codec->card, snd_ctl_new1(&tegra_call_mode_control, NULL)); if (err < 0) - return err; + goto fail; /* Default to HP output */ tegra_jack_func = TEGRA_HP; @@ -563,93 +433,18 @@ static int tegra_codec_init(struct snd_soc_codec *codec) snd_soc_dapm_sync(codec); return 0; -} - -extern struct snd_soc_dai tegra_i2s_dai; -extern struct snd_soc_platform tegra_soc_platform; - -static struct snd_soc_dai_link tegra_soc_dai = { - .name = "WM8903", - .stream_name = "WM8903 HiFi", - .cpu_dai = &tegra_i2s_dai, - .codec_dai = &wm8903_dai, - .init = tegra_codec_init, - .ops = &tegra_hifi_ops, -}; - -static struct snd_soc_card tegra_snd_soc = { - .name = "tegra", - .platform = &tegra_soc_platform, - .dai_link = &tegra_soc_dai, - .num_links = 1, -}; - -struct tegra_setup_data { - int i2c_bus; - unsigned short i2c_address; -}; - -static struct snd_soc_device tegra_snd_devdata = { - .card = &tegra_snd_soc, - .codec_dev = &soc_codec_dev_wm8903, -}; - -static int __init tegra_init(void) -{ - int ret = 0; - struct tegra_setup_data tegra_setup; - - tegra_snd_device = platform_device_alloc("soc-audio", -1); - if (!tegra_snd_device) { - pr_err("failed to allocate soc-audio \n"); - ret = -ENOMEM; - goto fail; - } - - audio_data = kzalloc(sizeof(*audio_data), GFP_KERNEL); - if (!audio_data) { - pr_err("failed to allocate tegra_audio_data \n"); - ret = -ENOMEM; - goto fail; - } - - memset(&tegra_setup,0,sizeof(struct tegra_setup_data)); - platform_set_drvdata(tegra_snd_device, &tegra_snd_devdata); - tegra_snd_devdata.dev = &tegra_snd_device->dev; - ret = platform_device_add(tegra_snd_device); - if (ret) { - pr_err("audio device could not be added \n"); - goto fail; - } - - return 0; - fail: if (audio_data) { kfree(audio_data); audio_data = 0; } - - if (tegra_snd_device) { - platform_device_put(tegra_snd_device); - tegra_snd_device = 0; - } - - return ret; + return err; } -static void __exit tegra_exit(void) +void tegra_controls_exit(void) { if (audio_data) { kfree(audio_data); audio_data = 0; } - platform_device_unregister(tegra_snd_device); } - -module_init(tegra_init); -module_exit(tegra_exit); - -/* Module information */ -MODULE_DESCRIPTION("Tegra ALSA SoC"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/tegra/tegra_soc_wm8903.c b/sound/soc/tegra/tegra_soc_wm8903.c new file mode 100644 index 000000000000..80d85f985fdf --- /dev/null +++ b/sound/soc/tegra/tegra_soc_wm8903.c @@ -0,0 +1,227 @@ +/* + * tegra_soc_wm8903.c -- SoC audio for tegra + * + * (c) 2010 Nvidia Graphics Pvt. Ltd. + * http://www.nvidia.com + * + * Copyright 2007 Wolfson Microelectronics PLC. + * Author: Graeme Gregory + * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include "tegra_soc.h" +#include "../codecs/wm8903.h" + +static struct platform_device *tegra_snd_device; + +extern struct snd_soc_dai tegra_i2s_dai; +extern struct snd_soc_platform tegra_soc_platform; + +/* codec register values */ +#define B07_INEMUTE 7 +#define B06_VOL_M3DB 6 +#define B00_IN_VOL 0 +#define B00_INR_ENA 0 +#define B01_INL_ENA 1 +#define R06_MICBIAS_CTRL_0 6 +#define B07_MICDET_HYST_ENA 7 +#define B04_MICDET_THR 4 +#define B02_MICSHORT_THR 2 +#define B01_MICDET_ENA 1 +#define B00_MICBIAS_ENA 0 +#define B15_DRC_ENA 15 +#define B03_DACL_ENA 3 +#define B02_DACR_ENA 2 +#define B01_ADCL_ENA 1 +#define B00_ADCR_ENA 0 +#define B06_IN_CM_ENA 6 +#define B04_IP_SEL_N 4 +#define B02_IP_SEL_P 2 +#define B00_MODE 0 +#define B06_AIF_ADCL 7 +#define B06_AIF_ADCR 6 +#define B05_ADC_HPF_CUT 5 +#define B04_ADC_HPF_ENA 4 +#define B01_ADCL_DATINV 1 +#define B00_ADCR_DATINV 0 +#define R20_SIDETONE_CTRL 32 +#define R29_DRC_1 41 +#define SET_REG_VAL(r,m,l,v) (((r)&(~((m)<<(l))))|(((v)&(m))<<(l))) + + +static int tegra_hifi_hw_params(struct snd_pcm_substream *substream, + 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; + struct snd_soc_codec *codec = codec_dai->codec; + int CtrlReg = 0; + int VolumeCtrlReg = 0; + int SidetoneCtrlReg = 0; + int SideToneAtenuation = 0; + + err = snd_soc_dai_set_fmt(codec_dai, + SND_SOC_DAIFMT_I2S | \ + SND_SOC_DAIFMT_NB_NF | \ + SND_SOC_DAIFMT_CBS_CFS); + if (err < 0) { + printk(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); + if (err < 0) { + printk(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); + if (err < 0) { + printk(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); + if (err < 0) { + printk(KERN_ERR "cpu_dai clock not set\n"); + return err; + } + + if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) { + snd_soc_write(codec, WM8903_ANALOGUE_LEFT_INPUT_0, 0X7); + snd_soc_write(codec, WM8903_ANALOGUE_RIGHT_INPUT_0, 0X7); + // Mic Bias enable + CtrlReg = (0x1<<B00_MICBIAS_ENA) | (0x1<<B01_MICDET_ENA); + snd_soc_write(codec, WM8903_MIC_BIAS_CONTROL_0, CtrlReg); + // Enable DRC + CtrlReg = snd_soc_read(codec, WM8903_DRC_0); + CtrlReg |= (1<<B15_DRC_ENA); + snd_soc_write(codec, WM8903_DRC_0, CtrlReg); + // Single Ended Mic + CtrlReg = (0x0<<B06_IN_CM_ENA) | + (0x0<<B00_MODE) | (0x0<<B04_IP_SEL_N) + | (0x1<<B02_IP_SEL_P); + VolumeCtrlReg = (0x5 << B00_IN_VOL); + // Mic Setting + snd_soc_write(codec, WM8903_ANALOGUE_LEFT_INPUT_1, CtrlReg); + snd_soc_write(codec, WM8903_ANALOGUE_RIGHT_INPUT_1, CtrlReg); + // voulme for single ended mic + snd_soc_write(codec, WM8903_ANALOGUE_LEFT_INPUT_0, + VolumeCtrlReg); + snd_soc_write(codec, WM8903_ANALOGUE_RIGHT_INPUT_0, + VolumeCtrlReg); + // replicate mic setting on both channels + CtrlReg = snd_soc_read(codec, WM8903_AUDIO_INTERFACE_0); + CtrlReg = SET_REG_VAL(CtrlReg, 0x1, B06_AIF_ADCR, 0x0); + CtrlReg = SET_REG_VAL(CtrlReg, 0x1, B06_AIF_ADCL, 0x0); + snd_soc_write(codec, WM8903_AUDIO_INTERFACE_0, CtrlReg); + // Enable analog inputs + CtrlReg = (0x1<<B01_INL_ENA) | (0x1<<B00_INR_ENA); + snd_soc_write(codec, WM8903_POWER_MANAGEMENT_0, CtrlReg); + // ADC Settings + CtrlReg = snd_soc_read(codec, WM8903_ADC_DIGITAL_0); + CtrlReg |= (0x1<<B04_ADC_HPF_ENA); + snd_soc_write(codec, WM8903_ADC_DIGITAL_0, CtrlReg); + SidetoneCtrlReg = 0; + snd_soc_write(codec, R20_SIDETONE_CTRL, SidetoneCtrlReg); + // Enable ADC + CtrlReg = snd_soc_read(codec, WM8903_POWER_MANAGEMENT_6); + CtrlReg |= (0x1<<B00_ADCR_ENA)|(0x1<<B01_ADCL_ENA); + snd_soc_write(codec, WM8903_POWER_MANAGEMENT_6, CtrlReg); + // Enable Sidetone + SidetoneCtrlReg = (0x1<<2) | (0x2<<0); + SideToneAtenuation = 12 ; // sidetone 0 db + SidetoneCtrlReg |= (SideToneAtenuation<<8) + | (SideToneAtenuation<<4); + snd_soc_write(codec, R20_SIDETONE_CTRL, SidetoneCtrlReg); + CtrlReg = snd_soc_read(codec, R29_DRC_1); + CtrlReg |= 0x3; //mic volume 18 db + snd_soc_write(codec, R29_DRC_1, CtrlReg); + } + + return 0; +} + +static struct snd_soc_ops tegra_hifi_ops = { + .hw_params = tegra_hifi_hw_params, +}; + +static int tegra_codec_init(struct snd_soc_codec *codec) +{ + return tegra_controls_init(codec); +} + + +static struct snd_soc_dai_link tegra_soc_dai = { + .name = "WM8903", + .stream_name = "WM8903 HiFi", + .cpu_dai = &tegra_i2s_dai, + .codec_dai = &wm8903_dai, + .init = tegra_codec_init, + .ops = &tegra_hifi_ops, +}; + +static struct snd_soc_card tegra_snd_soc = { + .name = "tegra", + .platform = &tegra_soc_platform, + .dai_link = &tegra_soc_dai, + .num_links = 1, +}; + +static struct snd_soc_device tegra_snd_devdata = { + .card = &tegra_snd_soc, + .codec_dev = &soc_codec_dev_wm8903, +}; + +static int __init tegra_init(void) +{ + int ret = 0; + + tegra_snd_device = platform_device_alloc("soc-audio", -1); + if (!tegra_snd_device) { + pr_err("failed to allocate soc-audio \n"); + return ENOMEM; + } + + platform_set_drvdata(tegra_snd_device, &tegra_snd_devdata); + tegra_snd_devdata.dev = &tegra_snd_device->dev; + ret = platform_device_add(tegra_snd_device); + if (ret) { + pr_err("audio device could not be added \n"); + goto fail; + } + + return 0; + +fail: + if (tegra_snd_device) { + platform_device_put(tegra_snd_device); + tegra_snd_device = 0; + } + + return ret; +} + +static void __exit tegra_exit(void) +{ + tegra_controls_exit(); + platform_device_unregister(tegra_snd_device); +} + +module_init(tegra_init); +module_exit(tegra_exit); + +/* Module information */ +MODULE_DESCRIPTION("Tegra ALSA SoC"); +MODULE_LICENSE("GPL"); |