diff options
author | Ravindra Lokhande <rlokhande@nvidia.com> | 2011-03-08 14:17:30 +0530 |
---|---|---|
committer | Niket Sirsi <nsirsi@nvidia.com> | 2011-05-18 10:38:38 -0700 |
commit | ee550c20967fccfae7b13f2fac6271ae17339f53 (patch) | |
tree | fbb962da4e57df4ddd5a3d7ff634bfaf080f0680 /sound | |
parent | 3655e9a4940bfa39ba103903f2e2f1d5f0cf7e2d (diff) |
[tegra alsa] support digital mic on ventana
added code to support digital mic on wm8903 for ventana. By default
analog mic is enabled. To enable digital mic write 1 and to disable
write 0 to
/sys/devices/platform/soc-audio/enable_digital_mic
Change-Id: I36e239d10404a9bc8446e275e5c59e9829409608
Reviewed-on: http://git-master/r/29615
Reviewed-by: Niket Sirsi <nsirsi@nvidia.com>
Tested-by: Niket Sirsi <nsirsi@nvidia.com>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/tegra/tegra_i2s.c | 5 | ||||
-rw-r--r-- | sound/soc/tegra/tegra_soc_wm8903.c | 89 |
2 files changed, 93 insertions, 1 deletions
diff --git a/sound/soc/tegra/tegra_i2s.c b/sound/soc/tegra/tegra_i2s.c index 1f40cff697d8..ee197165dc9d 100644 --- a/sound/soc/tegra/tegra_i2s.c +++ b/sound/soc/tegra/tegra_i2s.c @@ -19,6 +19,8 @@ #include "tegra_soc.h" +int en_dmic; + /* i2s controller */ struct tegra_i2s_info { struct platform_device *pdev; @@ -294,6 +296,9 @@ static int i2s_configure(struct tegra_i2s_info *info ) i2s_set_bit_size(i2s_id, pdata->bit_size); i2s_set_fifo_format(i2s_id, pdata->fifo_fmt); + if (i2s_id == 0) + en_dmic = pdata->en_dmic; + return 0; } diff --git a/sound/soc/tegra/tegra_soc_wm8903.c b/sound/soc/tegra/tegra_soc_wm8903.c index 59fc6ddd0c9a..efad1e607e9d 100644 --- a/sound/soc/tegra/tegra_soc_wm8903.c +++ b/sound/soc/tegra/tegra_soc_wm8903.c @@ -19,10 +19,13 @@ #include <linux/gpio.h> #include <sound/soc-dapm.h> #include <linux/regulator/consumer.h> +#include <linux/sysfs.h> #include "../codecs/wm8903.h" static struct platform_device *tegra_snd_device; +extern int en_dmic; + extern struct snd_soc_dai tegra_i2s_dai[]; extern struct snd_soc_dai tegra_spdif_dai; extern struct snd_soc_dai tegra_generic_codec_dai[]; @@ -47,8 +50,81 @@ extern struct wired_jack_conf tegra_wired_jack_conf; #define B04_ADC_HPF_ENA 4 #define R20_SIDETONE_CTRL 32 #define R29_DRC_1 41 + +#define B08_GPx_FN 8 +#define B07_GPx_DIR 7 + +#define DMIC_CLK_OUT (0x6 << B08_GPx_FN) +#define DMIC_DAT_DATA_IN (0x6 << B08_GPx_FN) +#define GPIO_DIR_OUT (0x0 << B07_GPx_DIR) +#define GPIO_DIR_IN (0x1 << B07_GPx_DIR) + +#define ADC_DIGITAL_VOL_9DB 0x1D8 +#define ADC_DIGITAL_VOL_12DB 0x1E0 +#define ADC_ANALOG_VOLUME 0x1C +#define DRC_MAX_36DB 0x03 + #define SET_REG_VAL(r,m,l,v) (((r)&(~((m)<<(l))))|(((v)&(m))<<(l))) +static ssize_t digital_mic_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", en_dmic); +} + +static ssize_t digital_mic_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + if (count > 3) { + pr_err("%s: buffer size %d too big\n", __func__, count); + return -EINVAL; + } + + if (sscanf(buf, "%d", &en_dmic) != 1) { + pr_err("%s: invalid input string [%s]\n", __func__, buf); + return -EINVAL; + } + return count; +} + +static DEVICE_ATTR(enable_digital_mic, 0644, digital_mic_show, digital_mic_store); + +static void configure_dmic(struct snd_soc_codec *codec) +{ + u16 test4, reg; + + if (en_dmic) { + /* Set GP1_FN as DMIC_LR */ + snd_soc_write(codec, WM8903_GPIO_CONTROL_1, + DMIC_CLK_OUT | GPIO_DIR_OUT); + + /* Set GP2_FN as DMIC_DAT */ + snd_soc_write(codec, WM8903_GPIO_CONTROL_2, + DMIC_DAT_DATA_IN | GPIO_DIR_IN); + + /* Enable ADC Digital volumes */ + snd_soc_write(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT, + ADC_DIGITAL_VOL_9DB); + snd_soc_write(codec, WM8903_ADC_DIGITAL_VOLUME_RIGHT, + ADC_DIGITAL_VOL_9DB); + + /* Enable DIG_MIC */ + test4 = WM8903_ADC_DIG_MIC; + } else { + /* Disable DIG_MIC */ + test4 = snd_soc_read(codec, WM8903_CLOCK_RATE_TEST_4); + test4 &= ~WM8903_ADC_DIG_MIC; + } + + reg = snd_soc_read(codec, WM8903_CONTROL_INTERFACE_TEST_1); + snd_soc_write(codec, WM8903_CONTROL_INTERFACE_TEST_1, + reg | WM8903_TEST_KEY); + snd_soc_write(codec, WM8903_CLOCK_RATE_TEST_4, test4); + snd_soc_write(codec, WM8903_CONTROL_INTERFACE_TEST_1, reg); + +} static int tegra_hifi_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) @@ -104,7 +180,6 @@ static int tegra_hifi_hw_params(struct snd_pcm_substream *substream, int CtrlReg = 0; int VolumeCtrlReg = 0; int SidetoneCtrlReg = 0; - int SideToneAtenuation = 0; snd_soc_write(codec, WM8903_ANALOGUE_LEFT_INPUT_0, 0X7); snd_soc_write(codec, WM8903_ANALOGUE_RIGHT_INPUT_0, 0X7); @@ -149,6 +224,9 @@ static int tegra_hifi_hw_params(struct snd_pcm_substream *substream, CtrlReg = snd_soc_read(codec, R29_DRC_1); CtrlReg |= 0x3; /*mic volume 18 db */ snd_soc_write(codec, R29_DRC_1, CtrlReg); + + configure_dmic(codec); + } return 0; @@ -530,6 +608,15 @@ static int __init tegra_init(void) goto fail; } + ret = device_create_file(&tegra_snd_device->dev, + &dev_attr_enable_digital_mic); + if (ret < 0) { + dev_err(&tegra_snd_device->dev, + "%s: could not create sysfs entry %s: %d\n", + __func__, dev_attr_enable_digital_mic.attr.name, ret); + return ret; + } + return 0; fail: |