From 0d34e91596ef537c2893a031f0483014bb82adf3 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 27 Jan 2010 18:56:23 +0100 Subject: ASoC: add a WM8978 codec driver The WM8978 codec from Wolfson Microelectronics is very similar to wm8974, but is stereo and also has some differences in pin configuration and internal signal routing. This driver is based on wm8974 and takes the differences into account. Signed-off-by: Guennadi Liakhovetski Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/codecs/wm8978.h | 89 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 sound/soc/codecs/wm8978.h (limited to 'sound/soc/codecs/wm8978.h') diff --git a/sound/soc/codecs/wm8978.h b/sound/soc/codecs/wm8978.h new file mode 100644 index 000000000000..b58f0bf947e7 --- /dev/null +++ b/sound/soc/codecs/wm8978.h @@ -0,0 +1,89 @@ +/* + * wm8978.h -- codec driver for WM8978 + * + * Copyright 2009 Guennadi Liakhovetski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __WM8978_H__ +#define __WM8978_H__ + +/* + * Register values. + */ +#define WM8978_RESET 0x00 +#define WM8978_POWER_MANAGEMENT_1 0x01 +#define WM8978_POWER_MANAGEMENT_2 0x02 +#define WM8978_POWER_MANAGEMENT_3 0x03 +#define WM8978_AUDIO_INTERFACE 0x04 +#define WM8978_COMPANDING_CONTROL 0x05 +#define WM8978_CLOCKING 0x06 +#define WM8978_ADDITIONAL_CONTROL 0x07 +#define WM8978_GPIO_CONTROL 0x08 +#define WM8978_JACK_DETECT_CONTROL_1 0x09 +#define WM8978_DAC_CONTROL 0x0A +#define WM8978_LEFT_DAC_DIGITAL_VOLUME 0x0B +#define WM8978_RIGHT_DAC_DIGITAL_VOLUME 0x0C +#define WM8978_JACK_DETECT_CONTROL_2 0x0D +#define WM8978_ADC_CONTROL 0x0E +#define WM8978_LEFT_ADC_DIGITAL_VOLUME 0x0F +#define WM8978_RIGHT_ADC_DIGITAL_VOLUME 0x10 +#define WM8978_EQ1 0x12 +#define WM8978_EQ2 0x13 +#define WM8978_EQ3 0x14 +#define WM8978_EQ4 0x15 +#define WM8978_EQ5 0x16 +#define WM8978_DAC_LIMITER_1 0x18 +#define WM8978_DAC_LIMITER_2 0x19 +#define WM8978_NOTCH_FILTER_1 0x1b +#define WM8978_NOTCH_FILTER_2 0x1c +#define WM8978_NOTCH_FILTER_3 0x1d +#define WM8978_NOTCH_FILTER_4 0x1e +#define WM8978_ALC_CONTROL_1 0x20 +#define WM8978_ALC_CONTROL_2 0x21 +#define WM8978_ALC_CONTROL_3 0x22 +#define WM8978_NOISE_GATE 0x23 +#define WM8978_PLL_N 0x24 +#define WM8978_PLL_K1 0x25 +#define WM8978_PLL_K2 0x26 +#define WM8978_PLL_K3 0x27 +#define WM8978_3D_CONTROL 0x29 +#define WM8978_BEEP_CONTROL 0x2b +#define WM8978_INPUT_CONTROL 0x2c +#define WM8978_LEFT_INP_PGA_CONTROL 0x2d +#define WM8978_RIGHT_INP_PGA_CONTROL 0x2e +#define WM8978_LEFT_ADC_BOOST_CONTROL 0x2f +#define WM8978_RIGHT_ADC_BOOST_CONTROL 0x30 +#define WM8978_OUTPUT_CONTROL 0x31 +#define WM8978_LEFT_MIXER_CONTROL 0x32 +#define WM8978_RIGHT_MIXER_CONTROL 0x33 +#define WM8978_LOUT1_HP_CONTROL 0x34 +#define WM8978_ROUT1_HP_CONTROL 0x35 +#define WM8978_LOUT2_SPK_CONTROL 0x36 +#define WM8978_ROUT2_SPK_CONTROL 0x37 +#define WM8978_OUT3_MIXER_CONTROL 0x38 +#define WM8978_OUT4_MIXER_CONTROL 0x39 + +#define WM8978_CACHEREGNUM 58 + +/* Clock divider Id's */ +enum wm8978_clk_id { + WM8978_OPCLKRATE, + WM8978_MCLKDIV, + WM8978_ADCCLK, + WM8978_DACCLK, + WM8978_BCLKDIV, +}; + +enum wm8978_sysclk_src { + WM8978_PLL, + WM8978_MCLK +}; + +extern struct snd_soc_dai wm8978_dai; +extern struct snd_soc_codec_device soc_codec_dev_wm8978; + +#endif /* __WM8978_H__ */ -- cgit v1.2.3 From b2c3e923110f6ca60ccb30cf4a6bda5211454c4f Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 29 Jan 2010 15:31:06 +0100 Subject: ASoC: clean up wm8974 and wm8978 clock divider handling wm8974 and wm8978 codec drivers control DAC and ADC oversampling rates in their .set_clkdiv() methods, which is wrong, because these are simple boolean switches and not clock dividers. Move these bits to sound controls. Also remove manual configuration of the MCLK divider in wm8978, since it is configured automatically. Signed-off-by: Guennadi Liakhovetski Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/codecs/wm8974.c | 12 ++++-------- sound/soc/codecs/wm8974.h | 12 +----------- sound/soc/codecs/wm8978.c | 19 ++++--------------- sound/soc/codecs/wm8978.h | 3 --- sound/soc/sh/migor.c | 4 ---- 5 files changed, 9 insertions(+), 41 deletions(-) (limited to 'sound/soc/codecs/wm8978.h') diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index 8812751da8c9..ee637af4737a 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c @@ -170,6 +170,10 @@ SOC_ENUM("Aux Mode", wm8974_auxmode), SOC_SINGLE("Capture Boost(+20dB)", WM8974_ADCBOOST, 8, 1, 0), SOC_SINGLE("Mono Playback Switch", WM8974_MONOMIX, 6, 1, 1), + +/* DAC / ADC oversampling */ +SOC_SINGLE("DAC 128x Oversampling Switch", WM8974_DAC, 8, 1, 0), +SOC_SINGLE("ADC 128x Oversampling Switch", WM8974_ADC, 8, 1, 0), }; /* Speaker Output Mixer */ @@ -381,14 +385,6 @@ static int wm8974_set_dai_clkdiv(struct snd_soc_dai *codec_dai, reg = snd_soc_read(codec, WM8974_CLOCK) & 0x11f; snd_soc_write(codec, WM8974_CLOCK, reg | div); break; - case WM8974_ADCCLK: - reg = snd_soc_read(codec, WM8974_ADC) & 0x1f7; - snd_soc_write(codec, WM8974_ADC, reg | div); - break; - case WM8974_DACCLK: - reg = snd_soc_read(codec, WM8974_DAC) & 0x1f7; - snd_soc_write(codec, WM8974_DAC, reg | div); - break; case WM8974_BCLKDIV: reg = snd_soc_read(codec, WM8974_CLOCK) & 0x1e3; snd_soc_write(codec, WM8974_CLOCK, reg | div); diff --git a/sound/soc/codecs/wm8974.h b/sound/soc/codecs/wm8974.h index 98de9562d4d2..896a7f0f3fc4 100644 --- a/sound/soc/codecs/wm8974.h +++ b/sound/soc/codecs/wm8974.h @@ -57,17 +57,7 @@ /* Clock divider Id's */ #define WM8974_OPCLKDIV 0 #define WM8974_MCLKDIV 1 -#define WM8974_ADCCLK 2 -#define WM8974_DACCLK 3 -#define WM8974_BCLKDIV 4 - -/* DAC clock dividers */ -#define WM8974_DACCLK_F2 (1 << 3) -#define WM8974_DACCLK_F4 (0 << 3) - -/* ADC clock dividers */ -#define WM8974_ADCCLK_F2 (1 << 3) -#define WM8974_ADCCLK_F4 (0 << 3) +#define WM8974_BCLKDIV 2 /* PLL Out dividers */ #define WM8974_OPCLKDIV_1 (0 << 4) diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index 8dcebaa8604a..ec2624b4c370 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c @@ -210,6 +210,10 @@ static const struct snd_kcontrol_new wm8978_snd_controls[] = { /* Speaker */ SOC_DOUBLE_R("Speaker Switch", WM8978_LOUT2_SPK_CONTROL, WM8978_ROUT2_SPK_CONTROL, 6, 1, 1), + + /* DAC / ADC oversampling */ + SOC_SINGLE("DAC 128x Oversampling Switch", WM8978_DAC_CONTROL, 8, 1, 0), + SOC_SINGLE("ADC 128x Oversampling Switch", WM8978_ADC_CONTROL, 8, 1, 0), }; /* Mixer #1: Output (OUT1, OUT2) Mixer: mix AUX, Input mixer output and DAC */ @@ -513,21 +517,6 @@ static int wm8978_set_dai_clkdiv(struct snd_soc_dai *codec_dai, if (wm8978->f_mclk) ret = wm8978_configure_pll(codec); break; - case WM8978_MCLKDIV: - if (div & ~0xe0) - return -EINVAL; - snd_soc_update_bits(codec, WM8978_CLOCKING, 0xe0, div); - break; - case WM8978_ADCCLK: - if (div & ~8) - return -EINVAL; - snd_soc_update_bits(codec, WM8978_ADC_CONTROL, 8, div); - break; - case WM8978_DACCLK: - if (div & ~8) - return -EINVAL; - snd_soc_update_bits(codec, WM8978_DAC_CONTROL, 8, div); - break; case WM8978_BCLKDIV: if (div & ~0x1c) return -EINVAL; diff --git a/sound/soc/codecs/wm8978.h b/sound/soc/codecs/wm8978.h index b58f0bf947e7..56ec83270917 100644 --- a/sound/soc/codecs/wm8978.h +++ b/sound/soc/codecs/wm8978.h @@ -72,9 +72,6 @@ /* Clock divider Id's */ enum wm8978_clk_id { WM8978_OPCLKRATE, - WM8978_MCLKDIV, - WM8978_ADCCLK, - WM8978_DACCLK, WM8978_BCLKDIV, }; diff --git a/sound/soc/sh/migor.c b/sound/soc/sh/migor.c index 3ccd9b393312..b823a5c9b9bc 100644 --- a/sound/soc/sh/migor.c +++ b/sound/soc/sh/migor.c @@ -59,10 +59,6 @@ static int migor_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; - ret = snd_soc_dai_set_clkdiv(codec_dai, WM8978_DACCLK, 8); - if (ret < 0) - return ret; - ret = snd_soc_dai_set_clkdiv(codec_dai, WM8978_OPCLKRATE, rate * 512); if (ret < 0) return ret; -- cgit v1.2.3