ALSA SOC driver for uda134x codec
cover ALSA SOC driver for uda134x codec
This patch adds support for the UDA1341 codec. It is *heavily* based on the one made by Zoltan Devai but:
since the UDA is the only use of the L3 protocol I can find I just embedded a stripped-down L3 bit-banging algorithm from the original RMK work. It is really small.
Generated on 20081113 against f7e1798a78a30bae1cf3ebc3e1b6f7c1bac57756
--- include/sound/l3.h | 18 ++ include/sound/uda134x.h | 58 ++++ sound/soc/codecs/Kconfig | 8 + sound/soc/codecs/Makefile | 4 + sound/soc/codecs/l3.c | 91 +++++++ sound/soc/codecs/uda134x.c | 636 ++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 815 insertions(+), 0 deletions(-)
include/sound/l3.h new file +18 -0
@@ -0,0 +1,18 @@ +#ifndef _L3_H_ +#define _L3_H_ 1 + +struct l3_pins { +void (*setdat)(int ); +void (*setclk)(int ); +void (*setmode)(int ); +int data_hold; +int data_setup; +int clock_high; +int mode_hold; +int mode; +int mode_setup; +}; + +int l3_write (struct l3_pins *adap,u8 addr,u8 *data,int len); + +#endif
include/sound/uda134x.h new file +58 -0
58 lines not on this page · raw message
sound/soc/codecs/Kconfig +8 -0
@@ -10,6 +10,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_TLV320AIC26 if SPI_MASTER select SND_SOC_TLV320AIC3X if I2C select SND_SOC_TWL4030 if TWL4030_CORE + select SND_SOC_UDA134X select SND_SOC_UDA1380 if I2C select SND_SOC_WM8510 if (I2C || SPI_MASTER) select SND_SOC_WM8580 if I2C
@@ -84,6 +85,13 @@ config SND_SOC_TWL4030 tristate depends on TWL4030_CORE +config SND_SOC_L3 + tristate + +config SND_SOC_UDA134X + tristate + select SND_SOC_L3 + config SND_SOC_UDA1380 tristate
sound/soc/codecs/Makefile +4 -0
@@ -8,6 +8,8 @@ snd-soc-tlv320aic23-objs := tlv320aic23.o snd-soc-tlv320aic26-objs := tlv320aic26.o snd-soc-tlv320aic3x-objs := tlv320aic3x.o snd-soc-twl4030-objs := twl4030.o +snd-soc-l3-objs := l3.o +snd-soc-uda134x-objs := uda134x.o snd-soc-uda1380-objs := uda1380.o snd-soc-wm8510-objs := wm8510.o snd-soc-wm8580-objs := wm8580.o
@@ -31,6 +33,8 @@ obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o +obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o +obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o obj-$(CONFIG_SND_SOC_WM8580) += snd-soc-wm8580.o
sound/soc/codecs/l3.c new file +91 -0
91 lines not on this page · raw message
sound/soc/codecs/uda134x.c new file +636 -0
636 lines not on this page · raw message
--
1.4.4.4
Quoted 8 lines · Christian Pellegrin
This patch adds support for the UDA1341 codec. It is *heavily* based on the one made by Zoltan Devai but:
since the UDA is the only use of the L3 protocol I can find I just embedded a stripped-down L3 bit-banging algorithm from the original RMK work. It is really small.
Generated on 20081113 against
f7e1798a78a30bae1cf3ebc3e1b6f7c1bac57756
A couple of minor procedural points:
- Normally the patches in a series are numbered starting from 1 with mail 0 being a cover letter ("This series does..." or similar).
- Information like the "Generated on" should go after the --- with the diffstat so that it doesn't go in the commit message.
include/sound/uda134x.h line 47
Quoted 4 lines
+++
b/include/sound/uda134x.hinclude/sound/uda134x.h new file +2
-0+extern struct snd_soc_dai uda134x_dai; +extern struct snd_soc_codec_device soc_codec_dev_uda134x;
At least this should be in a header sound/soc/codecs - as I said previously that is the idiom used by codec drivers. However...
include/sound/uda134x.h line 56
Quoted 8 lines
include/sound/uda134x.h new file +8
-0+struct uda134x_platform_data { +struct l3_pins l3; +void (*power) (int ); +int model; +#define UDA134X_UDA1340 0 +#define UDA134X_UDA1341 1 +#define UDA134X_UDA1344 2 +};
...putting this in a separate file in include/sound is a good idea.
Is having UDA1340 as zero a good idea - that'll mean that if someone forgets to initialise the model it'll come out as UDA1340? It might be better to start the model numbers from 1 so that it'll be obvious if that happens. Might also be an idea to use an enum rather than the series of #defines?
sound/soc/codecs/Kconfig config SND_SOC_TWL4030 · line 94
Quoted 4 lines
sound/soc/codecs/Kconfig +4
-0+config SND_SOC_UDA134X + tristate + select SND_SOC_L3 +
Note that the select here won't actually do any good but it's useful for documentation.
sound/soc/codecs/Makefile snd-soc-tlv320aic23-objs := tlv320aic23.o · line 12
Quoted 10 lines
sound/soc/codecs/Makefile +2
-0@@ -8,6 +8,8 @@ snd-soc-tlv320aic23-objs := tlv320aic23.o snd-soc-tlv320aic26-objs := tlv320aic26.o snd-soc-tlv320aic3x-objs := tlv320aic3x.o snd-soc-twl4030-objs := twl4030.o +snd-soc-l3-objs := l3.o +snd-soc-uda134x-objs := uda134x.o
Please keep this and the other build stuff sorted (it helps merges).
sound/soc/codecs/Makefile snd-soc-tlv320aic23-objs := tlv320aic23.o · line 15
Quoted 3 lines
sound/soc/codecs/Makefile +3
-0+ if (reg >= UDA134X_REGS_NUM) { + printk(KERN_ERR "%s unkown register: reg: %d", + __func__, reg);
Could use pr_error() here and elsewhere but doesn't make much difference either way - up to you.
sound/soc/codecs/Makefile snd-soc-tlv320aic23-objs := tlv320aic23.o
Quoted 12 lines
sound/soc/codecs/Makefile +12
-0+static int uda134x_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_device *socdev = rtd->socdev; + struct snd_soc_codec *codec = socdev->codec; + struct uda134x_priv *uda134x = codec->private_data; + struct snd_pcm_runtime *master_runtime; + + if (uda134x->master_substream) { + master_runtime = uda134x->master_substream->runtime; + + pr_debug("%s costrining to %d bits at %d\n", __func__,
constraining.
Quoted 12 lines
sound/soc/codecs/Makefile +12
-0+static int uda134x_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + u8 reg; + struct uda134x_platform_data *pd = codec->control_data; + int i; + u8 *cache = codec->reg_cache; + + pr_debug("%s bias level %d\n", __func__, level); + + switch (level) { + case SND_SOC_BIAS_ON:
sound/soc/codecs/Makefile
Quoted 10 lines
sound/soc/codecs/Makefile +10
-0+ /* power on */ + if (pd->power) + pd->power(1); + /* Sync reg_cache with the hardware */ + for (i = 0; i < ARRAY_SIZE(uda134x_reg); i++) + codec->write(codec, i, *cache++); + /* ADC, DAC on */ + reg = uda134x_read_reg_cache(codec, UDA134X_STATUS1); + uda134x_write(codec, UDA134X_STATUS1, reg | 0x03); + break;
This should probably be done when going into SND_SOC_BIAS_STANDBY or at least _PREPARE. The codec will be brought up to _ON whenever a playback or record is active, spending most of the rest of the time at _STANDBY. The result will be that you're syncing the register cache to the codec every time playback starts, even if the codec is already on. _ON is expected to be very quick.
It might be worth implementing DAPM for the ADC and DAC power - the savings are probably very small but it should be very straightforward to implement. Not essential, though - doing it in bias_level() is also OK.
Quoted 1 line
+EXPORT_SYMBOL(uda134x_dai);
Note that since ASoC core is all EXPORT_SYMBOL_GPL() it'll be difficult for anyone to actually use this from non-GPLed code.
sound/soc/codecs/Makefile
Quoted 10 lines
sound/soc/codecs/Makefile +10
-0+ pd = codec_setup_data; + switch (pd->model) { + case UDA134X_UDA1340: + case UDA134X_UDA1341: + case UDA134X_UDA1344: + break; + default: + printk(KERN_ERR "UDA134X SoC codec: " + "unsupported model\n"); + return -EINVAL;
Probably worth printing out what the model was set to if it's not recognised.
sound/soc/codecs/Makefile
Quoted 10 lines
sound/soc/codecs/Makefile +10
-0+struct snd_soc_codec_device soc_codec_dev_uda134x = { + .probe = uda134x_soc_probe, + .remove = uda134x_soc_remove, +#if defined(CONFIG_PM) + .suspend = uda134x_soc_suspend, + .resume = uda134x_soc_resume, +#else + .suspend = NULL, + .resume = NULL, +#endif /* CONFIG_PM */
The #else should be with the definition of the functions so there's no need for a conditional here.
Quoted 8 lines · Mark Brown
On Thu, Nov 13, 2008 at 04:41:30PM +0100, Christian Pellegrin wrote:
A couple of minor procedural points:
- Normally the patches in a series are numbered starting from 1 with mail 0 being a cover letter ("This series does..." or similar).
- Information like the "Generated on" should go after the --- with the diffstat so that it doesn't go in the commit message.
ack
Quoted 8 lines
include/sound/uda134x.h line 47
Quoted 4 lines
+++
b/include/sound/uda134x.hinclude/sound/uda134x.h new file +2
-0+extern struct snd_soc_dai uda134x_dai; +extern struct snd_soc_codec_device soc_codec_dev_uda134x;At least this should be in a header
sound/soc/codecs- as I said previously that is the idiom used by codec drivers. However...
ack
Quoted 9 lines
...putting this in a separate file in
include/soundis a good idea.Is having UDA1340 as zero a good idea - that'll mean that if someone forgets to initialise the model it'll come out as UDA1340? It might be better to start the model numbers from 1 so that it'll be obvious if that happens. Might also be an idea to use an enum rather than the series of #defines?
good point, ack
Quoted 11 lines
sound/soc/codecs/Makefile snd-soc-tlv320aic23-objs := tlv320aic23.o · line 12
Quoted 8 lines
sound/soc/codecs/Makefile +2
-0@@ -8,6 +8,8 @@ snd-soc-tlv320aic23-objs := tlv320aic23.o snd-soc-tlv320aic26-objs := tlv320aic26.o snd-soc-tlv320aic3x-objs := tlv320aic3x.o snd-soc-twl4030-objs := twl4030.o +snd-soc-l3-objs := l3.o +snd-soc-uda134x-objs := uda134x.oPlease keep this and the other build stuff sorted (it helps merges).
I'll sort alphabetically
Quoted 7 lines
sound/soc/codecs/Makefile snd-soc-tlv320aic23-objs := tlv320aic23.o · line 15
Quoted 3 lines
sound/soc/codecs/Makefile +3
-0+ if (reg >= UDA134X_REGS_NUM) { + printk(KERN_ERR "%s unkown register: reg: %d", + __func__, reg);Could use
pr_error()here and elsewhere but doesn't make much difference either way - up to you.
didn't know about it. The next driver will use it because it's shorter.
Quoted 4 lines
Quoted 1 line
+ pr_debug("%s costrining to %d bits at %d\n",
__func__,constraining.
ack
Quoted 6 lines
sound/soc/codecs/Makefile
Quoted 5 lines
sound/soc/codecs/Makefile +5
-0+ codec->write(codec, i, *cache++); + /* ADC, DAC on */ + reg = uda134x_read_reg_cache(codec, UDA134X_STATUS1); + uda134x_write(codec, UDA134X_STATUS1, reg | 0x03); + break;
Quoted 6 lines
This should probably be done when going into
SND_SOC_BIAS_STANDBYor at least_PREPARE. The codec will be brought up to_ONwhenever a playback or record is active, spending most of the rest of the time at_STANDBY. The result will be that you're syncing the register cache to the codec every time playback starts, even if the codec is already on._ONis expected to be very quick.
ack, I was thinking to put it in prepare but I wasn't sure.
Quoted 6 lines
Quoted 2 lines
+EXPORT_SYMBOL(uda134x_dai);
Note that since ASoC core is all
EXPORT_SYMBOL_GPL()it'll be difficult for anyone to actually use this from non-GPLed code.
ack
Quoted 7 lines
sound/soc/codecs/Makefile
Quoted 3 lines
sound/soc/codecs/Makefile +3
-0+ printk(KERN_ERR "UDA134X SoC codec: " + "unsupported model\n"); + return -EINVAL;Probably worth printing out what the model was set to if it's not recognised.
ack
Quoted 4 lines
The #else should be with the definition of the functions so there's no need for a conditional here.
ack
Signature · 5 lines
Christian Pellegrin, see http://www.evolware.org/chri/ "Real Programmers don't play tennis, or any other sport which requires you to change clothes. Mountain climbing is OK, and Real Programmers wear their climbing boots to work in case a mountain should suddenly spring up in the middle of the computer room."