[alsa-devel] [PATCH] STAC92xx : add support for missing features
Hi,
As promised, those are patches that extend patch_sigmatel.c driver to add missing functionality
They all are runtime tested with my STAC9227, and datasheet tested with others Note that I did my best to ensure that even if a codec doesn't support a feature (and I don't know sbout that), maximum impact will be a new, non-working mixer control
STAC927x are almost exactly the same as STAC922x, but have DAC4
1) Center/LFE swap : It can be sometimes useful to swap those channels, since they are on same line.
I add that control only in case Center/LFE DAC is there, and supports L/R swap, it should be very safe.
2) Analog loopback: Added for 922x, 927x, and for 9204/5 which has a different verb, that offers same analog loopback
3) Volume Knob: Added for 9204/5, 9220/1/3, 922x 92-7x I made it a master volume
4) Fixed support for codecs that have 2 or 3 ADC: I added separate mixer controls for all 2/3 ADCs, and made PCM capture device sub-streams count to depend on actual number of ADCs
I am looking for your comments, Best regards, Maxim Levitsky
From c9392b0293f7d39e40e4a5e07e7b140d5a385079 Mon Sep 17 00:00:00 2001 From: Maxim Levitsky maximlevitsky@gmail.com Date: Mon, 27 Aug 2007 22:49:49 +0300 Subject: [PATCH] HDA : patch_sigmatel.c : cleanups
--- sound/pci/hda/patch_sigmatel.c | 65 ++++++++++----------------------------- 1 files changed, 17 insertions(+), 48 deletions(-)
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 3f25de7..1627ca3 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -316,17 +316,21 @@ static struct hda_verb stac9205_core_init[] = { {} };
+#define STAC_INPUT_SOURCE \ + { \ + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .name = "Input Source", \ + .count = 1, \ + .info = stac92xx_mux_enum_info, \ + .get = stac92xx_mux_enum_get, \ + .put = stac92xx_mux_enum_put, \ + } + + static struct snd_kcontrol_new stac9200_mixer[] = { HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT), HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Input Source", - .count = 1, - .info = stac92xx_mux_enum_info, - .get = stac92xx_mux_enum_get, - .put = stac92xx_mux_enum_put, - }, + STAC_INPUT_SOURCE, HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT), HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT), HDA_CODEC_VOLUME("Capture Mux Volume", 0x0c, 0, HDA_OUTPUT), @@ -334,14 +338,7 @@ static struct snd_kcontrol_new stac9200_mixer[] = { };
static struct snd_kcontrol_new stac925x_mixer[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Input Source", - .count = 1, - .info = stac92xx_mux_enum_info, - .get = stac92xx_mux_enum_get, - .put = stac92xx_mux_enum_put, - }, + STAC_INPUT_SOURCE, HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_OUTPUT), HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_OUTPUT), HDA_CODEC_VOLUME("Capture Mux Volume", 0x0f, 0, HDA_OUTPUT), @@ -350,14 +347,7 @@ static struct snd_kcontrol_new stac925x_mixer[] = {
/* This needs to be generated dynamically based on sequence */ static struct snd_kcontrol_new stac922x_mixer[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Input Source", - .count = 1, - .info = stac92xx_mux_enum_info, - .get = stac92xx_mux_enum_get, - .put = stac92xx_mux_enum_put, - }, + STAC_INPUT_SOURCE, HDA_CODEC_VOLUME("Capture Volume", 0x17, 0x0, HDA_INPUT), HDA_CODEC_MUTE("Capture Switch", 0x17, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Mux Capture Volume", 0x12, 0x0, HDA_OUTPUT), @@ -366,28 +356,14 @@ static struct snd_kcontrol_new stac922x_mixer[] = {
/* This needs to be generated dynamically based on sequence */ static struct snd_kcontrol_new stac9227_mixer[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Input Source", - .count = 1, - .info = stac92xx_mux_enum_info, - .get = stac92xx_mux_enum_get, - .put = stac92xx_mux_enum_put, - }, + STAC_INPUT_SOURCE, HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Capture Switch", 0x1b, 0x0, HDA_OUTPUT), { } /* end */ };
static struct snd_kcontrol_new stac927x_mixer[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Input Source", - .count = 1, - .info = stac92xx_mux_enum_info, - .get = stac92xx_mux_enum_get, - .put = stac92xx_mux_enum_put, - }, + STAC_INPUT_SOURCE, HDA_CODEC_VOLUME("InMux Capture Volume", 0x15, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("InVol Capture Volume", 0x18, 0x0, HDA_INPUT), HDA_CODEC_MUTE("ADCMux Capture Switch", 0x1b, 0x0, HDA_OUTPUT), @@ -403,14 +379,7 @@ static struct snd_kcontrol_new stac9205_mixer[] = { .get = stac92xx_dmux_enum_get, .put = stac92xx_dmux_enum_put, }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Input Source", - .count = 1, - .info = stac92xx_mux_enum_info, - .get = stac92xx_mux_enum_get, - .put = stac92xx_mux_enum_put, - }, + STAC_INPUT_SOURCE, HDA_CODEC_VOLUME("InMux Capture Volume", 0x19, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("InVol Capture Volume", 0x1b, 0x0, HDA_INPUT), HDA_CODEC_MUTE("ADCMux Capture Switch", 0x1d, 0x0, HDA_OUTPUT),
At Tue, 28 Aug 2007 05:07:48 +0300, Maxim Levitsky wrote:
From c9392b0293f7d39e40e4a5e07e7b140d5a385079 Mon Sep 17 00:00:00 2001 From: Maxim Levitsky maximlevitsky@gmail.com Date: Mon, 27 Aug 2007 22:49:49 +0300 Subject: [PATCH] HDA : patch_sigmatel.c : cleanups
OK, it's a nice clean-up. Can be merged as is.
Takashi
At Tue, 28 Aug 2007 12:46:01 +0200, I wrote:
At Tue, 28 Aug 2007 05:07:48 +0300, Maxim Levitsky wrote:
From c9392b0293f7d39e40e4a5e07e7b140d5a385079 Mon Sep 17 00:00:00 2001 From: Maxim Levitsky maximlevitsky@gmail.com Date: Mon, 27 Aug 2007 22:49:49 +0300 Subject: [PATCH] HDA : patch_sigmatel.c : cleanups
OK, it's a nice clean-up. Can be merged as is.
Now merged to ALSA HG tree.
If the fixes for other patches are ready, please let me know. I'll merge them to HG tree, too.
Thanks,
Takashi
On Friday 31 August 2007 13:56:19 Takashi Iwai wrote:
At Tue, 28 Aug 2007 12:46:01 +0200, I wrote:
At Tue, 28 Aug 2007 05:07:48 +0300, Maxim Levitsky wrote:
From c9392b0293f7d39e40e4a5e07e7b140d5a385079 Mon Sep 17 00:00:00 2001 From: Maxim Levitsky maximlevitsky@gmail.com Date: Mon, 27 Aug 2007 22:49:49 +0300 Subject: [PATCH] HDA : patch_sigmatel.c : cleanups
OK, it's a nice clean-up. Can be merged as is.
Now merged to ALSA HG tree.
If the fixes for other patches are ready, please let me know. I'll merge them to HG tree, too.
Thanks,
Takashi
Hi,
I run into unexpected problems: latest hg adds a power saving mode to hda codec, and while the idea is nice, it plays very bad with my patches.
1) The analog loop-back becomes a nightmare, since power-saving code turns the codec off, but for loopback to function it has to be powered. I tried to add a snd_hda_power_up/down calls to .put function, and while it did stop the unwanted powerdown of codec, on resume from ram , analog loopback vanishes. any access to device (arecord/aplay or any mixer change make analog loop work again). Can you tell me how I properly tell the core that user _uses_ the device, and device should be powered.
2) on resume all playback apps hang, and recording (arecord) exits with message "Resource temporary unavailable" restarting apps help.
Looking for your comments, Best regards, Maxim Levitsky
At Sat, 1 Sep 2007 11:11:24 +0300, Maxim Levitsky wrote:
On Friday 31 August 2007 13:56:19 Takashi Iwai wrote:
At Tue, 28 Aug 2007 12:46:01 +0200, I wrote:
At Tue, 28 Aug 2007 05:07:48 +0300, Maxim Levitsky wrote:
From c9392b0293f7d39e40e4a5e07e7b140d5a385079 Mon Sep 17 00:00:00 2001 From: Maxim Levitsky maximlevitsky@gmail.com Date: Mon, 27 Aug 2007 22:49:49 +0300 Subject: [PATCH] HDA : patch_sigmatel.c : cleanups
OK, it's a nice clean-up. Can be merged as is.
Now merged to ALSA HG tree.
If the fixes for other patches are ready, please let me know. I'll merge them to HG tree, too.
Thanks,
Takashi
Hi,
I run into unexpected problems: latest hg adds a power saving mode to hda codec, and while the idea is nice, it plays very bad with my patches.
- The analog loop-back becomes a nightmare, since power-saving code turns the codec off, but for loopback to function it has to be powered.
I tried to add a snd_hda_power_up/down calls to .put function, and while it did stop the unwanted powerdown of codec, on resume from ram , analog loopback vanishes. any access to device (arecord/aplay or any mixer change make analog loop work again). Can you tell me how I properly tell the core that user _uses_ the device, and device should be powered.
- on resume all playback apps hang, and recording (arecord) exits with message "Resource temporary unavailable"
restarting apps help.
First, you need to use snd_hda_codec_write_cache() for values to be resumed, especially in control put callbacks. The amp values accessed via snd_hda_codec_amp_update() are always cached, but snd_hda_codec_write() doesn't cache.
The second thing is analog-loopback. The driver should keep the power when the analog-loopback is on, and enables power-saving again when it's off. So far, I thought only the amp controls, but now it's a different one.
In this case, the put callback would need to call snd_hda_pwoer_up() and snd_hda_power_down() appropriately to turn on/off power-save. They should be called only at transition. Namely, when 0->1 transition of spec->aloopback occurs in put callback, it calls snd_hda_power_up(). When 1->0 occurs, call snd_hda_power_down().
Takashi
On Saturday 01 September 2007 14:49:29 Takashi Iwai wrote:
At Sat, 1 Sep 2007 11:11:24 +0300, Maxim Levitsky wrote:
On Friday 31 August 2007 13:56:19 Takashi Iwai wrote:
At Tue, 28 Aug 2007 12:46:01 +0200, I wrote:
At Tue, 28 Aug 2007 05:07:48 +0300, Maxim Levitsky wrote:
From c9392b0293f7d39e40e4a5e07e7b140d5a385079 Mon Sep 17 00:00:00 2001 From: Maxim Levitsky maximlevitsky@gmail.com Date: Mon, 27 Aug 2007 22:49:49 +0300 Subject: [PATCH] HDA : patch_sigmatel.c : cleanups
OK, it's a nice clean-up. Can be merged as is.
Now merged to ALSA HG tree.
If the fixes for other patches are ready, please let me know. I'll merge them to HG tree, too.
Thanks,
Takashi
Hi,
I run into unexpected problems: latest hg adds a power saving mode to hda codec, and while the idea is nice, it plays very bad with my patches.
- The analog loop-back becomes a nightmare, since power-saving code turns the codec off, but for loopback to function it has to be powered.
I tried to add a snd_hda_power_up/down calls to .put function, and while it did stop the unwanted powerdown of codec, on resume from ram , analog loopback vanishes. any access to device (arecord/aplay or any mixer change make analog loop work again). Can you tell me how I properly tell the core that user _uses_ the device, and device should be powered.
- on resume all playback apps hang, and recording (arecord) exits with message "Resource temporary unavailable"
restarting apps help.
First, you need to use snd_hda_codec_write_cache() for values to be resumed, especially in control put callbacks. The amp values accessed via snd_hda_codec_amp_update() are always cached, but snd_hda_codec_write() doesn't cache.
The second thing is analog-loopback. The driver should keep the power when the analog-loopback is on, and enables power-saving again when it's off. So far, I thought only the amp controls, but now it's a different one.
In this case, the put callback would need to call snd_hda_pwoer_up() and snd_hda_power_down() appropriately to turn on/off power-save. They should be called only at transition. Namely, when 0->1 transition of spec->aloopback occurs in put callback, it calls snd_hda_power_up(). When 1->0 occurs, call snd_hda_power_down().
Takashi
Hi, Well, did you read my email? :-)
I did call snd_hda_power_up/down in .put callback, but as I said, on resume, driver didn't powered up the codec, and as usual any access to device powers up the codec.
Well and I found another bug, The problem is that on resume all "use mic/line-in as output' controls are disabled, and I know why:
.resume() before introduction of snd_hda_codec_write_cache() / dynamic power managment: stac92xx_init() -> inits inputs/outputs of chip (sets all dynamic pins to output mode)
snd_hda_resume_ctls() > hacky, but working way of resuming mixer controls : read from memory, write to device
.resume() now: stac92xx_init() -> inits inputs/outputs of chip (sets all dynamic pins to output mode), and touches the command cache. snd_hda_codec_resume_cache() writes (modifed) cache to codec, thus making dynamic outputs be in input mode.
I suggest skipping call to stac92xx_init() at all, after all no initialization is nessesary, since all commands are in cache.
Best regards, Maxim Levitsky
At Sun, 2 Sep 2007 11:28:43 +0300, Maxim Levitsky wrote:
On Saturday 01 September 2007 14:49:29 Takashi Iwai wrote:
At Sat, 1 Sep 2007 11:11:24 +0300, Maxim Levitsky wrote:
On Friday 31 August 2007 13:56:19 Takashi Iwai wrote:
At Tue, 28 Aug 2007 12:46:01 +0200, I wrote:
At Tue, 28 Aug 2007 05:07:48 +0300, Maxim Levitsky wrote:
From c9392b0293f7d39e40e4a5e07e7b140d5a385079 Mon Sep 17 00:00:00 2001 From: Maxim Levitsky maximlevitsky@gmail.com Date: Mon, 27 Aug 2007 22:49:49 +0300 Subject: [PATCH] HDA : patch_sigmatel.c : cleanups
OK, it's a nice clean-up. Can be merged as is.
Now merged to ALSA HG tree.
If the fixes for other patches are ready, please let me know. I'll merge them to HG tree, too.
Thanks,
Takashi
Hi,
I run into unexpected problems: latest hg adds a power saving mode to hda codec, and while the idea is nice, it plays very bad with my patches.
- The analog loop-back becomes a nightmare, since power-saving code turns the codec off, but for loopback to function it has to be powered.
I tried to add a snd_hda_power_up/down calls to .put function, and while it did stop the unwanted powerdown of codec, on resume from ram , analog loopback vanishes. any access to device (arecord/aplay or any mixer change make analog loop work again). Can you tell me how I properly tell the core that user _uses_ the device, and device should be powered.
- on resume all playback apps hang, and recording (arecord) exits with message "Resource temporary unavailable"
restarting apps help.
First, you need to use snd_hda_codec_write_cache() for values to be resumed, especially in control put callbacks. The amp values accessed via snd_hda_codec_amp_update() are always cached, but snd_hda_codec_write() doesn't cache.
The second thing is analog-loopback. The driver should keep the power when the analog-loopback is on, and enables power-saving again when it's off. So far, I thought only the amp controls, but now it's a different one.
In this case, the put callback would need to call snd_hda_pwoer_up() and snd_hda_power_down() appropriately to turn on/off power-save. They should be called only at transition. Namely, when 0->1 transition of spec->aloopback occurs in put callback, it calls snd_hda_power_up(). When 1->0 occurs, call snd_hda_power_down().
Takashi
Hi, Well, did you read my email? :-)
Yeah, but not carefully as I was in travel.
I did call snd_hda_power_up/down in .put callback, but as I said, on resume, driver didn't powered up the codec, and as usual any access to device powers up the codec.
Well, did you use snd_hda_codec_write_cache() there? Otherwise the changed analog-loopback setup won't be called.
Well and I found another bug, The problem is that on resume all "use mic/line-in as output' controls are disabled, and I know why:
.resume() before introduction of snd_hda_codec_write_cache() / dynamic power managment: stac92xx_init() -> inits inputs/outputs of chip (sets all dynamic pins to output mode)
snd_hda_resume_ctls() > hacky, but working way of resuming mixer controls : read from memory, write to device
.resume() now: stac92xx_init() -> inits inputs/outputs of chip (sets all dynamic pins to output mode), and touches the command cache. snd_hda_codec_resume_cache() writes (modifed) cache to codec, thus making dynamic outputs be in input mode.
I suggest skipping call to stac92xx_init() at all, after all no initialization is nessesary, since all commands are in cache.
Some stuff in stac92xx_init() isn't cached, so we cannot remove it completely. I fixed it now on HG tree. Give it a try.
Takashi
On Monday 03 September 2007 10:39:29 Takashi Iwai wrote:
At Sun, 2 Sep 2007 11:28:43 +0300, Maxim Levitsky wrote:
On Saturday 01 September 2007 14:49:29 Takashi Iwai wrote:
At Sat, 1 Sep 2007 11:11:24 +0300, Maxim Levitsky wrote:
On Friday 31 August 2007 13:56:19 Takashi Iwai wrote:
At Tue, 28 Aug 2007 12:46:01 +0200, I wrote:
At Tue, 28 Aug 2007 05:07:48 +0300, Maxim Levitsky wrote: > > From c9392b0293f7d39e40e4a5e07e7b140d5a385079 Mon Sep 17 00:00:00 2001 > From: Maxim Levitsky maximlevitsky@gmail.com > Date: Mon, 27 Aug 2007 22:49:49 +0300 > Subject: [PATCH] HDA : patch_sigmatel.c : cleanups
OK, it's a nice clean-up. Can be merged as is.
Now merged to ALSA HG tree.
If the fixes for other patches are ready, please let me know. I'll merge them to HG tree, too.
Thanks,
Takashi
Hi,
I run into unexpected problems: latest hg adds a power saving mode to hda codec, and while the idea is nice, it plays very bad with my patches.
- The analog loop-back becomes a nightmare, since power-saving code turns the codec off, but for loopback to function it has to be powered.
I tried to add a snd_hda_power_up/down calls to .put function, and while it did stop the unwanted powerdown of codec, on resume from ram , analog loopback vanishes. any access to device (arecord/aplay or any mixer change make analog loop work again). Can you tell me how I properly tell the core that user _uses_ the device, and device should be powered.
- on resume all playback apps hang, and recording (arecord) exits with message "Resource temporary unavailable"
restarting apps help.
First, you need to use snd_hda_codec_write_cache() for values to be resumed, especially in control put callbacks. The amp values accessed via snd_hda_codec_amp_update() are always cached, but snd_hda_codec_write() doesn't cache.
The second thing is analog-loopback. The driver should keep the power when the analog-loopback is on, and enables power-saving again when it's off. So far, I thought only the amp controls, but now it's a different one.
In this case, the put callback would need to call snd_hda_pwoer_up() and snd_hda_power_down() appropriately to turn on/off power-save. They should be called only at transition. Namely, when 0->1 transition of spec->aloopback occurs in put callback, it calls snd_hda_power_up(). When 1->0 occurs, call snd_hda_power_down().
Takashi
Hi, Well, did you read my email? :-)
Yeah, but not carefully as I was in travel.
I did call snd_hda_power_up/down in .put callback, but as I said, on resume, driver didn't powered up the codec, and as usual any access to device powers up the codec.
Well, did you use snd_hda_codec_write_cache() there? Otherwise the changed analog-loopback setup won't be called.
Well and I found another bug, The problem is that on resume all "use mic/line-in as output' controls are disabled, and I know why:
.resume() before introduction of snd_hda_codec_write_cache() / dynamic power managment: stac92xx_init() -> inits inputs/outputs of chip (sets all dynamic pins to output mode)
snd_hda_resume_ctls() > hacky, but working way of resuming mixer controls : read from memory, write to device
.resume() now: stac92xx_init() -> inits inputs/outputs of chip (sets all dynamic pins to output mode), and touches the command cache. snd_hda_codec_resume_cache() writes (modifed) cache to codec, thus making dynamic outputs be in input mode.
I suggest skipping call to stac92xx_init() at all, after all no initialization is nessesary, since all commands are in cache.
Some stuff in stac92xx_init() isn't cached, so we cannot remove it completely. I fixed it now on HG tree. Give it a try.
Takashi
Hi,
Yes , 'Mic/Line-out as ouput' switches work fine now after suspend-resume, your patch works fine. Thanks.
Best regards, Maxim Levitsky
From 50e9864ecccb70aa6ba72fe542cf898add11f43a Mon Sep 17 00:00:00 2001 From: Maxim Levitsky maximlevitsky@gmail.com Date: Mon, 27 Aug 2007 20:21:29 +0300 Subject: [PATCH] HDA : add L/R swap of center/LFE for sigmatel codecs
--- sound/pci/hda/patch_sigmatel.c | 64 ++++++++++++++++++++++++++++++++++++++-- 1 files changed, 61 insertions(+), 3 deletions(-)
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 1627ca3..12b318e 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -127,6 +127,7 @@ struct sigmatel_spec {
/* i/o switches */ unsigned int io_switch[2]; + unsigned int clfe_swap;
struct hda_pcm pcm_rec[2]; /* PCM information */
@@ -1078,8 +1079,43 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ return 1; }
+static int stac92xx_clfe_switch_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} + +static int stac92xx_clfe_switch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + struct sigmatel_spec *spec = codec->spec; + + ucontrol->value.integer.value[0] = spec->clfe_swap; + return 0; +} + +static int stac92xx_clfe_switch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + struct sigmatel_spec *spec = codec->spec; + hda_nid_t nid = kcontrol->private_value & 0xff; + + spec->clfe_swap = ucontrol->value.integer.value[0]; + + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE, + spec->clfe_swap ? 0x4 : 0x0); + + return 1; +} + #define STAC_CODEC_IO_SWITCH(xname, xpval) \ - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + {.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ .name = xname, \ .index = 0, \ .info = stac92xx_io_switch_info, \ @@ -1088,17 +1124,28 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ .private_value = xpval, \ }
+#define STAC_CODEC_CLFE_SWITCH(xname, xpval) \ + { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .name = xname, \ + .index = 0, \ + .info = stac92xx_clfe_switch_info, \ + .get = stac92xx_clfe_switch_get, \ + .put = stac92xx_clfe_switch_put, \ + .private_value = xpval, \ + }
enum { STAC_CTL_WIDGET_VOL, STAC_CTL_WIDGET_MUTE, STAC_CTL_WIDGET_IO_SWITCH, + STAC_CTL_WIDGET_CLFE_SWITCH };
static struct snd_kcontrol_new stac92xx_control_templates[] = { HDA_CODEC_VOLUME(NULL, 0, 0, 0), HDA_CODEC_MUTE(NULL, 0, 0, 0), STAC_CODEC_IO_SWITCH(NULL, 0), + STAC_CODEC_CLFE_SWITCH(NULL, 0), };
/* add dynamic controls */ @@ -1287,7 +1334,7 @@ static int create_controls(struct sigmatel_spec *spec, const char *pfx, hda_nid_ }
/* add playback controls from the parsed DAC table */ -static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, +static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, const struct auto_pin_cfg *cfg) { static const char *chname[4] = { @@ -1296,6 +1343,10 @@ static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, hda_nid_t nid; int i, err;
+ struct sigmatel_spec *spec = codec->spec; + unsigned int wid_caps; + + for (i = 0; i < cfg->line_outs; i++) { if (!spec->multiout.dac_nids[i]) continue; @@ -1310,6 +1361,13 @@ static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, err = create_controls(spec, "LFE", nid, 2); if (err < 0) return err; + + wid_caps = get_wcaps(codec, nid); + + if (wid_caps & AC_WCAP_LR_SWAP) + if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_CLFE_SWITCH, "Swap Center/LFE Playback Switch", nid)) < 0) + return err; + } else { err = create_controls(spec, chname[i], nid, 3); if (err < 0) @@ -1562,7 +1620,7 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out if ((err = stac92xx_auto_fill_dac_nids(codec, &spec->autocfg)) < 0) return err;
- if ((err = stac92xx_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || + if ((err = stac92xx_auto_create_multi_out_ctls(codec, &spec->autocfg)) < 0 || (err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg)) < 0 || (err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0) return err;
At Tue, 28 Aug 2007 05:07:56 +0300, Maxim Levitsky wrote:
From 50e9864ecccb70aa6ba72fe542cf898add11f43a Mon Sep 17 00:00:00 2001 From: Maxim Levitsky maximlevitsky@gmail.com Date: Mon, 27 Aug 2007 20:21:29 +0300 Subject: [PATCH] HDA : add L/R swap of center/LFE for sigmatel codecs
sound/pci/hda/patch_sigmatel.c | 64 ++++++++++++++++++++++++++++++++++++++-- 1 files changed, 61 insertions(+), 3 deletions(-)
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 1627ca3..12b318e 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -127,6 +127,7 @@ struct sigmatel_spec {
/* i/o switches */ unsigned int io_switch[2];
unsigned int clfe_swap;
struct hda_pcm pcm_rec[2]; /* PCM information */
@@ -1078,8 +1079,43 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ return 1; }
+static int stac92xx_clfe_switch_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
+{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
+}
You can use a common helper snd_ctl_boolean_mono_info() that was added recently.
+static int stac92xx_clfe_switch_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
+{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct sigmatel_spec *spec = codec->spec;
- ucontrol->value.integer.value[0] = spec->clfe_swap;
- return 0;
+}
+static int stac92xx_clfe_switch_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
+{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct sigmatel_spec *spec = codec->spec;
- hda_nid_t nid = kcontrol->private_value & 0xff;
- spec->clfe_swap = ucontrol->value.integer.value[0];
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
spec->clfe_swap ? 0x4 : 0x0);
- return 1;
+}
The put callback should check whether the value is changed or not. It should change the value only when changed, and then return 1. If unchanged, it returns 0.
Also, the recent hda-intel driver uses snd_hda_codec_write_cache() for the register values to be resumed after suspend or power-save. I think it's the case, too. Simply use snd_hda_codec_write_cache() there.
#define STAC_CODEC_IO_SWITCH(xname, xpval) \
- { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
- {.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ .name = xname, \ .index = 0, \ .info = stac92xx_io_switch_info, \
@@ -1088,17 +1124,28 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ .private_value = xpval, \ }
+#define STAC_CODEC_CLFE_SWITCH(xname, xpval) \
- { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.name = xname, \
.index = 0, \
.info = stac92xx_clfe_switch_info, \
.get = stac92xx_clfe_switch_get, \
.put = stac92xx_clfe_switch_put, \
.private_value = xpval, \
- }
enum { STAC_CTL_WIDGET_VOL, STAC_CTL_WIDGET_MUTE, STAC_CTL_WIDGET_IO_SWITCH,
- STAC_CTL_WIDGET_CLFE_SWITCH
};
static struct snd_kcontrol_new stac92xx_control_templates[] = { HDA_CODEC_VOLUME(NULL, 0, 0, 0), HDA_CODEC_MUTE(NULL, 0, 0, 0), STAC_CODEC_IO_SWITCH(NULL, 0),
- STAC_CODEC_CLFE_SWITCH(NULL, 0),
};
/* add dynamic controls */ @@ -1287,7 +1334,7 @@ static int create_controls(struct sigmatel_spec *spec, const char *pfx, hda_nid_ }
/* add playback controls from the parsed DAC table */ -static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, +static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, const struct auto_pin_cfg *cfg) { static const char *chname[4] = { @@ -1296,6 +1343,10 @@ static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, hda_nid_t nid; int i, err;
- struct sigmatel_spec *spec = codec->spec;
- unsigned int wid_caps;
- for (i = 0; i < cfg->line_outs; i++) { if (!spec->multiout.dac_nids[i]) continue;
@@ -1310,6 +1361,13 @@ static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, err = create_controls(spec, "LFE", nid, 2); if (err < 0) return err;
wid_caps = get_wcaps(codec, nid);
if (wid_caps & AC_WCAP_LR_SWAP)
if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_CLFE_SWITCH, "Swap Center/LFE Playback Switch", nid)) < 0)
return err;
Please avoid if ((err = xxx) < 0) style. Split err = xxx and if (err < 0). Also, try to keep the line within 80 chars (at least for the new stuff :)
Takashi
From 204b216691b2d74e100bc321654ddadd2ff710af Mon Sep 17 00:00:00 2001 From: Maxim Levitsky maximlevitsky@gmail.com Date: Tue, 28 Aug 2007 01:06:00 +0300 Subject: [PATCH] HDA: add support for analog loopback to STAC9204/9205/922x/927x
--- sound/pci/hda/patch_sigmatel.c | 59 ++++++++++++++++++++++++++++++++++++++++ 1 files changed, 59 insertions(+), 0 deletions(-)
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 12b318e..a1f55d1 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -128,6 +128,7 @@ struct sigmatel_spec { /* i/o switches */ unsigned int io_switch[2]; unsigned int clfe_swap; + unsigned int aloopback;
struct hda_pcm pcm_rec[2]; /* PCM information */
@@ -277,6 +278,50 @@ static int stac92xx_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e spec->mux_nids[adc_idx], &spec->cur_mux[adc_idx]); }
+static int stac92xx_aloopback_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} + +static int stac92xx_aloopback_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + struct sigmatel_spec *spec = codec->spec; + + ucontrol->value.integer.value[0] = spec->aloopback; + return 0; +} + +static int stac92xx_aloopback_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + struct sigmatel_spec *spec = codec->spec; + unsigned int dac_mode; + + spec->aloopback = ucontrol->value.integer.value[0]; + + dac_mode = snd_hda_codec_read(codec, codec->afg, 0, + kcontrol->private_value & 0xFFFF, 0x0); + + if (spec->aloopback) + dac_mode |= 0x40; + else + dac_mode &= ~0x40; + + snd_hda_codec_write(codec, codec->afg, 0, + kcontrol->private_value >> 16, dac_mode); + + return 1; +} + + static struct hda_verb stac9200_core_init[] = { /* set dac0mux for dac converter */ { 0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, @@ -327,6 +372,17 @@ static struct hda_verb stac9205_core_init[] = { .put = stac92xx_mux_enum_put, \ }
+#define STAC_ANALOG_LOOPBACK(verb_read,verb_write) \ + { \ + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .name = "Analog Loopback", \ + .count = 1, \ + .info = stac92xx_aloopback_info, \ + .get = stac92xx_aloopback_get, \ + .put = stac92xx_aloopback_put, \ + .private_value = verb_read | (verb_write << 16), \ + } +
static struct snd_kcontrol_new stac9200_mixer[] = { HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT), @@ -358,6 +414,7 @@ static struct snd_kcontrol_new stac922x_mixer[] = { /* This needs to be generated dynamically based on sequence */ static struct snd_kcontrol_new stac9227_mixer[] = { STAC_INPUT_SOURCE, + STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB), HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Capture Switch", 0x1b, 0x0, HDA_OUTPUT), { } /* end */ @@ -365,6 +422,7 @@ static struct snd_kcontrol_new stac9227_mixer[] = {
static struct snd_kcontrol_new stac927x_mixer[] = { STAC_INPUT_SOURCE, + STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB), HDA_CODEC_VOLUME("InMux Capture Volume", 0x15, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("InVol Capture Volume", 0x18, 0x0, HDA_INPUT), HDA_CODEC_MUTE("ADCMux Capture Switch", 0x1b, 0x0, HDA_OUTPUT), @@ -381,6 +439,7 @@ static struct snd_kcontrol_new stac9205_mixer[] = { .put = stac92xx_dmux_enum_put, }, STAC_INPUT_SOURCE, + STAC_ANALOG_LOOPBACK(0xFE0, 0x7E0), HDA_CODEC_VOLUME("InMux Capture Volume", 0x19, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("InVol Capture Volume", 0x1b, 0x0, HDA_INPUT), HDA_CODEC_MUTE("ADCMux Capture Switch", 0x1d, 0x0, HDA_OUTPUT),
At Tue, 28 Aug 2007 05:08:02 +0300, Maxim Levitsky wrote:
From 204b216691b2d74e100bc321654ddadd2ff710af Mon Sep 17 00:00:00 2001 From: Maxim Levitsky maximlevitsky@gmail.com Date: Tue, 28 Aug 2007 01:06:00 +0300 Subject: [PATCH] HDA: add support for analog loopback to STAC9204/9205/922x/927x
sound/pci/hda/patch_sigmatel.c | 59 ++++++++++++++++++++++++++++++++++++++++ 1 files changed, 59 insertions(+), 0 deletions(-)
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 12b318e..a1f55d1 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -128,6 +128,7 @@ struct sigmatel_spec { /* i/o switches */ unsigned int io_switch[2]; unsigned int clfe_swap;
unsigned int aloopback;
struct hda_pcm pcm_rec[2]; /* PCM information */
@@ -277,6 +278,50 @@ static int stac92xx_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e spec->mux_nids[adc_idx], &spec->cur_mux[adc_idx]); }
+static int stac92xx_aloopback_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
+{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
+}
Use snd_ctl_boolean_mono_info().
+static int stac92xx_aloopback_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct sigmatel_spec *spec = codec->spec;
- ucontrol->value.integer.value[0] = spec->aloopback;
- return 0;
+}
+static int stac92xx_aloopback_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
+{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct sigmatel_spec *spec = codec->spec;
- unsigned int dac_mode;
- spec->aloopback = ucontrol->value.integer.value[0];
- dac_mode = snd_hda_codec_read(codec, codec->afg, 0,
kcontrol->private_value & 0xFFFF, 0x0);
- if (spec->aloopback)
dac_mode |= 0x40;
- else
dac_mode &= ~0x40;
- snd_hda_codec_write(codec, codec->afg, 0,
kcontrol->private_value >> 16, dac_mode);
- return 1;
+}
Check the value change, and use snd_hda_codec_write_cache().
Takashi
From 2b72257ec523662a580d8a6d93af72987c2855a5 Mon Sep 17 00:00:00 2001 From: Maxim Levitsky maximlevitsky@gmail.com Date: Tue, 28 Aug 2007 01:22:54 +0300 Subject: [PATCH] HDA: make volume knob, the master volume for sigmatel codecs that support it
--- sound/pci/hda/patch_sigmatel.c | 45 ++++++++++++++++++++++++++++++++++++++++ 1 files changed, 45 insertions(+), 0 deletions(-)
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index a1f55d1..ca21521 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -321,6 +321,36 @@ static int stac92xx_aloopback_put(struct snd_kcontrol *kcontrol, return 1; }
+static int stac92xx_volknob_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 127; + return 0; +} + +static int stac92xx_volknob_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = kcontrol->private_value; + return 0; +} + +static int stac92xx_volknob_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + + kcontrol->private_value = ucontrol->value.integer.value[0]; + + snd_hda_codec_write(codec, 0x24, 0, + AC_VERB_SET_VOLUME_KNOB_CONTROL, + kcontrol->private_value | 0x80); + return 1; +} +
static struct hda_verb stac9200_core_init[] = { /* set dac0mux for dac converter */ @@ -383,6 +413,17 @@ static struct hda_verb stac9205_core_init[] = { .private_value = verb_read | (verb_write << 16), \ }
+#define STAC_VOLKNOB \ + { \ + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .name = "Master Playback Volume", \ + .count = 1, \ + .info = stac92xx_volknob_info, \ + .get = stac92xx_volknob_get, \ + .put = stac92xx_volknob_put, \ + .private_value = 127, \ + } +
static struct snd_kcontrol_new stac9200_mixer[] = { HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT), @@ -405,6 +446,7 @@ static struct snd_kcontrol_new stac925x_mixer[] = { /* This needs to be generated dynamically based on sequence */ static struct snd_kcontrol_new stac922x_mixer[] = { STAC_INPUT_SOURCE, + STAC_VOLKNOB, HDA_CODEC_VOLUME("Capture Volume", 0x17, 0x0, HDA_INPUT), HDA_CODEC_MUTE("Capture Switch", 0x17, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Mux Capture Volume", 0x12, 0x0, HDA_OUTPUT), @@ -414,6 +456,7 @@ static struct snd_kcontrol_new stac922x_mixer[] = { /* This needs to be generated dynamically based on sequence */ static struct snd_kcontrol_new stac9227_mixer[] = { STAC_INPUT_SOURCE, + STAC_VOLKNOB, STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB), HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Capture Switch", 0x1b, 0x0, HDA_OUTPUT), @@ -422,6 +465,7 @@ static struct snd_kcontrol_new stac9227_mixer[] = {
static struct snd_kcontrol_new stac927x_mixer[] = { STAC_INPUT_SOURCE, + STAC_VOLKNOB, STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB), HDA_CODEC_VOLUME("InMux Capture Volume", 0x15, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("InVol Capture Volume", 0x18, 0x0, HDA_INPUT), @@ -440,6 +484,7 @@ static struct snd_kcontrol_new stac9205_mixer[] = { }, STAC_INPUT_SOURCE, STAC_ANALOG_LOOPBACK(0xFE0, 0x7E0), + STAC_VOLKNOB, HDA_CODEC_VOLUME("InMux Capture Volume", 0x19, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("InVol Capture Volume", 0x1b, 0x0, HDA_INPUT), HDA_CODEC_MUTE("ADCMux Capture Switch", 0x1d, 0x0, HDA_OUTPUT),
From d618bcd55f43fff3ca9c4948e7c99db75d21f3d6 Mon Sep 17 00:00:00 2001 From: Maxim Levitsky maximlevitsky@gmail.com Date: Tue, 28 Aug 2007 04:01:50 +0300 Subject: [PATCH] HDA: Fix support for sigmatel codecs that have 2 or more ADCs
--- sound/pci/hda/patch_sigmatel.c | 97 +++++++++++++++++++++++---------------- 1 files changed, 57 insertions(+), 40 deletions(-)
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index ca21521..77634ee 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -392,11 +392,11 @@ static struct hda_verb stac9205_core_init[] = { {} };
-#define STAC_INPUT_SOURCE \ +#define STAC_INPUT_SOURCE(cnt) \ { \ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ .name = "Input Source", \ - .count = 1, \ + .count = cnt, \ .info = stac92xx_mux_enum_info, \ .get = stac92xx_mux_enum_get, \ .put = stac92xx_mux_enum_put, \ @@ -428,7 +428,7 @@ static struct hda_verb stac9205_core_init[] = { static struct snd_kcontrol_new stac9200_mixer[] = { HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT), HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT), - STAC_INPUT_SOURCE, + STAC_INPUT_SOURCE(1), HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT), HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT), HDA_CODEC_VOLUME("Capture Mux Volume", 0x0c, 0, HDA_OUTPUT), @@ -436,58 +436,68 @@ static struct snd_kcontrol_new stac9200_mixer[] = { };
static struct snd_kcontrol_new stac925x_mixer[] = { - STAC_INPUT_SOURCE, + STAC_INPUT_SOURCE(1), HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_OUTPUT), HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_OUTPUT), HDA_CODEC_VOLUME("Capture Mux Volume", 0x0f, 0, HDA_OUTPUT), { } /* end */ };
-/* This needs to be generated dynamically based on sequence */ -static struct snd_kcontrol_new stac922x_mixer[] = { - STAC_INPUT_SOURCE, +static struct snd_kcontrol_new stac9205_mixer[] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Digital Input Source", + .count = 1, + .info = stac92xx_dmux_enum_info, + .get = stac92xx_dmux_enum_get, + .put = stac92xx_dmux_enum_put, + }, + STAC_INPUT_SOURCE(2), + STAC_ANALOG_LOOPBACK(0xFE0, 0x7E0), STAC_VOLKNOB, - HDA_CODEC_VOLUME("Capture Volume", 0x17, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Capture Switch", 0x17, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Mux Capture Volume", 0x12, 0x0, HDA_OUTPUT), + + HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1b, 0x0, HDA_INPUT), + HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1d, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x0, 0x19, 0x0, HDA_OUTPUT), + + HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x1c, 0x0, HDA_INPUT), + HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x1e, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x1, 0x1A, 0x0, HDA_OUTPUT), + { } /* end */ };
/* This needs to be generated dynamically based on sequence */ -static struct snd_kcontrol_new stac9227_mixer[] = { - STAC_INPUT_SOURCE, +static struct snd_kcontrol_new stac922x_mixer[] = { + STAC_INPUT_SOURCE(2), STAC_VOLKNOB, - STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB), - HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Capture Switch", 0x1b, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x17, 0x0, HDA_INPUT), + HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x17, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x0, 0x12, 0x0, HDA_OUTPUT), + + HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x18, 0x0, HDA_INPUT), + HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x18, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x1, 0x13, 0x0, HDA_OUTPUT), { } /* end */ };
+ static struct snd_kcontrol_new stac927x_mixer[] = { - STAC_INPUT_SOURCE, + STAC_INPUT_SOURCE(3), STAC_VOLKNOB, STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB), - HDA_CODEC_VOLUME("InMux Capture Volume", 0x15, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("InVol Capture Volume", 0x18, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("ADCMux Capture Switch", 0x1b, 0x0, HDA_OUTPUT), - { } /* end */ -};
-static struct snd_kcontrol_new stac9205_mixer[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Digital Input Source", - .count = 1, - .info = stac92xx_dmux_enum_info, - .get = stac92xx_dmux_enum_get, - .put = stac92xx_dmux_enum_put, - }, - STAC_INPUT_SOURCE, - STAC_ANALOG_LOOPBACK(0xFE0, 0x7E0), - STAC_VOLKNOB, - HDA_CODEC_VOLUME("InMux Capture Volume", 0x19, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("InVol Capture Volume", 0x1b, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("ADCMux Capture Switch", 0x1d, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x18, 0x0, HDA_INPUT), + HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1b, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x0, 0x15, 0x0, HDA_OUTPUT), + + HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x19, 0x0, HDA_INPUT), + HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x1c, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x1, 0x16, 0x0, HDA_OUTPUT), + + HDA_CODEC_VOLUME_IDX("Capture Volume", 0x2, 0x1A, 0x0, HDA_INPUT), + HDA_CODEC_MUTE_IDX("Capture Switch", 0x2, 0x1d, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x2, 0x17, 0x0, HDA_OUTPUT), { } /* end */ };
@@ -1074,10 +1084,9 @@ static struct hda_pcm_stream stac92xx_pcm_analog_alt_playback = { };
static struct hda_pcm_stream stac92xx_pcm_analog_capture = { - .substreams = 2, .channels_min = 2, .channels_max = 2, - /* NID is set in stac92xx_build_pcms */ + /* NID + .substreams is set in stac92xx_build_pcms */ .ops = { .prepare = stac92xx_capture_pcm_prepare, .cleanup = stac92xx_capture_pcm_cleanup @@ -1096,6 +1105,7 @@ static int stac92xx_build_pcms(struct hda_codec *codec) info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_playback; info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_analog_capture; info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0]; + info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adcs;
if (spec->alt_switch) { codec->num_pcms++; @@ -2133,6 +2143,7 @@ static int patch_stac9200(struct hda_codec *codec) spec->mux_nids = stac9200_mux_nids; spec->num_muxes = 1; spec->num_dmics = 0; + spec->num_adcs = 1;
spec->init = stac9200_core_init; spec->mixer = stac9200_mixer; @@ -2184,6 +2195,7 @@ static int patch_stac925x(struct hda_codec *codec) spec->adc_nids = stac925x_adc_nids; spec->mux_nids = stac925x_mux_nids; spec->num_muxes = 1; + spec->num_adcs = 1; switch (codec->vendor_id) { case 0x83847632: /* STAC9202 */ case 0x83847633: /* STAC9202D */ @@ -2287,6 +2299,7 @@ static int patch_stac922x(struct hda_codec *codec) spec->adc_nids = stac922x_adc_nids; spec->mux_nids = stac922x_mux_nids; spec->num_muxes = ARRAY_SIZE(stac922x_mux_nids); + spec->num_adcs = ARRAY_SIZE(stac922x_adc_nids); spec->num_dmics = 0;
spec->init = stac922x_core_init; @@ -2355,22 +2368,25 @@ static int patch_stac927x(struct hda_codec *codec) spec->adc_nids = stac927x_adc_nids; spec->mux_nids = stac927x_mux_nids; spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids); + spec->num_adcs = ARRAY_SIZE(stac927x_adc_nids); spec->num_dmics = 0; spec->init = d965_core_init; - spec->mixer = stac9227_mixer; + spec->mixer = stac927x_mixer; break; case STAC_D965_5ST: spec->adc_nids = stac927x_adc_nids; spec->mux_nids = stac927x_mux_nids; spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids); + spec->num_adcs = ARRAY_SIZE(stac927x_adc_nids); spec->num_dmics = 0; spec->init = d965_core_init; - spec->mixer = stac9227_mixer; + spec->mixer = stac927x_mixer; break; default: spec->adc_nids = stac927x_adc_nids; spec->mux_nids = stac927x_mux_nids; spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids); + spec->num_adcs = ARRAY_SIZE(stac927x_adc_nids); spec->num_dmics = 0; spec->init = stac927x_core_init; spec->mixer = stac927x_mixer; @@ -2430,6 +2446,7 @@ static int patch_stac9205(struct hda_codec *codec) }
spec->adc_nids = stac9205_adc_nids; + spec->num_adcs = ARRAY_SIZE(stac9205_adc_nids); spec->mux_nids = stac9205_mux_nids; spec->num_muxes = ARRAY_SIZE(stac9205_mux_nids); spec->dmic_nids = stac9205_dmic_nids;
At Tue, 28 Aug 2007 05:08:13 +0300, Maxim Levitsky wrote:
From d618bcd55f43fff3ca9c4948e7c99db75d21f3d6 Mon Sep 17 00:00:00 2001 From: Maxim Levitsky maximlevitsky@gmail.com Date: Tue, 28 Aug 2007 04:01:50 +0300 Subject: [PATCH] HDA: Fix support for sigmatel codecs that have 2 or more ADCs
sound/pci/hda/patch_sigmatel.c | 97 +++++++++++++++++++++++---------------- 1 files changed, 57 insertions(+), 40 deletions(-)
This looks OK to me. Can anyone test it?
Takashi
At Tue, 28 Aug 2007 04:54:29 +0300, Maxim Levitsky wrote:
Hi,
As promised, those are patches that extend patch_sigmatel.c driver to add missing functionality
Thanks for the patches!
They all are runtime tested with my STAC9227, and datasheet tested with others Note that I did my best to ensure that even if a codec doesn't support a feature (and I don't know sbout that), maximum impact will be a new, non-working mixer control
STAC927x are almost exactly the same as STAC922x, but have DAC4
- Center/LFE swap :
It can be sometimes useful to swap those channels, since they are on same line.
I add that control only in case Center/LFE DAC is there, and supports L/R swap, it should be very safe.
- Analog loopback:
Added for 922x, 927x, and for 9204/5 which has a different verb, that offers same analog loopback
- Volume Knob:
Added for 9204/5, 9220/1/3, 922x 92-7x I made it a master volume
- Fixed support for codecs that have 2 or 3 ADC:
I added separate mixer controls for all 2/3 ADCs, and made PCM capture device sub-streams count to depend on actual number of ADCs
I am looking for your comments, Best regards, Maxim Levitsky
All patches except 3 look almost good to me. I'll give review back to each post. For the next version, could you give the changelog text for each patch (not only the subject line) together with your sign-off? Then I can merge to HG tree.
About 3 (volume-knob), we'd need a bit more checks and tests. Does the volume knob widget work always as a mater control regardless whetehr the real hardware component exists or not? I.e. can we use it blindly?
Tobin, Matt, could you test these patches, especially patch 3, with your hardwares? Anyone who has STAC92xx hardwares are welcome for testing it, too!
Thanks,
Takashi
At Tue, 28 Aug 2007 12:45:21 +0200, I wrote:
At Tue, 28 Aug 2007 04:54:29 +0300, Maxim Levitsky wrote:
Hi,
As promised, those are patches that extend patch_sigmatel.c driver to add missing functionality
Thanks for the patches!
They all are runtime tested with my STAC9227, and datasheet tested with others Note that I did my best to ensure that even if a codec doesn't support a feature (and I don't know sbout that), maximum impact will be a new, non-working mixer control
STAC927x are almost exactly the same as STAC922x, but have DAC4
- Center/LFE swap :
It can be sometimes useful to swap those channels, since they are on same line.
I add that control only in case Center/LFE DAC is there, and supports L/R swap, it should be very safe.
- Analog loopback:
Added for 922x, 927x, and for 9204/5 which has a different verb, that offers same analog loopback
- Volume Knob:
Added for 9204/5, 9220/1/3, 922x 92-7x I made it a master volume
- Fixed support for codecs that have 2 or 3 ADC:
I added separate mixer controls for all 2/3 ADCs, and made PCM capture device sub-streams count to depend on actual number of ADCs
I am looking for your comments, Best regards, Maxim Levitsky
All patches except 3 look almost good to me. I'll give review back to each post. For the next version, could you give the changelog text for each patch (not only the subject line) together with your sign-off? Then I can merge to HG tree.
About 3 (volume-knob), we'd need a bit more checks and tests. Does the volume knob widget work always as a mater control regardless whetehr the real hardware component exists or not? I.e. can we use it blindly?
Tobin, Matt, could you test these patches, especially patch 3, with your hardwares? Anyone who has STAC92xx hardwares are welcome for testing it, too!
Just to be sure: the posted patch number seems confusing. The "patch 4/5" is the volume-knob one although it's listed as 3 in the above.
Takashi
On Tuesday 28 August 2007 13:52:06 Takashi Iwai wrote:
At Tue, 28 Aug 2007 12:45:21 +0200, I wrote:
At Tue, 28 Aug 2007 04:54:29 +0300, Maxim Levitsky wrote:
Hi,
As promised, those are patches that extend patch_sigmatel.c driver to add missing functionality
Thanks for the patches!
They all are runtime tested with my STAC9227, and datasheet tested with others Note that I did my best to ensure that even if a codec doesn't support a feature (and I don't know sbout that), maximum impact will be a new, non-working mixer control
STAC927x are almost exactly the same as STAC922x, but have DAC4
- Center/LFE swap :
It can be sometimes useful to swap those channels, since they are on same line.
I add that control only in case Center/LFE DAC is there, and supports L/R swap, it should be very safe.
- Analog loopback:
Added for 922x, 927x, and for 9204/5 which has a different verb, that offers same analog loopback
- Volume Knob:
Added for 9204/5, 9220/1/3, 922x 92-7x I made it a master volume
- Fixed support for codecs that have 2 or 3 ADC:
I added separate mixer controls for all 2/3 ADCs, and made PCM capture device sub-streams count to depend on actual number of ADCs
I am looking for your comments, Best regards, Maxim Levitsky
All patches except 3 look almost good to me. I'll give review back to each post. For the next version, could you give the changelog text for each patch (not only the subject line) together with your sign-off? Then I can merge to HG tree.
About 3 (volume-knob), we'd need a bit more checks and tests. Does the volume knob widget work always as a mater control regardless whetehr the real hardware component exists or not? I.e. can we use it blindly?
Tobin, Matt, could you test these patches, especially patch 3, with your hardwares? Anyone who has STAC92xx hardwares are welcome for testing it, too!
Just to be sure: the posted patch number seems confusing. The "patch 4/5" is the volume-knob one although it's listed as 3 in the above.
Takashi
Hi,
Sorry for confusion, In main letter I numbered just the features I added, I could just use "*" instead of numbers, There is no connection between patch numbers and numbers in main letter.
Best regards Maxim Levitsky
I plan on testing these later this week. Will let you know what I find then.
I have systems with a 3-stack 9227 configuration, and I might be able to get on a 5 stack system as well.
Tobin
On Tue, 2007-08-28 at 12:45 +0200, Takashi Iwai wrote:
At Tue, 28 Aug 2007 04:54:29 +0300, Maxim Levitsky wrote:
Hi,
As promised, those are patches that extend patch_sigmatel.c driver to add missing functionality
Thanks for the patches!
They all are runtime tested with my STAC9227, and datasheet tested with others Note that I did my best to ensure that even if a codec doesn't support a feature (and I don't know sbout that), maximum impact will be a new, non-working mixer control
STAC927x are almost exactly the same as STAC922x, but have DAC4
- Center/LFE swap :
It can be sometimes useful to swap those channels, since they are on same line.
I add that control only in case Center/LFE DAC is there, and supports L/R swap, it should be very safe.
- Analog loopback:
Added for 922x, 927x, and for 9204/5 which has a different verb, that offers same analog loopback
- Volume Knob:
Added for 9204/5, 9220/1/3, 922x 92-7x I made it a master volume
- Fixed support for codecs that have 2 or 3 ADC:
I added separate mixer controls for all 2/3 ADCs, and made PCM capture device sub-streams count to depend on actual number of ADCs
I am looking for your comments, Best regards, Maxim Levitsky
All patches except 3 look almost good to me. I'll give review back to each post. For the next version, could you give the changelog text for each patch (not only the subject line) together with your sign-off? Then I can merge to HG tree.
About 3 (volume-knob), we'd need a bit more checks and tests. Does the volume knob widget work always as a mater control regardless whetehr the real hardware component exists or not? I.e. can we use it blindly?
Tobin, Matt, could you test these patches, especially patch 3, with your hardwares? Anyone who has STAC92xx hardwares are welcome for testing it, too!
Thanks,
Takashi
On Tuesday 28 August 2007 16:55:36 Tobin Davis wrote:
I plan on testing these later this week. Will let you know what I find then.
I have systems with a 3-stack 9227 configuration, and I might be able to get on a 5 stack system as well.
Tobin
On Tue, 2007-08-28 at 12:45 +0200, Takashi Iwai wrote:
At Tue, 28 Aug 2007 04:54:29 +0300, Maxim Levitsky wrote:
Hi,
As promised, those are patches that extend patch_sigmatel.c driver to add missing functionality
Thanks for the patches!
They all are runtime tested with my STAC9227, and datasheet tested with others Note that I did my best to ensure that even if a codec doesn't support a feature (and I don't know sbout that), maximum impact will be a new, non-working mixer control
STAC927x are almost exactly the same as STAC922x, but have DAC4
- Center/LFE swap :
It can be sometimes useful to swap those channels, since they are on same line.
I add that control only in case Center/LFE DAC is there, and supports L/R swap, it should be very safe.
- Analog loopback:
Added for 922x, 927x, and for 9204/5 which has a different verb, that offers same analog loopback
- Volume Knob:
Added for 9204/5, 9220/1/3, 922x 92-7x I made it a master volume
- Fixed support for codecs that have 2 or 3 ADC:
I added separate mixer controls for all 2/3 ADCs, and made PCM capture device sub-streams count to depend on actual number of ADCs
I am looking for your comments, Best regards, Maxim Levitsky
All patches except 3 look almost good to me. I'll give review back to each post. For the next version, could you give the changelog text for each patch (not only the subject line) together with your sign-off? Then I can merge to HG tree.
I haven't written them :-), I will add changelogs
About 3 (volume-knob), we'd need a bit more checks and tests. Does the volume knob widget work always as a mater control regardless whetehr the real hardware component exists or not? I.e. can we use it blindly?
According to datasheet, it works, also driver already assumes it there, and sets it to maximum volume see hda_verb stac922x_core_init, hda_verb d965_core_init, hda_verb stac927x_core_init,hda_verb stac9205_core_init
Tobin, Matt, could you test these patches, especially patch 3, with your hardwares? Anyone who has STAC92xx hardwares are welcome for testing it, too!
Thanks,
Takashi
Hi,
Thanks for review, I will fix all things you pointed out, but I am coding against latest linus' kernel tree, and snd_ctl_boolean_mono_info() isn't there, and thus I didn't use it, I will download latest alsa tree, and compile against it
But I have a question: can I only complile snd-hda-intel from that tree, and leave kernel's sound core modules?
Best regards, Maxim Levitsky
At Tue, 28 Aug 2007 21:41:32 +0300, Maxim Levitsky wrote:
About 3 (volume-knob), we'd need a bit more checks and tests. Does the volume knob widget work always as a mater control regardless whetehr the real hardware component exists or not? I.e. can we use it blindly?
According to datasheet, it works, also driver already assumes it there, and sets it to maximum volume see hda_verb stac922x_core_init, hda_verb d965_core_init, hda_verb stac927x_core_init,hda_verb stac9205_core_init
Interesting. So, writing to the volume knob widget actually works just like a normal mixer amp?
Tobin, Matt, could you test these patches, especially patch 3, with your hardwares? Anyone who has STAC92xx hardwares are welcome for testing it, too!
Thanks,
Takashi
Hi,
Thanks for review, I will fix all things you pointed out, but I am coding against latest linus' kernel tree, and snd_ctl_boolean_mono_info() isn't there, and thus I didn't use it, I will download latest alsa tree, and compile against it
But I have a question: can I only complile snd-hda-intel from that tree, and leave kernel's sound core modules?
If you build from alsa-driver tree, then yes, only modules.
You can get use kernel.git perex/alsa.git mm branch for the latest ALSA codes, too: http://git.kernel.org/?p=linux/kernel/git/perex/alsa.git;a=shortlog;h=mm
thanks,
Takashi
2007/8/29, Takashi Iwai tiwai@suse.de:
At Tue, 28 Aug 2007 21:41:32 +0300, Maxim Levitsky wrote:
About 3 (volume-knob), we'd need a bit more checks and tests. Does the volume knob widget work always as a mater control regardless whetehr the real hardware component exists or not? I.e. can we use it blindly?
According to datasheet, it works, also driver already assumes it there, and sets it to maximum volume see hda_verb stac922x_core_init, hda_verb d965_core_init, hda_verb stac927x_core_init,hda_verb stac9205_core_init
Interesting. So, writing to the volume knob widget actually works just like a normal mixer amp?
Yes, but volumeknob doesn't support standard verbs that amps do, thus I coded it as a custom control, but generally it is a amp
Tobin, Matt, could you test these patches, especially patch 3, with your hardwares? Anyone who has STAC92xx hardwares are welcome for testing it, too!
Thanks,
Takashi
Hi,
Thanks for review, I will fix all things you pointed out, but I am coding against latest linus' kernel tree, and snd_ctl_boolean_mono_info() isn't there, and thus I didn't use it, I will download latest alsa tree, and compile against it
But I have a question: can I only complile snd-hda-intel from that tree, and leave kernel's sound core modules?
If you build from alsa-driver tree, then yes, only modules.
You can get use kernel.git perex/alsa.git mm branch for the latest ALSA codes, too: http://git.kernel.org/?p=linux/kernel/git/perex/alsa.git;a=shortlog;h=mm
thanks,
Takashi
Hi, Thanks for information, I will send updated patches soon.
Best regards, Maxim Levitsky
participants (3)
-
Maxim Levitsky
-
Takashi Iwai
-
Tobin Davis