* ca0132: add generic parser fallback for broken DSP path
@ 2026-05-10 9:38 eziogale
2026-05-16 13:41 ` Takashi Iwai
0 siblings, 1 reply; 7+ messages in thread
From: eziogale @ 2026-05-10 9:38 UTC (permalink / raw)
To: Takashi Iwai `, Jaroslav Kysela `; +Cc: linux-sound, alsa-devel
[-- Attachment #1: Type: text/plain, Size: 570 bytes --]
Some CA0132 implementations (e.g. Gigabyte GA-Z170X-Gaming G1)
produce white noise when using the DSP firmware path. Add a
QUIRK_GENERIC path that uses the standard HDA generic parser
instead, with custom pin configs that disable the broken auto-mute
from HP jack detection.
Also applies VREF_50 on the mic pin and adds an init_hook for
suspend/resume stability.
Kernel version: 6.18.24
The PCI SSID this was tested on: `1458:a046`
it's been tested with PulseAudio and speaker-test
That the DSP path (QUIRK_SBZ) remains unchanged for cards that work with it.
Thanks
[-- Attachment #2: ca0132-generic-parser.patch --]
[-- Type: text/x-patch, Size: 5164 bytes --]
--- /home/ezio/tmp/kernel/linux-6.18.24/sound/hda/codecs/ca0132.c.0 2026-05-02 09:19:21.217137158 +0200
+++ /home/ezio/tmp/kernel/linux-6.18.24/sound/hda/codecs/ca0132.c 2026-05-10 11:21:41.933355825 +0200
@@ -24,6 +24,7 @@
#include "hda_local.h"
#include "hda_auto_parser.h"
#include "hda_jack.h"
+#include "generic.h"
#include "ca0132_regs.h"
@@ -1060,6 +1061,8 @@
*/
struct ca0132_spec {
+ struct hda_gen_spec gen;
+
const struct snd_kcontrol_new *mixers[5];
unsigned int num_mixers;
const struct hda_verb *base_init_verbs;
@@ -1175,6 +1178,7 @@
QUIRK_AE5,
QUIRK_AE7,
QUIRK_NONE = HDA_FIXUP_ID_NOT_SET,
+ QUIRK_GENERIC,
};
#ifdef CONFIG_PCI
@@ -1304,6 +1308,7 @@
SND_PCI_QUIRK(0x1458, 0xA016, "Recon3Di", QUIRK_R3DI),
SND_PCI_QUIRK(0x1458, 0xA026, "Gigabyte G1.Sniper Z97", QUIRK_R3DI),
SND_PCI_QUIRK(0x1458, 0xA036, "Gigabyte GA-Z170X-Gaming 7", QUIRK_R3DI),
+ SND_PCI_QUIRK(0x1458, 0xA046, "Gigabyte GA-Z170X-Gaming G1", QUIRK_GENERIC),
SND_PCI_QUIRK(0x3842, 0x1038, "EVGA X99 Classified", QUIRK_R3DI),
SND_PCI_QUIRK(0x3842, 0x104b, "EVGA X299 Dark", QUIRK_R3DI),
SND_PCI_QUIRK(0x3842, 0x1055, "EVGA Z390 DARK", QUIRK_R3DI),
@@ -1325,11 +1330,13 @@
{ .id = QUIRK_R3D, .name = "r3d" },
{ .id = QUIRK_AE5, .name = "ae5" },
{ .id = QUIRK_AE7, .name = "ae7" },
+ { .id = QUIRK_GENERIC, .name = "generic" },
{}
};
/* Output selection quirk info structures. */
#define MAX_QUIRK_MMIO_GPIO_SET_VALS 3
+
#define MAX_QUIRK_SCP_SET_VALS 2
struct ca0132_alt_out_set_info {
unsigned int dac2port; /* ParamID 0x0d value. */
@@ -9821,7 +9828,7 @@
static int ca0132_prepare_verbs(struct hda_codec *codec)
{
/* Verbs + terminator (an empty element) */
-#define NUM_SPEC_VERBS 2
+#define NUM_SPEC_VERBS 3
struct ca0132_spec *spec = codec->spec;
spec->chip_init_verbs = ca0132_init_verbs0;
@@ -9842,6 +9849,11 @@
spec->spec_init_verbs[0].param = 0x78D;
spec->spec_init_verbs[0].verb = 0x00;
+ /* VREF_50 for mic pin */
+ spec->spec_init_verbs[1].nid = 0x12;
+ spec->spec_init_verbs[1].verb = AC_VERB_SET_PIN_WIDGET_CONTROL;
+ spec->spec_init_verbs[1].param = 0x21; /* IN | VREF_50 */
+
/* Previously commented configuration */
/*
spec->spec_init_verbs[2].nid = 0x0b;
@@ -9882,10 +9894,20 @@
}
}
+static void ca0132_generic_init_hook(struct hda_codec *codec)
+{
+ struct ca0132_spec *spec = codec->spec;
+ snd_hda_sequence_write(codec, spec->spec_init_verbs);
+}
+
static void ca0132_codec_remove(struct hda_codec *codec)
{
struct ca0132_spec *spec = codec->spec;
+ if (ca0132_quirk(spec) == QUIRK_GENERIC) {
+ snd_hda_gen_remove(codec);
+ return;
+ }
if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO)
return dbpro_free(codec);
else
@@ -9906,14 +9928,55 @@
codec->spec = spec;
spec->codec = codec;
+ /* These must be set before any path is taken */
+ codec->pcm_format_first = 1;
+ codec->no_sticky_stream = 1;
+
/* Detect codec quirk */
snd_hda_pick_fixup(codec, ca0132_quirk_models, ca0132_quirks, NULL);
if (ca0132_quirk(spec) == QUIRK_SBZ)
sbz_detect_quirk(codec);
- codec->pcm_format_first = 1;
- codec->no_sticky_stream = 1;
+ if (ca0132_quirk(spec) == QUIRK_GENERIC) {
+ struct auto_pin_cfg *cfg = &spec->gen.autocfg;
+
+ snd_hda_gen_spec_init(&spec->gen);
+
+ snd_hda_apply_pincfgs(codec,
+ (const struct hda_pintbl[]) {
+ { 0x0b, 0x41014111 },
+ { 0x0c, 0x414520f0 }, /* SPDIF out */
+ { 0x0d, 0x01014010 }, /* lineout */
+ { 0x0e, 0x41c501f0 },
+ { 0x0f, 0x411111f0 }, /* disabled */
+ { 0x10, 0x411111f0 }, /* disabled */
+ { 0x11, 0x41012014 },
+ { 0x12, 0x37a790f0 }, /* mic */
+ { 0x13, 0x77a701f0 },
+ { 0x18, 0x500000f0 },
+ {}
+ });
+ ca0132_init_chip(codec);
+
+ err = ca0132_prepare_verbs(codec);
+ if (err < 0)
+ goto error;
+
+ err = snd_hda_parse_pin_def_config(codec, cfg, NULL);
+ if (err < 0)
+ goto error;
+ err = snd_hda_gen_parse_auto_config(codec, cfg);
+ if (err < 0)
+ goto error;
+
+ spec->gen.init_hook = ca0132_generic_init_hook;
+ spec->gen.automute_speaker = 0;
+ spec->gen.automute_lo = 0;
+
+ snd_hda_sequence_write(codec, spec->spec_init_verbs);
+ return 0;
+ }
spec->dsp_state = DSP_DOWNLOAD_INIT;
spec->num_mixers = 1;
@@ -10014,6 +10077,10 @@
{
struct ca0132_spec *spec = codec->spec;
+ if (ca0132_quirk(spec) == QUIRK_GENERIC) {
+ return snd_hda_gen_build_controls(codec);
+ }
+
if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO)
return dbpro_build_controls(codec);
else
@@ -10024,6 +10091,10 @@
{
struct ca0132_spec *spec = codec->spec;
+ if (ca0132_quirk(spec) == QUIRK_GENERIC) {
+ return snd_hda_gen_build_pcms(codec);
+ }
+
if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO)
return dbpro_build_pcms(codec);
else
@@ -10034,6 +10105,10 @@
{
struct ca0132_spec *spec = codec->spec;
+ if (ca0132_quirk(spec) == QUIRK_GENERIC) {
+ return snd_hda_gen_init(codec);
+ }
+
if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO)
return dbpro_init(codec);
else
@@ -10044,6 +10119,9 @@
{
struct ca0132_spec *spec = codec->spec;
+ if (ca0132_quirk(spec) == QUIRK_GENERIC)
+ return 0;
+
cancel_delayed_work_sync(&spec->unsol_hp_work);
return 0;
}
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: ca0132: add generic parser fallback for broken DSP path 2026-05-10 9:38 ca0132: add generic parser fallback for broken DSP path eziogale @ 2026-05-16 13:41 ` Takashi Iwai 2026-05-17 16:29 ` [PATCH] ALSA: hda/ca0132: add QUIRK_GENERIC path for Gigabyte, GA-Z170X-Gaming G1 eziogale 0 siblings, 1 reply; 7+ messages in thread From: Takashi Iwai @ 2026-05-16 13:41 UTC (permalink / raw) To: eziogale@gmail.com Cc: Takashi Iwai `, Jaroslav Kysela `, linux-sound, alsa-devel On Sun, 10 May 2026 11:38:49 +0200, eziogale@gmail.com wrote: > > Some CA0132 implementations (e.g. Gigabyte GA-Z170X-Gaming G1) > produce white noise when using the DSP firmware path. Add a > QUIRK_GENERIC path that uses the standard HDA generic parser > instead, with custom pin configs that disable the broken auto-mute > from HP jack detection. > > Also applies VREF_50 on the mic pin and adds an init_hook for > suspend/resume stability. > > Kernel version: 6.18.24 > The PCI SSID this was tested on: `1458:a046` > it's been tested with PulseAudio and speaker-test > That the DSP path (QUIRK_SBZ) remains unchanged for cards that work with it. > > Thanks The idea sounds reasonable, and most of the changes look OK. Could you submit a patch in a proper format (with a proper Signed-off-by tag)? About the code changes: > --- /home/ezio/tmp/kernel/linux-6.18.24/sound/hda/codecs/ca0132.c.0 2026-05-02 09:19:21.217137158 +0200 > +++ /home/ezio/tmp/kernel/linux-6.18.24/sound/hda/codecs/ca0132.c 2026-05-10 11:21:41.933355825 +0200 A patch should be applicable with -p1 option. > @@ -24,6 +24,7 @@ > #include "hda_local.h" > #include "hda_auto_parser.h" > #include "hda_jack.h" > +#include "generic.h" I guess you need also add the selection of CONFIG_SND_HDA_CODEC_GENERIC in Kconfig, too. > #include "ca0132_regs.h" > > @@ -1060,6 +1061,8 @@ > */ > > struct ca0132_spec { > + struct hda_gen_spec gen; > + > const struct snd_kcontrol_new *mixers[5]; > unsigned int num_mixers; > const struct hda_verb *base_init_verbs; > @@ -1175,6 +1178,7 @@ > QUIRK_AE5, > QUIRK_AE7, > QUIRK_NONE = HDA_FIXUP_ID_NOT_SET, > + QUIRK_GENERIC, Better to put QUIRK_GENERIC before QUIRK_NONE. > static void ca0132_codec_remove(struct hda_codec *codec) > { > struct ca0132_spec *spec = codec->spec; > > + if (ca0132_quirk(spec) == QUIRK_GENERIC) { > + snd_hda_gen_remove(codec); > + return; > + } > if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO) > return dbpro_free(codec); > else Better to replace with switch(). > + if (ca0132_quirk(spec) == QUIRK_GENERIC) { > + struct auto_pin_cfg *cfg = &spec->gen.autocfg; > + > + snd_hda_gen_spec_init(&spec->gen); > + > + snd_hda_apply_pincfgs(codec, > + (const struct hda_pintbl[]) { > + { 0x0b, 0x41014111 }, > + { 0x0c, 0x414520f0 }, /* SPDIF out */ > + { 0x0d, 0x01014010 }, /* lineout */ > + { 0x0e, 0x41c501f0 }, > + { 0x0f, 0x411111f0 }, /* disabled */ > + { 0x10, 0x411111f0 }, /* disabled */ > + { 0x11, 0x41012014 }, > + { 0x12, 0x37a790f0 }, /* mic */ > + { 0x13, 0x77a701f0 }, > + { 0x18, 0x500000f0 }, > + {} > + }); > > + ca0132_init_chip(codec); > + > + err = ca0132_prepare_verbs(codec); > + if (err < 0) > + goto error; > + > + err = snd_hda_parse_pin_def_config(codec, cfg, NULL); > + if (err < 0) > + goto error; > + err = snd_hda_gen_parse_auto_config(codec, cfg); > + if (err < 0) > + goto error; > + > + spec->gen.init_hook = ca0132_generic_init_hook; > + spec->gen.automute_speaker = 0; > + spec->gen.automute_lo = 0; > + > + snd_hda_sequence_write(codec, spec->spec_init_verbs); > + return 0; > + } It's a too big block, and better to be factored out as a function. The verb table should be also defined outside the argument, too; otherwise it looks too hackish. > @@ -10014,6 +10077,10 @@ > { > struct ca0132_spec *spec = codec->spec; > > + if (ca0132_quirk(spec) == QUIRK_GENERIC) { > + return snd_hda_gen_build_controls(codec); > + } > + > if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO) > return dbpro_build_controls(codec); > else > @@ -10024,6 +10091,10 @@ > { > struct ca0132_spec *spec = codec->spec; > > + if (ca0132_quirk(spec) == QUIRK_GENERIC) { > + return snd_hda_gen_build_pcms(codec); > + } > + > if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO) > return dbpro_build_pcms(codec); > else > @@ -10034,6 +10105,10 @@ > { > struct ca0132_spec *spec = codec->spec; > > + if (ca0132_quirk(spec) == QUIRK_GENERIC) { > + return snd_hda_gen_init(codec); > + } > + > if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO) > return dbpro_init(codec); > else All those seem better with switch(). thanks, Takashi ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH] ALSA: hda/ca0132: add QUIRK_GENERIC path for Gigabyte, GA-Z170X-Gaming G1 2026-05-16 13:41 ` Takashi Iwai @ 2026-05-17 16:29 ` eziogale 2026-05-17 19:53 ` Takashi Iwai 0 siblings, 1 reply; 7+ messages in thread From: eziogale @ 2026-05-17 16:29 UTC (permalink / raw) To: Takashi Iwai; +Cc: Jaroslav Kysela `, linux-sound, alsa-devel Some CA0132 implementations (e.g. Gigabyte GA-Z170X-Gaming G1) produce white noise when using the DSP firmware path. Add a QUIRK_GENERIC path that uses the standard HDA generic parser instead, with custom pin configs. This patch applies against v6.18.24. --- sound/hda/codecs/Kconfig | 1 + sound/hda/codecs/ca0132.c | 111 +++++++++++++++++++++++++++++++++----- 2 files changed, 99 insertions(+), 13 deletions(-) diff --git a/sound/hda/codecs/Kconfig b/sound/hda/codecs/Kconfig index addbc94..dcf340e 100644 --- a/sound/hda/codecs/Kconfig +++ b/sound/hda/codecs/Kconfig @@ -69,6 +69,7 @@ comment "Set to Y if you want auto-loading the codec driver" config SND_HDA_CODEC_CA0132 tristate "Build Creative CA0132 codec support" + select SND_HDA_GENERIC help Say Y or M here to include Creative CA0132 codec support in snd-hda-intel driver. diff --git a/sound/hda/codecs/ca0132.c b/sound/hda/codecs/ca0132.c index dd054ae..92fc93f 100644 --- a/sound/hda/codecs/ca0132.c +++ b/sound/hda/codecs/ca0132.c @@ -24,6 +24,7 @@ #include "hda_local.h" #include "hda_auto_parser.h" #include "hda_jack.h" +#include "generic.h" #include "ca0132_regs.h" @@ -1060,6 +1061,8 @@ enum dsp_download_state { */ struct ca0132_spec { + struct hda_gen_spec gen; + const struct snd_kcontrol_new *mixers[5]; unsigned int num_mixers; const struct hda_verb *base_init_verbs; @@ -1174,6 +1177,7 @@ enum { QUIRK_R3D, QUIRK_AE5, QUIRK_AE7, + QUIRK_GENERIC, QUIRK_NONE = HDA_FIXUP_ID_NOT_SET, }; @@ -1292,6 +1296,20 @@ static const struct hda_pintbl ae7_pincfgs[] = { {} }; +static const struct hda_pintbl ca0132_generic_pincfgs[] = { + { 0x0b, 0x41014111 }, + { 0x0c, 0x414520f0 }, /* SPDIF out */ + { 0x0d, 0x01014010 }, /* lineout */ + { 0x0e, 0x41c501f0 }, + { 0x0f, 0x411111f0 }, /* disabled */ + { 0x10, 0x411111f0 }, /* disabled */ + { 0x11, 0x41012014 }, + { 0x12, 0x37a790f0 }, /* mic */ + { 0x13, 0x77a701f0 }, + { 0x18, 0x500000f0 }, + {} +}; + static const struct hda_quirk ca0132_quirks[] = { SND_PCI_QUIRK(0x1028, 0x057b, "Alienware M17x R4", QUIRK_ALIENWARE_M17XR4), SND_PCI_QUIRK(0x1028, 0x0685, "Alienware 15 2015", QUIRK_ALIENWARE), @@ -1304,6 +1322,7 @@ static const struct hda_quirk ca0132_quirks[] = { SND_PCI_QUIRK(0x1458, 0xA016, "Recon3Di", QUIRK_R3DI), SND_PCI_QUIRK(0x1458, 0xA026, "Gigabyte G1.Sniper Z97", QUIRK_R3DI), SND_PCI_QUIRK(0x1458, 0xA036, "Gigabyte GA-Z170X-Gaming 7", QUIRK_R3DI), + SND_PCI_QUIRK(0x1458, 0xA046, "Gigabyte GA-Z170X-Gaming G1", QUIRK_GENERIC), SND_PCI_QUIRK(0x3842, 0x1038, "EVGA X99 Classified", QUIRK_R3DI), SND_PCI_QUIRK(0x3842, 0x104b, "EVGA X299 Dark", QUIRK_R3DI), SND_PCI_QUIRK(0x3842, 0x1055, "EVGA Z390 DARK", QUIRK_R3DI), @@ -1325,6 +1344,7 @@ static const struct hda_model_fixup ca0132_quirk_models[] = { { .id = QUIRK_R3D, .name = "r3d" }, { .id = QUIRK_AE5, .name = "ae5" }, { .id = QUIRK_AE7, .name = "ae7" }, + { .id = QUIRK_GENERIC, .name = "generic" }, {} }; @@ -9882,14 +9902,57 @@ static void sbz_detect_quirk(struct hda_codec *codec) } } +static void ca0132_generic_init_hook(struct hda_codec *codec) +{ + struct ca0132_spec *spec = codec->spec; + + snd_hda_sequence_write(codec, spec->spec_init_verbs); +} + +static int ca0132_generic_probe(struct hda_codec *codec) +{ + struct ca0132_spec *spec = codec->spec; + struct auto_pin_cfg *cfg = &spec->gen.autocfg; + int err; + + snd_hda_gen_spec_init(&spec->gen); + + snd_hda_apply_pincfgs(codec, ca0132_generic_pincfgs); + + ca0132_init_chip(codec); + + err = ca0132_prepare_verbs(codec); + if (err < 0) + return err; + + err = snd_hda_parse_pin_def_config(codec, cfg, NULL); + if (err < 0) + return err; + err = snd_hda_gen_parse_auto_config(codec, cfg); + if (err < 0) + return err; + + spec->gen.init_hook = ca0132_generic_init_hook; + spec->gen.automute_speaker = 0; + spec->gen.automute_lo = 0; + + snd_hda_sequence_write(codec, spec->spec_init_verbs); + return 0; +} + static void ca0132_codec_remove(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; - if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO) + switch (ca0132_quirk(spec)) { + case QUIRK_GENERIC: + snd_hda_gen_remove(codec); + return; + case QUIRK_ZXR_DBPRO: return dbpro_free(codec); - else + default: return ca0132_free(codec); + } } static int ca0132_codec_probe(struct hda_codec *codec, @@ -9906,14 +9969,21 @@ static int ca0132_codec_probe(struct hda_codec *codec, codec->spec = spec; spec->codec = codec; - /* Detect codec quirk */ - snd_hda_pick_fixup(codec, ca0132_quirk_models, ca0132_quirks, NULL); - if (ca0132_quirk(spec) == QUIRK_SBZ) - sbz_detect_quirk(codec); - + /* These must be set before any path is taken */ codec->pcm_format_first = 1; codec->no_sticky_stream = 1; + /* Detect codec quirk */ + snd_hda_pick_fixup(codec, ca0132_quirk_models, ca0132_quirks, NULL); + switch (ca0132_quirk(spec)) { + case QUIRK_SBZ: + sbz_detect_quirk(codec); + break; + case QUIRK_GENERIC: + return ca0132_generic_probe(codec); + default: + break; + } spec->dsp_state = DSP_DOWNLOAD_INIT; spec->num_mixers = 1; @@ -10014,36 +10084,51 @@ static int ca0132_codec_build_controls(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; - if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO) + switch (ca0132_quirk(spec)) { + case QUIRK_GENERIC: + return snd_hda_gen_build_controls(codec); + case QUIRK_ZXR_DBPRO: return dbpro_build_controls(codec); - else + default: return ca0132_build_controls(codec); + } } static int ca0132_codec_build_pcms(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; - if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO) + switch (ca0132_quirk(spec)) { + case QUIRK_GENERIC: + return snd_hda_gen_build_pcms(codec); + case QUIRK_ZXR_DBPRO: return dbpro_build_pcms(codec); - else + default: return ca0132_build_pcms(codec); + } } static int ca0132_codec_init(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; - if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO) + switch (ca0132_quirk(spec)) { + case QUIRK_GENERIC: + return snd_hda_gen_init(codec); + case QUIRK_ZXR_DBPRO: return dbpro_init(codec); - else + default: return ca0132_init(codec); + } } static int ca0132_codec_suspend(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; + if (ca0132_quirk(spec) == QUIRK_GENERIC) + return 0; + cancel_delayed_work_sync(&spec->unsol_hp_work); return 0; } -- 2.54.0 Signed-off-by: Ezio Galeazzi <eziogale@gmail.com> ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH] ALSA: hda/ca0132: add QUIRK_GENERIC path for Gigabyte, GA-Z170X-Gaming G1 2026-05-17 16:29 ` [PATCH] ALSA: hda/ca0132: add QUIRK_GENERIC path for Gigabyte, GA-Z170X-Gaming G1 eziogale @ 2026-05-17 19:53 ` Takashi Iwai 2026-05-18 9:19 ` eziogale 2026-05-18 9:23 ` eziogale 0 siblings, 2 replies; 7+ messages in thread From: Takashi Iwai @ 2026-05-17 19:53 UTC (permalink / raw) To: eziogale@gmail.com; +Cc: Jaroslav Kysela `, linux-sound, alsa-devel On Sun, 17 May 2026 18:29:51 +0200, eziogale@gmail.com wrote: > > Some CA0132 implementations (e.g. Gigabyte GA-Z170X-Gaming G1) produce > white noise when using the DSP firmware path. > > Add a QUIRK_GENERIC path that uses the standard HDA generic parser > instead, with custom pin configs. > > This patch applies against v6.18.24. You seem to have put your Signed-off-by tag at a wrong place. It must be put here instead. The code change itself looks OK, but the indentation tabs and spaces seem incorrect. If it's not in your original code, it must be due to your mailer. Try to fix your mailer setup and resubmit. thanks, Takashi > --- > sound/hda/codecs/Kconfig | 1 + > sound/hda/codecs/ca0132.c | 111 +++++++++++++++++++++++++++++++++----- > 2 files changed, 99 insertions(+), 13 deletions(-) > > diff --git a/sound/hda/codecs/Kconfig b/sound/hda/codecs/Kconfig > index addbc94..dcf340e 100644 > --- a/sound/hda/codecs/Kconfig > +++ b/sound/hda/codecs/Kconfig > @@ -69,6 +69,7 @@ comment "Set to Y if you want auto-loading the codec > driver" > > config SND_HDA_CODEC_CA0132 > tristate "Build Creative CA0132 codec support" > + select SND_HDA_GENERIC > help > Say Y or M here to include Creative CA0132 codec support in > snd-hda-intel driver. > diff --git a/sound/hda/codecs/ca0132.c b/sound/hda/codecs/ca0132.c > index dd054ae..92fc93f 100644 > --- a/sound/hda/codecs/ca0132.c > +++ b/sound/hda/codecs/ca0132.c > @@ -24,6 +24,7 @@ > #include "hda_local.h" > #include "hda_auto_parser.h" > #include "hda_jack.h" > +#include "generic.h" > > #include "ca0132_regs.h" > > @@ -1060,6 +1061,8 @@ enum dsp_download_state { > */ > > struct ca0132_spec { > + struct hda_gen_spec gen; > + > const struct snd_kcontrol_new *mixers[5]; > unsigned int num_mixers; > const struct hda_verb *base_init_verbs; > @@ -1174,6 +1177,7 @@ enum { > QUIRK_R3D, > QUIRK_AE5, > QUIRK_AE7, > + QUIRK_GENERIC, > QUIRK_NONE = HDA_FIXUP_ID_NOT_SET, > }; > > @@ -1292,6 +1296,20 @@ static const struct hda_pintbl ae7_pincfgs[] = { > {} > }; > > +static const struct hda_pintbl ca0132_generic_pincfgs[] = { > + { 0x0b, 0x41014111 }, > + { 0x0c, 0x414520f0 }, /* SPDIF out */ > + { 0x0d, 0x01014010 }, /* lineout */ > + { 0x0e, 0x41c501f0 }, > + { 0x0f, 0x411111f0 }, /* disabled */ > + { 0x10, 0x411111f0 }, /* disabled */ > + { 0x11, 0x41012014 }, > + { 0x12, 0x37a790f0 }, /* mic */ > + { 0x13, 0x77a701f0 }, > + { 0x18, 0x500000f0 }, > + {} > +}; > + > static const struct hda_quirk ca0132_quirks[] = { > SND_PCI_QUIRK(0x1028, 0x057b, "Alienware M17x R4", > QUIRK_ALIENWARE_M17XR4), > SND_PCI_QUIRK(0x1028, 0x0685, "Alienware 15 2015", QUIRK_ALIENWARE), > @@ -1304,6 +1322,7 @@ static const struct hda_quirk ca0132_quirks[] = { > SND_PCI_QUIRK(0x1458, 0xA016, "Recon3Di", QUIRK_R3DI), > SND_PCI_QUIRK(0x1458, 0xA026, "Gigabyte G1.Sniper Z97", QUIRK_R3DI), > SND_PCI_QUIRK(0x1458, 0xA036, "Gigabyte GA-Z170X-Gaming 7", > QUIRK_R3DI), > + SND_PCI_QUIRK(0x1458, 0xA046, "Gigabyte GA-Z170X-Gaming G1", > QUIRK_GENERIC), > SND_PCI_QUIRK(0x3842, 0x1038, "EVGA X99 Classified", QUIRK_R3DI), > SND_PCI_QUIRK(0x3842, 0x104b, "EVGA X299 Dark", QUIRK_R3DI), > SND_PCI_QUIRK(0x3842, 0x1055, "EVGA Z390 DARK", QUIRK_R3DI), > @@ -1325,6 +1344,7 @@ static const struct hda_model_fixup > ca0132_quirk_models[] = { > { .id = QUIRK_R3D, .name = "r3d" }, > { .id = QUIRK_AE5, .name = "ae5" }, > { .id = QUIRK_AE7, .name = "ae7" }, > + { .id = QUIRK_GENERIC, .name = "generic" }, > {} > }; > > @@ -9882,14 +9902,57 @@ static void sbz_detect_quirk(struct hda_codec > *codec) > } > } > > +static void ca0132_generic_init_hook(struct hda_codec *codec) > +{ > + struct ca0132_spec *spec = codec->spec; > + > + snd_hda_sequence_write(codec, spec->spec_init_verbs); > +} > + > +static int ca0132_generic_probe(struct hda_codec *codec) > +{ > + struct ca0132_spec *spec = codec->spec; > + struct auto_pin_cfg *cfg = &spec->gen.autocfg; > + int err; > + > + snd_hda_gen_spec_init(&spec->gen); > + > + snd_hda_apply_pincfgs(codec, ca0132_generic_pincfgs); > + > + ca0132_init_chip(codec); > + > + err = ca0132_prepare_verbs(codec); > + if (err < 0) > + return err; > + > + err = snd_hda_parse_pin_def_config(codec, cfg, NULL); > + if (err < 0) > + return err; > + err = snd_hda_gen_parse_auto_config(codec, cfg); > + if (err < 0) > + return err; > + > + spec->gen.init_hook = ca0132_generic_init_hook; > + spec->gen.automute_speaker = 0; > + spec->gen.automute_lo = 0; > + > + snd_hda_sequence_write(codec, spec->spec_init_verbs); > + return 0; > +} > + > static void ca0132_codec_remove(struct hda_codec *codec) > { > struct ca0132_spec *spec = codec->spec; > > - if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO) > + switch (ca0132_quirk(spec)) { > + case QUIRK_GENERIC: > + snd_hda_gen_remove(codec); > + return; > + case QUIRK_ZXR_DBPRO: > return dbpro_free(codec); > - else > + default: > return ca0132_free(codec); > + } > } > > static int ca0132_codec_probe(struct hda_codec *codec, > @@ -9906,14 +9969,21 @@ static int ca0132_codec_probe(struct hda_codec > *codec, > codec->spec = spec; > spec->codec = codec; > > - /* Detect codec quirk */ > - snd_hda_pick_fixup(codec, ca0132_quirk_models, ca0132_quirks, NULL); > - if (ca0132_quirk(spec) == QUIRK_SBZ) > - sbz_detect_quirk(codec); > - > + /* These must be set before any path is taken */ > codec->pcm_format_first = 1; > codec->no_sticky_stream = 1; > > + /* Detect codec quirk */ > + snd_hda_pick_fixup(codec, ca0132_quirk_models, ca0132_quirks, NULL); > + switch (ca0132_quirk(spec)) { > + case QUIRK_SBZ: > + sbz_detect_quirk(codec); > + break; > + case QUIRK_GENERIC: > + return ca0132_generic_probe(codec); > + default: > + break; > + } > > spec->dsp_state = DSP_DOWNLOAD_INIT; > spec->num_mixers = 1; > @@ -10014,36 +10084,51 @@ static int > ca0132_codec_build_controls(struct hda_codec *codec) > { > struct ca0132_spec *spec = codec->spec; > > - if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO) > + switch (ca0132_quirk(spec)) { > + case QUIRK_GENERIC: > + return snd_hda_gen_build_controls(codec); > + case QUIRK_ZXR_DBPRO: > return dbpro_build_controls(codec); > - else > + default: > return ca0132_build_controls(codec); > + } > } > > static int ca0132_codec_build_pcms(struct hda_codec *codec) > { > struct ca0132_spec *spec = codec->spec; > > - if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO) > + switch (ca0132_quirk(spec)) { > + case QUIRK_GENERIC: > + return snd_hda_gen_build_pcms(codec); > + case QUIRK_ZXR_DBPRO: > return dbpro_build_pcms(codec); > - else > + default: > return ca0132_build_pcms(codec); > + } > } > > static int ca0132_codec_init(struct hda_codec *codec) > { > struct ca0132_spec *spec = codec->spec; > > - if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO) > + switch (ca0132_quirk(spec)) { > + case QUIRK_GENERIC: > + return snd_hda_gen_init(codec); > + case QUIRK_ZXR_DBPRO: > return dbpro_init(codec); > - else > + default: > return ca0132_init(codec); > + } > } > > static int ca0132_codec_suspend(struct hda_codec *codec) > { > struct ca0132_spec *spec = codec->spec; > > + if (ca0132_quirk(spec) == QUIRK_GENERIC) > + return 0; > + > cancel_delayed_work_sync(&spec->unsol_hp_work); > return 0; > } > -- > 2.54.0 > > Signed-off-by: Ezio Galeazzi <eziogale@gmail.com> > > ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH] ALSA: hda/ca0132: add QUIRK_GENERIC path for Gigabyte, GA-Z170X-Gaming G1 2026-05-17 19:53 ` Takashi Iwai @ 2026-05-18 9:19 ` eziogale 2026-05-18 9:23 ` eziogale 1 sibling, 0 replies; 7+ messages in thread From: eziogale @ 2026-05-18 9:19 UTC (permalink / raw) To: Takashi Iwai; +Cc: Jaroslav Kysela `, linux-sound, alsa-devel Some CA0132 implementations (e.g. Gigabyte GA-Z170X-Gaming G1) produce white noise when using the DSP firmware path. Add a QUIRK_GENERIC path that uses the standard HDA generic parser instead, with custom pin configs. This patch applies against v6.18.24. Signed-off-by: Ezio Galeazzi <eziogale@gmail.com> --- sound/hda/codecs/Kconfig | 1 + sound/hda/codecs/ca0132.c | 111 +++++++++++++++++++++++++++++++++----- 2 files changed, 99 insertions(+), 13 deletions(-) diff --git a/sound/hda/codecs/Kconfig b/sound/hda/codecs/Kconfig index addbc94..dcf340e 100644 --- a/sound/hda/codecs/Kconfig +++ b/sound/hda/codecs/Kconfig @@ -69,6 +69,7 @@ comment "Set to Y if you want auto-loading the codec driver" config SND_HDA_CODEC_CA0132 tristate "Build Creative CA0132 codec support" + select SND_HDA_GENERIC help Say Y or M here to include Creative CA0132 codec support in snd-hda-intel driver. diff --git a/sound/hda/codecs/ca0132.c b/sound/hda/codecs/ca0132.c index dd054ae..92fc93f 100644 --- a/sound/hda/codecs/ca0132.c +++ b/sound/hda/codecs/ca0132.c @@ -24,6 +24,7 @@ #include "hda_local.h" #include "hda_auto_parser.h" #include "hda_jack.h" +#include "generic.h" #include "ca0132_regs.h" @@ -1060,6 +1061,8 @@ enum dsp_download_state { */ struct ca0132_spec { + struct hda_gen_spec gen; + const struct snd_kcontrol_new *mixers[5]; unsigned int num_mixers; const struct hda_verb *base_init_verbs; @@ -1174,6 +1177,7 @@ enum { QUIRK_R3D, QUIRK_AE5, QUIRK_AE7, + QUIRK_GENERIC, QUIRK_NONE = HDA_FIXUP_ID_NOT_SET, }; @@ -1292,6 +1296,20 @@ static const struct hda_pintbl ae7_pincfgs[] = { {} }; +static const struct hda_pintbl ca0132_generic_pincfgs[] = { + { 0x0b, 0x41014111 }, + { 0x0c, 0x414520f0 }, /* SPDIF out */ + { 0x0d, 0x01014010 }, /* lineout */ + { 0x0e, 0x41c501f0 }, + { 0x0f, 0x411111f0 }, /* disabled */ + { 0x10, 0x411111f0 }, /* disabled */ + { 0x11, 0x41012014 }, + { 0x12, 0x37a790f0 }, /* mic */ + { 0x13, 0x77a701f0 }, + { 0x18, 0x500000f0 }, + {} +}; + static const struct hda_quirk ca0132_quirks[] = { SND_PCI_QUIRK(0x1028, 0x057b, "Alienware M17x R4", QUIRK_ALIENWARE_M17XR4), SND_PCI_QUIRK(0x1028, 0x0685, "Alienware 15 2015", QUIRK_ALIENWARE), @@ -1304,6 +1322,7 @@ static const struct hda_quirk ca0132_quirks[] = { SND_PCI_QUIRK(0x1458, 0xA016, "Recon3Di", QUIRK_R3DI), SND_PCI_QUIRK(0x1458, 0xA026, "Gigabyte G1.Sniper Z97", QUIRK_R3DI), SND_PCI_QUIRK(0x1458, 0xA036, "Gigabyte GA-Z170X-Gaming 7", QUIRK_R3DI), + SND_PCI_QUIRK(0x1458, 0xA046, "Gigabyte GA-Z170X-Gaming G1", QUIRK_GENERIC), SND_PCI_QUIRK(0x3842, 0x1038, "EVGA X99 Classified", QUIRK_R3DI), SND_PCI_QUIRK(0x3842, 0x104b, "EVGA X299 Dark", QUIRK_R3DI), SND_PCI_QUIRK(0x3842, 0x1055, "EVGA Z390 DARK", QUIRK_R3DI), @@ -1325,6 +1344,7 @@ static const struct hda_model_fixup ca0132_quirk_models[] = { { .id = QUIRK_R3D, .name = "r3d" }, { .id = QUIRK_AE5, .name = "ae5" }, { .id = QUIRK_AE7, .name = "ae7" }, + { .id = QUIRK_GENERIC, .name = "generic" }, {} }; @@ -9882,14 +9902,57 @@ static void sbz_detect_quirk(struct hda_codec *codec) } } +static void ca0132_generic_init_hook(struct hda_codec *codec) +{ + struct ca0132_spec *spec = codec->spec; + + snd_hda_sequence_write(codec, spec->spec_init_verbs); +} + +static int ca0132_generic_probe(struct hda_codec *codec) +{ + struct ca0132_spec *spec = codec->spec; + struct auto_pin_cfg *cfg = &spec->gen.autocfg; + int err; + + snd_hda_gen_spec_init(&spec->gen); + + snd_hda_apply_pincfgs(codec, ca0132_generic_pincfgs); + + ca0132_init_chip(codec); + + err = ca0132_prepare_verbs(codec); + if (err < 0) + return err; + + err = snd_hda_parse_pin_def_config(codec, cfg, NULL); + if (err < 0) + return err; + err = snd_hda_gen_parse_auto_config(codec, cfg); + if (err < 0) + return err; + + spec->gen.init_hook = ca0132_generic_init_hook; + spec->gen.automute_speaker = 0; + spec->gen.automute_lo = 0; + + snd_hda_sequence_write(codec, spec->spec_init_verbs); + return 0; +} + static void ca0132_codec_remove(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; - if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO) + switch (ca0132_quirk(spec)) { + case QUIRK_GENERIC: + snd_hda_gen_remove(codec); + return; + case QUIRK_ZXR_DBPRO: return dbpro_free(codec); - else + default: return ca0132_free(codec); + } } static int ca0132_codec_probe(struct hda_codec *codec, @@ -9906,14 +9969,21 @@ static int ca0132_codec_probe(struct hda_codec *codec, codec->spec = spec; spec->codec = codec; - /* Detect codec quirk */ - snd_hda_pick_fixup(codec, ca0132_quirk_models, ca0132_quirks, NULL); - if (ca0132_quirk(spec) == QUIRK_SBZ) - sbz_detect_quirk(codec); - + /* These must be set before any path is taken */ codec->pcm_format_first = 1; codec->no_sticky_stream = 1; + /* Detect codec quirk */ + snd_hda_pick_fixup(codec, ca0132_quirk_models, ca0132_quirks, NULL); + switch (ca0132_quirk(spec)) { + case QUIRK_SBZ: + sbz_detect_quirk(codec); + break; + case QUIRK_GENERIC: + return ca0132_generic_probe(codec); + default: + break; + } spec->dsp_state = DSP_DOWNLOAD_INIT; spec->num_mixers = 1; @@ -10014,36 +10084,51 @@ static int ca0132_codec_build_controls(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; - if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO) + switch (ca0132_quirk(spec)) { + case QUIRK_GENERIC: + return snd_hda_gen_build_controls(codec); + case QUIRK_ZXR_DBPRO: return dbpro_build_controls(codec); - else + default: return ca0132_build_controls(codec); + } } static int ca0132_codec_build_pcms(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; - if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO) + switch (ca0132_quirk(spec)) { + case QUIRK_GENERIC: + return snd_hda_gen_build_pcms(codec); + case QUIRK_ZXR_DBPRO: return dbpro_build_pcms(codec); - else + default: return ca0132_build_pcms(codec); + } } static int ca0132_codec_init(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; - if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO) + switch (ca0132_quirk(spec)) { + case QUIRK_GENERIC: + return snd_hda_gen_init(codec); + case QUIRK_ZXR_DBPRO: return dbpro_init(codec); - else + default: return ca0132_init(codec); + } } static int ca0132_codec_suspend(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; + if (ca0132_quirk(spec) == QUIRK_GENERIC) + return 0; + cancel_delayed_work_sync(&spec->unsol_hp_work); return 0; } -- 2.54.0 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH] ALSA: hda/ca0132: add QUIRK_GENERIC path for Gigabyte, GA-Z170X-Gaming G1 2026-05-17 19:53 ` Takashi Iwai 2026-05-18 9:19 ` eziogale @ 2026-05-18 9:23 ` eziogale 2026-05-19 5:35 ` Takashi Iwai 1 sibling, 1 reply; 7+ messages in thread From: eziogale @ 2026-05-18 9:23 UTC (permalink / raw) To: Takashi Iwai; +Cc: Jaroslav Kysela `, linux-sound, alsa-devel [-- Attachment #1: Type: text/plain, Size: 106 bytes --] Sorry, with gmail and OAUTH2 it's a bit complicated. I'v to make an attachmant. Tanks for the patience. [-- Attachment #2: 0001-ALSA-hda-ca0132-add-QUIRK_GENERIC-path-for-Gigabyte-GA-Z170X-Gaming-G1-2.patch --] [-- Type: text/plain, Size: 6771 bytes --] From 6411be653404246e661d6bcf418345abf866e098 Mon Sep 17 00:00:00 2001 From: Ezio Galeazzi <eziogale@gmail.com> Date: Sun, 17 May 2026 17:42:36 +0200 Subject: [PATCH] ALSA: hda/ca0132: add QUIRK_GENERIC path for Gigabyte GA-Z170X-Gaming G1 Some CA0132 implementations (e.g. Gigabyte GA-Z170X-Gaming G1) produce white noise when using the DSP firmware path. Add a QUIRK_GENERIC path that uses the standard HDA generic parser instead, with custom pin configs. This patch applies against v6.18.24. Signed-off-by: Ezio Galeazzi <eziogale@gmail.com> --- sound/hda/codecs/Kconfig | 1 + sound/hda/codecs/ca0132.c | 111 +++++++++++++++++++++++++++++++++----- 2 files changed, 99 insertions(+), 13 deletions(-) diff --git a/sound/hda/codecs/Kconfig b/sound/hda/codecs/Kconfig index addbc94..dcf340e 100644 --- a/sound/hda/codecs/Kconfig +++ b/sound/hda/codecs/Kconfig @@ -69,6 +69,7 @@ comment "Set to Y if you want auto-loading the codec driver" config SND_HDA_CODEC_CA0132 tristate "Build Creative CA0132 codec support" + select SND_HDA_GENERIC help Say Y or M here to include Creative CA0132 codec support in snd-hda-intel driver. diff --git a/sound/hda/codecs/ca0132.c b/sound/hda/codecs/ca0132.c index dd054ae..92fc93f 100644 --- a/sound/hda/codecs/ca0132.c +++ b/sound/hda/codecs/ca0132.c @@ -24,6 +24,7 @@ #include "hda_local.h" #include "hda_auto_parser.h" #include "hda_jack.h" +#include "generic.h" #include "ca0132_regs.h" @@ -1060,6 +1061,8 @@ enum dsp_download_state { */ struct ca0132_spec { + struct hda_gen_spec gen; + const struct snd_kcontrol_new *mixers[5]; unsigned int num_mixers; const struct hda_verb *base_init_verbs; @@ -1174,6 +1177,7 @@ enum { QUIRK_R3D, QUIRK_AE5, QUIRK_AE7, + QUIRK_GENERIC, QUIRK_NONE = HDA_FIXUP_ID_NOT_SET, }; @@ -1292,6 +1296,20 @@ static const struct hda_pintbl ae7_pincfgs[] = { {} }; +static const struct hda_pintbl ca0132_generic_pincfgs[] = { + { 0x0b, 0x41014111 }, + { 0x0c, 0x414520f0 }, /* SPDIF out */ + { 0x0d, 0x01014010 }, /* lineout */ + { 0x0e, 0x41c501f0 }, + { 0x0f, 0x411111f0 }, /* disabled */ + { 0x10, 0x411111f0 }, /* disabled */ + { 0x11, 0x41012014 }, + { 0x12, 0x37a790f0 }, /* mic */ + { 0x13, 0x77a701f0 }, + { 0x18, 0x500000f0 }, + {} +}; + static const struct hda_quirk ca0132_quirks[] = { SND_PCI_QUIRK(0x1028, 0x057b, "Alienware M17x R4", QUIRK_ALIENWARE_M17XR4), SND_PCI_QUIRK(0x1028, 0x0685, "Alienware 15 2015", QUIRK_ALIENWARE), @@ -1304,6 +1322,7 @@ static const struct hda_quirk ca0132_quirks[] = { SND_PCI_QUIRK(0x1458, 0xA016, "Recon3Di", QUIRK_R3DI), SND_PCI_QUIRK(0x1458, 0xA026, "Gigabyte G1.Sniper Z97", QUIRK_R3DI), SND_PCI_QUIRK(0x1458, 0xA036, "Gigabyte GA-Z170X-Gaming 7", QUIRK_R3DI), + SND_PCI_QUIRK(0x1458, 0xA046, "Gigabyte GA-Z170X-Gaming G1", QUIRK_GENERIC), SND_PCI_QUIRK(0x3842, 0x1038, "EVGA X99 Classified", QUIRK_R3DI), SND_PCI_QUIRK(0x3842, 0x104b, "EVGA X299 Dark", QUIRK_R3DI), SND_PCI_QUIRK(0x3842, 0x1055, "EVGA Z390 DARK", QUIRK_R3DI), @@ -1325,6 +1344,7 @@ static const struct hda_model_fixup ca0132_quirk_models[] = { { .id = QUIRK_R3D, .name = "r3d" }, { .id = QUIRK_AE5, .name = "ae5" }, { .id = QUIRK_AE7, .name = "ae7" }, + { .id = QUIRK_GENERIC, .name = "generic" }, {} }; @@ -9882,14 +9902,57 @@ static void sbz_detect_quirk(struct hda_codec *codec) } } +static void ca0132_generic_init_hook(struct hda_codec *codec) +{ + struct ca0132_spec *spec = codec->spec; + + snd_hda_sequence_write(codec, spec->spec_init_verbs); +} + +static int ca0132_generic_probe(struct hda_codec *codec) +{ + struct ca0132_spec *spec = codec->spec; + struct auto_pin_cfg *cfg = &spec->gen.autocfg; + int err; + + snd_hda_gen_spec_init(&spec->gen); + + snd_hda_apply_pincfgs(codec, ca0132_generic_pincfgs); + + ca0132_init_chip(codec); + + err = ca0132_prepare_verbs(codec); + if (err < 0) + return err; + + err = snd_hda_parse_pin_def_config(codec, cfg, NULL); + if (err < 0) + return err; + err = snd_hda_gen_parse_auto_config(codec, cfg); + if (err < 0) + return err; + + spec->gen.init_hook = ca0132_generic_init_hook; + spec->gen.automute_speaker = 0; + spec->gen.automute_lo = 0; + + snd_hda_sequence_write(codec, spec->spec_init_verbs); + return 0; +} + static void ca0132_codec_remove(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; - if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO) + switch (ca0132_quirk(spec)) { + case QUIRK_GENERIC: + snd_hda_gen_remove(codec); + return; + case QUIRK_ZXR_DBPRO: return dbpro_free(codec); - else + default: return ca0132_free(codec); + } } static int ca0132_codec_probe(struct hda_codec *codec, @@ -9906,14 +9969,21 @@ static int ca0132_codec_probe(struct hda_codec *codec, codec->spec = spec; spec->codec = codec; - /* Detect codec quirk */ - snd_hda_pick_fixup(codec, ca0132_quirk_models, ca0132_quirks, NULL); - if (ca0132_quirk(spec) == QUIRK_SBZ) - sbz_detect_quirk(codec); - + /* These must be set before any path is taken */ codec->pcm_format_first = 1; codec->no_sticky_stream = 1; + /* Detect codec quirk */ + snd_hda_pick_fixup(codec, ca0132_quirk_models, ca0132_quirks, NULL); + switch (ca0132_quirk(spec)) { + case QUIRK_SBZ: + sbz_detect_quirk(codec); + break; + case QUIRK_GENERIC: + return ca0132_generic_probe(codec); + default: + break; + } spec->dsp_state = DSP_DOWNLOAD_INIT; spec->num_mixers = 1; @@ -10014,36 +10084,51 @@ static int ca0132_codec_build_controls(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; - if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO) + switch (ca0132_quirk(spec)) { + case QUIRK_GENERIC: + return snd_hda_gen_build_controls(codec); + case QUIRK_ZXR_DBPRO: return dbpro_build_controls(codec); - else + default: return ca0132_build_controls(codec); + } } static int ca0132_codec_build_pcms(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; - if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO) + switch (ca0132_quirk(spec)) { + case QUIRK_GENERIC: + return snd_hda_gen_build_pcms(codec); + case QUIRK_ZXR_DBPRO: return dbpro_build_pcms(codec); - else + default: return ca0132_build_pcms(codec); + } } static int ca0132_codec_init(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; - if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO) + switch (ca0132_quirk(spec)) { + case QUIRK_GENERIC: + return snd_hda_gen_init(codec); + case QUIRK_ZXR_DBPRO: return dbpro_init(codec); - else + default: return ca0132_init(codec); + } } static int ca0132_codec_suspend(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; + if (ca0132_quirk(spec) == QUIRK_GENERIC) + return 0; + cancel_delayed_work_sync(&spec->unsol_hp_work); return 0; } -- 2.54.0 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH] ALSA: hda/ca0132: add QUIRK_GENERIC path for Gigabyte, GA-Z170X-Gaming G1 2026-05-18 9:23 ` eziogale @ 2026-05-19 5:35 ` Takashi Iwai 0 siblings, 0 replies; 7+ messages in thread From: Takashi Iwai @ 2026-05-19 5:35 UTC (permalink / raw) To: eziogale@gmail.com; +Cc: Jaroslav Kysela `, linux-sound, alsa-devel On Mon, 18 May 2026 11:23:25 +0200, eziogale@gmail.com wrote: > > Sorry, with gmail and OAUTH2 it's a bit complicated. I'v to make an > attachmant. > Tanks for the patience. > > From 6411be653404246e661d6bcf418345abf866e098 Mon Sep 17 00:00:00 2001 > From: Ezio Galeazzi <eziogale@gmail.com> > Date: Sun, 17 May 2026 17:42:36 +0200 > Subject: [PATCH] ALSA: hda/ca0132: add QUIRK_GENERIC path for Gigabyte > GA-Z170X-Gaming G1 > > Some CA0132 implementations (e.g. Gigabyte GA-Z170X-Gaming G1) produce white noise when using the DSP firmware path. Add a QUIRK_GENERIC path that uses the standard HDA generic parser instead, with custom pin configs. > This patch applies against v6.18.24. > > Signed-off-by: Ezio Galeazzi <eziogale@gmail.com> Thanks, applied to for-next branch now. Takashi ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-05-19 5:35 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-05-10 9:38 ca0132: add generic parser fallback for broken DSP path eziogale 2026-05-16 13:41 ` Takashi Iwai 2026-05-17 16:29 ` [PATCH] ALSA: hda/ca0132: add QUIRK_GENERIC path for Gigabyte, GA-Z170X-Gaming G1 eziogale 2026-05-17 19:53 ` Takashi Iwai 2026-05-18 9:19 ` eziogale 2026-05-18 9:23 ` eziogale 2026-05-19 5:35 ` Takashi Iwai
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.