mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 10:09:10 +02:00
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> Link: https://lore.kernel.org/0c0b781f-1595-4595-921a-66d83cf5930b@gmail.com Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
456ad3cdaf
commit
e79615b05c
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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" },
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
@ -9879,14 +9899,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,
|
||||
|
|
@ -9903,14 +9966,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;
|
||||
|
|
@ -10011,36 +10081,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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user