There is a mistake in current uda134x_mute function: mute_reg has been changed in line 162 or line 164, so uda134x_write should write "mute_reg" but not "mute_reg & ~(1<<2)" to UDA134X_DATA010.
Besides, because there is no DAPM configuration for uda134x, when system starts up, snd_soc_int_card calls snd_soc_dapm_new_widgets, and snd_soc_dapm_new_widgets calls dapm_power_widgets. In function dapm_power_widgets, codec->dapm_widgets has no list entry, so sys_power retains it's original value zero. Then snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_PREPARE) and snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_STANDBY) are called sequentially. Finally, the uda134x codec goes to STANDBY mode, so the ADC/DAC power control bits of UDA134X_STATUS1 register keeps the 0 value.
UDA134X has no trigger function currently, and the ADC/DAC power control bits of UDA134X_STATUS1 register are not exported in uda1341_snd_controls, so there's no way to enable the ADC/DAC power control bits when you want to use the codec. When playing with aplay or recording with arecord, there is no sound output or no wave input.
I have added the uda134x_trigger function, which turns on/off the ADC/DAC power control bits according the substream type and the command. I also exported the ADC/DAC power control bits to uda1341_snd_controls, so we can also turn these bits on/off as we need via a mixer tool like alsamixer.
The patch created against linux-2.6.31-rc3. Tested on a s3c2440 development board with UDA1341TS codec.
Signed-off-by: Shine Liu shinel@foxmail.com
--- sound/soc/codecs/uda134x.c.orig 2009-07-14 09:18:52.000000000 +0800 +++ sound/soc/codecs/uda134x.c 2009-08-17 13:46:57.000000000 +0800 @@ -163,7 +163,7 @@ else mute_reg &= ~(1<<2);
- uda134x_write(codec, UDA134X_DATA010, mute_reg & ~(1<<2)); + uda134x_write(codec, UDA134X_DATA010, mute_reg);
return 0; } @@ -339,6 +339,38 @@ return 0; }
+static int uda134x_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *dai) +{ + int stream = substream->stream; + struct snd_soc_codec *codec = dai->codec; + u8 power_ctrl_reg = uda134x_read_reg_cache(codec, UDA134X_STATUS1); + + pr_debug("%s stream: %d, cmd: %d\n", __func__, stream, cmd); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + if (stream == SNDRV_PCM_STREAM_PLAYBACK) + power_ctrl_reg |= (1<<0); + else + power_ctrl_reg |= (1<<1); + break; + + case SNDRV_PCM_TRIGGER_STOP: + if (stream == SNDRV_PCM_STREAM_PLAYBACK) + power_ctrl_reg &= ~(1<<0); + else + power_ctrl_reg &= ~(1<<1); + break; + + default: + return 0; + } + + uda134x_write(codec, UDA134X_STATUS1, power_ctrl_reg); + return 0; +} + static int uda134x_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { @@ -416,6 +448,8 @@ SOC_SINGLE("ADC Polarity Switch", UDA134X_STATUS1, 4, 1, 0), SOC_SINGLE("DAC Polarity Switch", UDA134X_STATUS1, 3, 1, 0), SOC_SINGLE("Double Speed Playback Switch", UDA134X_STATUS1, 2, 1, 0), +SOC_SINGLE("ADC Power Switch", UDA134X_STATUS1, 1, 1, 0), +SOC_SINGLE("DAC Power Switch", UDA134X_STATUS1, 0, 1, 0), SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0), };
@@ -438,6 +472,7 @@ .digital_mute = uda134x_mute, .set_sysclk = uda134x_set_dai_sysclk, .set_fmt = uda134x_set_dai_fmt, + .trigger = uda134x_trigger, };
struct snd_soc_dai uda134x_dai = {