[alsa-devel] Digital-Out (Toslink) on HDA-Intal (AD1986A)?
Hi,
is there any way to use the digital output via toslink on my Samsung P50 notebook?
It has an integrated Intel Corporation 82801G (ICH7 Family) High Definition Audio Controller. The soundchip is supported via HDA-Intel and the codec is Analog Devices AD1986A.
If the digital output is not supported at the moment, I'd like to help the developers with information, testing an even coding.
You can find all alsa related information about my system at [1]
Regards Martin
At Tue, 22 Jan 2008 21:20:49 +0100, Martin Egge wrote:
Hi,
is there any way to use the digital output via toslink on my Samsung P50 notebook?
It has an integrated Intel Corporation 82801G (ICH7 Family) High Definition Audio Controller. The soundchip is supported via HDA-Intel and the codec is Analog Devices AD1986A.
If the digital output is not supported at the moment, I'd like to help the developers with information, testing an even coding.
You can find all alsa related information about my system at [1]
The SPDIF is disabled intentionally for your model because no one could test it. Does the patch below work?
Takashi
---
diff -r 8ba16b4a9e2d pci/hda/patch_analog.c --- a/pci/hda/patch_analog.c Wed Jan 23 11:52:38 2008 +0100 +++ b/pci/hda/patch_analog.c Wed Jan 23 12:05:02 2008 +0100 @@ -921,6 +921,13 @@ static struct hda_amp_list ad1986a_loopb }; #endif
+static int is_jack_available(struct hda_codec *codec, hda_nid_t nid) +{ + unsigned int conf = snd_hda_codec_read(codec, nid, 0, + AC_VERB_GET_CONFIG_DEFAULT, 0); + return get_defcfg_connect(conf) != AC_JACK_PORT_NONE; +} + static int patch_ad1986a(struct hda_codec *codec) { struct ad198x_spec *spec; @@ -980,7 +987,8 @@ static int patch_ad1986a(struct hda_code spec->multiout.max_channels = 2; spec->multiout.num_dacs = 1; spec->multiout.dac_nids = ad1986a_laptop_dac_nids; - spec->multiout.dig_out_nid = 0; + if (!is_jack_available(codec, 0x25)) + spec->multiout.dig_out_nid = 0; spec->input_mux = &ad1986a_laptop_eapd_capture_source; break; case AD1986A_LAPTOP_AUTOMUTE: @@ -991,7 +999,8 @@ static int patch_ad1986a(struct hda_code spec->multiout.max_channels = 2; spec->multiout.num_dacs = 1; spec->multiout.dac_nids = ad1986a_laptop_dac_nids; - spec->multiout.dig_out_nid = 0; + if (!is_jack_available(codec, 0x25)) + spec->multiout.dig_out_nid = 0; spec->input_mux = &ad1986a_laptop_eapd_capture_source; codec->patch_ops.unsol_event = ad1986a_hp_unsol_event; codec->patch_ops.init = ad1986a_hp_init;
Hi Takashi,
Am Mittwoch, 23. Januar 2008 schrieb Takashi Iwai:
The SPDIF is disabled intentionally for your model because no one could test it. Does the patch below work?
Thanks for the patch. I'll test it later. Which version of ALSA-Drivers should I apply the patch on?
Greetz Martin
At Wed, 23 Jan 2008 12:34:42 +0100, Martin Egge wrote:
Hi Takashi,
Am Mittwoch, 23. Januar 2008 schrieb Takashi Iwai:
The SPDIF is disabled intentionally for your model because no one could test it. Does the patch below work?
Thanks for the patch. I'll test it later. Which version of ALSA-Drivers should I apply the patch on?
For testing, always try ALSA HG version unless explicitly specified. 1.0.16rc1 should be OK for now, though.
Takashi
Hi Takashi
Am Mittwoch, 23. Januar 2008 schrieb Takashi Iwai:
For testing, always try ALSA HG version unless explicitly specified. 1.0.16rc1 should be OK for now, though.
I cannot compile neither of them. I always get a compiler error. See [1] for details. Can you help me?
Regards Martin
At Wed, 23 Jan 2008 15:44:38 +0100, Martin Egge wrote:
Hi Takashi
Am Mittwoch, 23. Januar 2008 schrieb Takashi Iwai:
For testing, always try ALSA HG version unless explicitly specified. 1.0.16rc1 should be OK for now, though.
I cannot compile neither of them. I always get a compiler error. See [1] for details. Can you help me?
Already fixed today. Pull the latest HG repo from hg.alsa-project.org. hg-mirror seems out of sync.
Takashi
Hi again,
Am Mittwoch, 23. Januar 2008 schrieb Takashi Iwai:
At Wed, 23 Jan 2008 15:44:38 +0100, Martin Egge wrote:
Am Mittwoch, 23. Januar 2008 schrieb Takashi Iwai:
For testing, always try ALSA HG version unless explicitly specified. 1.0.16rc1 should be OK for now, though.
I cannot compile neither of them. I always get a compiler error. See [1] for details. Can you help me?
Already fixed today. Pull the latest HG repo from hg.alsa-project.org. hg-mirror seems out of sync.
Sorry, but I cannot confirm that. I downloaded alsa-driver and alsa-kernel from hg.alsa-project.org. But compiling with hgcompile resulted in the same error. I'll try it again tomorrow.
Regards, Martin
At Wed, 23 Jan 2008 22:58:49 +0100, Martin Egge wrote:
Hi again,
Am Mittwoch, 23. Januar 2008 schrieb Takashi Iwai:
At Wed, 23 Jan 2008 15:44:38 +0100, Martin Egge wrote:
Am Mittwoch, 23. Januar 2008 schrieb Takashi Iwai:
For testing, always try ALSA HG version unless explicitly specified. 1.0.16rc1 should be OK for now, though.
I cannot compile neither of them. I always get a compiler error. See [1] for details. Can you help me?
Already fixed today. Pull the latest HG repo from hg.alsa-project.org. hg-mirror seems out of sync.
Sorry, but I cannot confirm that. I downloaded alsa-driver and alsa-kernel from hg.alsa-project.org. But compiling with hgcompile resulted in the same error. I'll try it again tomorrow.
Did you run hgcompile again? If still doesn't work, check init_utsname in config.log. You must have a compile error there.
Takashi
At Thu, 24 Jan 2008 11:42:46 +0100, I wrote:
At Wed, 23 Jan 2008 22:58:49 +0100, Martin Egge wrote:
Hi again,
Am Mittwoch, 23. Januar 2008 schrieb Takashi Iwai:
At Wed, 23 Jan 2008 15:44:38 +0100, Martin Egge wrote:
Am Mittwoch, 23. Januar 2008 schrieb Takashi Iwai:
For testing, always try ALSA HG version unless explicitly specified. 1.0.16rc1 should be OK for now, though.
I cannot compile neither of them. I always get a compiler error. See [1] for details. Can you help me?
Already fixed today. Pull the latest HG repo from hg.alsa-project.org. hg-mirror seems out of sync.
Sorry, but I cannot confirm that. I downloaded alsa-driver and alsa-kernel from hg.alsa-project.org. But compiling with hgcompile resulted in the same error. I'll try it again tomorrow.
Did you run hgcompile again? If still doesn't work, check init_utsname in config.log. You must have a compile error there.
OK, found another problem which is gcc-version specific. Now fixed again on HG tree. Give it a try.
Takashi
Hi,
Am Mittwoch, 23. Januar 2008 schrieb Takashi Iwai:
The SPDIF is disabled intentionally for your model because no one could test it. Does the patch below work?
I tried this patch on the newest hg-version a few minutes ago. Digital-Out still does not work, even though there is a IEC958 in the alsamixer now. By the way the digital-out is shared with the analog one (green 3,5mm jack). I only get an analog stereo signal whatever the state of the IEC958 is.
Regards, Martin
P.S.: There is also the not so demanding problem that the internal mic has never been working
At Fri, 25 Jan 2008 15:57:55 +0100, Martin Egge wrote:
Hi,
Am Mittwoch, 23. Januar 2008 schrieb Takashi Iwai:
The SPDIF is disabled intentionally for your model because no one could test it. Does the patch below work?
I tried this patch on the newest hg-version a few minutes ago. Digital-Out still does not work, even though there is a IEC958 in the alsamixer now. By the way the digital-out is shared with the analog one (green 3,5mm jack). I only get an analog stereo signal whatever the state of the IEC958 is.
Is it an optical SPDIF out shared with the headphone jack? Then you can see the red light when the SPDIF is turned on. Make sure that you turned on "IEC958 Playback Switch".
P.S.: There is also the not so demanding problem that the internal mic has never been working
Details please?
Takashi
Hi,
Am Freitag, 25. Januar 2008 schrieb Takashi Iwai:
Is it an optical SPDIF out shared with the headphone jack?
Yes it is.
Then you can see the red light when the SPDIF is turned on. Make sure that you turned on "IEC958 Playback Switch".
The red light is never turned on.
P.S.: There is also the not so demanding problem that the internal mic has never been working
Details please?
There are two sliders and switches for mics: 1. Mic 2. Internal Mic There is on MicBoost slider.
An external microphone (connect to the pink microphone jack) works completely and can be controlled via the Mic slider and switch. The internal mic is unusable, I can neither hear (playback) nor capture it. The Intenal Mic slider and switch don't change anything.
Regards Martin
At Fri, 25 Jan 2008 16:27:28 +0100, Martin Egge wrote:
Hi,
Am Freitag, 25. Januar 2008 schrieb Takashi Iwai:
Is it an optical SPDIF out shared with the headphone jack?
Yes it is.
Then you can see the red light when the SPDIF is turned on. Make sure that you turned on "IEC958 Playback Switch".
The red light is never turned on.
OK, then please attach the content of /proc/asound/card0/codec#* and the generated file via "alsactl -f somefile store".
P.S.: There is also the not so demanding problem that the internal mic has never been working
Details please?
There are two sliders and switches for mics:
- Mic
- Internal Mic
There is on MicBoost slider.
An external microphone (connect to the pink microphone jack) works completely and can be controlled via the Mic slider and switch. The internal mic is unusable, I can neither hear (playback) nor capture it. The Intenal Mic slider and switch don't change anything.
This sounds like that the pin mapping is different from the currently used preset. I'd need to check codec proc file also for this, too.
Takashi
At Fri, 25 Jan 2008 16:44:52 +0100, Martin Egge wrote:
Hi,
Am Freitag, 25. Januar 2008 schrieb Takashi Iwai:
OK, then please attach the content of /proc/asound/card0/codec#* and the generated file via "alsactl -f somefile store".
Done
Thanks. I couldn't find any missing setup for the SPDIF. I thought the similar setup worked well on other machines with AD1986A, but I'm not sure whether it's still OK with the recent version...
Anyay, the patch below is to change the mic input behavior. With the patch, the mic input is toggled automatically via jack plug. It assumes that you didn't change the model preset (i.e. model=laptop-eapd).
Give it a try.
Takashi
---
diff -r b0d97ac73e0f pci/hda/patch_analog.c --- a/pci/hda/patch_analog.c Fri Jan 25 15:24:50 2008 +0100 +++ b/pci/hda/patch_analog.c Fri Jan 25 17:23:23 2008 +0100 @@ -609,13 +609,19 @@ static struct hda_input_mux ad1986a_lapt }, };
+static struct hda_input_mux ad1986a_automic_capture_source = { + .num_items = 2, + .items = { + { "Mic", 0x0 }, + { "Mix", 0x5 }, + }, +}; + static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = { HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol), HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw), HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), @@ -638,6 +644,32 @@ static struct snd_kcontrol_new ad1986a_l }, { } /* end */ }; + +/* re-connect the mic boost input according to the jack sensing */ +static void ad1986a_automic(struct hda_codec *codec) +{ + unsigned int present; + present = snd_hda_codec_read(codec, 0x1f, 0, AC_VERB_GET_PIN_SENSE, 0); + snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_CONNECT_SEL, + (present & AC_PINSENSE_PRESENCE) ? 0 : 1); +} + +#define AD1986A_MIC_EVENT 0x36 + +static void ad1986a_automic_unsol_event(struct hda_codec *codec, + unsigned int res) +{ + if ((res >> 26) != AD1986A_MIC_EVENT) + return; + ad1986a_automic(codec); +} + +static int ad1986a_automic_init(struct hda_codec *codec) +{ + ad198x_init(codec); + ad1986a_automic(codec); + return 0; +}
/* laptop-automute - 2ch only */
@@ -842,6 +874,12 @@ static struct hda_verb ad1986a_eapd_init {} };
+static struct hda_verb ad1986a_automic_verbs[] = { + {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, + {0x1f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_MIC_EVENT}, + {} +}; + /* Ultra initialization */ static struct hda_verb ad1986a_ultra_init[] = { /* eapd initialization */ @@ -977,13 +1015,16 @@ static int patch_ad1986a(struct hda_code break; case AD1986A_LAPTOP_EAPD: spec->mixers[0] = ad1986a_laptop_eapd_mixers; - spec->num_init_verbs = 2; + spec->num_init_verbs = 3; spec->init_verbs[1] = ad1986a_eapd_init_verbs; + spec->init_verbs[2] = ad1986a_automic_verbs; spec->multiout.max_channels = 2; spec->multiout.num_dacs = 1; spec->multiout.dac_nids = ad1986a_laptop_dac_nids; spec->multiout.dig_out_nid = 0; - spec->input_mux = &ad1986a_laptop_eapd_capture_source; + spec->input_mux = &ad1986a_automic_capture_source; + codec->patch_ops.unsol_event = ad1986a_automic_unsol_event; + codec->patch_ops.init = ad1986a_automic_init; break; case AD1986A_LAPTOP_AUTOMUTE: spec->mixers[0] = ad1986a_laptop_automute_mixers;
Hi,
Am Freitag, 25. Januar 2008 schrieb Takashi Iwai:
Thanks. I couldn't find any missing setup for the SPDIF. I thought the similar setup worked well on other machines with AD1986A, but I'm not sure whether it's still OK with the recent version...
Is there anything I can do, to help you to get it working?
Anyay, the patch below is to change the mic input behavior. With the patch, the mic input is toggled automatically via jack plug.
The external mic input is toggled via jack plug now. But the internal mic still is not working.
It assumes that you didn't change the model preset (i.e. model=laptop-eapd).
What does this mean? Do I have to insert options snd_hda_intel model=laptop-eapd in my /etc/modprobe.d/alsa-base or not?
Regards, Martin
Hi,
Am Freitag, 25. Januar 2008 schrieb Martin Egge:
Am Freitag, 25. Januar 2008 schrieb Takashi Iwai:
Anyay, the patch below is to change the mic input behavior. With the patch, the mic input is toggled automatically via jack plug.
The external mic input is toggled via jack plug now. But the internal mic still is not working.
I've got some information that might help you. If I set model=3stack the internal and external mic are working in parallel. There is no jack-sense which disables the internal mic when an external mic is connected.
HTH Martin
At Sun, 27 Jan 2008 23:15:03 +0100, Martin Egge wrote:
Hi,
Am Freitag, 25. Januar 2008 schrieb Martin Egge:
Am Freitag, 25. Januar 2008 schrieb Takashi Iwai:
Anyay, the patch below is to change the mic input behavior. With the patch, the mic input is toggled automatically via jack plug.
The external mic input is toggled via jack plug now. But the internal mic still is not working.
I've got some information that might help you. If I set model=3stack the internal and external mic are working in parallel. There is no jack-sense which disables the internal mic when an external mic is connected.
Then get codec#* proc dump for both working and non-working states to compare.
Takashi
Hi,
Am Montag, 28. Januar 2008 schrieb Takashi Iwai:
At Sun, 27 Jan 2008 23:15:03 +0100, Martin Egge wrote:
I've got some information that might help you. If I set model=3stack the internal and external mic are working in parallel. There is no jack-sense which disables the internal mic when an external mic is connected.
Then get codec#* proc dump for both working and non-working states to compare.
See the attachments. The naming of the files should be comprehensible. I've updated to latest hg before dumping the codecs yesterday evening.
Regards, Martin
At Tue, 29 Jan 2008 11:06:24 +0100, Martin Egge wrote:
Hi,
Am Montag, 28. Januar 2008 schrieb Takashi Iwai:
At Sun, 27 Jan 2008 23:15:03 +0100, Martin Egge wrote:
I've got some information that might help you. If I set model=3stack the internal and external mic are working in parallel. There is no jack-sense which disables the internal mic when an external mic is connected.
Then get codec#* proc dump for both working and non-working states to compare.
See the attachments. The naming of the files should be comprehensible. I've updated to latest hg before dumping the codecs yesterday evening.
Thanks. That both mics are working in parallel means they are recorded at the same time, or you can switch them via "Capture Source"? In the latter case, which input as internal mic?
Unfortuantely the BIOS sets pretty useless information so it's hard to guess which pin is really correctly assigned.
Takashi
At Tue, 29 Jan 2008 15:55:24 +0100, I wrote:
At Tue, 29 Jan 2008 11:06:24 +0100, Martin Egge wrote:
Hi,
Am Montag, 28. Januar 2008 schrieb Takashi Iwai:
At Sun, 27 Jan 2008 23:15:03 +0100, Martin Egge wrote:
I've got some information that might help you. If I set model=3stack the internal and external mic are working in parallel. There is no jack-sense which disables the internal mic when an external mic is connected.
Then get codec#* proc dump for both working and non-working states to compare.
See the attachments. The naming of the files should be comprehensible. I've updated to latest hg before dumping the codecs yesterday evening.
Thanks. That both mics are working in parallel means they are recorded at the same time, or you can switch them via "Capture Source"? In the latter case, which input as internal mic?
Unfortuantely the BIOS sets pretty useless information so it's hard to guess which pin is really correctly assigned.
The patch below adds the automatic mic switch for Samsung. Give it a try.
Takashi
diff -r e9318a2cceaf pci/hda/patch_analog.c --- a/pci/hda/patch_analog.c Thu Feb 07 17:12:51 2008 +0100 +++ b/pci/hda/patch_analog.c Thu Feb 07 17:40:03 2008 +0100 @@ -612,13 +612,19 @@ static struct hda_input_mux ad1986a_lapt }, };
+static struct hda_input_mux ad1986a_automic_capture_source = { + .num_items = 2, + .items = { + { "Mic", 0x0 }, + { "Mix", 0x5 }, + }, +}; + static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = { HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol), HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw), HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), @@ -641,6 +647,34 @@ static struct snd_kcontrol_new ad1986a_l }, { } /* end */ }; + +/* re-connect the mic boost input according to the jack sensing */ +static void ad1986a_automic(struct hda_codec *codec) +{ + unsigned int present; + present = snd_hda_codec_read(codec, 0x1f, 0, AC_VERB_GET_PIN_SENSE, 0); + snd_hda_codec_write(codec, 0x1d, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, + ((present & AC_PINSENSE_PRESENCE) ? + 0 : PIN_VREF80)); +} + +#define AD1986A_MIC_EVENT 0x36 + +static void ad1986a_automic_unsol_event(struct hda_codec *codec, + unsigned int res) +{ + if ((res >> 26) != AD1986A_MIC_EVENT) + return; + ad1986a_automic(codec); +} + +static int ad1986a_automic_init(struct hda_codec *codec) +{ + ad198x_init(codec); + ad1986a_automic(codec); + return 0; +}
/* laptop-automute - 2ch only */
@@ -845,6 +879,15 @@ static struct hda_verb ad1986a_eapd_init {} };
+static struct hda_verb ad1986a_automic_verbs[] = { + {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, + {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, + /*{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},*/ + {0x0f, AC_VERB_SET_CONNECT_SEL, 0x4}, + {0x1f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_MIC_EVENT}, + {} +}; + /* Ultra initialization */ static struct hda_verb ad1986a_ultra_init[] = { /* eapd initialization */ @@ -987,14 +1030,17 @@ static int patch_ad1986a(struct hda_code break; case AD1986A_LAPTOP_EAPD: spec->mixers[0] = ad1986a_laptop_eapd_mixers; - spec->num_init_verbs = 2; + spec->num_init_verbs = 3; spec->init_verbs[1] = ad1986a_eapd_init_verbs; + spec->init_verbs[2] = ad1986a_automic_verbs; spec->multiout.max_channels = 2; spec->multiout.num_dacs = 1; spec->multiout.dac_nids = ad1986a_laptop_dac_nids; if (!is_jack_available(codec, 0x25)) spec->multiout.dig_out_nid = 0; - spec->input_mux = &ad1986a_laptop_eapd_capture_source; + spec->input_mux = &ad1986a_automic_capture_source; + codec->patch_ops.unsol_event = ad1986a_automic_unsol_event; + codec->patch_ops.init = ad1986a_automic_init; break; case AD1986A_LAPTOP_AUTOMUTE: spec->mixers[0] = ad1986a_laptop_automute_mixers;
Hi,
Am Donnerstag, 7. Februar 2008 schrieb Takashi Iwai:
The patch below adds the automatic mic switch for Samsung. Give it a try.
I gave it a try on the latest HG. You almost got the hang on it. The internal mic works for the first time with model=laptop-eapd. But the jack sense (autmatic switch to external mic when connected) does not work. Both mics are recorded at the same time.
Regards, Martin
At Thu, 7 Feb 2008 22:55:40 +0100, Martin Egge wrote:
Hi,
Am Donnerstag, 7. Februar 2008 schrieb Takashi Iwai:
The patch below adds the automatic mic switch for Samsung. Give it a try.
I gave it a try on the latest HG. You almost got the hang on it. The internal mic works for the first time with model=laptop-eapd. But the jack sense (autmatic switch to external mic when connected) does not work. Both mics are recorded at the same time.
Do you see in codec# proc file between mic-plugged and unplugged states?
Takashi
At Fri, 08 Feb 2008 11:59:48 +0100, I wrote:
At Thu, 7 Feb 2008 22:55:40 +0100, Martin Egge wrote:
Hi,
Am Donnerstag, 7. Februar 2008 schrieb Takashi Iwai:
The patch below adds the automatic mic switch for Samsung. Give it a try.
I gave it a try on the latest HG. You almost got the hang on it. The internal mic works for the first time with model=laptop-eapd. But the jack sense (autmatic switch to external mic when connected) does not work. Both mics are recorded at the same time.
Do you see in codec# proc file between mic-plugged and unplugged
^ any difference
states?
Anyway, the patch below might work better. Give it a try.
Takashi
diff -r e9318a2cceaf pci/hda/patch_analog.c --- a/pci/hda/patch_analog.c Thu Feb 07 17:12:51 2008 +0100 +++ b/pci/hda/patch_analog.c Thu Feb 07 17:40:03 2008 +0100 @@ -612,13 +612,19 @@ static struct hda_input_mux ad1986a_lapt }, };
+static struct hda_input_mux ad1986a_automic_capture_source = { + .num_items = 2, + .items = { + { "Mic", 0x0 }, + { "Mix", 0x5 }, + }, +}; + static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = { HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol), HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw), HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), @@ -641,6 +647,34 @@ static struct snd_kcontrol_new ad1986a_l }, { } /* end */ }; + +/* re-connect the mic boost input according to the jack sensing */ +static void ad1986a_automic(struct hda_codec *codec) +{ + unsigned int present; + present = snd_hda_codec_read(codec, 0x1d, 0, AC_VERB_GET_PIN_SENSE, 0); + snd_hda_codec_write(codec, 0x1f, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, + ((present & AC_PINSENSE_PRESENCE) ? + 0 : PIN_VREF80)); +} + +#define AD1986A_MIC_EVENT 0x36 + +static void ad1986a_automic_unsol_event(struct hda_codec *codec, + unsigned int res) +{ + if ((res >> 26) != AD1986A_MIC_EVENT) + return; + ad1986a_automic(codec); +} + +static int ad1986a_automic_init(struct hda_codec *codec) +{ + ad198x_init(codec); + ad1986a_automic(codec); + return 0; +}
/* laptop-automute - 2ch only */
@@ -845,6 +879,15 @@ static struct hda_verb ad1986a_eapd_init {} };
+static struct hda_verb ad1986a_automic_verbs[] = { + {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, + {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, + /*{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},*/ + {0x0f, AC_VERB_SET_CONNECT_SEL, 0x4}, + {0x1d, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_MIC_EVENT}, + {} +}; + /* Ultra initialization */ static struct hda_verb ad1986a_ultra_init[] = { /* eapd initialization */ @@ -987,14 +1030,17 @@ static int patch_ad1986a(struct hda_code break; case AD1986A_LAPTOP_EAPD: spec->mixers[0] = ad1986a_laptop_eapd_mixers; - spec->num_init_verbs = 2; + spec->num_init_verbs = 3; spec->init_verbs[1] = ad1986a_eapd_init_verbs; + spec->init_verbs[2] = ad1986a_automic_verbs; spec->multiout.max_channels = 2; spec->multiout.num_dacs = 1; spec->multiout.dac_nids = ad1986a_laptop_dac_nids; if (!is_jack_available(codec, 0x25)) spec->multiout.dig_out_nid = 0; - spec->input_mux = &ad1986a_laptop_eapd_capture_source; + spec->input_mux = &ad1986a_automic_capture_source; + codec->patch_ops.unsol_event = ad1986a_automic_unsol_event; + codec->patch_ops.init = ad1986a_automic_init; break; case AD1986A_LAPTOP_AUTOMUTE: spec->mixers[0] = ad1986a_laptop_automute_mixers;
Hi,
Am Freitag, 8. Februar 2008 schrieb Takashi Iwai:
At Fri, 08 Feb 2008 11:59:48 +0100, I wrote:
At Thu, 7 Feb 2008 22:55:40 +0100, Martin Egge wrote:
Am Donnerstag, 7. Februar 2008 schrieb Takashi Iwai:
The patch below adds the automatic mic switch for Samsung. Give it a try.
I gave it a try on the latest HG. You almost got the hang on it. The internal mic works for the first time with model=laptop-eapd. But the jack sense (autmatic switch to external mic when connected) does not work. Both mics are recorded at the same time.
Do you see any difference in codec# proc file between mic-plugged and unplugged states?
Yes there is a difference:
With mic plugged I get the following in lines 161 to 172 of codec#0: ------------------------------------------------------------ Node 0x1d [Pin Complex] wcaps 0x400985: Stereo Amp-Out R/L Amp-Out caps: ofs=0x1f, nsteps=0x1f, stepsize=0x05, mute=1 Amp-Out vals: [0x80 0x80] Pincap 0x081737: IN OUT Detect Trigger ImpSense Vref caps: HIZ 50 GRD 80 Pin Default 0x01019015: [Jack] Line Out at Ext Rear Conn = 1/8, Color = Pink DefAssociation = 0x1, Sequence = 0x5 Pin-ctls: 0x00: VREF_HIZ Unsolicited: tag=00, enabled=0 Connection: 1 0x0d ------------------------------------------------------------
With mic unplugged I get the following in lines 161 to 172 of codec#0: ------------------------------------------------------------ Node 0x1d [Pin Complex] wcaps 0x400985: Stereo Amp-Out R/L Amp-Out caps: ofs=0x1f, nsteps=0x1f, stepsize=0x05, mute=1 Amp-Out vals: [0x80 0x80] Pincap 0x081737: IN OUT Detect Trigger ImpSense Vref caps: HIZ 50 GRD 80 Pin Default 0x01019015: [Jack] Line Out at Ext Rear Conn = 1/8, Color = Pink DefAssociation = 0x1, Sequence = 0x5 Pin-ctls: 0x24: IN VREF_80 Unsolicited: tag=00, enabled=0 Connection: 1 0x0d ------------------------------------------------------------
Anyway, the patch below might work better. Give it a try.
This patch does not work. The external mic is always disabled and there are not differences in the codec# proc files.
Regards, Martin
At Sat, 9 Feb 2008 13:01:18 +0100, Martin Egge wrote:
Hi,
Am Freitag, 8. Februar 2008 schrieb Takashi Iwai:
At Fri, 08 Feb 2008 11:59:48 +0100, I wrote:
At Thu, 7 Feb 2008 22:55:40 +0100, Martin Egge wrote:
Am Donnerstag, 7. Februar 2008 schrieb Takashi Iwai:
The patch below adds the automatic mic switch for Samsung. Give it a try.
I gave it a try on the latest HG. You almost got the hang on it. The internal mic works for the first time with model=laptop-eapd. But the jack sense (autmatic switch to external mic when connected) does not work. Both mics are recorded at the same time.
Do you see any difference in codec# proc file between mic-plugged and unplugged states?
Yes there is a difference:
With mic plugged I get the following in lines 161 to 172 of codec#0:
Node 0x1d [Pin Complex] wcaps 0x400985: Stereo Amp-Out R/L Amp-Out caps: ofs=0x1f, nsteps=0x1f, stepsize=0x05, mute=1 Amp-Out vals: [0x80 0x80] Pincap 0x081737: IN OUT Detect Trigger ImpSense Vref caps: HIZ 50 GRD 80 Pin Default 0x01019015: [Jack] Line Out at Ext Rear Conn = 1/8, Color = Pink DefAssociation = 0x1, Sequence = 0x5 Pin-ctls: 0x00: VREF_HIZ Unsolicited: tag=00, enabled=0 Connection: 1 0x0d
With mic unplugged I get the following in lines 161 to 172 of codec#0:
Node 0x1d [Pin Complex] wcaps 0x400985: Stereo Amp-Out R/L Amp-Out caps: ofs=0x1f, nsteps=0x1f, stepsize=0x05, mute=1 Amp-Out vals: [0x80 0x80] Pincap 0x081737: IN OUT Detect Trigger ImpSense Vref caps: HIZ 50 GRD 80 Pin Default 0x01019015: [Jack] Line Out at Ext Rear Conn = 1/8, Color = Pink DefAssociation = 0x1, Sequence = 0x5 Pin-ctls: 0x24: IN VREF_80 Unsolicited: tag=00, enabled=0 Connection: 1 0x0d
Interesting. So, the pin ctl of the widget 0x1d plays no role, apparently.
How about the patch below? If it still doesn't work, please show the whole codec#* proc file again.
Also, what about another spdif-share-switch patch?
Takashi
---
diff -r 6db3c028922a pci/hda/patch_analog.c --- a/pci/hda/patch_analog.c Mon Feb 11 16:19:58 2008 +0100 +++ b/pci/hda/patch_analog.c Mon Feb 11 16:35:02 2008 +0100 @@ -612,13 +612,19 @@ static struct hda_input_mux ad1986a_lapt }, };
+static struct hda_input_mux ad1986a_automic_capture_source = { + .num_items = 2, + .items = { + { "Mic", 0x0 }, + { "Mix", 0x5 }, + }, +}; + static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = { HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol), HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw), HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), @@ -641,6 +647,33 @@ static struct snd_kcontrol_new ad1986a_l }, { } /* end */ }; + +/* re-connect the mic boost input according to the jack sensing */ +static void ad1986a_automic(struct hda_codec *codec) +{ + unsigned int present; + present = snd_hda_codec_read(codec, 0x1f, 0, AC_VERB_GET_PIN_SENSE, 0); + /* 0 = 0x1f, 2 = 0x1d, 4 = mixed */ + snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_CONNECT_SEL, + (present & AC_PINSENSE_PRESENCE) ? 0 : 2); +} + +#define AD1986A_MIC_EVENT 0x36 + +static void ad1986a_automic_unsol_event(struct hda_codec *codec, + unsigned int res) +{ + if ((res >> 26) != AD1986A_MIC_EVENT) + return; + ad1986a_automic(codec); +} + +static int ad1986a_automic_init(struct hda_codec *codec) +{ + ad198x_init(codec); + ad1986a_automic(codec); + return 0; +}
/* laptop-automute - 2ch only */
@@ -845,6 +878,15 @@ static struct hda_verb ad1986a_eapd_init {} };
+static struct hda_verb ad1986a_automic_verbs[] = { + {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, + {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, + /*{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},*/ + {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0}, + {0x1f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_MIC_EVENT}, + {} +}; + /* Ultra initialization */ static struct hda_verb ad1986a_ultra_init[] = { /* eapd initialization */ @@ -987,14 +1029,17 @@ static int patch_ad1986a(struct hda_code break; case AD1986A_LAPTOP_EAPD: spec->mixers[0] = ad1986a_laptop_eapd_mixers; - spec->num_init_verbs = 2; + spec->num_init_verbs = 3; spec->init_verbs[1] = ad1986a_eapd_init_verbs; + spec->init_verbs[2] = ad1986a_automic_verbs; spec->multiout.max_channels = 2; spec->multiout.num_dacs = 1; spec->multiout.dac_nids = ad1986a_laptop_dac_nids; if (!is_jack_available(codec, 0x25)) spec->multiout.dig_out_nid = 0; - spec->input_mux = &ad1986a_laptop_eapd_capture_source; + spec->input_mux = &ad1986a_automic_capture_source; + codec->patch_ops.unsol_event = ad1986a_automic_unsol_event; + codec->patch_ops.init = ad1986a_automic_init; break; case AD1986A_LAPTOP_AUTOMUTE: spec->mixers[0] = ad1986a_laptop_automute_mixers;
Hi,
Am Montag, 11. Februar 2008 schrieb Takashi Iwai:
How about the patch below? If it still doesn't work, please show the whole codec#* proc file again.
Hey, after some hard work you've solved the problem: Internal, external mic and jack sensing are working perfectly.
Thanks a lot! Martin
At Mon, 11 Feb 2008 19:13:06 +0100, Martin Egge wrote:
Hi,
Am Montag, 11. Februar 2008 schrieb Takashi Iwai:
How about the patch below? If it still doesn't work, please show the whole codec#* proc file again.
Hey, after some hard work you've solved the problem: Internal, external mic and jack sensing are working perfectly.
OK, the patch is committed to HG tree now.
thanks,
Takashi
Hi Takashi,
Am Mittwoch, 23. Januar 2008 schrieb Takashi Iwai:
The SPDIF is disabled intentionally for your model because no one could test it. Does the patch below work?
As I already have written: this patch does not work with the code from hg. But I've applied it successfully on 1.0.15. The digital output is working and can be disabled with the IEC958 switch.
Using the code from hg the digital output is not working as well when I set model=3stack. This has has been working with the original code from 1.0.15 and 1.0.14. So there must be a general problem with IEC958 in the hg code.
I've another question regarding the digital output. Is there a way to control the volume of the digital output? Neither the Master nor the PCM control have any effect on the volume of the digital output. In addition the output can't be switched off by muting PCM or Master.
Regards, Martin
At Sun, 27 Jan 2008 23:03:20 +0100, Martin Egge wrote:
Hi Takashi,
Am Mittwoch, 23. Januar 2008 schrieb Takashi Iwai:
The SPDIF is disabled intentionally for your model because no one could test it. Does the patch below work?
As I already have written: this patch does not work with the code from hg. But I've applied it successfully on 1.0.15. The digital output is working and can be disabled with the IEC958 switch.
Using the code from hg the digital output is not working as well when I set model=3stack. This has has been working with the original code from 1.0.15 and 1.0.14. So there must be a general problem with IEC958 in the hg code.
OK, then again, get the codec dump to compare.
I've another question regarding the digital output. Is there a way to control the volume of the digital output? Neither the Master nor the PCM control have any effect on the volume of the digital output. In addition the output can't be switched off by muting PCM or Master.
No, this signal route has no volume control.
Takashi
Hi,
Am Montag, 28. Januar 2008 schrieb Takashi Iwai:
At Sun, 27 Jan 2008 23:03:20 +0100, Martin Egge wrote:
As I already have written: this patch does not work with the code from hg. But I've applied it successfully on 1.0.15. The digital output is working and can be disabled with the IEC958 switch.
Using the code from hg the digital output is not working as well when I set model=3stack. This has has been working with the original code from 1.0.15 and 1.0.14. So there must be a general problem with IEC958 in the hg code.
OK, then again, get the codec dump to compare.
See the attachments. The naming of the files should be comprehensible. I've updated to latest hg before dumping the codecs yesterday evening.
Regards, Martin
At Tue, 29 Jan 2008 11:05:36 +0100, Martin Egge wrote:
Hi,
Am Montag, 28. Januar 2008 schrieb Takashi Iwai:
At Sun, 27 Jan 2008 23:03:20 +0100, Martin Egge wrote:
As I already have written: this patch does not work with the code from hg. But I've applied it successfully on 1.0.15. The digital output is working and can be disabled with the IEC958 switch.
Using the code from hg the digital output is not working as well when I set model=3stack. This has has been working with the original code from 1.0.15 and 1.0.14. So there must be a general problem with IEC958 in the hg code.
OK, then again, get the codec dump to compare.
See the attachments. The naming of the files should be comprehensible. I've updated to latest hg before dumping the codecs yesterday evening.
Thanks. It's weird that there is really no significant difference in these proc files. So it should be something else.
Could you try HG bisect? It'd be greatly helpful.
Takashi
At Tue, 29 Jan 2008 19:19:48 +0100, Martin Egge wrote:
Hi,
Am Dienstag, 29. Januar 2008 schrieb Takashi Iwai:
Thanks. It's weird that there is really no significant difference in these proc files. So it should be something else.
Could you try HG bisect? It'd be greatly helpful.
What does HG bisect mean?
Run "hg bisect -h". It's a method to track down the regression point during changesets. A brief instruction is below:
- First, initizliaze % hg bisect init - Go to the broken point (usually the latest changeset, tip) % hg update -rtip - Mark it as bad % hg bisect bad - Go to the changeset that is known to work (e.g. v1.0.15) % hg update -rv1.0.15 - Mark it as good % hg bisect good then the bisect will move to a next changeset to try. - Try this changeset, and mark either good or bad. - Repeat until the problematic changeset is found. - Reset bisect % hg bisect reset
Note that when you need an additonal patch, you have to apply the patch at each time, and revert it (hg revert --all) before marking good/bad.
Takashi
Hi,
Am Dienstag, 29. Januar 2008 schrieb Takashi Iwai:
Could you try HG bisect? It'd be greatly helpful.
I've tried HG bisect this evening. It took me some time to discover that the problem is not within alsa-driver or alsa-kernel but within alsa-lib. This is the result of HG bisect:
The first bad revision is: changeset: 2397:d1e9a2f92e7b user: tiwai date: Fri Jan 18 13:42:51 2008 +0100 summary: dmix - Enable auto format detection as default
Regards, Martin
Hi, sorry for the late reply. At the next time, please add my address to Cc so that I don't miss your post...
At Fri, 1 Feb 2008 22:02:51 +0100, Martin Egge wrote:
Hi,
Am Dienstag, 29. Januar 2008 schrieb Takashi Iwai:
Could you try HG bisect? It'd be greatly helpful.
I've tried HG bisect this evening. It took me some time to discover that the problem is not within alsa-driver or alsa-kernel but within alsa-lib. This is the result of HG bisect:
The first bad revision is: changeset: 2397:d1e9a2f92e7b user: tiwai date: Fri Jan 18 13:42:51 2008 +0100 summary: dmix - Enable auto format detection as default
Thanks for checkign this. Now the thing gets a bit clearer. The problem is explained like this: via "default" PCM, 32bit format is chosen now because the analog audio-out widget supports. But the SPDIF out widget doesn't support that format. Thus it's not played properly.
If my guess is correct, you can propbably get SPDIF output via "spdif" output. What happens with the below?
% aplay -Dplug:spdif foo.wav
Takashi
Hi,
Am Donnerstag, 7. Februar 2008 schrieb Takashi Iwai:
Hi, sorry for the late reply.
No problem.
At the next time, please add my address to Cc so that I don't miss your post...
I'll try to keep this in mind.
At Fri, 1 Feb 2008 22:02:51 +0100, Martin Egge wrote:
Am Dienstag, 29. Januar 2008 schrieb Takashi Iwai:
Could you try HG bisect? It'd be greatly helpful.
I've tried HG bisect this evening. It took me some time to discover that the problem is not within alsa-driver or alsa-kernel but within alsa-lib. This is the result of HG bisect:
The first bad revision is: changeset: 2397:d1e9a2f92e7b user: tiwai date: Fri Jan 18 13:42:51 2008 +0100 summary: dmix - Enable auto format detection as default
Thanks for checkign this. Now the thing gets a bit clearer. The problem is explained like this: via "default" PCM, 32bit format is chosen now because the analog audio-out widget supports. But the SPDIF out widget doesn't support that format. Thus it's not played properly.
Oh I see, but why has this behavior changed since 1.0.15?
If my guess is correct, you can propbably get SPDIF output via "spdif" output. What happens with the below?
% aplay -Dplug:spdif foo.wav
You are right. Choosing plug:spdif plays the sound cia the SDIF-Out. Of course this does not play the sound via the internal speakers when no SPDIF is connected.
But I'd prefer the old behavior from 1.0.15 where the default device was playing sound via SPDIF when connected and via internal speakers when SDIF is not connected.
Regards, Martin
At Thu, 7 Feb 2008 23:04:00 +0100, Martin Egge wrote:
At Fri, 1 Feb 2008 22:02:51 +0100, Martin Egge wrote:
Am Dienstag, 29. Januar 2008 schrieb Takashi Iwai:
Could you try HG bisect? It'd be greatly helpful.
I've tried HG bisect this evening. It took me some time to discover that the problem is not within alsa-driver or alsa-kernel but within alsa-lib. This is the result of HG bisect:
The first bad revision is: changeset: 2397:d1e9a2f92e7b user: tiwai date: Fri Jan 18 13:42:51 2008 +0100 summary: dmix - Enable auto format detection as default
Thanks for checkign this. Now the thing gets a bit clearer. The problem is explained like this: via "default" PCM, 32bit format is chosen now because the analog audio-out widget supports. But the SPDIF out widget doesn't support that format. Thus it's not played properly.
Oh I see, but why has this behavior changed since 1.0.15?
Because we want to use the best quality of format as default. In the older version, it was fixed to S16 although the device supports 32bit.
You can set the following in your ~/.asoundrc to use S16 again defaults.pcm.dmix.format S16
If my guess is correct, you can propbably get SPDIF output via "spdif" output. What happens with the below?
% aplay -Dplug:spdif foo.wav
You are right. Choosing plug:spdif plays the sound cia the SDIF-Out. Of course this does not play the sound via the internal speakers when no SPDIF is connected.
But I'd prefer the old behavior from 1.0.15 where the default device was playing sound via SPDIF when connected and via internal speakers when SDIF is not connected.
Try the patch below. This adds the mixer switch "Analog To SPDIF". If this is on, the supported format is more limited so that the default PCM can route to SPDIF. If this switch is off, dmix will choose 32bit automatically.
Takashi
diff -r 7c1928ffe1f3 pci/hda/hda_codec.c --- a/pci/hda/hda_codec.c Thu Feb 07 17:12:01 2008 +0100 +++ b/pci/hda/hda_codec.c Fri Feb 08 11:58:12 2008 +0100 @@ -1527,6 +1527,43 @@ int snd_hda_create_spdif_out_ctls(struct }
/* + * SPDIF sharing with analog output + */ +static int spdif_share_sw_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol); + ucontrol->value.integer.value[0] = mout->share_spdif; + return 0; +} + +static int spdif_share_sw_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol); + mout->share_spdif = !!ucontrol->value.integer.value[0]; + return 0; +} + +static struct snd_kcontrol_new spdif_share_sw = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Analog To SPDIF Playback Switch", + .info = snd_ctl_boolean_mono_info, + .get = spdif_share_sw_get, + .put = spdif_share_sw_put, +}; + +int snd_hda_create_spdif_share_sw(struct hda_codec *codec, + struct hda_multi_out *mout) +{ + if (!mout->dig_out_nid) + return 0; + /* ATTENTION: here mout is passed as private_data, instead of codec */ + return snd_ctl_add(codec->bus->card, + snd_ctl_new1(&spdif_share_sw, mout)); +} + +/* * SPDIF input */
@@ -2551,9 +2588,36 @@ int snd_hda_multi_out_dig_close(struct h */ int snd_hda_multi_out_analog_open(struct hda_codec *codec, struct hda_multi_out *mout, - struct snd_pcm_substream *substream) + struct snd_pcm_substream *substream, + struct hda_pcm_stream *hinfo) { - substream->runtime->hw.channels_max = mout->max_channels; + struct snd_pcm_runtime *runtime = substream->runtime; + runtime->hw.channels_max = mout->max_channels; + if (mout->dig_out_nid) { + if (!mout->analog_rates) { + mout->analog_rates = hinfo->rates; + mout->analog_formats = hinfo->formats; + mout->analog_maxbps = hinfo->maxbps; + } else { + runtime->hw.rates = mout->analog_rates; + runtime->hw.formats = mout->analog_formats; + hinfo->maxbps = mout->analog_maxbps; + } + if (!mout->spdif_rates) { + snd_hda_query_supported_pcm(codec, mout->dig_out_nid, + &mout->spdif_rates, + &mout->spdif_formats, + &mout->spdif_maxbps); + } + mutex_lock(&codec->spdif_mutex); + if (mout->share_spdif) { + runtime->hw.rates &= mout->spdif_rates; + runtime->hw.formats &= mout->spdif_formats; + if (mout->spdif_maxbps < hinfo->maxbps) + hinfo->maxbps = mout->spdif_maxbps; + } + } + mutex_unlock(&codec->spdif_mutex); return snd_pcm_hw_constraint_step(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 2); } @@ -2573,7 +2637,8 @@ int snd_hda_multi_out_analog_prepare(str int i;
mutex_lock(&codec->spdif_mutex); - if (mout->dig_out_nid && mout->dig_out_used != HDA_DIG_EXCLUSIVE) { + if (mout->dig_out_nid && mout->share_spdif && + mout->dig_out_used != HDA_DIG_EXCLUSIVE) { if (chs == 2 && snd_hda_is_supported_format(codec, mout->dig_out_nid, format) && diff -r 7c1928ffe1f3 pci/hda/hda_local.h --- a/pci/hda/hda_local.h Thu Feb 07 17:12:01 2008 +0100 +++ b/pci/hda/hda_local.h Fri Feb 08 11:58:12 2008 +0100 @@ -228,8 +228,18 @@ struct hda_multi_out { int max_channels; /* currently supported analog channels */ int dig_out_used; /* current usage of digital out (HDA_DIG_XXX) */ int no_share_stream; /* don't share a stream with multiple pins */ + int share_spdif; /* share SPDIF pin */ + /* PCM information for both analog and SPDIF DACs */ + unsigned int analog_rates; + unsigned int analog_maxbps; + u64 analog_formats; + unsigned int spdif_rates; + unsigned int spdif_maxbps; + u64 spdif_formats; };
+int snd_hda_create_spdif_share_sw(struct hda_codec *codec, + struct hda_multi_out *mout); int snd_hda_multi_out_dig_open(struct hda_codec *codec, struct hda_multi_out *mout); int snd_hda_multi_out_dig_close(struct hda_codec *codec, @@ -241,7 +251,8 @@ int snd_hda_multi_out_dig_prepare(struct struct snd_pcm_substream *substream); int snd_hda_multi_out_analog_open(struct hda_codec *codec, struct hda_multi_out *mout, - struct snd_pcm_substream *substream); + struct snd_pcm_substream *substream, + struct hda_pcm_stream *hinfo); int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_out *mout, unsigned int stream_tag, diff -r 7c1928ffe1f3 pci/hda/patch_analog.c --- a/pci/hda/patch_analog.c Thu Feb 07 17:12:01 2008 +0100 +++ b/pci/hda/patch_analog.c Fri Feb 08 11:58:12 2008 +0100 @@ -171,6 +171,11 @@ static int ad198x_build_controls(struct err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); if (err < 0) return err; + err = snd_hda_create_spdif_share_sw(codec, + &spec->multiout); + if (err < 0) + return err; + spec->multiout.share_spdif = 1; } if (spec->dig_in_nid) { err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); @@ -217,7 +222,8 @@ static int ad198x_playback_pcm_open(stru struct snd_pcm_substream *substream) { struct ad198x_spec *spec = codec->spec; - return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream); + return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, + hinfo); }
static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo, diff -r 7c1928ffe1f3 pci/hda/patch_cmedia.c --- a/pci/hda/patch_cmedia.c Thu Feb 07 17:12:01 2008 +0100 +++ b/pci/hda/patch_cmedia.c Fri Feb 08 11:58:12 2008 +0100 @@ -329,6 +329,11 @@ static int cmi9880_build_controls(struct err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); if (err < 0) return err; + err = snd_hda_create_spdif_share_sw(codec, + &spec->multiout); + if (err < 0) + return err; + spec->multiout.share_spdif = 1; } if (spec->dig_in_nid) { err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); @@ -432,7 +437,8 @@ static int cmi9880_playback_pcm_open(str struct snd_pcm_substream *substream) { struct cmi_spec *spec = codec->spec; - return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream); + return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, + hinfo); }
static int cmi9880_playback_pcm_prepare(struct hda_pcm_stream *hinfo, diff -r 7c1928ffe1f3 pci/hda/patch_conexant.c --- a/pci/hda/patch_conexant.c Thu Feb 07 17:12:01 2008 +0100 +++ b/pci/hda/patch_conexant.c Fri Feb 08 11:58:12 2008 +0100 @@ -98,7 +98,8 @@ static int conexant_playback_pcm_open(st struct snd_pcm_substream *substream) { struct conexant_spec *spec = codec->spec; - return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream); + return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, + hinfo); }
static int conexant_playback_pcm_prepare(struct hda_pcm_stream *hinfo, @@ -372,6 +373,11 @@ static int conexant_build_controls(struc spec->multiout.dig_out_nid); if (err < 0) return err; + err = snd_hda_create_spdif_share_sw(codec, + &spec->multiout); + if (err < 0) + return err; + spec->multiout.share_spdif = 1; } if (spec->dig_in_nid) { err = snd_hda_create_spdif_in_ctls(codec,spec->dig_in_nid); diff -r 7c1928ffe1f3 pci/hda/patch_realtek.c --- a/pci/hda/patch_realtek.c Thu Feb 07 17:12:01 2008 +0100 +++ b/pci/hda/patch_realtek.c Fri Feb 08 11:58:12 2008 +0100 @@ -1517,6 +1517,11 @@ static int alc_build_controls(struct hda spec->multiout.dig_out_nid); if (err < 0) return err; + err = snd_hda_create_spdif_share_sw(codec, + &spec->multiout); + if (err < 0) + return err; + spec->multiout.share_spdif = 1; } if (spec->dig_in_nid) { err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); @@ -2319,7 +2324,8 @@ static int alc880_playback_pcm_open(stru struct snd_pcm_substream *substream) { struct alc_spec *spec = codec->spec; - return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream); + return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, + hinfo); }
static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo, diff -r 7c1928ffe1f3 pci/hda/patch_sigmatel.c --- a/pci/hda/patch_sigmatel.c Thu Feb 07 17:12:01 2008 +0100 +++ b/pci/hda/patch_sigmatel.c Fri Feb 08 11:58:12 2008 +0100 @@ -916,6 +916,11 @@ static int stac92xx_build_controls(struc err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); if (err < 0) return err; + err = snd_hda_create_spdif_share_sw(codec, + &spec->multiout); + if (err < 0) + return err; + spec->multiout.share_spdif = 1; } if (spec->dig_in_nid) { err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); @@ -1748,7 +1753,8 @@ static int stac92xx_playback_pcm_open(st struct snd_pcm_substream *substream) { struct sigmatel_spec *spec = codec->spec; - return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream); + return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, + hinfo); }
static int stac92xx_playback_pcm_prepare(struct hda_pcm_stream *hinfo, diff -r 7c1928ffe1f3 pci/hda/patch_via.c --- a/pci/hda/patch_via.c Thu Feb 07 17:12:01 2008 +0100 +++ b/pci/hda/patch_via.c Fri Feb 08 11:58:12 2008 +0100 @@ -357,7 +357,8 @@ static int via_playback_pcm_open(struct struct snd_pcm_substream *substream) { struct via_spec *spec = codec->spec; - return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream); + return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, + hinfo); }
static int via_playback_pcm_prepare(struct hda_pcm_stream *hinfo, @@ -493,6 +494,11 @@ static int via_build_controls(struct hda spec->multiout.dig_out_nid); if (err < 0) return err; + err = snd_hda_create_spdif_share_sw(codec, + &spec->multiout); + if (err < 0) + return err; + spec->multiout.share_spdif = 1; } if (spec->dig_in_nid) { err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
Hi,
Am Freitag, 8. Februar 2008 schrieb Takashi Iwai:
At Thu, 7 Feb 2008 23:04:00 +0100, Martin Egge wrote:
Am Donnerstag, 7. Februar 2008 schrieb Takashi Iwai:
If my guess is correct, you can propbably get SPDIF output via "spdif" output. What happens with the below?
% aplay -Dplug:spdif foo.wav
You are right. Choosing plug:spdif plays the sound cia the SDIF-Out. Of course this does not play the sound via the internal speakers when no SPDIF is connected.
But I'd prefer the old behavior from 1.0.15 where the default device was playing sound via SPDIF when connected and via internal speakers when SDIF is not connected.
Try the patch below. This adds the mixer switch "Analog To SPDIF". If this is on, the supported format is more limited so that the default PCM can route to SPDIF. If this switch is off, dmix will choose 32bit automatically.
The patch works perfectly for me. I like this new switch. Perhaps you should rename it to "Analog to IEC958 Output". I've seen this name on some other cards with ALSA.
Regards, Martin
At Mon, 11 Feb 2008 19:22:19 +0100, Martin Egge wrote:
Hi,
Am Freitag, 8. Februar 2008 schrieb Takashi Iwai:
At Thu, 7 Feb 2008 23:04:00 +0100, Martin Egge wrote:
Am Donnerstag, 7. Februar 2008 schrieb Takashi Iwai:
If my guess is correct, you can propbably get SPDIF output via "spdif" output. What happens with the below?
% aplay -Dplug:spdif foo.wav
You are right. Choosing plug:spdif plays the sound cia the SDIF-Out. Of course this does not play the sound via the internal speakers when no SPDIF is connected.
But I'd prefer the old behavior from 1.0.15 where the default device was playing sound via SPDIF when connected and via internal speakers when SDIF is not connected.
Try the patch below. This adds the mixer switch "Analog To SPDIF". If this is on, the supported format is more limited so that the default PCM can route to SPDIF. If this switch is off, dmix will choose 32bit automatically.
The patch works perfectly for me. I like this new switch. Perhaps you should rename it to "Analog to IEC958 Output". I've seen this name on some other cards with ALSA.
This name is a bit difficult to define. Usually "Analog To IEC958 Output" is the mixer switch for the loopback from the analog inputs like mic-in or line-in. In your case, it's a switch that allows the signal duplication to SPDIF for the default PCM output. So actually my naming is also pretty confusing.
How about "IEC958 Default PCM Playback Switch"? Then it's a bit clearer. On the mixer, it apperas in the playback view as "IEC958 Default PCM". If you turn it on, SPDIF plays with the default PCM.
Takashi
participants (2)
-
Martin Egge
-
Takashi Iwai