Linux Sound subsystem development
 help / color / mirror / Atom feed
From: "eziogale@gmail.com" <eziogale@gmail.com>
To: Takashi Iwai <tiwai@suse.de>
Cc: Jaroslav Kysela ` <perex@perex.cz>,
	linux-sound@vger.kernel.org, alsa-devel@alsa-project.org
Subject: [PATCH] ALSA: hda/ca0132: add QUIRK_GENERIC path for Gigabyte, GA-Z170X-Gaming G1
Date: Sun, 17 May 2026 18:29:51 +0200	[thread overview]
Message-ID: <2f45fd6e-0a5b-4f47-9f2b-75d8b323ced8@gmail.com> (raw)
In-Reply-To: <87tss7xyj5.wl-tiwai@suse.de>

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>


  reply	other threads:[~2026-05-17 16:29 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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   ` eziogale [this message]
2026-05-17 19:53     ` [PATCH] ALSA: hda/ca0132: add QUIRK_GENERIC path for Gigabyte, GA-Z170X-Gaming G1 Takashi Iwai
2026-05-18  9:19       ` eziogale
2026-05-18  9:23       ` eziogale
2026-05-19  5:35         ` Takashi Iwai

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=2f45fd6e-0a5b-4f47-9f2b-75d8b323ced8@gmail.com \
    --to=eziogale@gmail.com \
    --cc=alsa-devel@alsa-project.org \
    --cc=linux-sound@vger.kernel.org \
    --cc=perex@perex.cz \
    --cc=tiwai@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox