[alsa-devel] Intel HDA / ca0132: support for Alienware 15 Creative Sound Core3D-EX

Hi, the new Alienware 15 laptop (2015, not the M15x) has a Creative Sound Core3D-EX Audio which seems to work with ca0132. I'm using a 4.0.0 kernel with gentoo patchset, but with the default configuration: - the line out/headphone jack doesn't work, it only outputs some white noise - alsamixer shows only "Master" and "PCM" channel, no "Front", "Line Out" or similar - alsamixer has a toggle switch for the "HP/Speaker" but no headphone/line out switch - the jack detection is enabled on the "line in" jack instead of the "line out" (if I plug something on the "line in", the speakers are muted) - if I play too much with these switches, the speakers stop working until suspend/reboot
To fix the first issue I run "hdajacksensetest" to get the headphone jack pin: hdajacksensetest -c 1 -a Pin 0x0b (Internal Speaker): present = Yes Pin 0x0c (Not connected): present = No Pin 0x0d (Not connected): present = No Pin 0x0e (Not connected): present = No Pin 0x0f (Not connected): present = Yes Pin 0x10 (Not connected): present = No Pin 0x11 (Black Line In, Left side): present = No Pin 0x12 (Internal Mic, Mobile-In): present = No Pin 0x13 (Not connected): present = No Pin 0x18 (Not connected): present = No
and replaced the pin number:
--- /usr/src/linux-4.0.0-gentoo/sound/pci/hda/patch_ca0132.c.old 2015-04-13 00:12:50.000000000 +0200 +++ /usr/src/linux-4.0.0-gentoo/sound/pci/hda/patch_ca0132.c 2015-04-25 01:43:09.607531550 +0200 @@ -4625,7 +4625,7 @@
spec->num_outputs = 2; spec->out_pins[0] = 0x0b; /* speaker out */ - spec->out_pins[1] = 0x10; /* headphone out */ + spec->out_pins[1] = 0x0f; /* default: 0x10 - headphone out -0x0f on Alienware 15 2015 */ spec->shared_out_nid = 0x2;
spec->num_inputs = 3;
Now the "HP/Speaker Auto Detect" is ignored on both jacks, but I can switch between headphones and speakers manually with the "HP/Speaker" item.
This is a dirty hack (and probably won't work on different cards), is there a better way to fix this and get at least the jack detection working?
Regards, Gabriele

At Sat, 25 Apr 2015 02:50:23 +0200, Gabriele Martino wrote:
Hi, the new Alienware 15 laptop (2015, not the M15x) has a Creative Sound Core3D-EX Audio which seems to work with ca0132. I'm using a 4.0.0 kernel with gentoo patchset, but with the default configuration:
- the line out/headphone jack doesn't work, it only outputs some white noise
- alsamixer shows only "Master" and "PCM" channel, no "Front", "Line
Out" or similar
- alsamixer has a toggle switch for the "HP/Speaker" but no
headphone/line out switch
- the jack detection is enabled on the "line in" jack instead of the
"line out" (if I plug something on the "line in", the speakers are muted)
- if I play too much with these switches, the speakers stop working
until suspend/reboot
To fix the first issue I run "hdajacksensetest" to get the headphone jack pin: hdajacksensetest -c 1 -a Pin 0x0b (Internal Speaker): present = Yes Pin 0x0c (Not connected): present = No Pin 0x0d (Not connected): present = No Pin 0x0e (Not connected): present = No Pin 0x0f (Not connected): present = Yes Pin 0x10 (Not connected): present = No Pin 0x11 (Black Line In, Left side): present = No Pin 0x12 (Internal Mic, Mobile-In): present = No Pin 0x13 (Not connected): present = No Pin 0x18 (Not connected): present = No
and replaced the pin number:
--- /usr/src/linux-4.0.0-gentoo/sound/pci/hda/patch_ca0132.c.old 2015-04-13 00:12:50.000000000 +0200 +++ /usr/src/linux-4.0.0-gentoo/sound/pci/hda/patch_ca0132.c 2015-04-25 01:43:09.607531550 +0200 @@ -4625,7 +4625,7 @@
spec->num_outputs = 2; spec->out_pins[0] = 0x0b; /* speaker out */
spec->out_pins[1] = 0x10; /* headphone out */
spec->out_pins[1] = 0x0f; /* default: 0x10 - headphone out -0x0f
on Alienware 15 2015 */ spec->shared_out_nid = 0x2;
spec->num_inputs = 3;
Now the "HP/Speaker Auto Detect" is ignored on both jacks, but I can switch between headphones and speakers manually with the "HP/Speaker" item.
This is a dirty hack (and probably won't work on different cards), is there a better way to fix this and get at least the jack detection working?
In general, we check either PCI or codec SSID to identify the model and applies the quirk accordingly. Does your board have also a unique SSID?
Takashi

At Mon, 27 Apr 2015 20:08:52 +0200, Gabriele Martino wrote:
On 27/04/2015 11:09, Takashi Iwai wrote:
In general, we check either PCI or codec SSID to identify the model and applies the quirk accordingly. Does your board have also a unique SSID?
Good question. How do I find it? I can't see any in alsa-info.
!!Advanced information - PCI Vendor/Device/Subsystem ID's !!-------------------------------------------------------
00:03.0 0403: 8086:0c0c (rev 06) Subsystem: 1028:0685 -- 00:1b.0 0403: 8086:8c20 (rev 05) Subsystem: 1028:0685
PCI SSID is 1028:0685.
Codec: Creative CA0132 Address: 0 AFG Function Id: 0x1 (unsol 1) Vendor Id: 0x11020011 Subsystem Id: 0x10280685
Codec SSID is also 1028:0685.
Takashi

On 27/04/2015 20:51, Takashi Iwai wrote:
At Mon, 27 Apr 2015 20:08:52 +0200, Gabriele Martino wrote:
!!Advanced information - PCI Vendor/Device/Subsystem ID's !!-------------------------------------------------------
00:03.0 0403: 8086:0c0c (rev 06) Subsystem: 1028:0685 -- 00:1b.0 0403: 8086:8c20 (rev 05) Subsystem: 1028:0685
PCI SSID is 1028:0685.
Codec: Creative CA0132 Address: 0 AFG Function Id: 0x1 (unsol 1) Vendor Id: 0x11020011 Subsystem Id: 0x10280685
Codec SSID is also 1028:0685.
I couldn't find any occurrence of SND_PCI_QUIRK() to mess up with in patch_ca0132.c. I gave a look at patch_realtek.c and got something like:
enum { CA0132_FIXUP_CORE3D_EX }
static const struct hda_fixup ca0132_fixups[] = { [CA0132_FIXUP_CORE3D_EX] = { .type = HDA_FIXUP_PINS, .v.pins = (const struct hda_pintbl[]) { { 0x0f, 0x032110f0 }, /* headphones */ { } } }, {} }
static const struct snd_pci_quirk alc861_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x0685, "Alienware 15", CA0132_FIXUP_CORE3D_EX), {} };
But I don't know how to load this on ca0132. It there any simple documentation about quirks? I fear this is beyond my capabilities.
Regards, Gabriele

At Tue, 28 Apr 2015 00:17:01 +0200, Gabriele Martino wrote:
On 27/04/2015 20:51, Takashi Iwai wrote:
At Mon, 27 Apr 2015 20:08:52 +0200, Gabriele Martino wrote:
!!Advanced information - PCI Vendor/Device/Subsystem ID's !!-------------------------------------------------------
00:03.0 0403: 8086:0c0c (rev 06) Subsystem: 1028:0685 -- 00:1b.0 0403: 8086:8c20 (rev 05) Subsystem: 1028:0685
PCI SSID is 1028:0685.
Codec: Creative CA0132 Address: 0 AFG Function Id: 0x1 (unsol 1) Vendor Id: 0x11020011 Subsystem Id: 0x10280685
Codec SSID is also 1028:0685.
I couldn't find any occurrence of SND_PCI_QUIRK() to mess up with in patch_ca0132.c. I gave a look at patch_realtek.c and got something like:
enum { CA0132_FIXUP_CORE3D_EX }
static const struct hda_fixup ca0132_fixups[] = { [CA0132_FIXUP_CORE3D_EX] = { .type = HDA_FIXUP_PINS, .v.pins = (const struct hda_pintbl[]) { { 0x0f, 0x032110f0 }, /* headphones */ { } } }, {} }
static const struct snd_pci_quirk alc861_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x0685, "Alienware 15", CA0132_FIXUP_CORE3D_EX), {} };
But I don't know how to load this on ca0132. It there any simple documentation about quirks? I fear this is beyond my capabilities.
snd_pci_quirk_lookup() just returns a value matching in the given table. Provide a table like:
enum { QUIRK_NONE, QUIRK_ALIENWARE, };
static const struct snd_pci_quirk ca0132_quirks[] = { SND_PCI_QUIRK(0x1028, 0x0685, "Alienware 15", QUIRK_ALIENWARE), {} };
then somewhere in the probe, check the table
spec->quirk = snd_pci_quirk_lookup(codec->bus->pci, ca0132_quirks);
then refer it appropriately
if (spec->quirk == QUIRK_ALIENWARE) { spec->out_pins[1] = 0x0f; .... } else { spec->out_pins[1] = 0x10; .... }
The current ca0132 code has way too may fixed assignment, so the pin reassignment like other codec drivers doesn't work as is. We'd need to sort it out first. So, start from the simple workaround.
Takashi

On 28/04/2015 08:15, Takashi Iwai wrote:
snd_pci_quirk_lookup() just returns a value matching in the given table. Provide a table like:
enum { QUIRK_NONE, QUIRK_ALIENWARE, };
static const struct snd_pci_quirk ca0132_quirks[] = { SND_PCI_QUIRK(0x1028, 0x0685, "Alienware 15", QUIRK_ALIENWARE), {} };
then somewhere in the probe, check the table
spec->quirk = snd_pci_quirk_lookup(codec->bus->pci, ca0132_quirks);
then refer it appropriately
if (spec->quirk == QUIRK_ALIENWARE) { spec->out_pins[1] = 0x0f; .... } else { spec->out_pins[1] = 0x10; .... }
The current ca0132 code has way too may fixed assignment, so the pin reassignment like other codec drivers doesn't work as is. We'd need to sort it out first. So, start from the simple workaround.
Thank you for your explanation. I managed to fix the pin address, but as I told before the jack detection is totally messed up. "hdajacksensetest" fails with: Ioctl call failed with error 16
I can't understand why, as ca0132_select_out() already relies on spec->out_pins[0] and spec->out_pins[1].
Regards, Gabriele

At Wed, 29 Apr 2015 00:47:16 +0200, Gabriele Martino wrote:
On 28/04/2015 08:15, Takashi Iwai wrote:
snd_pci_quirk_lookup() just returns a value matching in the given table. Provide a table like:
enum { QUIRK_NONE, QUIRK_ALIENWARE, };
static const struct snd_pci_quirk ca0132_quirks[] = { SND_PCI_QUIRK(0x1028, 0x0685, "Alienware 15", QUIRK_ALIENWARE), {} };
then somewhere in the probe, check the table
spec->quirk = snd_pci_quirk_lookup(codec->bus->pci, ca0132_quirks);
then refer it appropriately
if (spec->quirk == QUIRK_ALIENWARE) { spec->out_pins[1] = 0x0f; .... } else { spec->out_pins[1] = 0x10; .... }
The current ca0132 code has way too may fixed assignment, so the pin reassignment like other codec drivers doesn't work as is. We'd need to sort it out first. So, start from the simple workaround.
Thank you for your explanation. I managed to fix the pin address, but as I told before the jack detection is totally messed up. "hdajacksensetest" fails with: Ioctl call failed with error 16
The error message looks irrelevant with the patch itself. Did you build with proper kernel configs? CONFIG_SND_HDA_HWDEP=y CONFIG_SND_HDA_RECONFIG=y CONFIG_SND_HDA_PATCH_LOADER=y
Takashi

On 29/04/2015 15:38, Takashi Iwai wrote:
At Wed, 29 Apr 2015 00:47:16 +0200, Gabriele Martino wrote:
Thank you for your explanation. I managed to fix the pin address, but as I told before the jack detection is totally messed up. "hdajacksensetest" fails with: Ioctl call failed with error 16
The error message looks irrelevant with the patch itself. Did you build with proper kernel configs? CONFIG_SND_HDA_HWDEP=y CONFIG_SND_HDA_RECONFIG=y CONFIG_SND_HDA_PATCH_LOADER=y
It should be ok:
$ grep CONFIG_SND_HDA_ /usr/src/linux/.config | grep -v '^#' CONFIG_SND_HDA_INTEL=m CONFIG_SND_HDA_DSP_LOADER=y CONFIG_SND_HDA_PREALLOC_SIZE=2048 CONFIG_SND_HDA_HWDEP=y CONFIG_SND_HDA_RECONFIG=y CONFIG_SND_HDA_INPUT_JACK=y CONFIG_SND_HDA_PATCH_LOADER=y CONFIG_SND_HDA_CODEC_HDMI=m CONFIG_SND_HDA_I915=y CONFIG_SND_HDA_CODEC_CA0132=m CONFIG_SND_HDA_CODEC_CA0132_DSP=y CONFIG_SND_HDA_GENERIC=m CONFIG_SND_HDA_POWER_SAVE_DEFAULT=60
Regards, Gabriele

At Wed, 29 Apr 2015 17:42:55 +0200, Gabriele Martino wrote:
On 29/04/2015 15:38, Takashi Iwai wrote:
At Wed, 29 Apr 2015 00:47:16 +0200, Gabriele Martino wrote:
Thank you for your explanation. I managed to fix the pin address, but as I told before the jack detection is totally messed up. "hdajacksensetest" fails with: Ioctl call failed with error 16
The error message looks irrelevant with the patch itself. Did you build with proper kernel configs? CONFIG_SND_HDA_HWDEP=y CONFIG_SND_HDA_RECONFIG=y CONFIG_SND_HDA_PATCH_LOADER=y
It should be ok:
$ grep CONFIG_SND_HDA_ /usr/src/linux/.config | grep -v '^#' CONFIG_SND_HDA_INTEL=m CONFIG_SND_HDA_DSP_LOADER=y CONFIG_SND_HDA_PREALLOC_SIZE=2048 CONFIG_SND_HDA_HWDEP=y CONFIG_SND_HDA_RECONFIG=y CONFIG_SND_HDA_INPUT_JACK=y CONFIG_SND_HDA_PATCH_LOADER=y CONFIG_SND_HDA_CODEC_HDMI=m CONFIG_SND_HDA_I915=y CONFIG_SND_HDA_CODEC_CA0132=m CONFIG_SND_HDA_CODEC_CA0132_DSP=y CONFIG_SND_HDA_GENERIC=m CONFIG_SND_HDA_POWER_SAVE_DEFAULT=60
OK, then it's something else. Errno 16 is EBUSY, so something else must be accessing the same device (e.g. hwdep) and blocking the operation.
Are you sure that you never see this error when a kernel is without the patch?
Takashi

On 29/04/2015 20:42, Takashi Iwai wrote:
At Wed, 29 Apr 2015 17:42:55 +0200, Gabriele Martino wrote:
On 29/04/2015 15:38, Takashi Iwai wrote:
At Wed, 29 Apr 2015 00:47:16 +0200, Gabriele Martino wrote:
Thank you for your explanation. I managed to fix the pin address, but as I told before the jack detection is totally messed up. "hdajacksensetest" fails with: Ioctl call failed with error 16
The error message looks irrelevant with the patch itself. Did you build with proper kernel configs? CONFIG_SND_HDA_HWDEP=y CONFIG_SND_HDA_RECONFIG=y CONFIG_SND_HDA_PATCH_LOADER=y
It should be ok:
$ grep CONFIG_SND_HDA_ /usr/src/linux/.config | grep -v '^#' CONFIG_SND_HDA_INTEL=m CONFIG_SND_HDA_DSP_LOADER=y CONFIG_SND_HDA_PREALLOC_SIZE=2048 CONFIG_SND_HDA_HWDEP=y CONFIG_SND_HDA_RECONFIG=y CONFIG_SND_HDA_INPUT_JACK=y CONFIG_SND_HDA_PATCH_LOADER=y CONFIG_SND_HDA_CODEC_HDMI=m CONFIG_SND_HDA_I915=y CONFIG_SND_HDA_CODEC_CA0132=m CONFIG_SND_HDA_CODEC_CA0132_DSP=y CONFIG_SND_HDA_GENERIC=m CONFIG_SND_HDA_POWER_SAVE_DEFAULT=60
OK, then it's something else. Errno 16 is EBUSY, so something else must be accessing the same device (e.g. hwdep) and blocking the operation.
Are you sure that you never see this error when a kernel is without the patch?
It was an error on my part, my apologies. I did a full kernel clean and rebuild, and the error 16 went away. But the jack detection is still broken.
hdajacksensetest -c 1 -a Pin 0x0b (Internal Speaker): present = Yes Pin 0x0c (Not connected): present = No Pin 0x0d (Not connected): present = No Pin 0x0e (Not connected): present = No Pin 0x0f (Not connected): present = Yes Pin 0x10 (Not connected): present = No Pin 0x11 (Black Line In, Left side): present = No Pin 0x12 (Internal Mic, Mobile-In): present = No Pin 0x13 (Not connected): present = No Pin 0x18 (Not connected): present = No
Pin 0x0f is still reported as not connected, but correctly detects the jack if plugged. If I turn off and on the "HP/Speaker Auto Detect" in alsamixer while "HP/Speaker" is off, the correct output is detected. If "HP/Speaker" is on, the behaviour is inconsistent.
Is there a configuration file? Where can I find the metadata "Black Line In, Left side"? I don't know if it is related, but pavucontrol detects only the "speakers" port. On my previous laptop (with Creative Recon 3Di, another ca0132 card) I could choose between "speakers and "headphones".
Regards, Gabriele

At Thu, 30 Apr 2015 01:40:30 +0200, Gabriele Martino wrote:
On 29/04/2015 20:42, Takashi Iwai wrote:
At Wed, 29 Apr 2015 17:42:55 +0200, Gabriele Martino wrote:
On 29/04/2015 15:38, Takashi Iwai wrote:
At Wed, 29 Apr 2015 00:47:16 +0200, Gabriele Martino wrote:
Thank you for your explanation. I managed to fix the pin address, but as I told before the jack detection is totally messed up. "hdajacksensetest" fails with: Ioctl call failed with error 16
The error message looks irrelevant with the patch itself. Did you build with proper kernel configs? CONFIG_SND_HDA_HWDEP=y CONFIG_SND_HDA_RECONFIG=y CONFIG_SND_HDA_PATCH_LOADER=y
It should be ok:
$ grep CONFIG_SND_HDA_ /usr/src/linux/.config | grep -v '^#' CONFIG_SND_HDA_INTEL=m CONFIG_SND_HDA_DSP_LOADER=y CONFIG_SND_HDA_PREALLOC_SIZE=2048 CONFIG_SND_HDA_HWDEP=y CONFIG_SND_HDA_RECONFIG=y CONFIG_SND_HDA_INPUT_JACK=y CONFIG_SND_HDA_PATCH_LOADER=y CONFIG_SND_HDA_CODEC_HDMI=m CONFIG_SND_HDA_I915=y CONFIG_SND_HDA_CODEC_CA0132=m CONFIG_SND_HDA_CODEC_CA0132_DSP=y CONFIG_SND_HDA_GENERIC=m CONFIG_SND_HDA_POWER_SAVE_DEFAULT=60
OK, then it's something else. Errno 16 is EBUSY, so something else must be accessing the same device (e.g. hwdep) and blocking the operation.
Are you sure that you never see this error when a kernel is without the patch?
It was an error on my part, my apologies. I did a full kernel clean and rebuild, and the error 16 went away. But the jack detection is still broken.
hdajacksensetest -c 1 -a Pin 0x0b (Internal Speaker): present = Yes Pin 0x0c (Not connected): present = No Pin 0x0d (Not connected): present = No Pin 0x0e (Not connected): present = No Pin 0x0f (Not connected): present = Yes Pin 0x10 (Not connected): present = No Pin 0x11 (Black Line In, Left side): present = No Pin 0x12 (Internal Mic, Mobile-In): present = No Pin 0x13 (Not connected): present = No Pin 0x18 (Not connected): present = No
Pin 0x0f is still reported as not connected, but correctly detects the jack if plugged. If I turn off and on the "HP/Speaker Auto Detect" in alsamixer while "HP/Speaker" is off, the correct output is detected. If "HP/Speaker" is on, the behaviour is inconsistent.
Is there a configuration file? Where can I find the metadata "Black Line In, Left side"? I don't know if it is related, but pavucontrol detects only the "speakers" port. On my previous laptop (with Creative Recon 3Di, another ca0132 card) I could choose between "speakers and "headphones".
It implies that the whole pin config BIOS provides is buggy. The jack color, location, etc, all are parsed from 32bit pin configuration value for each pin.
You need to correct the pin config and sets it statically in the driver. hdajackretask can give you the map and reload it dynamically.
Takashi

On 30/04/2015 07:51, Takashi Iwai wrote:
At Thu, 30 Apr 2015 01:40:30 +0200, Gabriele Martino wrote:
It was an error on my part, my apologies. I did a full kernel clean and rebuild, and the error 16 went away. But the jack detection is still broken.
hdajacksensetest -c 1 -a Pin 0x0b (Internal Speaker): present = Yes Pin 0x0c (Not connected): present = No Pin 0x0d (Not connected): present = No Pin 0x0e (Not connected): present = No Pin 0x0f (Not connected): present = Yes Pin 0x10 (Not connected): present = No Pin 0x11 (Black Line In, Left side): present = No Pin 0x12 (Internal Mic, Mobile-In): present = No Pin 0x13 (Not connected): present = No Pin 0x18 (Not connected): present = No
Pin 0x0f is still reported as not connected, but correctly detects the jack if plugged. If I turn off and on the "HP/Speaker Auto Detect" in alsamixer while "HP/Speaker" is off, the correct output is detected. If "HP/Speaker" is on, the behaviour is inconsistent.
Is there a configuration file? Where can I find the metadata "Black Line In, Left side"? I don't know if it is related, but pavucontrol detects only the "speakers" port. On my previous laptop (with Creative Recon 3Di, another ca0132 card) I could choose between "speakers and "headphones".
It implies that the whole pin config BIOS provides is buggy. The jack color, location, etc, all are parsed from 32bit pin configuration value for each pin.
You need to correct the pin config and sets it statically in the driver. hdajackretask can give you the map and reload it dynamically.
Ok, I overrided the pin 0x0f to: -Connectivity: jack -Device: headphones and now it shows the ports "Speakers" and "Headphones" as it should. It correctly switches from "Speakers" to "Headphones" when I plug the jack, but the sound comes still from the speakers. I have to mess with the alsamixer's switches to get the correct output device, as I did before.
What is the meaning of "Channel group" and "Channel (in group)" controls of in hdajackretask? I can't find any documentation. The speakers are on channel group 15, channel in group "Front". The headphones got as default value channel group 3, channel in group "Channel 30 & 31".
Regards, Gabriele

On 30/04/2015 07:51, Takashi Iwai wrote:
At Thu, 30 Apr 2015 01:40:30 +0200, Gabriele Martino wrote:
hdajacksensetest -c 1 -a Pin 0x0b (Internal Speaker): present = Yes Pin 0x0c (Not connected): present = No Pin 0x0d (Not connected): present = No Pin 0x0e (Not connected): present = No Pin 0x0f (Not connected): present = Yes Pin 0x10 (Not connected): present = No Pin 0x11 (Black Line In, Left side): present = No Pin 0x12 (Internal Mic, Mobile-In): present = No Pin 0x13 (Not connected): present = No Pin 0x18 (Not connected): present = No
Pin 0x0f is still reported as not connected, but correctly detects the jack if plugged. If I turn off and on the "HP/Speaker Auto Detect" in alsamixer while "HP/Speaker" is off, the correct output is detected. If "HP/Speaker" is on, the behaviour is inconsistent.
Is there a configuration file? Where can I find the metadata "Black Line In, Left side"? I don't know if it is related, but pavucontrol detects only the "speakers" port. On my previous laptop (with Creative Recon 3Di, another ca0132 card) I could choose between "speakers and "headphones".
It implies that the whole pin config BIOS provides is buggy. The jack color, location, etc, all are parsed from 32bit pin configuration value for each pin.
You need to correct the pin config and sets it statically in the driver. hdajackretask can give you the map and reload it dynamically.
Finally got it. I'm not sure about overriding the BIOS configuration: there is a new version which fixes all the unconnected pins. There is only a small issue: the internal speakers are now marked as "Line out", which seems to mess up the "Ports" section in Pulseaudio.
Regards, Gabriele

At Mon, 04 May 2015 01:53:37 +0200, Gabriele Martino wrote:
On 30/04/2015 07:51, Takashi Iwai wrote:
At Thu, 30 Apr 2015 01:40:30 +0200, Gabriele Martino wrote:
hdajacksensetest -c 1 -a Pin 0x0b (Internal Speaker): present = Yes Pin 0x0c (Not connected): present = No Pin 0x0d (Not connected): present = No Pin 0x0e (Not connected): present = No Pin 0x0f (Not connected): present = Yes Pin 0x10 (Not connected): present = No Pin 0x11 (Black Line In, Left side): present = No Pin 0x12 (Internal Mic, Mobile-In): present = No Pin 0x13 (Not connected): present = No Pin 0x18 (Not connected): present = No
Pin 0x0f is still reported as not connected, but correctly detects the jack if plugged. If I turn off and on the "HP/Speaker Auto Detect" in alsamixer while "HP/Speaker" is off, the correct output is detected. If "HP/Speaker" is on, the behaviour is inconsistent.
Is there a configuration file? Where can I find the metadata "Black Line In, Left side"? I don't know if it is related, but pavucontrol detects only the "speakers" port. On my previous laptop (with Creative Recon 3Di, another ca0132 card) I could choose between "speakers and "headphones".
It implies that the whole pin config BIOS provides is buggy. The jack color, location, etc, all are parsed from 32bit pin configuration value for each pin.
You need to correct the pin config and sets it statically in the driver. hdajackretask can give you the map and reload it dynamically.
Finally got it. I'm not sure about overriding the BIOS configuration: there is a new version which fixes all the unconnected pins. There is only a small issue: the internal speakers are now marked as "Line out", which seems to mess up the "Ports" section in Pulseaudio.
Hm, this can be changed via a proper pin config?
In anyway, I'm traveling in this week and next week, so cannot debug the things. Will check it later once when I back from vacation. Just ping me.
thanks,
Takashi

On 04/05/2015 14:30, Takashi Iwai wrote:
At Mon, 04 May 2015 01:53:37 +0200, Gabriele Martino wrote:
Finally got it. I'm not sure about overriding the BIOS configuration: there is a new version which fixes all the unconnected pins. There is only a small issue: the internal speakers are now marked as "Line out", which seems to mess up the "Ports" section in Pulseaudio.
Hm, this can be changed via a proper pin config?
Sure, that's why I attached hda-jack-retask.fw.
In anyway, I'm traveling in this week and next week, so cannot debug the things. Will check it later once when I back from vacation. Just ping me.
Enjoy your vacation, I'll try to tidy up the code and make a decent patch in the meanwhile.
Regards, Gabriele

On 04/05/2015 14:30, Takashi Iwai wrote:
Hm, this can be changed via a proper pin config?
In anyway, I'm traveling in this week and next week, so cannot debug the things. Will check it later once when I back from vacation. Just ping me.
Hi, this should be the final version. There are some big changes: - all the pin configuration is now performed in ca0132_config(), no more static definitions - some initialization verbs depend on the pin configuration, so they are generated from the pin configuration - the quirks management code now is a simple "if" in the pin configuration
I can't split the patch because the quirks part requires the dynamic verbs generation. I'm using this since 5 May without any trouble, so it shouldn't blow up things.
Regards, Gabriele

At Mon, 11 May 2015 22:17:01 +0200, Gabriele Martino wrote:
On 04/05/2015 14:30, Takashi Iwai wrote:
Hm, this can be changed via a proper pin config?
In anyway, I'm traveling in this week and next week, so cannot debug the things. Will check it later once when I back from vacation. Just ping me.
Hi, this should be the final version. There are some big changes:
- all the pin configuration is now performed in ca0132_config(), no more
static definitions
- some initialization verbs depend on the pin configuration, so they are
generated from the pin configuration
- the quirks management code now is a simple "if" in the pin configuration
I can't split the patch because the quirks part requires the dynamic verbs generation. I'm using this since 5 May without any trouble, so it shouldn't blow up things.
The patch looks almost OK, but just a few things:
+static int ca0132_prepare_verbs(struct hda_codec *codec) +{
- struct ca0132_spec *spec = codec->spec;
- static struct hda_verb empty_verb = {};
+#define NUM_SPEC_VERBS 4
- spec->chip_init_verbs = ca0132_init_verbs0;
- spec->spec_init_verbs = kzalloc(sizeof(struct hda_verb) * NUM_SPEC_VERBS, GFP_KERNEL);
- if (!spec->spec_init_verbs)
return -ENOMEM;
- /* HP jack autodetection */
- spec->spec_init_verbs[0].nid = spec->unsol_tag_hp;
- spec->spec_init_verbs[0].param = AC_VERB_SET_UNSOLICITED_ENABLE;
- spec->spec_init_verbs[0].verb = AC_USRSP_EN | spec->unsol_tag_hp;
- /* MIC1 jack autodetection */
- spec->spec_init_verbs[1].nid = spec->unsol_tag_amic1;
- spec->spec_init_verbs[1].param = AC_VERB_SET_UNSOLICITED_ENABLE;
- spec->spec_init_verbs[1].verb = AC_USRSP_EN | spec->unsol_tag_amic1;
- /* config EAPD */
- spec->spec_init_verbs[2].nid = 0x0b;
- spec->spec_init_verbs[2].param = 0x78D;
- spec->spec_init_verbs[2].verb = 0x00;
- /* Previously commented configuration */
- /*
- spec->spec_init_verbs[3].nid = 0x0b;
- spec->spec_init_verbs[3].param = AC_VERB_SET_EAPD_BTLENABLE;
- spec->spec_init_verbs[3].verb = 0x02;
- spec->spec_init_verbs[4].nid = 0x10;
- spec->spec_init_verbs[4].param = 0x78D;
- spec->spec_init_verbs[4].verb = 0x02;
- spec->spec_init_verbs[5].nid = 0x10;
- spec->spec_init_verbs[5].param = AC_VERB_SET_EAPD_BTLENABLE;
- spec->spec_init_verbs[5].verb = 0x02;
- */
- /* Empty element */
- spec->spec_init_verbs[NUM_SPEC_VERBS-1] = empty_verb;
This line is superfluous when you allocated via kzalloc().
Could you fix it and give a proper patch changelog and your signed-off-by tag?
thanks,
Takashi

This patch adds quirks detection to the Creative CA0132 codec, and the quirk for Alienware 15 (2015). Some quirks may need different pin configuration, so the relevant compile-time configuration has been removed. The pin configuration and related initialization verbs are generated at runtime instead, in ca0132_config() and ca0132_prepare_verbs().
Signed-off-by: Gabriele Martino g.martino@gmx.com

At Mon, 18 May 2015 21:15:13 +0200, Gabriele Martino wrote:
This patch adds quirks detection to the Creative CA0132 codec, and the quirk for Alienware 15 (2015). Some quirks may need different pin configuration, so the relevant compile-time configuration has been removed. The pin configuration and related initialization verbs are generated at runtime instead, in ca0132_config() and ca0132_prepare_verbs().
Signed-off-by: Gabriele Martino g.martino@gmx.com
Applied, thanks.
Takashi
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 4a4e7b2..1c7a9ec 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -43,8 +43,6 @@ #define FLOAT_TWO 0x40000000 #define FLOAT_MINUS_5 0xc0a00000
-#define UNSOL_TAG_HP 0x10 -#define UNSOL_TAG_AMIC1 0x12 #define UNSOL_TAG_DSP 0x16
#define DSP_DMA_WRITE_BUFLEN_INIT (1UL<<18) @@ -703,8 +701,8 @@ unsigned int num_mixers; const struct hda_verb *base_init_verbs; const struct hda_verb *base_exit_verbs;
- const struct hda_verb *init_verbs[5];
- unsigned int num_init_verbs; /* exclude base init verbs */
const struct hda_verb *chip_init_verbs;
struct hda_verb *spec_init_verbs; struct auto_pin_cfg autocfg;
/* Nodes configurations */
@@ -719,6 +717,8 @@ unsigned int num_inputs; hda_nid_t shared_mic_nid; hda_nid_t shared_out_nid;
hda_nid_t unsol_tag_hp;
hda_nid_t unsol_tag_amic1;
/* chip access */ struct mutex chipio_mutex; /* chip access mutex */
@@ -748,10 +748,24 @@
struct hda_codec *codec; struct delayed_work unsol_hp_work;
- int quirk;
#ifdef ENABLE_TUNING_CONTROLS long cur_ctl_vals[TUNING_CTLS_COUNT]; #endif +};
+/*
- CA0132 quirks table
- */
+enum {
- QUIRK_NONE,
- QUIRK_ALIENWARE,
+};
+static const struct snd_pci_quirk ca0132_quirks[] = {
- SND_PCI_QUIRK(0x1028, 0x0685, "Alienware 15", QUIRK_ALIENWARE),
- {}
};
/* @@ -3227,7 +3241,7 @@ struct hda_jack_tbl *jack;
ca0132_select_out(spec->codec);
- jack = snd_hda_jack_tbl_get(spec->codec, UNSOL_TAG_HP);
- jack = snd_hda_jack_tbl_get(spec->codec, spec->unsol_tag_hp); if (jack) { jack->block_report = 0; snd_hda_jack_report_sync(spec->codec);
@@ -4417,8 +4431,9 @@
static void ca0132_init_unsol(struct hda_codec *codec) {
- snd_hda_jack_detect_enable_callback(codec, UNSOL_TAG_HP, hp_callback);
- snd_hda_jack_detect_enable_callback(codec, UNSOL_TAG_AMIC1,
- struct ca0132_spec *spec = codec->spec;
- snd_hda_jack_detect_enable_callback(codec, spec->unsol_tag_hp, hp_callback);
- snd_hda_jack_detect_enable_callback(codec, spec->unsol_tag_amic1, amic_callback); snd_hda_jack_detect_enable_callback(codec, UNSOL_TAG_DSP, ca0132_process_dsp_response);
@@ -4476,17 +4491,6 @@ {0x15, 0x5E8, 0xC9}, {0x15, 0x717, 0x0D}, {0x15, 0x718, 0x20},
- {}
-};
-static struct hda_verb ca0132_init_verbs1[] = {
- {0x10, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | UNSOL_TAG_HP},
- {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | UNSOL_TAG_AMIC1},
- /* config EAPD */
- {0x0b, 0x78D, 0x00},
- /*{0x0b, AC_VERB_SET_EAPD_BTLENABLE, 0x02},*/
- /*{0x10, 0x78D, 0x02},*/
- /*{0x10, AC_VERB_SET_EAPD_BTLENABLE, 0x02},*/ {}
};
@@ -4569,8 +4573,8 @@
init_input(codec, cfg->dig_in_pin, spec->dig_in);
- for (i = 0; i < spec->num_init_verbs; i++)
snd_hda_sequence_write(codec, spec->init_verbs[i]);
snd_hda_sequence_write(codec, spec->chip_init_verbs);
snd_hda_sequence_write(codec, spec->spec_init_verbs);
ca0132_select_out(codec); ca0132_select_mic(codec);
@@ -4591,6 +4595,7 @@ snd_hda_sequence_write(codec, spec->base_exit_verbs); ca0132_exit_chip(codec); snd_hda_power_down(codec);
- kfree(spec->spec_init_verbs); kfree(codec->spec);
}
@@ -4617,18 +4622,26 @@
spec->num_outputs = 2; spec->out_pins[0] = 0x0b; /* speaker out */
- spec->out_pins[1] = 0x10; /* headphone out */
- if (spec->quirk == QUIRK_ALIENWARE) {
codec_dbg(codec, "ca0132_config: QUIRK_ALIENWARE applied.\n");
spec->out_pins[1] = 0x0f;
- }
- else{
spec->out_pins[1] = 0x10; /* headphone out */
- } spec->shared_out_nid = 0x2;
- spec->unsol_tag_hp = spec->out_pins[1];
- spec->num_inputs = 3; spec->adcs[0] = 0x7; /* digital mic / analog mic1 */ spec->adcs[1] = 0x8; /* analog mic2 */ spec->adcs[2] = 0xa; /* what u hear */
- spec->shared_mic_nid = 0x7;
spec->num_inputs = 3; spec->input_pins[0] = 0x12; spec->input_pins[1] = 0x11; spec->input_pins[2] = 0x13;
spec->shared_mic_nid = 0x7;
spec->unsol_tag_amic1 = spec->input_pins[0];
/* SPDIF I/O */ spec->dig_out = 0x05;
@@ -4641,10 +4654,56 @@ cfg->dig_in_type = HDA_PCM_TYPE_SPDIF; }
+static int ca0132_prepare_verbs(struct hda_codec *codec) +{ +/* Verbs + terminator (an empty element) */ +#define NUM_SPEC_VERBS 4
- struct ca0132_spec *spec = codec->spec;
- spec->chip_init_verbs = ca0132_init_verbs0;
- spec->spec_init_verbs = kzalloc(sizeof(struct hda_verb) * NUM_SPEC_VERBS, GFP_KERNEL);
- if (!spec->spec_init_verbs)
return -ENOMEM;
- /* HP jack autodetection */
- spec->spec_init_verbs[0].nid = spec->unsol_tag_hp;
- spec->spec_init_verbs[0].param = AC_VERB_SET_UNSOLICITED_ENABLE;
- spec->spec_init_verbs[0].verb = AC_USRSP_EN | spec->unsol_tag_hp;
- /* MIC1 jack autodetection */
- spec->spec_init_verbs[1].nid = spec->unsol_tag_amic1;
- spec->spec_init_verbs[1].param = AC_VERB_SET_UNSOLICITED_ENABLE;
- spec->spec_init_verbs[1].verb = AC_USRSP_EN | spec->unsol_tag_amic1;
- /* config EAPD */
- spec->spec_init_verbs[2].nid = 0x0b;
- spec->spec_init_verbs[2].param = 0x78D;
- spec->spec_init_verbs[2].verb = 0x00;
- /* Previously commented configuration */
- /*
- spec->spec_init_verbs[3].nid = 0x0b;
- spec->spec_init_verbs[3].param = AC_VERB_SET_EAPD_BTLENABLE;
- spec->spec_init_verbs[3].verb = 0x02;
- spec->spec_init_verbs[4].nid = 0x10;
- spec->spec_init_verbs[4].param = 0x78D;
- spec->spec_init_verbs[4].verb = 0x02;
- spec->spec_init_verbs[5].nid = 0x10;
- spec->spec_init_verbs[5].param = AC_VERB_SET_EAPD_BTLENABLE;
- spec->spec_init_verbs[5].verb = 0x02;
- */
- /* Terminator: spec->spec_init_verbs[NUM_SPEC_VERBS-1] */
- return 0;
+}
static int patch_ca0132(struct hda_codec *codec) { struct ca0132_spec *spec; int err;
const struct snd_pci_quirk *quirk;
codec_dbg(codec, "patch_ca0132\n");
@@ -4654,15 +4713,19 @@ codec->spec = spec; spec->codec = codec;
/* Detect codec quirk */
quirk = snd_pci_quirk_lookup(codec->bus->pci, ca0132_quirks);
if (quirk)
spec->quirk = quirk->value;
else
spec->quirk = QUIRK_NONE;
spec->dsp_state = DSP_DOWNLOAD_INIT; spec->num_mixers = 1; spec->mixers[0] = ca0132_mixer;
spec->base_init_verbs = ca0132_base_init_verbs; spec->base_exit_verbs = ca0132_base_exit_verbs;
spec->init_verbs[0] = ca0132_init_verbs0;
spec->init_verbs[1] = ca0132_init_verbs1;
spec->num_init_verbs = 2;
INIT_DELAYED_WORK(&spec->unsol_hp_work, ca0132_unsol_hp_delayed);
@@ -4670,6 +4733,10 @@
ca0132_config(codec);
- err = ca0132_prepare_verbs(codec);
- if (err < 0)
return err;
- err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL); if (err < 0) return err;
Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

At Wed, 29 Apr 2015 00:47:16 +0200, Gabriele Martino wrote:
@@ -4653,6 +4667,7 @@ return -ENOMEM; codec->spec = spec; spec->codec = codec;
spec->quirk = snd_pci_quirk_lookup(codec->bus->pci, ca0132_quirks);
spec->dsp_state = DSP_DOWNLOAD_INIT; spec->num_mixers = 1;
@@ -4670,6 +4685,12 @@
ca0132_config(codec);
- /* Apply detected quirks */
- if (spec->quirk->value == QUIRK_ALIENWARE) {
Add a NULL check. Or, rather just record only quirk->value as spec->quirk.
quirk = snd_pci_quirk_lookup(pci, quirks); if (quirk) spec->quirk = quirk->value;
....
if (spec->quirk == QUIRK_ALIENWARE) ....
Takashi
participants (2)
-
Gabriele Martino
-
Takashi Iwai