summaryrefslogtreecommitdiff
path: root/sound/pci
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci')
-rw-r--r--sound/pci/Kconfig2
-rw-r--r--sound/pci/Makefile1
-rw-r--r--sound/pci/ac97/ac97_codec.c23
-rw-r--r--sound/pci/ac97/ac97_local.h2
-rw-r--r--sound/pci/ac97/ac97_patch.c8
-rw-r--r--sound/pci/ac97/ac97_proc.c2
-rw-r--r--sound/pci/ad1889.c6
-rw-r--r--sound/pci/ak4531_codec.c2
-rw-r--r--sound/pci/ali5451/ali5451.c6
-rw-r--r--sound/pci/als300.c4
-rw-r--r--sound/pci/als4000.c4
-rw-r--r--sound/pci/asihpi/asihpi.c10
-rw-r--r--sound/pci/asihpi/hpi6000.c2
-rw-r--r--sound/pci/atiixp.c10
-rw-r--r--sound/pci/atiixp_modem.c6
-rw-r--r--sound/pci/au88x0/au88x0.c4
-rw-r--r--sound/pci/au88x0/au88x0_mixer.c2
-rw-r--r--sound/pci/aw2/aw2-alsa.c10
-rw-r--r--sound/pci/azt3328.c12
-rw-r--r--sound/pci/bt87x.c6
-rw-r--r--sound/pci/ca0106/ca0106_main.c6
-rw-r--r--sound/pci/ca0106/ca0106_mixer.c4
-rw-r--r--sound/pci/ca0106/ca_midi.c2
-rw-r--r--sound/pci/cmipci.c25
-rw-r--r--sound/pci/cs4281.c8
-rw-r--r--sound/pci/cs46xx/cs46xx.c4
-rw-r--r--sound/pci/cs46xx/cs46xx_lib.c20
-rw-r--r--sound/pci/cs46xx/dsp_spos.c8
-rw-r--r--sound/pci/cs5530.c4
-rw-r--r--sound/pci/cs5535audio/cs5535audio.c4
-rw-r--r--sound/pci/cs5535audio/cs5535audio_pcm.c2
-rw-r--r--sound/pci/ctxfi/ctmixer.c2
-rw-r--r--sound/pci/echoaudio/echoaudio.c13
-rw-r--r--sound/pci/echoaudio/midi.c2
-rw-r--r--sound/pci/emu10k1/emu10k1.c3
-rw-r--r--sound/pci/emu10k1/emu10k1x.c13
-rw-r--r--sound/pci/emu10k1/emufx.c23
-rw-r--r--sound/pci/emu10k1/emumixer.c9
-rw-r--r--sound/pci/emu10k1/emumpu401.c2
-rw-r--r--sound/pci/emu10k1/emupcm.c10
-rw-r--r--sound/pci/emu10k1/p16v.c2
-rw-r--r--sound/pci/emu10k1/timer.c2
-rw-r--r--sound/pci/ens1370.c10
-rw-r--r--sound/pci/es1938.c8
-rw-r--r--sound/pci/es1968.c14
-rw-r--r--sound/pci/fm801.c6
-rw-r--r--sound/pci/hda/Kconfig436
-rw-r--r--sound/pci/hda/Makefile84
-rw-r--r--sound/pci/hda/ca0132_regs.h396
-rw-r--r--sound/pci/hda/cirrus_scodec.c73
-rw-r--r--sound/pci/hda/cirrus_scodec.h13
-rw-r--r--sound/pci/hda/cirrus_scodec_test.c332
-rw-r--r--sound/pci/hda/cs35l41_hda.c2087
-rw-r--r--sound/pci/hda/cs35l41_hda.h109
-rw-r--r--sound/pci/hda/cs35l41_hda_i2c.c69
-rw-r--r--sound/pci/hda/cs35l41_hda_property.c578
-rw-r--r--sound/pci/hda/cs35l41_hda_property.h18
-rw-r--r--sound/pci/hda/cs35l41_hda_spi.c64
-rw-r--r--sound/pci/hda/cs35l56_hda.c1124
-rw-r--r--sound/pci/hda/cs35l56_hda.h50
-rw-r--r--sound/pci/hda/cs35l56_hda_i2c.c87
-rw-r--r--sound/pci/hda/cs35l56_hda_spi.c90
-rw-r--r--sound/pci/hda/hda_acpi.c325
-rw-r--r--sound/pci/hda/hda_auto_parser.c1104
-rw-r--r--sound/pci/hda/hda_auto_parser.h118
-rw-r--r--sound/pci/hda/hda_beep.c345
-rw-r--r--sound/pci/hda/hda_beep.h46
-rw-r--r--sound/pci/hda/hda_bind.c343
-rw-r--r--sound/pci/hda/hda_codec.c4060
-rw-r--r--sound/pci/hda/hda_component.c212
-rw-r--r--sound/pci/hda/hda_component.h103
-rw-r--r--sound/pci/hda/hda_controller.c1336
-rw-r--r--sound/pci/hda/hda_controller.h215
-rw-r--r--sound/pci/hda/hda_controller_trace.h99
-rw-r--r--sound/pci/hda/hda_eld.c402
-rw-r--r--sound/pci/hda/hda_generic.c6159
-rw-r--r--sound/pci/hda/hda_generic.h357
-rw-r--r--sound/pci/hda/hda_hwdep.c119
-rw-r--r--sound/pci/hda/hda_intel.c2835
-rw-r--r--sound/pci/hda/hda_intel.h38
-rw-r--r--sound/pci/hda/hda_intel_trace.h52
-rw-r--r--sound/pci/hda/hda_jack.c770
-rw-r--r--sound/pci/hda/hda_jack.h195
-rw-r--r--sound/pci/hda/hda_local.h720
-rw-r--r--sound/pci/hda/hda_proc.c948
-rw-r--r--sound/pci/hda/hda_sysfs.c792
-rw-r--r--sound/pci/hda/hda_tegra.c652
-rw-r--r--sound/pci/hda/hp_x360_helper.c95
-rw-r--r--sound/pci/hda/ideapad_hotkey_led_helper.c36
-rw-r--r--sound/pci/hda/ideapad_s740_helper.c492
-rw-r--r--sound/pci/hda/patch_analog.c1176
-rw-r--r--sound/pci/hda/patch_ca0110.c88
-rw-r--r--sound/pci/hda/patch_ca0132.c10123
-rw-r--r--sound/pci/hda/patch_cirrus.c1243
-rw-r--r--sound/pci/hda/patch_cmedia.c396
-rw-r--r--sound/pci/hda/patch_conexant.c1331
-rw-r--r--sound/pci/hda/patch_cs8409-tables.c623
-rw-r--r--sound/pci/hda/patch_cs8409.c1484
-rw-r--r--sound/pci/hda/patch_cs8409.h375
-rw-r--r--sound/pci/hda/patch_hdmi.c4676
-rw-r--r--sound/pci/hda/patch_realtek.c13756
-rw-r--r--sound/pci/hda/patch_senarytech.c244
-rw-r--r--sound/pci/hda/patch_si3054.c304
-rw-r--r--sound/pci/hda/patch_sigmatel.c5161
-rw-r--r--sound/pci/hda/patch_via.c1247
-rw-r--r--sound/pci/hda/tas2781_hda.c377
-rw-r--r--sound/pci/hda/tas2781_hda.h90
-rw-r--r--sound/pci/hda/tas2781_hda_i2c.c747
-rw-r--r--sound/pci/hda/tas2781_hda_spi.c958
-rw-r--r--sound/pci/hda/thinkpad_helper.c36
-rw-r--r--sound/pci/ice1712/ice1712.c14
-rw-r--r--sound/pci/ice1712/ice1724.c18
-rw-r--r--sound/pci/intel8x0.c16
-rw-r--r--sound/pci/intel8x0m.c10
-rw-r--r--sound/pci/korg1212/korg1212.c6
-rw-r--r--sound/pci/lola/lola.c4
-rw-r--r--sound/pci/lx6464es/lx6464es.c4
-rw-r--r--sound/pci/maestro3.c8
-rw-r--r--sound/pci/mixart/mixart.c6
-rw-r--r--sound/pci/nm256/nm256.c6
-rw-r--r--sound/pci/oxygen/oxygen_lib.c6
-rw-r--r--sound/pci/oxygen/oxygen_pcm.c8
-rw-r--r--sound/pci/pcxhr/pcxhr.c4
-rw-r--r--sound/pci/riptide/riptide.c6
-rw-r--r--sound/pci/rme32.c12
-rw-r--r--sound/pci/rme96.c16
-rw-r--r--sound/pci/rme9652/hdsp.c12
-rw-r--r--sound/pci/rme9652/hdspm.c8
-rw-r--r--sound/pci/rme9652/rme9652.c12
-rw-r--r--sound/pci/sis7019.c6
-rw-r--r--sound/pci/sonicvibes.c8
-rw-r--r--sound/pci/trident/trident.c6
-rw-r--r--sound/pci/trident/trident_main.c14
-rw-r--r--sound/pci/via82xx.c20
-rw-r--r--sound/pci/via82xx_modem.c4
-rw-r--r--sound/pci/ymfpci/ymfpci.c2
-rw-r--r--sound/pci/ymfpci/ymfpci_main.c8
137 files changed, 289 insertions, 73296 deletions
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 787868c9e91b..e0996a9d90b0 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -933,5 +933,3 @@ config SND_YMFPCI
will be called snd-ymfpci.
endif # SND_PCI
-
-source "sound/pci/hda/Kconfig"
diff --git a/sound/pci/Makefile b/sound/pci/Makefile
index 18b673018dfd..9d5e8e12ae73 100644
--- a/sound/pci/Makefile
+++ b/sound/pci/Makefile
@@ -69,7 +69,6 @@ obj-$(CONFIG_SND) += \
lx6464es/ \
echoaudio/ \
emu10k1/ \
- hda/ \
ice1712/ \
korg1212/ \
mixart/ \
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index 88ac37739b76..cd60c856a92e 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -1840,7 +1840,8 @@ static const struct ac97_codec_id *look_for_codec_id(const struct ac97_codec_id
return NULL;
}
-void snd_ac97_get_name(struct snd_ac97 *ac97, unsigned int id, char *name, int modem)
+void snd_ac97_get_name(struct snd_ac97 *ac97, unsigned int id, char *name,
+ size_t maxlen, int modem)
{
const struct ac97_codec_id *pid;
@@ -1852,7 +1853,7 @@ void snd_ac97_get_name(struct snd_ac97 *ac97, unsigned int id, char *name, int m
if (! pid)
return;
- strcpy(name, pid->name);
+ strscpy(name, pid->name, maxlen);
if (ac97 && pid->patch) {
if ((modem && (pid->flags & AC97_MODEM_PATCH)) ||
(! modem && ! (pid->flags & AC97_MODEM_PATCH)))
@@ -1861,8 +1862,8 @@ void snd_ac97_get_name(struct snd_ac97 *ac97, unsigned int id, char *name, int m
pid = look_for_codec_id(snd_ac97_codec_ids, id);
if (pid) {
- strcat(name, " ");
- strcat(name, pid->name);
+ strlcat(name, " ", maxlen);
+ strlcat(name, pid->name, maxlen);
if (pid->mask != 0xffffffff)
sprintf(name + strlen(name), " rev %u", id & ~pid->mask);
if (ac97 && pid->patch) {
@@ -1870,8 +1871,10 @@ void snd_ac97_get_name(struct snd_ac97 *ac97, unsigned int id, char *name, int m
(! modem && ! (pid->flags & AC97_MODEM_PATCH)))
pid->patch(ac97);
}
- } else
- sprintf(name + strlen(name), " id %x", id & 0xff);
+ } else {
+ int l = strlen(name);
+ snprintf(name + l, maxlen - l, " id %x", id & 0xff);
+ }
}
/**
@@ -2295,15 +2298,15 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template,
/* additional initializations */
if (bus->ops->init)
bus->ops->init(ac97);
- snd_ac97_get_name(ac97, ac97->id, name, !ac97_is_audio(ac97));
- snd_ac97_get_name(NULL, ac97->id, name, !ac97_is_audio(ac97)); // ac97->id might be changed in the special setup code
+ snd_ac97_get_name(ac97, ac97->id, name, sizeof(name), !ac97_is_audio(ac97));
+ snd_ac97_get_name(NULL, ac97->id, name, sizeof(name), !ac97_is_audio(ac97)); // ac97->id might be changed in the special setup code
if (! ac97->build_ops)
ac97->build_ops = &null_build_ops;
if (ac97_is_audio(ac97)) {
char comp[16];
if (card->mixername[0] == '\0') {
- strcpy(card->mixername, name);
+ strscpy(card->mixername, name);
} else {
if (strlen(card->mixername) + 1 + strlen(name) + 1 <= sizeof(card->mixername)) {
strcat(card->mixername, ",");
@@ -2324,7 +2327,7 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template,
if (ac97_is_modem(ac97)) {
char comp[16];
if (card->mixername[0] == '\0') {
- strcpy(card->mixername, name);
+ strscpy(card->mixername, name);
} else {
if (strlen(card->mixername) + 1 + strlen(name) + 1 <= sizeof(card->mixername)) {
strcat(card->mixername, ",");
diff --git a/sound/pci/ac97/ac97_local.h b/sound/pci/ac97/ac97_local.h
index 8eeae2dec552..965284eb4b33 100644
--- a/sound/pci/ac97/ac97_local.h
+++ b/sound/pci/ac97/ac97_local.h
@@ -8,7 +8,7 @@
*/
void snd_ac97_get_name(struct snd_ac97 *ac97, unsigned int id, char *name,
- int modem);
+ size_t maxlen, int modem);
int snd_ac97_update_bits_nolock(struct snd_ac97 *ac97, unsigned short reg,
unsigned short mask, unsigned short value);
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
index cd83aa864ea3..3002be9d88f3 100644
--- a/sound/pci/ac97/ac97_patch.c
+++ b/sound/pci/ac97/ac97_patch.c
@@ -298,7 +298,7 @@ static int patch_yamaha_ymf7x3_3d(struct snd_ac97 *ac97)
err = snd_ctl_add(ac97->bus->card, kctl);
if (err < 0)
return err;
- strcpy(kctl->id.name, "3D Control - Wide");
+ strscpy(kctl->id.name, "3D Control - Wide");
kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 9, 7, 0);
snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
err = snd_ctl_add(ac97->bus->card,
@@ -891,7 +891,7 @@ static int patch_sigmatel_stac9700_3d(struct snd_ac97 * ac97)
err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97));
if (err < 0)
return err;
- strcpy(kctl->id.name, "3D Control Sigmatel - Depth");
+ strscpy(kctl->id.name, "3D Control Sigmatel - Depth");
kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 2, 3, 0);
snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
return 0;
@@ -906,13 +906,13 @@ static int patch_sigmatel_stac9708_3d(struct snd_ac97 * ac97)
err = snd_ctl_add(ac97->bus->card, kctl);
if (err < 0)
return err;
- strcpy(kctl->id.name, "3D Control Sigmatel - Depth");
+ strscpy(kctl->id.name, "3D Control Sigmatel - Depth");
kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 0, 3, 0);
kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97);
err = snd_ctl_add(ac97->bus->card, kctl);
if (err < 0)
return err;
- strcpy(kctl->id.name, "3D Control Sigmatel - Rear Depth");
+ strscpy(kctl->id.name, "3D Control Sigmatel - Rear Depth");
kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 2, 3, 0);
snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
return 0;
diff --git a/sound/pci/ac97/ac97_proc.c b/sound/pci/ac97/ac97_proc.c
index 518834964b7b..2df3ba9a08dc 100644
--- a/sound/pci/ac97/ac97_proc.c
+++ b/sound/pci/ac97/ac97_proc.c
@@ -98,7 +98,7 @@ static void snd_ac97_proc_read_main(struct snd_ac97 *ac97, struct snd_info_buffe
static const char *spdif_rates_cs4205[4] = { " Rate=48kHz", " Rate=44.1kHz", " Rate=res", " Rate=res" };
static const char *double_rate_slots[4] = { "10/11", "7/8", "reserved", "reserved" };
- snd_ac97_get_name(NULL, ac97->id, name, 0);
+ snd_ac97_get_name(NULL, ac97->id, name, sizeof(name), 0);
snd_iprintf(buffer, "%d-%d/%d: %s\n\n", ac97->addr, ac97->num, subidx, name);
if ((ac97->scaps & AC97_SCAP_AUDIO) == 0)
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c
index ac27a93ce4ff..020cbb467e7e 100644
--- a/sound/pci/ad1889.c
+++ b/sound/pci/ad1889.c
@@ -605,7 +605,7 @@ snd_ad1889_pcm_init(struct snd_ad1889 *chip, int device)
pcm->private_data = chip;
pcm->info_flags = 0;
- strcpy(pcm->name, chip->card->shortname);
+ strscpy(pcm->name, chip->card->shortname);
chip->pcm = pcm;
chip->psubs = NULL;
@@ -866,8 +866,8 @@ __snd_ad1889_probe(struct pci_dev *pci,
return err;
chip = card->private_data;
- strcpy(card->driver, "AD1889");
- strcpy(card->shortname, "Analog Devices AD1889");
+ strscpy(card->driver, "AD1889");
+ strscpy(card->shortname, "Analog Devices AD1889");
/* (3) */
err = snd_ad1889_create(card, pci);
diff --git a/sound/pci/ak4531_codec.c b/sound/pci/ak4531_codec.c
index 6af88e7b86f8..e54812bfb2c6 100644
--- a/sound/pci/ak4531_codec.c
+++ b/sound/pci/ak4531_codec.c
@@ -389,7 +389,7 @@ int snd_ak4531_mixer(struct snd_card *card,
snd_ak4531_free(ak4531);
return err;
}
- strcpy(card->mixername, "Asahi Kasei AK4531");
+ strscpy(card->mixername, "Asahi Kasei AK4531");
ak4531->write(ak4531, AK4531_RESET, 0x03); /* no RST, PD */
udelay(100);
ak4531->write(ak4531, AK4531_CLOCK, 0x00); /* CODEC ADC and CODEC DAC use {LR,B}CLK2 and run off LRCLK2 PLL */
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index 69c02bdd38ce..a6e499e0ceda 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -1645,7 +1645,7 @@ static int snd_ali_pcm(struct snd_ali *codec, int device,
pcm->info_flags = 0;
pcm->dev_class = desc->class;
pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
- strcpy(pcm->name, desc->name);
+ strscpy(pcm->name, desc->name);
codec->pcm[0] = pcm;
return 0;
}
@@ -2133,8 +2133,8 @@ static int __snd_ali_probe(struct pci_dev *pci,
snd_ali_proc_init(codec);
- strcpy(card->driver, "ALI5451");
- strcpy(card->shortname, "ALI 5451");
+ strscpy(card->driver, "ALI5451");
+ strscpy(card->shortname, "ALI 5451");
sprintf(card->longname, "%s at 0x%lx, irq %i",
card->shortname, codec->port, codec->irq);
diff --git a/sound/pci/als300.c b/sound/pci/als300.c
index 43f98719e61b..f9e8424dc77f 100644
--- a/sound/pci/als300.c
+++ b/sound/pci/als300.c
@@ -546,7 +546,7 @@ static int snd_als300_new_pcm(struct snd_als300 *chip)
if (err < 0)
return err;
pcm->private_data = chip;
- strcpy(pcm->name, "ALS300");
+ strscpy(pcm->name, "ALS300");
chip->pcm = pcm;
/* set operators */
@@ -705,7 +705,7 @@ static int snd_als300_probe(struct pci_dev *pci,
if (err < 0)
goto error;
- strcpy(card->driver, "ALS300");
+ strscpy(card->driver, "ALS300");
if (chip->chip_type == DEVICE_ALS300_PLUS)
/* don't know much about ALS300+ yet
* print revision number for now */
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c
index 3f4f3037f71f..eb159497c905 100644
--- a/sound/pci/als4000.c
+++ b/sound/pci/als4000.c
@@ -877,8 +877,8 @@ static int __snd_card_als4000_probe(struct pci_dev *pci,
snd_als4000_configure(chip);
- strcpy(card->driver, "ALS4000");
- strcpy(card->shortname, "Avance Logic ALS4000");
+ strscpy(card->driver, "ALS4000");
+ strscpy(card->shortname, "Avance Logic ALS4000");
sprintf(card->longname, "%s at 0x%lx, irq %i",
card->shortname, chip->alt_port, chip->irq);
diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c
index cbd964f87349..8419f2b6e589 100644
--- a/sound/pci/asihpi/asihpi.c
+++ b/sound/pci/asihpi/asihpi.c
@@ -1257,7 +1257,7 @@ static int snd_card_asihpi_pcm_new(struct snd_card_asihpi *asihpi, int device)
pcm->private_data = asihpi;
pcm->info_flags = 0;
- strcpy(pcm->name, "Asihpi PCM");
+ strscpy(pcm->name, "Asihpi PCM");
/*? do we want to emulate MMAP for non-BBM cards?
Jack doesn't work with ALSAs MMAP emulation - WHY NOT? */
@@ -2310,7 +2310,7 @@ static int snd_asihpi_clksrc_info(struct snd_kcontrol *kcontrol,
uinfo->value.enumerated.item =
uinfo->value.enumerated.items - 1;
- strcpy(uinfo->value.enumerated.name,
+ strscpy(uinfo->value.enumerated.name,
clkcache->s[uinfo->value.enumerated.item].name);
return 0;
}
@@ -2530,7 +2530,7 @@ static int snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi)
if (snd_BUG_ON(!asihpi))
return -EINVAL;
card = asihpi->card;
- strcpy(card->mixername, "Asihpi Mixer");
+ strscpy(card->mixername, "Asihpi Mixer");
err =
hpi_mixer_open(asihpi->hpi->adapter->index,
@@ -2741,7 +2741,7 @@ static int snd_asihpi_hpi_new(struct snd_card_asihpi *asihpi, int device)
err = snd_hwdep_new(asihpi->card, "HPI", device, &hw);
if (err < 0)
return err;
- strcpy(hw->name, "asihpi (HPI)");
+ strscpy(hw->name, "asihpi (HPI)");
hw->iface = SNDRV_HWDEP_IFACE_LAST;
hw->ops.open = snd_asihpi_hpi_open;
hw->ops.ioctl = snd_asihpi_hpi_ioctl;
@@ -2889,7 +2889,7 @@ static int snd_asihpi_probe(struct pci_dev *pci_dev,
by enable_hwdep module param*/
snd_asihpi_hpi_new(asihpi, 0);
- strcpy(card->driver, "ASIHPI");
+ strscpy(card->driver, "ASIHPI");
sprintf(card->shortname, "AudioScience ASI%4X",
asihpi->hpi->adapter->type);
diff --git a/sound/pci/asihpi/hpi6000.c b/sound/pci/asihpi/hpi6000.c
index 72aa135d69f8..b08578c93c6a 100644
--- a/sound/pci/asihpi/hpi6000.c
+++ b/sound/pci/asihpi/hpi6000.c
@@ -608,7 +608,7 @@ static void adapter_get_asserts(struct hpi_adapter_obj *pao,
phr->u.ax.assert.p2 = 0;
phr->u.ax.assert.count = 1; /* assert count */
phr->u.ax.assert.dsp_index = -1; /* "dsp index" */
- strcpy(phr->u.ax.assert.sz_message, "PCI2040 error");
+ strscpy(phr->u.ax.assert.sz_message, "PCI2040 error");
phr->u.ax.assert.dsp_msg_addr = 0;
gw_pci_read_asserts = 0;
gw_pci_write_asserts = 0;
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index 427006be240b..4f544950ee7b 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -1271,7 +1271,7 @@ static int snd_atiixp_pcm_new(struct atiixp *chip)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_atiixp_playback_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_atiixp_capture_ops);
pcm->private_data = chip;
- strcpy(pcm->name, "ATI IXP AC97");
+ strscpy(pcm->name, "ATI IXP AC97");
chip->pcmdevs[ATI_PCMDEV_ANALOG] = pcm;
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
@@ -1301,9 +1301,9 @@ static int snd_atiixp_pcm_new(struct atiixp *chip)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_atiixp_spdif_ops);
pcm->private_data = chip;
if (chip->spdif_over_aclink)
- strcpy(pcm->name, "ATI IXP IEC958 (AC97)");
+ strscpy(pcm->name, "ATI IXP IEC958 (AC97)");
else
- strcpy(pcm->name, "ATI IXP IEC958 (Direct)");
+ strscpy(pcm->name, "ATI IXP IEC958 (Direct)");
chip->pcmdevs[ATI_PCMDEV_DIGITAL] = pcm;
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
@@ -1576,8 +1576,8 @@ static int __snd_atiixp_probe(struct pci_dev *pci,
return err;
chip = card->private_data;
- strcpy(card->driver, spdif_aclink ? "ATIIXP" : "ATIIXP-SPDMA");
- strcpy(card->shortname, "ATI IXP");
+ strscpy(card->driver, spdif_aclink ? "ATIIXP" : "ATIIXP-SPDMA");
+ strscpy(card->shortname, "ATI IXP");
err = snd_atiixp_init(card, pci);
if (err < 0)
return err;
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index 8d3083b9b024..f7417c2bb477 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -982,7 +982,7 @@ static int snd_atiixp_pcm_new(struct atiixp_modem *chip)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_atiixp_capture_ops);
pcm->dev_class = SNDRV_PCM_CLASS_MODEM;
pcm->private_data = chip;
- strcpy(pcm->name, "ATI IXP MC97");
+ strscpy(pcm->name, "ATI IXP MC97");
chip->pcmdevs[ATI_PCMDEV_ANALOG] = pcm;
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
@@ -1206,8 +1206,8 @@ static int __snd_atiixp_probe(struct pci_dev *pci,
return err;
chip = card->private_data;
- strcpy(card->driver, "ATIIXP-MODEM");
- strcpy(card->shortname, "ATI IXP Modem");
+ strscpy(card->driver, "ATIIXP-MODEM");
+ strscpy(card->shortname, "ATI IXP Modem");
err = snd_atiixp_init(card, pci);
if (err < 0)
return err;
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
index fd986247331a..de56e83d8e10 100644
--- a/sound/pci/au88x0/au88x0.c
+++ b/sound/pci/au88x0/au88x0.c
@@ -220,7 +220,7 @@ __snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
snd_vortex_workaround(pci, pcifix[dev]);
// Card details needed in snd_vortex_midi
- strcpy(card->driver, CARD_NAME_SHORT);
+ strscpy(card->driver, CARD_NAME_SHORT);
sprintf(card->shortname, "Aureal Vortex %s", CARD_NAME_SHORT);
sprintf(card->longname, "%s at 0x%lx irq %i",
card->shortname, chip->io, chip->irq);
@@ -270,7 +270,7 @@ __snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
snd_vortex_synth_arg_t *arg;
arg = SNDRV_SEQ_DEVICE_ARGPTR(wave);
- strcpy(wave->name, "Aureal Synth");
+ strscpy(wave->name, "Aureal Synth");
arg->hwptr = vortex;
arg->index = 1;
arg->seq_ports = seq_ports[dev];
diff --git a/sound/pci/au88x0/au88x0_mixer.c b/sound/pci/au88x0/au88x0_mixer.c
index aeba684b8d18..00781a7fd28c 100644
--- a/sound/pci/au88x0/au88x0_mixer.c
+++ b/sound/pci/au88x0/au88x0_mixer.c
@@ -15,7 +15,7 @@ static int remove_ctl(struct snd_card *card, const char *name)
{
struct snd_ctl_elem_id id;
memset(&id, 0, sizeof(id));
- strcpy(id.name, name);
+ strscpy(id.name, name);
id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
return snd_ctl_remove_id(card, &id);
}
diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c
index 7b4b8f785517..1d7aab14579e 100644
--- a/sound/pci/aw2/aw2-alsa.c
+++ b/sound/pci/aw2/aw2-alsa.c
@@ -281,8 +281,8 @@ static int snd_aw2_probe(struct pci_dev *pci,
/* init spinlock */
spin_lock_init(&chip->reg_lock);
/* (4) Define driver ID and name string */
- strcpy(card->driver, "aw2");
- strcpy(card->shortname, "Audiowerk2");
+ strscpy(card->driver, "aw2");
+ strscpy(card->shortname, "Audiowerk2");
sprintf(card->longname, "%s with SAA7146 irq %i",
card->shortname, chip->irq);
@@ -509,7 +509,7 @@ static int snd_aw2_new_pcm(struct aw2 *chip)
pcm_device = &chip->device_playback[NUM_STREAM_PLAYBACK_ANA];
/* Set PCM device name */
- strcpy(pcm_playback_ana->name, "Analog playback");
+ strscpy(pcm_playback_ana->name, "Analog playback");
/* Associate private data to PCM device */
pcm_playback_ana->private_data = pcm_device;
/* set operators of PCM device */
@@ -541,7 +541,7 @@ static int snd_aw2_new_pcm(struct aw2 *chip)
pcm_device = &chip->device_playback[NUM_STREAM_PLAYBACK_DIG];
/* Set PCM device name */
- strcpy(pcm_playback_num->name, "Digital playback");
+ strscpy(pcm_playback_num->name, "Digital playback");
/* Associate private data to PCM device */
pcm_playback_num->private_data = pcm_device;
/* set operators of PCM device */
@@ -574,7 +574,7 @@ static int snd_aw2_new_pcm(struct aw2 *chip)
pcm_device = &chip->device_capture[NUM_STREAM_CAPTURE_ANA];
/* Set PCM device name */
- strcpy(pcm_capture->name, "Capture");
+ strscpy(pcm_capture->name, "Capture");
/* Associate private data to PCM device */
pcm_capture->private_data = pcm_device;
/* set operators of PCM device */
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index 053a18f434bf..4418b9ae33e6 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -1188,7 +1188,7 @@ snd_azf3328_mixer_new(struct snd_azf3328 *chip)
return err;
}
snd_component_add(card, "AZF3328 mixer");
- strcpy(card->mixername, "AZF3328 mixer");
+ strscpy(card->mixername, "AZF3328 mixer");
return 0;
}
@@ -2095,7 +2095,7 @@ snd_azf3328_pcm(struct snd_azf3328 *chip)
pcm->private_data = chip;
pcm->info_flags = 0;
- strcpy(pcm->name, chip->card->shortname);
+ strscpy(pcm->name, chip->card->shortname);
/* same pcm object for playback/capture (see snd_pcm_new() above) */
chip->pcm[AZF_CODEC_PLAYBACK] = pcm;
chip->pcm[AZF_CODEC_CAPTURE] = pcm;
@@ -2112,7 +2112,7 @@ snd_azf3328_pcm(struct snd_azf3328 *chip)
pcm->private_data = chip;
pcm->info_flags = 0;
- strcpy(pcm->name, chip->card->shortname);
+ strscpy(pcm->name, chip->card->shortname);
chip->pcm[AZF_CODEC_I2S_OUT] = pcm;
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, &chip->pci->dev,
@@ -2217,7 +2217,7 @@ snd_azf3328_timer(struct snd_azf3328 *chip, int device)
if (err < 0)
goto out;
- strcpy(timer->name, "AZF3328 timer");
+ strscpy(timer->name, "AZF3328 timer");
timer->private_data = chip;
timer->hw = snd_azf3328_timer_hw;
@@ -2437,8 +2437,8 @@ __snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
return err;
chip = card->private_data;
- strcpy(card->driver, "AZF3328");
- strcpy(card->shortname, "Aztech AZF3328 (PCI168)");
+ strscpy(card->driver, "AZF3328");
+ strscpy(card->shortname, "Aztech AZF3328 (PCI168)");
err = snd_azf3328_create(card, pci, pci_id->driver_data);
if (err < 0)
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index 91492dd2b38a..b70f6f4ffe67 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -672,7 +672,7 @@ static int snd_bt87x_pcm(struct snd_bt87x *chip, int device, char *name)
if (err < 0)
return err;
pcm->private_data = chip;
- strcpy(pcm->name, name);
+ strscpy(pcm->name, name);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_bt87x_pcm_ops);
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
&chip->pci->dev,
@@ -872,12 +872,12 @@ static int __snd_bt87x_probe(struct pci_dev *pci,
chip->board.no_analog ? "no " : "",
chip->board.no_digital ? "no " : "", chip->board.dig_rate);
- strcpy(card->driver, "Bt87x");
+ strscpy(card->driver, "Bt87x");
sprintf(card->shortname, "Brooktree Bt%x", pci->device);
sprintf(card->longname, "%s at %#llx, irq %i",
card->shortname, (unsigned long long)pci_resource_start(pci, 0),
chip->irq);
- strcpy(card->mixername, "Bt87x");
+ strscpy(card->mixername, "Bt87x");
err = snd_card_register(card);
if (err < 0)
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index 7c7119cad63c..242618793181 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -1315,7 +1315,7 @@ static int snd_ca0106_pcm(struct snd_ca0106 *emu, int device)
}
pcm->info_flags = 0;
- strcpy(pcm->name, "CA0106");
+ strscpy(pcm->name, "CA0106");
for(substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
substream;
@@ -1617,8 +1617,8 @@ static int snd_ca0106_create(int dev, struct snd_card *card,
pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->model);
dev_info(card->dev, "Model %04x Rev %08x Serial %08x\n",
chip->model, pci->revision, chip->serial);
- strcpy(card->driver, "CA0106");
- strcpy(card->shortname, "CA0106");
+ strscpy(card->driver, "CA0106");
+ strscpy(card->shortname, "CA0106");
for (c = ca0106_chip_details; c->serial; c++) {
if (subsystem[dev]) {
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c
index 1d5a899b2c24..f7b6b2db889b 100644
--- a/sound/pci/ca0106/ca0106_mixer.c
+++ b/sound/pci/ca0106/ca0106_mixer.c
@@ -701,7 +701,7 @@ static int remove_ctl(struct snd_card *card, const char *name)
{
struct snd_ctl_elem_id id;
memset(&id, 0, sizeof(id));
- strcpy(id.name, name);
+ strscpy(id.name, name);
id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
return snd_ctl_remove_id(card, &id);
}
@@ -849,7 +849,7 @@ int snd_ca0106_mixer(struct snd_ca0106 *emu)
return err;
}
- strcpy(card->mixername, "CA0106");
+ strscpy(card->mixername, "CA0106");
return 0;
}
diff --git a/sound/pci/ca0106/ca_midi.c b/sound/pci/ca0106/ca_midi.c
index 957e60f64821..f9cec67f31ac 100644
--- a/sound/pci/ca0106/ca_midi.c
+++ b/sound/pci/ca0106/ca_midi.c
@@ -287,7 +287,7 @@ int ca_midi_init(void *dev_id, struct snd_ca_midi *midi, int device, char *name)
spin_lock_init(&midi->input_lock);
spin_lock_init(&midi->output_lock);
- strcpy(rmidi->name, name);
+ strscpy(rmidi->name, name);
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &ca_midi_output);
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &ca_midi_input);
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index b00df0a60d3f..c4ee550d7c96 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -1868,7 +1868,7 @@ static int snd_cmipci_pcm_new(struct cmipci *cm, int device)
pcm->private_data = cm;
pcm->info_flags = 0;
- strcpy(pcm->name, "C-Media PCI DAC/ADC");
+ strscpy(pcm->name, "C-Media PCI DAC/ADC");
cm->pcm = pcm;
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
@@ -1890,7 +1890,7 @@ static int snd_cmipci_pcm2_new(struct cmipci *cm, int device)
pcm->private_data = cm;
pcm->info_flags = 0;
- strcpy(pcm->name, "C-Media PCI 2nd DAC");
+ strscpy(pcm->name, "C-Media PCI 2nd DAC");
cm->pcm2 = pcm;
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
@@ -1913,7 +1913,7 @@ static int snd_cmipci_pcm_spdif_new(struct cmipci *cm, int device)
pcm->private_data = cm;
pcm->info_flags = 0;
- strcpy(pcm->name, "C-Media PCI IEC958");
+ strscpy(pcm->name, "C-Media PCI IEC958");
cm->pcm_spdif = pcm;
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
@@ -2633,7 +2633,7 @@ static int snd_cmipci_mixer_new(struct cmipci *cm, int pcm_spdif_device)
card = cm->card;
- strcpy(card->mixername, "CMedia PCI");
+ strscpy(card->mixername, "CMedia PCI");
spin_lock_irq(&cm->reg_lock);
snd_cmipci_mixer_write(cm, 0x00, 0x00); /* mixer reset */
@@ -3008,11 +3008,12 @@ static int snd_cmipci_create(struct snd_card *card, struct pci_dev *pci,
pci->device != PCI_DEVICE_ID_CMEDIA_CM8338B)
query_chip(cm);
/* added -MCx suffix for chip supporting multi-channels */
- if (cm->can_multi_ch)
- sprintf(cm->card->driver + strlen(cm->card->driver),
- "-MC%d", cm->max_channels);
- else if (cm->can_ac3_sw)
- strcpy(cm->card->driver + strlen(cm->card->driver), "-SWIEC");
+ if (cm->can_multi_ch) {
+ int l = strlen(cm->card->driver);
+ scnprintf(cm->card->driver + l, sizeof(cm->card->driver) - l,
+ "-MC%d", cm->max_channels);
+ } else if (cm->can_ac3_sw)
+ strlcat(cm->card->driver, "-SWIEC", sizeof(cm->card->driver));
cm->dig_status = SNDRV_PCM_DEFAULT_CON_SPDIF;
cm->dig_pcm_status = SNDRV_PCM_DEFAULT_CON_SPDIF;
@@ -3216,14 +3217,14 @@ static int snd_cmipci_probe(struct pci_dev *pci,
switch (pci->device) {
case PCI_DEVICE_ID_CMEDIA_CM8738:
case PCI_DEVICE_ID_CMEDIA_CM8738B:
- strcpy(card->driver, "CMI8738");
+ strscpy(card->driver, "CMI8738");
break;
case PCI_DEVICE_ID_CMEDIA_CM8338A:
case PCI_DEVICE_ID_CMEDIA_CM8338B:
- strcpy(card->driver, "CMI8338");
+ strscpy(card->driver, "CMI8338");
break;
default:
- strcpy(card->driver, "CMIPCI");
+ strscpy(card->driver, "CMIPCI");
break;
}
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index 90958a422b75..31cb9cbe2f03 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -950,7 +950,7 @@ static int snd_cs4281_pcm(struct cs4281 *chip, int device)
pcm->private_data = chip;
pcm->info_flags = 0;
- strcpy(pcm->name, "CS4281");
+ strscpy(pcm->name, "CS4281");
chip->pcm = pcm;
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, &chip->pci->dev,
@@ -1715,7 +1715,7 @@ static int snd_cs4281_midi(struct cs4281 *chip, int device)
err = snd_rawmidi_new(chip->card, "CS4281", device, 1, 1, &rmidi);
if (err < 0)
return err;
- strcpy(rmidi->name, "CS4281");
+ strscpy(rmidi->name, "CS4281");
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_cs4281_midi_output);
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_cs4281_midi_input);
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX;
@@ -1870,8 +1870,8 @@ static int __snd_cs4281_probe(struct pci_dev *pci,
if (err < 0)
return err;
snd_cs4281_create_gameport(chip);
- strcpy(card->driver, "CS4281");
- strcpy(card->shortname, "Cirrus Logic CS4281");
+ strscpy(card->driver, "CS4281");
+ strscpy(card->shortname, "Cirrus Logic CS4281");
sprintf(card->longname, "%s at 0x%lx, irq %d",
card->shortname,
chip->ba0_addr,
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c
index 8634004a606b..9c1995737eb7 100644
--- a/sound/pci/cs46xx/cs46xx.c
+++ b/sound/pci/cs46xx/cs46xx.c
@@ -107,8 +107,8 @@ static int snd_card_cs46xx_probe(struct pci_dev *pci,
snd_cs46xx_gameport(chip);
- strcpy(card->driver, "CS46xx");
- strcpy(card->shortname, "Sound Fusion CS46xx");
+ strscpy(card->driver, "CS46xx");
+ strscpy(card->shortname, "Sound Fusion CS46xx");
sprintf(card->longname, "%s at 0x%lx/0x%lx, irq %i",
card->shortname,
chip->ba0_addr,
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index fb733633740b..85a7988cf822 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -1760,7 +1760,7 @@ int snd_cs46xx_pcm(struct snd_cs46xx *chip, int device)
/* global setup */
pcm->info_flags = 0;
- strcpy(pcm->name, "CS46xx");
+ strscpy(pcm->name, "CS46xx");
chip->pcm = pcm;
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
@@ -1787,7 +1787,7 @@ int snd_cs46xx_pcm_rear(struct snd_cs46xx *chip, int device)
/* global setup */
pcm->info_flags = 0;
- strcpy(pcm->name, "CS46xx - Rear");
+ strscpy(pcm->name, "CS46xx - Rear");
chip->pcm_rear = pcm;
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
@@ -1812,7 +1812,7 @@ int snd_cs46xx_pcm_center_lfe(struct snd_cs46xx *chip, int device)
/* global setup */
pcm->info_flags = 0;
- strcpy(pcm->name, "CS46xx - Center LFE");
+ strscpy(pcm->name, "CS46xx - Center LFE");
chip->pcm_center_lfe = pcm;
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
@@ -1837,7 +1837,7 @@ int snd_cs46xx_pcm_iec958(struct snd_cs46xx *chip, int device)
/* global setup */
pcm->info_flags = 0;
- strcpy(pcm->name, "CS46xx - IEC958");
+ strscpy(pcm->name, "CS46xx - IEC958");
chip->pcm_iec958 = pcm;
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
@@ -2672,7 +2672,7 @@ int snd_cs46xx_midi(struct snd_cs46xx *chip, int device)
err = snd_rawmidi_new(chip->card, "CS46XX", device, 1, 1, &rmidi);
if (err < 0)
return err;
- strcpy(rmidi->name, "CS46XX");
+ strscpy(rmidi->name, "CS46XX");
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_cs46xx_midi_output);
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_cs46xx_midi_input);
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX;
@@ -3853,27 +3853,27 @@ int snd_cs46xx_create(struct snd_card *card,
}
region = &chip->region.name.ba0;
- strcpy(region->name, "CS46xx_BA0");
+ strscpy(region->name, "CS46xx_BA0");
region->base = chip->ba0_addr;
region->size = CS46XX_BA0_SIZE;
region = &chip->region.name.data0;
- strcpy(region->name, "CS46xx_BA1_data0");
+ strscpy(region->name, "CS46xx_BA1_data0");
region->base = chip->ba1_addr + BA1_SP_DMEM0;
region->size = CS46XX_BA1_DATA0_SIZE;
region = &chip->region.name.data1;
- strcpy(region->name, "CS46xx_BA1_data1");
+ strscpy(region->name, "CS46xx_BA1_data1");
region->base = chip->ba1_addr + BA1_SP_DMEM1;
region->size = CS46XX_BA1_DATA1_SIZE;
region = &chip->region.name.pmem;
- strcpy(region->name, "CS46xx_BA1_pmem");
+ strscpy(region->name, "CS46xx_BA1_pmem");
region->base = chip->ba1_addr + BA1_SP_PMEM;
region->size = CS46XX_BA1_PRG_SIZE;
region = &chip->region.name.reg;
- strcpy(region->name, "CS46xx_BA1_reg");
+ strscpy(region->name, "CS46xx_BA1_reg");
region->base = chip->ba1_addr + BA1_SP_REG;
region->size = CS46XX_BA1_REG_SIZE;
diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c
index 1db6bc58d6a6..e07f85322f1c 100644
--- a/sound/pci/cs46xx/dsp_spos.c
+++ b/sound/pci/cs46xx/dsp_spos.c
@@ -203,7 +203,7 @@ add_symbol (struct snd_cs46xx * chip, char * symbol_name, u32 address, int type)
index = find_free_symbol_index (ins);
- strcpy (ins->symbol_table.symbols[index].symbol_name, symbol_name);
+ strscpy (ins->symbol_table.symbols[index].symbol_name, symbol_name);
ins->symbol_table.symbols[index].address = address;
ins->symbol_table.symbols[index].symbol_type = type;
ins->symbol_table.symbols[index].module = NULL;
@@ -923,7 +923,7 @@ static struct dsp_scb_descriptor * _map_scb (struct snd_cs46xx *chip, char * nam
index = find_free_scb_index (ins);
memset(&ins->scbs[index], 0, sizeof(ins->scbs[index]));
- strcpy(ins->scbs[index].scb_name, name);
+ strscpy(ins->scbs[index].scb_name, name);
ins->scbs[index].address = dest;
ins->scbs[index].index = index;
ins->scbs[index].ref_count = 1;
@@ -953,9 +953,9 @@ _map_task_tree (struct snd_cs46xx *chip, char * name, u32 dest, u32 size)
}
if (name)
- strcpy(ins->tasks[ins->ntask].task_name, name);
+ strscpy(ins->tasks[ins->ntask].task_name, name);
else
- strcpy(ins->tasks[ins->ntask].task_name, "(NULL)");
+ strscpy(ins->tasks[ins->ntask].task_name, "(NULL)");
ins->tasks[ins->ntask].address = dest;
ins->tasks[ins->ntask].size = size;
diff --git a/sound/pci/cs5530.c b/sound/pci/cs5530.c
index 532891e67c34..292b65aa758a 100644
--- a/sound/pci/cs5530.c
+++ b/sound/pci/cs5530.c
@@ -207,8 +207,8 @@ static int snd_cs5530_probe(struct pci_dev *pci,
if (err < 0)
return err;
- strcpy(card->driver, "CS5530");
- strcpy(card->shortname, "CS5530 Audio");
+ strscpy(card->driver, "CS5530");
+ strscpy(card->shortname, "CS5530 Audio");
sprintf(card->longname, "%s at 0x%lx", card->shortname, chip->pci_base);
err = snd_card_register(card);
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c
index 0f319013a2a2..76566e7baea0 100644
--- a/sound/pci/cs5535audio/cs5535audio.c
+++ b/sound/pci/cs5535audio/cs5535audio.c
@@ -315,9 +315,9 @@ static int __snd_cs5535audio_probe(struct pci_dev *pci,
if (err < 0)
return err;
- strcpy(card->driver, DRIVER_NAME);
+ strscpy(card->driver, DRIVER_NAME);
- strcpy(card->shortname, "CS5535 Audio");
+ strscpy(card->shortname, "CS5535 Audio");
sprintf(card->longname, "%s %s at 0x%lx, irq %i",
card->shortname, card->driver,
cs5535au->port, cs5535au->irq);
diff --git a/sound/pci/cs5535audio/cs5535audio_pcm.c b/sound/pci/cs5535audio/cs5535audio_pcm.c
index 9c88e99e3750..f296b2c63026 100644
--- a/sound/pci/cs5535audio/cs5535audio_pcm.c
+++ b/sound/pci/cs5535audio/cs5535audio_pcm.c
@@ -423,7 +423,7 @@ int snd_cs5535audio_pcm(struct cs5535audio *cs5535au)
pcm->private_data = cs5535au;
pcm->info_flags = 0;
- strcpy(pcm->name, "CS5535 Audio");
+ strscpy(pcm->name, "CS5535 Audio");
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
&cs5535au->pci->dev,
diff --git a/sound/pci/ctxfi/ctmixer.c b/sound/pci/ctxfi/ctmixer.c
index 6797fde3d788..496682613db5 100644
--- a/sound/pci/ctxfi/ctmixer.c
+++ b/sound/pci/ctxfi/ctmixer.c
@@ -1219,7 +1219,7 @@ int ct_alsa_mix_create(struct ct_atc *atc,
if (err)
return err;
- strcpy(atc->card->mixername, device_name);
+ strscpy(atc->card->mixername, device_name);
return 0;
}
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
index 80d8ce75fdbb..2b33ef588ac3 100644
--- a/sound/pci/echoaudio/echoaudio.c
+++ b/sound/pci/echoaudio/echoaudio.c
@@ -6,6 +6,7 @@
*/
#include <linux/module.h>
+#include <linux/string.h>
MODULE_AUTHOR("Giuliano Pochini <pochini@shiny.it>");
MODULE_LICENSE("GPL v2");
@@ -916,7 +917,7 @@ static int snd_echo_new_pcm(struct echoaudio *chip)
return err;
pcm->private_data = chip;
chip->analog_pcm = pcm;
- strcpy(pcm->name, chip->card->shortname);
+ strscpy(pcm->name, chip->card->shortname);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &analog_playback_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &analog_capture_ops);
snd_echo_preallocate_pages(pcm, &chip->pci->dev);
@@ -929,7 +930,7 @@ static int snd_echo_new_pcm(struct echoaudio *chip)
return err;
pcm->private_data = chip;
chip->digital_pcm = pcm;
- strcpy(pcm->name, chip->card->shortname);
+ strscpy(pcm->name, chip->card->shortname);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &digital_capture_ops);
snd_echo_preallocate_pages(pcm, &chip->pci->dev);
#endif /* ECHOCARD_HAS_DIGITAL_IO */
@@ -949,7 +950,7 @@ static int snd_echo_new_pcm(struct echoaudio *chip)
return err;
pcm->private_data = chip;
chip->analog_pcm = pcm;
- strcpy(pcm->name, chip->card->shortname);
+ strscpy(pcm->name, chip->card->shortname);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &analog_playback_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &analog_capture_ops);
snd_echo_preallocate_pages(pcm, &chip->pci->dev);
@@ -963,7 +964,7 @@ static int snd_echo_new_pcm(struct echoaudio *chip)
return err;
pcm->private_data = chip;
chip->digital_pcm = pcm;
- strcpy(pcm->name, chip->card->shortname);
+ strscpy(pcm->name, chip->card->shortname);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &digital_playback_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &digital_capture_ops);
snd_echo_preallocate_pages(pcm, &chip->pci->dev);
@@ -1985,8 +1986,8 @@ static int __snd_echo_probe(struct pci_dev *pci,
if (err < 0)
return err;
- strcpy(card->driver, "Echo_" ECHOCARD_NAME);
- strcpy(card->shortname, chip->card_name);
+ strscpy(card->driver, "Echo_" ECHOCARD_NAME);
+ strscpy(card->shortname, chip->card_name);
dsp = "56301";
if (pci_id->device == 0x3410)
diff --git a/sound/pci/echoaudio/midi.c b/sound/pci/echoaudio/midi.c
index c3f3c9129561..4ee230794b4e 100644
--- a/sound/pci/echoaudio/midi.c
+++ b/sound/pci/echoaudio/midi.c
@@ -311,7 +311,7 @@ static int snd_echo_midi_create(struct snd_card *card,
if (err < 0)
return err;
- strcpy(chip->rmidi->name, card->shortname);
+ strscpy(chip->rmidi->name, card->shortname);
chip->rmidi->private_data = chip;
snd_rawmidi_set_ops(chip->rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
index dadeda7758ce..548e7d049901 100644
--- a/sound/pci/emu10k1/emu10k1.c
+++ b/sound/pci/emu10k1/emu10k1.c
@@ -7,6 +7,7 @@
#include <linux/init.h>
#include <linux/pci.h>
+#include <linux/string.h>
#include <linux/time.h>
#include <linux/module.h>
#include <sound/core.h>
@@ -154,7 +155,7 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci,
} else {
struct snd_emu10k1_synth_arg *arg;
arg = SNDRV_SEQ_DEVICE_ARGPTR(wave);
- strcpy(wave->name, "Emu-10k1 Synth");
+ strscpy(wave->name, "Emu-10k1 Synth");
arg->hwptr = emu;
arg->index = 1;
arg->seq_ports = seq_ports[dev];
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index 30ac37b5a214..8c18ad987223 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -20,6 +20,7 @@
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
+#include <linux/string.h>
#include <linux/module.h>
#include <sound/core.h>
#include <sound/initval.h>
@@ -840,15 +841,15 @@ static int snd_emu10k1x_pcm(struct emu10k1x *emu, int device)
pcm->info_flags = 0;
switch(device) {
case 0:
- strcpy(pcm->name, "EMU10K1X Front");
+ strscpy(pcm->name, "EMU10K1X Front");
map = snd_pcm_std_chmaps;
break;
case 1:
- strcpy(pcm->name, "EMU10K1X Rear");
+ strscpy(pcm->name, "EMU10K1X Rear");
map = surround_map;
break;
case 2:
- strcpy(pcm->name, "EMU10K1X Center/LFE");
+ strscpy(pcm->name, "EMU10K1X Center/LFE");
map = clfe_map;
break;
}
@@ -1461,7 +1462,7 @@ static int emu10k1x_midi_init(struct emu10k1x *emu,
spin_lock_init(&midi->open_lock);
spin_lock_init(&midi->input_lock);
spin_lock_init(&midi->output_lock);
- strcpy(rmidi->name, name);
+ strscpy(rmidi->name, name);
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_emu10k1x_midi_output);
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_emu10k1x_midi_input);
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
@@ -1540,8 +1541,8 @@ static int __snd_emu10k1x_probe(struct pci_dev *pci,
snd_emu10k1x_proc_init(chip);
- strcpy(card->driver, "EMU10K1X");
- strcpy(card->shortname, "Dell Sound Blaster Live!");
+ strscpy(card->driver, "EMU10K1X");
+ strscpy(card->shortname, "Dell Sound Blaster Live!");
sprintf(card->longname, "%s at 0x%lx irq %i",
card->shortname, chip->port, chip->irq);
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c
index 03efc317e05f..7db0660e6b61 100644
--- a/sound/pci/emu10k1/emufx.c
+++ b/sound/pci/emu10k1/emufx.c
@@ -12,6 +12,7 @@
#include <linux/capability.h>
#include <linux/delay.h>
#include <linux/slab.h>
+#include <linux/string.h>
#include <linux/vmalloc.h>
#include <linux/init.h>
#include <linux/mutex.h>
@@ -1175,7 +1176,7 @@ snd_emu10k1_init_mono_control2(struct snd_emu10k1_fx8010_control_gpr *ctl,
const char *name, int gpr, int defval, int defval_hr)
{
ctl->id.iface = (__force int)SNDRV_CTL_ELEM_IFACE_MIXER;
- strcpy(ctl->id.name, name);
+ strscpy(ctl->id.name, name);
ctl->vcount = ctl->count = 1;
if (high_res_gpr_volume) {
ctl->min = -1;
@@ -1199,7 +1200,7 @@ snd_emu10k1_init_stereo_control2(struct snd_emu10k1_fx8010_control_gpr *ctl,
const char *name, int gpr, int defval, int defval_hr)
{
ctl->id.iface = (__force int)SNDRV_CTL_ELEM_IFACE_MIXER;
- strcpy(ctl->id.name, name);
+ strscpy(ctl->id.name, name);
ctl->vcount = ctl->count = 2;
if (high_res_gpr_volume) {
ctl->min = -1;
@@ -1224,7 +1225,7 @@ snd_emu10k1_init_mono_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
const char *name, int gpr, int defval)
{
ctl->id.iface = (__force int)SNDRV_CTL_ELEM_IFACE_MIXER;
- strcpy(ctl->id.name, name);
+ strscpy(ctl->id.name, name);
ctl->vcount = ctl->count = 1;
ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;
ctl->min = 0;
@@ -1237,7 +1238,7 @@ snd_emu10k1_init_stereo_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl
const char *name, int gpr, int defval)
{
ctl->id.iface = (__force int)SNDRV_CTL_ELEM_IFACE_MIXER;
- strcpy(ctl->id.name, name);
+ strscpy(ctl->id.name, name);
ctl->vcount = ctl->count = 2;
ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;
ctl->gpr[1] = gpr + 1; ctl->value[1] = defval;
@@ -1325,7 +1326,7 @@ static int _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu)
/* clear TRAM data & address lines */
memset(icode->tram_valid, 0xff, 256 / 8);
- strcpy(icode->name, "Audigy DSP code for ALSA");
+ strscpy(icode->name, "Audigy DSP code for ALSA");
ptr = 0;
nctl = 0;
gpr_map[bit_shifter16] = 0x00008000;
@@ -1563,7 +1564,7 @@ static int _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu)
*/
ctl = &controls[nctl + 0];
ctl->id.iface = (__force int)SNDRV_CTL_ELEM_IFACE_MIXER;
- strcpy(ctl->id.name, "Tone Control - Bass");
+ strscpy(ctl->id.name, "Tone Control - Bass");
ctl->vcount = 2;
ctl->count = 10;
ctl->min = 0;
@@ -1572,7 +1573,7 @@ static int _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu)
ctl->translation = EMU10K1_GPR_TRANSLATION_BASS;
ctl = &controls[nctl + 1];
ctl->id.iface = (__force int)SNDRV_CTL_ELEM_IFACE_MIXER;
- strcpy(ctl->id.name, "Tone Control - Treble");
+ strscpy(ctl->id.name, "Tone Control - Treble");
ctl->vcount = 2;
ctl->count = 10;
ctl->min = 0;
@@ -1849,7 +1850,7 @@ static int _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
/* clear TRAM data & address lines */
memset(icode->tram_valid, 0xff, 160 / 8);
- strcpy(icode->name, "SB Live! FX8010 code for ALSA v1.2 by Jaroslav Kysela");
+ strscpy(icode->name, "SB Live! FX8010 code for ALSA v1.2 by Jaroslav Kysela");
ptr = 0; i = 0;
/* we have 12 inputs */
playback = SND_EMU10K1_INPUTS;
@@ -2160,7 +2161,7 @@ static int _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
*/
ctl = &controls[i + 0];
ctl->id.iface = (__force int)SNDRV_CTL_ELEM_IFACE_MIXER;
- strcpy(ctl->id.name, "Tone Control - Bass");
+ strscpy(ctl->id.name, "Tone Control - Bass");
ctl->vcount = 2;
ctl->count = 10;
ctl->min = 0;
@@ -2170,7 +2171,7 @@ static int _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
ctl->translation = EMU10K1_GPR_TRANSLATION_BASS;
ctl = &controls[i + 1];
ctl->id.iface = (__force int)SNDRV_CTL_ELEM_IFACE_MIXER;
- strcpy(ctl->id.name, "Tone Control - Treble");
+ strscpy(ctl->id.name, "Tone Control - Treble");
ctl->vcount = 2;
ctl->count = 10;
ctl->min = 0;
@@ -2623,7 +2624,7 @@ int snd_emu10k1_fx8010_new(struct snd_emu10k1 *emu, int device)
err = snd_hwdep_new(emu->card, "FX8010", device, &hw);
if (err < 0)
return err;
- strcpy(hw->name, "EMU10K1 (FX8010)");
+ strscpy(hw->name, "EMU10K1 (FX8010)");
hw->iface = SNDRV_HWDEP_IFACE_EMU10K1;
hw->ops.open = snd_emu10k1_fx8010_open;
hw->ops.ioctl = snd_emu10k1_fx8010_ioctl;
diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c
index 05b98d9b547b..d665d5d1ad7c 100644
--- a/sound/pci/emu10k1/emumixer.c
+++ b/sound/pci/emu10k1/emumixer.c
@@ -12,6 +12,7 @@
#include <linux/time.h>
#include <linux/init.h>
+#include <linux/string.h>
#include <sound/core.h>
#include <sound/emu10k1.h>
#include <linux/delay.h>
@@ -1983,7 +1984,7 @@ static int remove_ctl(struct snd_card *card, const char *name)
{
struct snd_ctl_elem_id id;
memset(&id, 0, sizeof(id));
- strcpy(id.name, name);
+ strscpy(id.name, name);
id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
return snd_ctl_remove_id(card, &id);
}
@@ -2188,11 +2189,11 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu,
} else {
no_ac97:
if (emu->card_capabilities->ecard)
- strcpy(emu->card->mixername, "EMU APS");
+ strscpy(emu->card->mixername, "EMU APS");
else if (emu->audigy)
- strcpy(emu->card->mixername, "SB Audigy");
+ strscpy(emu->card->mixername, "SB Audigy");
else
- strcpy(emu->card->mixername, "Emu10k1");
+ strscpy(emu->card->mixername, "Emu10k1");
}
if (emu->audigy)
diff --git a/sound/pci/emu10k1/emumpu401.c b/sound/pci/emu10k1/emumpu401.c
index 747c34b3d566..efff19bbc0e9 100644
--- a/sound/pci/emu10k1/emumpu401.c
+++ b/sound/pci/emu10k1/emumpu401.c
@@ -320,7 +320,7 @@ static int emu10k1_midi_init(struct snd_emu10k1 *emu, struct snd_emu10k1_midi *m
spin_lock_init(&midi->open_lock);
spin_lock_init(&midi->input_lock);
spin_lock_init(&midi->output_lock);
- strcpy(rmidi->name, name);
+ strscpy(rmidi->name, name);
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_emu10k1_midi_output);
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_emu10k1_midi_input);
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
index 1bf6e3d652f8..5414148057ea 100644
--- a/sound/pci/emu10k1/emupcm.c
+++ b/sound/pci/emu10k1/emupcm.c
@@ -1425,7 +1425,7 @@ int snd_emu10k1_pcm(struct snd_emu10k1 *emu, int device)
pcm->info_flags = 0;
pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
- strcpy(pcm->name, "ADC Capture/Standard PCM Playback");
+ strscpy(pcm->name, "ADC Capture/Standard PCM Playback");
emu->pcm = pcm;
/* playback substream can't use managed buffers due to alignment */
@@ -1457,7 +1457,7 @@ int snd_emu10k1_pcm_multi(struct snd_emu10k1 *emu, int device)
pcm->info_flags = 0;
pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
- strcpy(pcm->name, "Multichannel Playback");
+ strscpy(pcm->name, "Multichannel Playback");
emu->pcm_multi = pcm;
for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next)
@@ -1491,7 +1491,7 @@ int snd_emu10k1_pcm_mic(struct snd_emu10k1 *emu, int device)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1_capture_mic_ops);
pcm->info_flags = 0;
- strcpy(pcm->name, "Mic Capture");
+ strscpy(pcm->name, "Mic Capture");
emu->pcm_mic = pcm;
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, &emu->pci->dev,
@@ -1818,9 +1818,9 @@ int snd_emu10k1_pcm_efx(struct snd_emu10k1 *emu, int device)
pcm->info_flags = 0;
if (emu->audigy)
- strcpy(pcm->name, "Multichannel Capture");
+ strscpy(pcm->name, "Multichannel Capture");
else
- strcpy(pcm->name, "Multichannel Capture/PT Playback");
+ strscpy(pcm->name, "Multichannel Capture/PT Playback");
emu->pcm_efx = pcm;
if (!emu->card_capabilities->emu_model) {
diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c
index a9a75891f1da..e774174d10de 100644
--- a/sound/pci/emu10k1/p16v.c
+++ b/sound/pci/emu10k1/p16v.c
@@ -573,7 +573,7 @@ int snd_p16v_pcm(struct snd_emu10k1 *emu, int device)
pcm->info_flags = 0;
pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
- strcpy(pcm->name, "p16v");
+ strscpy(pcm->name, "p16v");
emu->pcm_p16v = pcm;
emu->p16v_interrupt = snd_p16v_interrupt;
diff --git a/sound/pci/emu10k1/timer.c b/sound/pci/emu10k1/timer.c
index bb2478319361..1231ae2bf931 100644
--- a/sound/pci/emu10k1/timer.c
+++ b/sound/pci/emu10k1/timer.c
@@ -80,7 +80,7 @@ int snd_emu10k1_timer(struct snd_emu10k1 *emu, int device)
tid.subdevice = 0;
err = snd_timer_new(emu->card, "EMU10K1", &tid, &timer);
if (err >= 0) {
- strcpy(timer->name, "EMU10K1 timer");
+ strscpy(timer->name, "EMU10K1 timer");
timer->private_data = emu;
timer->hw = snd_emu10k1_timer_hw;
}
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index 1e6adf1ae304..82e10ecb9196 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -1244,7 +1244,7 @@ static int snd_ensoniq_pcm(struct ensoniq *ensoniq, int device)
pcm->private_data = ensoniq;
pcm->info_flags = 0;
- strcpy(pcm->name, CHIP_NAME " DAC2/ADC");
+ strscpy(pcm->name, CHIP_NAME " DAC2/ADC");
ensoniq->pcm1 = pcm;
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
@@ -1276,7 +1276,7 @@ static int snd_ensoniq_pcm2(struct ensoniq *ensoniq, int device)
#endif
pcm->private_data = ensoniq;
pcm->info_flags = 0;
- strcpy(pcm->name, CHIP_NAME " DAC1");
+ strscpy(pcm->name, CHIP_NAME " DAC1");
ensoniq->pcm2 = pcm;
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
@@ -2250,7 +2250,7 @@ static int snd_ensoniq_midi(struct ensoniq *ensoniq, int device)
err = snd_rawmidi_new(ensoniq->card, "ES1370/1", device, 1, 1, &rmidi);
if (err < 0)
return err;
- strcpy(rmidi->name, CHIP_NAME);
+ strscpy(rmidi->name, CHIP_NAME);
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_ensoniq_midi_output);
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_ensoniq_midi_input);
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT |
@@ -2346,9 +2346,9 @@ static int __snd_audiopci_probe(struct pci_dev *pci,
snd_ensoniq_create_gameport(ensoniq, dev);
- strcpy(card->driver, DRIVER_NAME);
+ strscpy(card->driver, DRIVER_NAME);
- strcpy(card->shortname, "Ensoniq AudioPCI");
+ strscpy(card->shortname, "Ensoniq AudioPCI");
sprintf(card->longname, "%s %s at 0x%lx, irq %i",
card->shortname,
card->driver,
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index 27728bdfac57..0ce7076206f9 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -982,7 +982,7 @@ static int snd_es1938_new_pcm(struct es1938 *chip, int device)
pcm->private_data = chip;
pcm->info_flags = 0;
- strcpy(pcm->name, "ESS Solo-1");
+ strscpy(pcm->name, "ESS Solo-1");
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
&chip->pci->dev, 64*1024, 64*1024);
@@ -1658,7 +1658,7 @@ static int snd_es1938_mixer(struct es1938 *chip)
card = chip->card;
- strcpy(card->mixername, "ESS Solo-1");
+ strscpy(card->mixername, "ESS Solo-1");
for (idx = 0; idx < ARRAY_SIZE(snd_es1938_controls); idx++) {
struct snd_kcontrol *kctl;
@@ -1720,8 +1720,8 @@ static int __snd_es1938_probe(struct pci_dev *pci,
if (err < 0)
return err;
- strcpy(card->driver, "ES1938");
- strcpy(card->shortname, "ESS ES1938 (Solo-1)");
+ strscpy(card->driver, "ES1938");
+ strscpy(card->shortname, "ESS ES1938 (Solo-1)");
sprintf(card->longname, "%s rev %i, irq %i",
card->shortname,
chip->revision,
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index 37bac890613e..624ba7d47566 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -1812,7 +1812,7 @@ snd_es1968_pcm(struct es1968 *chip, int device)
pcm->info_flags = 0;
- strcpy(pcm->name, "ESS Maestro");
+ strscpy(pcm->name, "ESS Maestro");
chip->pcm = pcm;
@@ -2761,16 +2761,16 @@ static int __snd_es1968_probe(struct pci_dev *pci,
switch (chip->type) {
case TYPE_MAESTRO2E:
- strcpy(card->driver, "ES1978");
- strcpy(card->shortname, "ESS ES1978 (Maestro 2E)");
+ strscpy(card->driver, "ES1978");
+ strscpy(card->shortname, "ESS ES1978 (Maestro 2E)");
break;
case TYPE_MAESTRO2:
- strcpy(card->driver, "ES1968");
- strcpy(card->shortname, "ESS ES1968 (Maestro 2)");
+ strscpy(card->driver, "ES1968");
+ strscpy(card->shortname, "ESS ES1968 (Maestro 2)");
break;
case TYPE_MAESTRO:
- strcpy(card->driver, "ESM1");
- strcpy(card->shortname, "ESS Maestro 1");
+ strscpy(card->driver, "ESM1");
+ strscpy(card->shortname, "ESS Maestro 1");
break;
}
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index f283256eda0d..cf40bd06b734 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -726,7 +726,7 @@ static int snd_fm801_pcm(struct fm801 *chip, int device)
pcm->private_data = chip;
pcm->info_flags = 0;
- strcpy(pcm->name, "FM801");
+ strscpy(pcm->name, "FM801");
chip->pcm = pcm;
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, &pdev->dev,
@@ -1291,8 +1291,8 @@ static int __snd_card_fm801_probe(struct pci_dev *pci,
if (err < 0)
return err;
- strcpy(card->driver, "FM801");
- strcpy(card->shortname, "ForteMedia FM801-");
+ strscpy(card->driver, "FM801");
+ strscpy(card->shortname, "ForteMedia FM801-");
strcat(card->shortname, chip->multichannel ? "AU" : "AS");
sprintf(card->longname, "%s at 0x%lx, irq %i",
card->shortname, chip->port, chip->irq);
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig
deleted file mode 100644
index 745f120a5cee..000000000000
--- a/sound/pci/hda/Kconfig
+++ /dev/null
@@ -1,436 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-menu "HD-Audio"
-
-config SND_HDA
- tristate
- select SND_PCM
- select SND_VMASTER
- select SND_JACK
- select SND_HDA_CORE
-
-config SND_HDA_GENERIC_LEDS
- bool
-
-config SND_HDA_INTEL
- tristate "HD Audio PCI"
- depends on SND_PCI
- select SND_HDA
- select SND_INTEL_DSP_CONFIG
- help
- Say Y here to include support for Intel "High Definition
- Audio" (Azalia) and its compatible devices.
-
- This option enables the HD-audio controller. Don't forget
- to choose the appropriate codec options below.
-
- To compile this driver as a module, choose M here: the module
- will be called snd-hda-intel.
-
-config SND_HDA_TEGRA
- tristate "NVIDIA Tegra HD Audio"
- depends on ARCH_TEGRA
- select SND_HDA
- select SND_HDA_ALIGNED_MMIO
- help
- Say Y here to support the HDA controller present in NVIDIA
- Tegra SoCs
-
- This options enables support for the HD Audio controller
- present in some NVIDIA Tegra SoCs, used to communicate audio
- to the HDMI output.
-
- To compile this driver as a module, choose M here: the module
- will be called snd-hda-tegra.
-
-config SND_HDA_ACPI
- tristate "HD Audio ACPI"
- depends on ACPI
- select SND_HDA
- help
- Say Y here to include support for Azalia-compatible HDA controllers
- which are advertised via ACPI objects.
-
- To compile this driver as a module, choose M here: the module
- will be called snd-hda-acpi.
-
-if SND_HDA
-
-config SND_HDA_HWDEP
- bool "Build hwdep interface for HD-audio driver"
- select SND_HWDEP
- help
- Say Y here to build a hwdep interface for HD-audio driver.
- This interface can be used for out-of-band communication
- with codecs for debugging purposes.
-
-config SND_HDA_RECONFIG
- bool "Allow dynamic codec reconfiguration"
- help
- Say Y here to enable the HD-audio codec re-configuration feature.
- It allows user to clear the whole codec configuration, change the
- codec setup, add extra verbs, and re-configure the codec dynamically.
-
- Note that this item alone doesn't provide the sysfs interface, but
- enables the feature just for the patch loader below.
- If you need the traditional sysfs entries for the manual interaction,
- turn on CONFIG_SND_HDA_HWDEP as well.
-
-config SND_HDA_INPUT_BEEP
- bool "Support digital beep via input layer"
- depends on INPUT=y || INPUT=SND_HDA
- help
- Say Y here to build a digital beep interface for HD-audio
- driver. This interface is used to generate digital beeps.
-
-config SND_HDA_INPUT_BEEP_MODE
- int "Digital beep registration mode (0=off, 1=on)"
- depends on SND_HDA_INPUT_BEEP=y
- default "1"
- range 0 1
- help
- Set 0 to disable the digital beep interface for HD-audio by default.
- Set 1 to always enable the digital beep interface for HD-audio by
- default.
-
-config SND_HDA_PATCH_LOADER
- bool "Support initialization patch loading for HD-audio"
- select FW_LOADER
- select SND_HDA_RECONFIG
- help
- Say Y here to allow the HD-audio driver to load a pseudo
- firmware file ("patch") for overriding the BIOS setup at
- start up. The "patch" file can be specified via patch module
- option, such as patch=hda-init.
-
-config SND_HDA_CIRRUS_SCODEC
- tristate
-
-config SND_HDA_CIRRUS_SCODEC_KUNIT_TEST
- tristate "KUnit test for Cirrus side-codec library" if !KUNIT_ALL_TESTS
- depends on SND_HDA_CIRRUS_SCODEC && GPIOLIB && KUNIT
- default KUNIT_ALL_TESTS
- help
- This builds KUnit tests for the cirrus side-codec library.
- For more information on KUnit and unit tests in general,
- please refer to the KUnit documentation in
- Documentation/dev-tools/kunit/.
- If in doubt, say "N".
-
-config SND_HDA_SCODEC_CS35L41
- tristate
- select SND_HDA_GENERIC
- select REGMAP_IRQ
- select FW_CS_DSP
-
-config SND_HDA_SCODEC_COMPONENT
- tristate
-
-config SND_HDA_SCODEC_CS35L41_I2C
- tristate "Build CS35L41 HD-audio side codec support for I2C Bus"
- depends on I2C
- depends on ACPI
- depends on EFI
- depends on SND_SOC
- select SND_SOC_CS35L41_LIB
- select SND_HDA_SCODEC_CS35L41
- select SND_SOC_CS_AMP_LIB
- help
- Say Y or M here to include CS35L41 I2C HD-audio side codec support
- in snd-hda-intel driver, such as ALC287.
-
-comment "Set to Y if you want auto-loading the side codec driver"
- depends on SND_HDA=y && SND_HDA_SCODEC_CS35L41_I2C=m
-
-config SND_HDA_SCODEC_CS35L41_SPI
- tristate "Build CS35L41 HD-audio codec support for SPI Bus"
- depends on SPI_MASTER
- depends on ACPI
- depends on EFI
- depends on SND_SOC
- select SND_SOC_CS35L41_LIB
- select SND_HDA_SCODEC_CS35L41
- select SND_SOC_CS_AMP_LIB
- help
- Say Y or M here to include CS35L41 SPI HD-audio side codec support
- in snd-hda-intel driver, such as ALC287.
-
-comment "Set to Y if you want auto-loading the side codec driver"
- depends on SND_HDA=y && SND_HDA_SCODEC_CS35L41_SPI=m
-
-config SND_HDA_SCODEC_CS35L56
- tristate
-
-config SND_HDA_SCODEC_CS35L56_I2C
- tristate "Build CS35L56 HD-audio side codec support for I2C Bus"
- depends on I2C
- depends on ACPI
- depends on SND_SOC
- select FW_CS_DSP
- imply SERIAL_MULTI_INSTANTIATE
- select SND_HDA_GENERIC
- select SND_SOC_CS35L56_SHARED
- select SND_HDA_SCODEC_CS35L56
- select SND_HDA_CIRRUS_SCODEC
- select SND_SOC_CS_AMP_LIB
- help
- Say Y or M here to include CS35L56 amplifier support with
- I2C control.
-
-config SND_HDA_SCODEC_CS35L56_SPI
- tristate "Build CS35L56 HD-audio side codec support for SPI Bus"
- depends on SPI_MASTER
- depends on ACPI
- depends on SND_SOC
- select FW_CS_DSP
- imply SERIAL_MULTI_INSTANTIATE
- select SND_HDA_GENERIC
- select SND_SOC_CS35L56_SHARED
- select SND_HDA_SCODEC_CS35L56
- select SND_HDA_CIRRUS_SCODEC
- select SND_SOC_CS_AMP_LIB
- help
- Say Y or M here to include CS35L56 amplifier support with
- SPI control.
-
-config SND_HDA_SCODEC_TAS2781
- tristate
- select SND_HDA_GENERIC
-
-config SND_HDA_SCODEC_TAS2781_I2C
- tristate "Build TAS2781 HD-audio side codec support for I2C Bus"
- depends on I2C
- depends on ACPI
- depends on EFI
- depends on SND_SOC
- select SND_HDA_SCODEC_TAS2781
- select SND_SOC_TAS2781_COMLIB_I2C
- select SND_SOC_TAS2781_FMWLIB
- select CRC32
- help
- Say Y or M here to include TAS2781 I2C HD-audio side codec support
- in snd-hda-intel driver, such as ALC287.
-
-comment "Set to Y if you want auto-loading the side codec driver"
- depends on SND_HDA=y && SND_HDA_SCODEC_TAS2781_I2C=m
-
-config SND_HDA_SCODEC_TAS2781_SPI
- tristate "Build TAS2781 HD-audio side codec support for SPI Bus"
- depends on SPI_MASTER
- depends on ACPI
- depends on EFI
- depends on SND_SOC
- select SND_HDA_SCODEC_TAS2781
- select SND_SOC_TAS2781_COMLIB
- select SND_SOC_TAS2781_FMWLIB
- select CRC8
- select CRC32
- help
- Say Y or M here to include TAS2781 SPI HD-audio side codec support
- in snd-hda-intel driver, such as ALC287.
-
-comment "Set to Y if you want auto-loading the side codec driver"
- depends on SND_HDA=y && SND_HDA_SCODEC_TAS2781_SPI=m
-
-config SND_HDA_CODEC_REALTEK
- tristate "Build Realtek HD-audio codec support"
- depends on INPUT
- select SND_HDA_GENERIC
- select SND_HDA_GENERIC_LEDS
- select SND_HDA_SCODEC_COMPONENT
- help
- Say Y or M here to include Realtek HD-audio codec support in
- snd-hda-intel driver, such as ALC880.
-
-comment "Set to Y if you want auto-loading the codec driver"
- depends on SND_HDA=y && SND_HDA_CODEC_REALTEK=m
-
-config SND_HDA_CODEC_ANALOG
- tristate "Build Analog Devices HD-audio codec support"
- select SND_HDA_GENERIC
- help
- Say Y or M here to include Analog Devices HD-audio codec support in
- snd-hda-intel driver, such as AD1986A.
-
-comment "Set to Y if you want auto-loading the codec driver"
- depends on SND_HDA=y && SND_HDA_CODEC_ANALOG=m
-
-config SND_HDA_CODEC_SIGMATEL
- tristate "Build IDT/Sigmatel HD-audio codec support"
- select SND_HDA_GENERIC
- select SND_HDA_GENERIC_LEDS
- help
- Say Y or M here to include IDT (Sigmatel) HD-audio codec support in
- snd-hda-intel driver, such as STAC9200.
-
-comment "Set to Y if you want auto-loading the codec driver"
- depends on SND_HDA=y && SND_HDA_CODEC_SIGMATEL=m
-
-config SND_HDA_CODEC_VIA
- tristate "Build VIA HD-audio codec support"
- select SND_HDA_GENERIC
- help
- Say Y or M here to include VIA HD-audio codec support in
- snd-hda-intel driver, such as VT1708.
-
-comment "Set to Y if you want auto-loading the codec driver"
- depends on SND_HDA=y && SND_HDA_CODEC_VIA=m
-
-config SND_HDA_CODEC_HDMI
- tristate "Build HDMI/DisplayPort HD-audio codec support"
- select SND_DYNAMIC_MINORS
- select SND_PCM_ELD
- help
- Say Y or M here to include HDMI and DisplayPort HD-audio codec
- support in snd-hda-intel driver. This includes all AMD/ATI,
- Intel and Nvidia HDMI/DisplayPort codecs.
-
- Note that this option mandatorily enables CONFIG_SND_DYNAMIC_MINORS
- to assure the multiple streams for DP-MST support.
-
-comment "Set to Y if you want auto-loading the codec driver"
- depends on SND_HDA=y && SND_HDA_CODEC_HDMI=m
-
-config SND_HDA_CODEC_CIRRUS
- tristate "Build Cirrus Logic codec support"
- select SND_HDA_GENERIC
- help
- Say Y or M here to include Cirrus Logic codec support in
- snd-hda-intel driver, such as CS4206.
-
-comment "Set to Y if you want auto-loading the codec driver"
- depends on SND_HDA=y && SND_HDA_CODEC_CIRRUS=m
-
-config SND_HDA_CODEC_CS8409
- tristate "Build Cirrus Logic HDA bridge support"
- select SND_HDA_GENERIC
- help
- Say Y or M here to include Cirrus Logic HDA bridge support in
- snd-hda-intel driver, such as CS8409.
-
-comment "Set to Y if you want auto-loading the codec driver"
- depends on SND_HDA=y && SND_HDA_CODEC_CS8409=m
-
-config SND_HDA_CODEC_CONEXANT
- tristate "Build Conexant HD-audio codec support"
- select SND_HDA_GENERIC
- select SND_HDA_GENERIC_LEDS
- help
- Say Y or M here to include Conexant HD-audio codec support in
- snd-hda-intel driver, such as CX20549.
-
-comment "Set to Y if you want auto-loading the codec driver"
- depends on SND_HDA=y && SND_HDA_CODEC_CONEXANT=m
-
-config SND_HDA_CODEC_SENARYTECH
- tristate "Build Senarytech HD-audio codec support"
- select SND_HDA_GENERIC
- select SND_HDA_GENERIC_LEDS
- help
- Say Y or M here to include Senarytech HD-audio codec support in
- snd-hda-intel driver, such as SN6186.
-
-comment "Set to Y if you want auto-loading the codec driver"
- depends on SND_HDA=y && SND_HDA_CODEC_SENARYTECH=m
-
-config SND_HDA_CODEC_CA0110
- tristate "Build Creative CA0110-IBG codec support"
- select SND_HDA_GENERIC
- help
- Say Y or M here to include Creative CA0110-IBG codec support in
- snd-hda-intel driver, found on some Creative X-Fi cards.
-
-comment "Set to Y if you want auto-loading the codec driver"
- depends on SND_HDA=y && SND_HDA_CODEC_CA0110=m
-
-config SND_HDA_CODEC_CA0132
- tristate "Build Creative CA0132 codec support"
- help
- Say Y or M here to include Creative CA0132 codec support in
- snd-hda-intel driver.
-
-comment "Set to Y if you want auto-loading the codec driver"
- depends on SND_HDA=y && SND_HDA_CODEC_CA0132=m
-
-config SND_HDA_CODEC_CA0132_DSP
- bool "Support new DSP code for CA0132 codec"
- depends on SND_HDA_CODEC_CA0132
- default y
- select SND_HDA_DSP_LOADER
- select FW_LOADER
- help
- Say Y here to enable the DSP for Creative CA0132 for extended
- features like equalizer or echo cancellation.
-
- Note that this option requires the external firmware file
- (ctefx.bin).
-
-config SND_HDA_CODEC_CMEDIA
- tristate "Build C-Media HD-audio codec support"
- select SND_HDA_GENERIC
- help
- Say Y or M here to include C-Media HD-audio codec support in
- snd-hda-intel driver, such as CMI9880.
-
-comment "Set to Y if you want auto-loading the codec driver"
- depends on SND_HDA=y && SND_HDA_CODEC_CMEDIA=m
-
-config SND_HDA_CODEC_SI3054
- tristate "Build Silicon Labs 3054 HD-modem codec support"
- help
- Say Y or M here to include Silicon Labs 3054 HD-modem codec
- (and compatibles) support in snd-hda-intel driver.
-
-comment "Set to Y if you want auto-loading the codec driver"
- depends on SND_HDA=y && SND_HDA_CODEC_SI3054=m
-
-config SND_HDA_GENERIC
- tristate "Enable generic HD-audio codec parser"
- select SND_CTL_LED if SND_HDA_GENERIC_LEDS
- select LEDS_CLASS if SND_HDA_GENERIC_LEDS
- help
- Say Y or M here to enable the generic HD-audio codec parser
- in snd-hda-intel driver.
-
-comment "Set to Y if you want auto-loading the codec driver"
- depends on SND_HDA=y && SND_HDA_GENERIC=m
-
-config SND_HDA_POWER_SAVE_DEFAULT
- int "Default time-out for HD-audio power-save mode"
- depends on PM
- default 0
- help
- The default time-out value in seconds for HD-audio automatic
- power-save mode. 0 means to disable the power-save mode.
-
-config SND_HDA_INTEL_HDMI_SILENT_STREAM
- bool "Enable Silent Stream always for HDMI"
- depends on SND_HDA_INTEL
- help
- Say Y to enable HD-Audio Keep Alive (KAE) aka Silent Stream
- for HDMI on hardware that supports the feature.
-
- When enabled, the HDMI/DisplayPort codec will continue to provide
- a continuous clock and a valid but silent data stream to
- any connected external receiver. This allows to avoid gaps
- at start of playback. Many receivers require multiple seconds
- to start playing audio after the clock has been stopped.
- This feature can impact power consumption as resources
- are kept reserved both at transmitter and receiver.
-
-config SND_HDA_CTL_DEV_ID
- bool "Use the device identifier field for controls"
- depends on SND_HDA_INTEL
- help
- Say Y to use the device identifier field for (mixer)
- controls (old behaviour until this option is available).
-
- When enabled, the multiple HDA codecs may set the device
- field in control (mixer) element identifiers. The use
- of this field is not recommended and defined for mixer controls.
-
- The old behaviour (Y) is obsolete and will be removed. Consider
- to not enable this option.
-
-endif
-
-endmenu
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
deleted file mode 100644
index a5ab8ee2d7f9..000000000000
--- a/sound/pci/hda/Makefile
+++ /dev/null
@@ -1,84 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-snd-hda-intel-y := hda_intel.o
-snd-hda-tegra-y := hda_tegra.o
-snd-hda-acpi-y := hda_acpi.o
-
-snd-hda-codec-y := hda_bind.o hda_codec.o hda_jack.o hda_auto_parser.o hda_sysfs.o
-snd-hda-codec-y += hda_controller.o
-snd-hda-codec-$(CONFIG_SND_PROC_FS) += hda_proc.o
-
-snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o
-snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o
-
-# for trace-points
-CFLAGS_hda_controller.o := -I$(src)
-CFLAGS_hda_intel.o := -I$(src)
-
-snd-hda-codec-generic-y := hda_generic.o
-snd-hda-codec-realtek-y := patch_realtek.o
-snd-hda-codec-cmedia-y := patch_cmedia.o
-snd-hda-codec-analog-y := patch_analog.o
-snd-hda-codec-idt-y := patch_sigmatel.o
-snd-hda-codec-si3054-y := patch_si3054.o
-snd-hda-codec-cirrus-y := patch_cirrus.o
-snd-hda-codec-cs8409-y := patch_cs8409.o patch_cs8409-tables.o
-snd-hda-codec-ca0110-y := patch_ca0110.o
-snd-hda-codec-ca0132-y := patch_ca0132.o
-snd-hda-codec-conexant-y := patch_conexant.o
-snd-hda-codec-senarytech-y :=patch_senarytech.o
-snd-hda-codec-via-y := patch_via.o
-snd-hda-codec-hdmi-y := patch_hdmi.o hda_eld.o
-
-# side codecs
-snd-hda-cirrus-scodec-y := cirrus_scodec.o
-snd-hda-cirrus-scodec-test-y := cirrus_scodec_test.o
-snd-hda-scodec-cs35l41-y := cs35l41_hda.o cs35l41_hda_property.o
-snd-hda-scodec-cs35l41-i2c-y := cs35l41_hda_i2c.o
-snd-hda-scodec-cs35l41-spi-y := cs35l41_hda_spi.o
-snd-hda-scodec-cs35l56-y := cs35l56_hda.o
-snd-hda-scodec-cs35l56-i2c-y := cs35l56_hda_i2c.o
-snd-hda-scodec-cs35l56-spi-y := cs35l56_hda_spi.o
-snd-hda-scodec-component-y := hda_component.o
-snd-hda-scodec-tas2781-y := tas2781_hda.o
-snd-hda-scodec-tas2781-i2c-y := tas2781_hda_i2c.o
-snd-hda-scodec-tas2781-spi-y := tas2781_hda_spi.o
-
-# common driver
-obj-$(CONFIG_SND_HDA) := snd-hda-codec.o
-
-# codec drivers
-obj-$(CONFIG_SND_HDA_GENERIC) += snd-hda-codec-generic.o
-obj-$(CONFIG_SND_HDA_CODEC_REALTEK) += snd-hda-codec-realtek.o
-obj-$(CONFIG_SND_HDA_CODEC_CMEDIA) += snd-hda-codec-cmedia.o
-obj-$(CONFIG_SND_HDA_CODEC_ANALOG) += snd-hda-codec-analog.o
-obj-$(CONFIG_SND_HDA_CODEC_SIGMATEL) += snd-hda-codec-idt.o
-obj-$(CONFIG_SND_HDA_CODEC_SI3054) += snd-hda-codec-si3054.o
-obj-$(CONFIG_SND_HDA_CODEC_CIRRUS) += snd-hda-codec-cirrus.o
-obj-$(CONFIG_SND_HDA_CODEC_CS8409) += snd-hda-codec-cs8409.o
-obj-$(CONFIG_SND_HDA_CODEC_CA0110) += snd-hda-codec-ca0110.o
-obj-$(CONFIG_SND_HDA_CODEC_CA0132) += snd-hda-codec-ca0132.o
-obj-$(CONFIG_SND_HDA_CODEC_CONEXANT) += snd-hda-codec-conexant.o
-obj-$(CONFIG_SND_HDA_CODEC_SENARYTECH) += snd-hda-codec-senarytech.o
-obj-$(CONFIG_SND_HDA_CODEC_VIA) += snd-hda-codec-via.o
-obj-$(CONFIG_SND_HDA_CODEC_HDMI) += snd-hda-codec-hdmi.o
-
-# side codecs
-obj-$(CONFIG_SND_HDA_CIRRUS_SCODEC) += snd-hda-cirrus-scodec.o
-obj-$(CONFIG_SND_HDA_CIRRUS_SCODEC_KUNIT_TEST) += snd-hda-cirrus-scodec-test.o
-obj-$(CONFIG_SND_HDA_SCODEC_CS35L41) += snd-hda-scodec-cs35l41.o
-obj-$(CONFIG_SND_HDA_SCODEC_CS35L41_I2C) += snd-hda-scodec-cs35l41-i2c.o
-obj-$(CONFIG_SND_HDA_SCODEC_CS35L41_SPI) += snd-hda-scodec-cs35l41-spi.o
-obj-$(CONFIG_SND_HDA_SCODEC_CS35L56) += snd-hda-scodec-cs35l56.o
-obj-$(CONFIG_SND_HDA_SCODEC_CS35L56_I2C) += snd-hda-scodec-cs35l56-i2c.o
-obj-$(CONFIG_SND_HDA_SCODEC_CS35L56_SPI) += snd-hda-scodec-cs35l56-spi.o
-obj-$(CONFIG_SND_HDA_SCODEC_COMPONENT) += snd-hda-scodec-component.o
-obj-$(CONFIG_SND_HDA_SCODEC_TAS2781) += snd-hda-scodec-tas2781.o
-obj-$(CONFIG_SND_HDA_SCODEC_TAS2781_I2C) += snd-hda-scodec-tas2781-i2c.o
-obj-$(CONFIG_SND_HDA_SCODEC_TAS2781_SPI) += snd-hda-scodec-tas2781-spi.o
-
-# this must be the last entry after codec drivers;
-# otherwise the codec patches won't be hooked before the PCI probe
-# when built in kernel
-obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-intel.o
-obj-$(CONFIG_SND_HDA_TEGRA) += snd-hda-tegra.o
-obj-$(CONFIG_SND_HDA_ACPI) += snd-hda-acpi.o
diff --git a/sound/pci/hda/ca0132_regs.h b/sound/pci/hda/ca0132_regs.h
deleted file mode 100644
index 0ead571fb447..000000000000
--- a/sound/pci/hda/ca0132_regs.h
+++ /dev/null
@@ -1,396 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * HD audio interface patch for Creative CA0132 chip.
- * CA0132 registers defines.
- *
- * Copyright (c) 2011, Creative Technology Ltd.
- */
-
-#ifndef __CA0132_REGS_H
-#define __CA0132_REGS_H
-
-#define DSP_CHIP_OFFSET 0x100000
-#define DSP_DBGCNTL_MODULE_OFFSET 0xE30
-#define DSP_DBGCNTL_INST_OFFSET \
- (DSP_CHIP_OFFSET + DSP_DBGCNTL_MODULE_OFFSET)
-
-#define DSP_DBGCNTL_EXEC_LOBIT 0x0
-#define DSP_DBGCNTL_EXEC_HIBIT 0x3
-#define DSP_DBGCNTL_EXEC_MASK 0xF
-
-#define DSP_DBGCNTL_SS_LOBIT 0x4
-#define DSP_DBGCNTL_SS_HIBIT 0x7
-#define DSP_DBGCNTL_SS_MASK 0xF0
-
-#define DSP_DBGCNTL_STATE_LOBIT 0xA
-#define DSP_DBGCNTL_STATE_HIBIT 0xD
-#define DSP_DBGCNTL_STATE_MASK 0x3C00
-
-#define XRAM_CHIP_OFFSET 0x0
-#define XRAM_XRAM_CHANNEL_COUNT 0xE000
-#define XRAM_XRAM_MODULE_OFFSET 0x0
-#define XRAM_XRAM_CHAN_INCR 4
-#define XRAM_XRAM_INST_OFFSET(_chan) \
- (XRAM_CHIP_OFFSET + XRAM_XRAM_MODULE_OFFSET + \
- (_chan * XRAM_XRAM_CHAN_INCR))
-
-#define YRAM_CHIP_OFFSET 0x40000
-#define YRAM_YRAM_CHANNEL_COUNT 0x8000
-#define YRAM_YRAM_MODULE_OFFSET 0x0
-#define YRAM_YRAM_CHAN_INCR 4
-#define YRAM_YRAM_INST_OFFSET(_chan) \
- (YRAM_CHIP_OFFSET + YRAM_YRAM_MODULE_OFFSET + \
- (_chan * YRAM_YRAM_CHAN_INCR))
-
-#define UC_CHIP_OFFSET 0x80000
-#define UC_UC_CHANNEL_COUNT 0x10000
-#define UC_UC_MODULE_OFFSET 0x0
-#define UC_UC_CHAN_INCR 4
-#define UC_UC_INST_OFFSET(_chan) \
- (UC_CHIP_OFFSET + UC_UC_MODULE_OFFSET + \
- (_chan * UC_UC_CHAN_INCR))
-
-#define AXRAM_CHIP_OFFSET 0x3C000
-#define AXRAM_AXRAM_CHANNEL_COUNT 0x1000
-#define AXRAM_AXRAM_MODULE_OFFSET 0x0
-#define AXRAM_AXRAM_CHAN_INCR 4
-#define AXRAM_AXRAM_INST_OFFSET(_chan) \
- (AXRAM_CHIP_OFFSET + AXRAM_AXRAM_MODULE_OFFSET + \
- (_chan * AXRAM_AXRAM_CHAN_INCR))
-
-#define AYRAM_CHIP_OFFSET 0x78000
-#define AYRAM_AYRAM_CHANNEL_COUNT 0x1000
-#define AYRAM_AYRAM_MODULE_OFFSET 0x0
-#define AYRAM_AYRAM_CHAN_INCR 4
-#define AYRAM_AYRAM_INST_OFFSET(_chan) \
- (AYRAM_CHIP_OFFSET + AYRAM_AYRAM_MODULE_OFFSET + \
- (_chan * AYRAM_AYRAM_CHAN_INCR))
-
-#define DSPDMAC_CHIP_OFFSET 0x110000
-#define DSPDMAC_DMA_CFG_CHANNEL_COUNT 12
-#define DSPDMAC_DMACFG_MODULE_OFFSET 0xF00
-#define DSPDMAC_DMACFG_CHAN_INCR 0x10
-#define DSPDMAC_DMACFG_INST_OFFSET(_chan) \
- (DSPDMAC_CHIP_OFFSET + DSPDMAC_DMACFG_MODULE_OFFSET + \
- (_chan * DSPDMAC_DMACFG_CHAN_INCR))
-
-#define DSPDMAC_DMACFG_DBADR_LOBIT 0x0
-#define DSPDMAC_DMACFG_DBADR_HIBIT 0x10
-#define DSPDMAC_DMACFG_DBADR_MASK 0x1FFFF
-#define DSPDMAC_DMACFG_LP_LOBIT 0x11
-#define DSPDMAC_DMACFG_LP_HIBIT 0x11
-#define DSPDMAC_DMACFG_LP_MASK 0x20000
-
-#define DSPDMAC_DMACFG_AINCR_LOBIT 0x12
-#define DSPDMAC_DMACFG_AINCR_HIBIT 0x12
-#define DSPDMAC_DMACFG_AINCR_MASK 0x40000
-
-#define DSPDMAC_DMACFG_DWR_LOBIT 0x13
-#define DSPDMAC_DMACFG_DWR_HIBIT 0x13
-#define DSPDMAC_DMACFG_DWR_MASK 0x80000
-
-#define DSPDMAC_DMACFG_AJUMP_LOBIT 0x14
-#define DSPDMAC_DMACFG_AJUMP_HIBIT 0x17
-#define DSPDMAC_DMACFG_AJUMP_MASK 0xF00000
-
-#define DSPDMAC_DMACFG_AMODE_LOBIT 0x18
-#define DSPDMAC_DMACFG_AMODE_HIBIT 0x19
-#define DSPDMAC_DMACFG_AMODE_MASK 0x3000000
-
-#define DSPDMAC_DMACFG_LK_LOBIT 0x1A
-#define DSPDMAC_DMACFG_LK_HIBIT 0x1A
-#define DSPDMAC_DMACFG_LK_MASK 0x4000000
-
-#define DSPDMAC_DMACFG_AICS_LOBIT 0x1B
-#define DSPDMAC_DMACFG_AICS_HIBIT 0x1F
-#define DSPDMAC_DMACFG_AICS_MASK 0xF8000000
-
-#define DSPDMAC_DMACFG_LP_SINGLE 0
-#define DSPDMAC_DMACFG_LP_LOOPING 1
-
-#define DSPDMAC_DMACFG_AINCR_XANDY 0
-#define DSPDMAC_DMACFG_AINCR_XORY 1
-
-#define DSPDMAC_DMACFG_DWR_DMA_RD 0
-#define DSPDMAC_DMACFG_DWR_DMA_WR 1
-
-#define DSPDMAC_DMACFG_AMODE_LINEAR 0
-#define DSPDMAC_DMACFG_AMODE_RSV1 1
-#define DSPDMAC_DMACFG_AMODE_WINTLV 2
-#define DSPDMAC_DMACFG_AMODE_GINTLV 3
-
-#define DSPDMAC_DSP_ADR_OFS_CHANNEL_COUNT 12
-#define DSPDMAC_DSPADROFS_MODULE_OFFSET 0xF04
-#define DSPDMAC_DSPADROFS_CHAN_INCR 0x10
-#define DSPDMAC_DSPADROFS_INST_OFFSET(_chan) \
- (DSPDMAC_CHIP_OFFSET + DSPDMAC_DSPADROFS_MODULE_OFFSET + \
- (_chan * DSPDMAC_DSPADROFS_CHAN_INCR))
-
-#define DSPDMAC_DSPADROFS_COFS_LOBIT 0x0
-#define DSPDMAC_DSPADROFS_COFS_HIBIT 0xF
-#define DSPDMAC_DSPADROFS_COFS_MASK 0xFFFF
-
-#define DSPDMAC_DSPADROFS_BOFS_LOBIT 0x10
-#define DSPDMAC_DSPADROFS_BOFS_HIBIT 0x1F
-#define DSPDMAC_DSPADROFS_BOFS_MASK 0xFFFF0000
-
-#define DSPDMAC_DSP_ADR_WOFS_CHANNEL_COUNT 12
-#define DSPDMAC_DSPADRWOFS_MODULE_OFFSET 0xF04
-#define DSPDMAC_DSPADRWOFS_CHAN_INCR 0x10
-
-#define DSPDMAC_DSPADRWOFS_INST_OFFSET(_chan) \
- (DSPDMAC_CHIP_OFFSET + DSPDMAC_DSPADRWOFS_MODULE_OFFSET + \
- (_chan * DSPDMAC_DSPADRWOFS_CHAN_INCR))
-
-#define DSPDMAC_DSPADRWOFS_WCOFS_LOBIT 0x0
-#define DSPDMAC_DSPADRWOFS_WCOFS_HIBIT 0xA
-#define DSPDMAC_DSPADRWOFS_WCOFS_MASK 0x7FF
-
-#define DSPDMAC_DSPADRWOFS_WCBFR_LOBIT 0xB
-#define DSPDMAC_DSPADRWOFS_WCBFR_HIBIT 0xF
-#define DSPDMAC_DSPADRWOFS_WCBFR_MASK 0xF800
-
-#define DSPDMAC_DSPADRWOFS_WBOFS_LOBIT 0x10
-#define DSPDMAC_DSPADRWOFS_WBOFS_HIBIT 0x1A
-#define DSPDMAC_DSPADRWOFS_WBOFS_MASK 0x7FF0000
-
-#define DSPDMAC_DSPADRWOFS_WBBFR_LOBIT 0x1B
-#define DSPDMAC_DSPADRWOFS_WBBFR_HIBIT 0x1F
-#define DSPDMAC_DSPADRWOFS_WBBFR_MASK 0xF8000000
-
-#define DSPDMAC_DSP_ADR_GOFS_CHANNEL_COUNT 12
-#define DSPDMAC_DSPADRGOFS_MODULE_OFFSET 0xF04
-#define DSPDMAC_DSPADRGOFS_CHAN_INCR 0x10
-#define DSPDMAC_DSPADRGOFS_INST_OFFSET(_chan) \
- (DSPDMAC_CHIP_OFFSET + DSPDMAC_DSPADRGOFS_MODULE_OFFSET + \
- (_chan * DSPDMAC_DSPADRGOFS_CHAN_INCR))
-
-#define DSPDMAC_DSPADRGOFS_GCOFS_LOBIT 0x0
-#define DSPDMAC_DSPADRGOFS_GCOFS_HIBIT 0x9
-#define DSPDMAC_DSPADRGOFS_GCOFS_MASK 0x3FF
-
-#define DSPDMAC_DSPADRGOFS_GCS_LOBIT 0xA
-#define DSPDMAC_DSPADRGOFS_GCS_HIBIT 0xC
-#define DSPDMAC_DSPADRGOFS_GCS_MASK 0x1C00
-
-#define DSPDMAC_DSPADRGOFS_GCBFR_LOBIT 0xD
-#define DSPDMAC_DSPADRGOFS_GCBFR_HIBIT 0xF
-#define DSPDMAC_DSPADRGOFS_GCBFR_MASK 0xE000
-
-#define DSPDMAC_DSPADRGOFS_GBOFS_LOBIT 0x10
-#define DSPDMAC_DSPADRGOFS_GBOFS_HIBIT 0x19
-#define DSPDMAC_DSPADRGOFS_GBOFS_MASK 0x3FF0000
-
-#define DSPDMAC_DSPADRGOFS_GBS_LOBIT 0x1A
-#define DSPDMAC_DSPADRGOFS_GBS_HIBIT 0x1C
-#define DSPDMAC_DSPADRGOFS_GBS_MASK 0x1C000000
-
-#define DSPDMAC_DSPADRGOFS_GBBFR_LOBIT 0x1D
-#define DSPDMAC_DSPADRGOFS_GBBFR_HIBIT 0x1F
-#define DSPDMAC_DSPADRGOFS_GBBFR_MASK 0xE0000000
-
-#define DSPDMAC_XFR_CNT_CHANNEL_COUNT 12
-#define DSPDMAC_XFRCNT_MODULE_OFFSET 0xF08
-#define DSPDMAC_XFRCNT_CHAN_INCR 0x10
-
-#define DSPDMAC_XFRCNT_INST_OFFSET(_chan) \
- (DSPDMAC_CHIP_OFFSET + DSPDMAC_XFRCNT_MODULE_OFFSET + \
- (_chan * DSPDMAC_XFRCNT_CHAN_INCR))
-
-#define DSPDMAC_XFRCNT_CCNT_LOBIT 0x0
-#define DSPDMAC_XFRCNT_CCNT_HIBIT 0xF
-#define DSPDMAC_XFRCNT_CCNT_MASK 0xFFFF
-
-#define DSPDMAC_XFRCNT_BCNT_LOBIT 0x10
-#define DSPDMAC_XFRCNT_BCNT_HIBIT 0x1F
-#define DSPDMAC_XFRCNT_BCNT_MASK 0xFFFF0000
-
-#define DSPDMAC_IRQ_CNT_CHANNEL_COUNT 12
-#define DSPDMAC_IRQCNT_MODULE_OFFSET 0xF0C
-#define DSPDMAC_IRQCNT_CHAN_INCR 0x10
-#define DSPDMAC_IRQCNT_INST_OFFSET(_chan) \
- (DSPDMAC_CHIP_OFFSET + DSPDMAC_IRQCNT_MODULE_OFFSET + \
- (_chan * DSPDMAC_IRQCNT_CHAN_INCR))
-
-#define DSPDMAC_IRQCNT_CICNT_LOBIT 0x0
-#define DSPDMAC_IRQCNT_CICNT_HIBIT 0xF
-#define DSPDMAC_IRQCNT_CICNT_MASK 0xFFFF
-
-#define DSPDMAC_IRQCNT_BICNT_LOBIT 0x10
-#define DSPDMAC_IRQCNT_BICNT_HIBIT 0x1F
-#define DSPDMAC_IRQCNT_BICNT_MASK 0xFFFF0000
-
-#define DSPDMAC_AUD_CHSEL_CHANNEL_COUNT 12
-#define DSPDMAC_AUDCHSEL_MODULE_OFFSET 0xFC0
-#define DSPDMAC_AUDCHSEL_CHAN_INCR 0x4
-#define DSPDMAC_AUDCHSEL_INST_OFFSET(_chan) \
- (DSPDMAC_CHIP_OFFSET + DSPDMAC_AUDCHSEL_MODULE_OFFSET + \
- (_chan * DSPDMAC_AUDCHSEL_CHAN_INCR))
-
-#define DSPDMAC_AUDCHSEL_ACS_LOBIT 0x0
-#define DSPDMAC_AUDCHSEL_ACS_HIBIT 0x1F
-#define DSPDMAC_AUDCHSEL_ACS_MASK 0xFFFFFFFF
-
-#define DSPDMAC_CHNLSTART_MODULE_OFFSET 0xFF0
-#define DSPDMAC_CHNLSTART_INST_OFFSET \
- (DSPDMAC_CHIP_OFFSET + DSPDMAC_CHNLSTART_MODULE_OFFSET)
-
-#define DSPDMAC_CHNLSTART_EN_LOBIT 0x0
-#define DSPDMAC_CHNLSTART_EN_HIBIT 0xB
-#define DSPDMAC_CHNLSTART_EN_MASK 0xFFF
-
-#define DSPDMAC_CHNLSTART_VAI1_LOBIT 0xC
-#define DSPDMAC_CHNLSTART_VAI1_HIBIT 0xF
-#define DSPDMAC_CHNLSTART_VAI1_MASK 0xF000
-
-#define DSPDMAC_CHNLSTART_DIS_LOBIT 0x10
-#define DSPDMAC_CHNLSTART_DIS_HIBIT 0x1B
-#define DSPDMAC_CHNLSTART_DIS_MASK 0xFFF0000
-
-#define DSPDMAC_CHNLSTART_VAI2_LOBIT 0x1C
-#define DSPDMAC_CHNLSTART_VAI2_HIBIT 0x1F
-#define DSPDMAC_CHNLSTART_VAI2_MASK 0xF0000000
-
-#define DSPDMAC_CHNLSTATUS_MODULE_OFFSET 0xFF4
-#define DSPDMAC_CHNLSTATUS_INST_OFFSET \
- (DSPDMAC_CHIP_OFFSET + DSPDMAC_CHNLSTATUS_MODULE_OFFSET)
-
-#define DSPDMAC_CHNLSTATUS_ISC_LOBIT 0x0
-#define DSPDMAC_CHNLSTATUS_ISC_HIBIT 0xB
-#define DSPDMAC_CHNLSTATUS_ISC_MASK 0xFFF
-
-#define DSPDMAC_CHNLSTATUS_AOO_LOBIT 0xC
-#define DSPDMAC_CHNLSTATUS_AOO_HIBIT 0xC
-#define DSPDMAC_CHNLSTATUS_AOO_MASK 0x1000
-
-#define DSPDMAC_CHNLSTATUS_AOU_LOBIT 0xD
-#define DSPDMAC_CHNLSTATUS_AOU_HIBIT 0xD
-#define DSPDMAC_CHNLSTATUS_AOU_MASK 0x2000
-
-#define DSPDMAC_CHNLSTATUS_AIO_LOBIT 0xE
-#define DSPDMAC_CHNLSTATUS_AIO_HIBIT 0xE
-#define DSPDMAC_CHNLSTATUS_AIO_MASK 0x4000
-
-#define DSPDMAC_CHNLSTATUS_AIU_LOBIT 0xF
-#define DSPDMAC_CHNLSTATUS_AIU_HIBIT 0xF
-#define DSPDMAC_CHNLSTATUS_AIU_MASK 0x8000
-
-#define DSPDMAC_CHNLSTATUS_IEN_LOBIT 0x10
-#define DSPDMAC_CHNLSTATUS_IEN_HIBIT 0x1B
-#define DSPDMAC_CHNLSTATUS_IEN_MASK 0xFFF0000
-
-#define DSPDMAC_CHNLSTATUS_VAI0_LOBIT 0x1C
-#define DSPDMAC_CHNLSTATUS_VAI0_HIBIT 0x1F
-#define DSPDMAC_CHNLSTATUS_VAI0_MASK 0xF0000000
-
-#define DSPDMAC_CHNLPROP_MODULE_OFFSET 0xFF8
-#define DSPDMAC_CHNLPROP_INST_OFFSET \
- (DSPDMAC_CHIP_OFFSET + DSPDMAC_CHNLPROP_MODULE_OFFSET)
-
-#define DSPDMAC_CHNLPROP_DCON_LOBIT 0x0
-#define DSPDMAC_CHNLPROP_DCON_HIBIT 0xB
-#define DSPDMAC_CHNLPROP_DCON_MASK 0xFFF
-
-#define DSPDMAC_CHNLPROP_FFS_LOBIT 0xC
-#define DSPDMAC_CHNLPROP_FFS_HIBIT 0xC
-#define DSPDMAC_CHNLPROP_FFS_MASK 0x1000
-
-#define DSPDMAC_CHNLPROP_NAJ_LOBIT 0xD
-#define DSPDMAC_CHNLPROP_NAJ_HIBIT 0xD
-#define DSPDMAC_CHNLPROP_NAJ_MASK 0x2000
-
-#define DSPDMAC_CHNLPROP_ENH_LOBIT 0xE
-#define DSPDMAC_CHNLPROP_ENH_HIBIT 0xE
-#define DSPDMAC_CHNLPROP_ENH_MASK 0x4000
-
-#define DSPDMAC_CHNLPROP_MSPCE_LOBIT 0x10
-#define DSPDMAC_CHNLPROP_MSPCE_HIBIT 0x1B
-#define DSPDMAC_CHNLPROP_MSPCE_MASK 0xFFF0000
-
-#define DSPDMAC_CHNLPROP_AC_LOBIT 0x1C
-#define DSPDMAC_CHNLPROP_AC_HIBIT 0x1F
-#define DSPDMAC_CHNLPROP_AC_MASK 0xF0000000
-
-#define DSPDMAC_ACTIVE_MODULE_OFFSET 0xFFC
-#define DSPDMAC_ACTIVE_INST_OFFSET \
- (DSPDMAC_CHIP_OFFSET + DSPDMAC_ACTIVE_MODULE_OFFSET)
-
-#define DSPDMAC_ACTIVE_AAR_LOBIT 0x0
-#define DSPDMAC_ACTIVE_AAR_HIBIT 0xB
-#define DSPDMAC_ACTIVE_AAR_MASK 0xFFF
-
-#define DSPDMAC_ACTIVE_WFR_LOBIT 0xC
-#define DSPDMAC_ACTIVE_WFR_HIBIT 0x17
-#define DSPDMAC_ACTIVE_WFR_MASK 0xFFF000
-
-#define DSP_AUX_MEM_BASE 0xE000
-#define INVALID_CHIP_ADDRESS (~0U)
-
-#define X_SIZE (XRAM_XRAM_CHANNEL_COUNT * XRAM_XRAM_CHAN_INCR)
-#define Y_SIZE (YRAM_YRAM_CHANNEL_COUNT * YRAM_YRAM_CHAN_INCR)
-#define AX_SIZE (AXRAM_AXRAM_CHANNEL_COUNT * AXRAM_AXRAM_CHAN_INCR)
-#define AY_SIZE (AYRAM_AYRAM_CHANNEL_COUNT * AYRAM_AYRAM_CHAN_INCR)
-#define UC_SIZE (UC_UC_CHANNEL_COUNT * UC_UC_CHAN_INCR)
-
-#define XEXT_SIZE (X_SIZE + AX_SIZE)
-#define YEXT_SIZE (Y_SIZE + AY_SIZE)
-
-#define U64K 0x10000UL
-
-#define X_END (XRAM_CHIP_OFFSET + X_SIZE)
-#define X_EXT (XRAM_CHIP_OFFSET + XEXT_SIZE)
-#define AX_END (XRAM_CHIP_OFFSET + U64K*4)
-
-#define Y_END (YRAM_CHIP_OFFSET + Y_SIZE)
-#define Y_EXT (YRAM_CHIP_OFFSET + YEXT_SIZE)
-#define AY_END (YRAM_CHIP_OFFSET + U64K*4)
-
-#define UC_END (UC_CHIP_OFFSET + UC_SIZE)
-
-#define X_RANGE_MAIN(a, s) \
- (((a)+((s)-1)*XRAM_XRAM_CHAN_INCR < X_END))
-#define X_RANGE_AUX(a, s) \
- (((a) >= X_END) && ((a)+((s)-1)*XRAM_XRAM_CHAN_INCR < AX_END))
-#define X_RANGE_EXT(a, s) \
- (((a)+((s)-1)*XRAM_XRAM_CHAN_INCR < X_EXT))
-#define X_RANGE_ALL(a, s) \
- (((a)+((s)-1)*XRAM_XRAM_CHAN_INCR < AX_END))
-
-#define Y_RANGE_MAIN(a, s) \
- (((a) >= YRAM_CHIP_OFFSET) && \
- ((a)+((s)-1)*YRAM_YRAM_CHAN_INCR < Y_END))
-#define Y_RANGE_AUX(a, s) \
- (((a) >= Y_END) && \
- ((a)+((s)-1)*YRAM_YRAM_CHAN_INCR < AY_END))
-#define Y_RANGE_EXT(a, s) \
- (((a) >= YRAM_CHIP_OFFSET) && \
- ((a)+((s)-1)*YRAM_YRAM_CHAN_INCR < Y_EXT))
-#define Y_RANGE_ALL(a, s) \
- (((a) >= YRAM_CHIP_OFFSET) && \
- ((a)+((s)-1)*YRAM_YRAM_CHAN_INCR < AY_END))
-
-#define UC_RANGE(a, s) \
- (((a) >= UC_CHIP_OFFSET) && \
- ((a)+((s)-1)*UC_UC_CHAN_INCR < UC_END))
-
-#define X_OFF(a) \
- (((a) - XRAM_CHIP_OFFSET) / XRAM_XRAM_CHAN_INCR)
-#define AX_OFF(a) \
- (((a) % (AXRAM_AXRAM_CHANNEL_COUNT * \
- AXRAM_AXRAM_CHAN_INCR)) / AXRAM_AXRAM_CHAN_INCR)
-
-#define Y_OFF(a) \
- (((a) - YRAM_CHIP_OFFSET) / YRAM_YRAM_CHAN_INCR)
-#define AY_OFF(a) \
- (((a) % (AYRAM_AYRAM_CHANNEL_COUNT * \
- AYRAM_AYRAM_CHAN_INCR)) / AYRAM_AYRAM_CHAN_INCR)
-
-#define UC_OFF(a) (((a) - UC_CHIP_OFFSET) / UC_UC_CHAN_INCR)
-
-#define X_EXT_MAIN_SIZE(a) (XRAM_XRAM_CHANNEL_COUNT - X_OFF(a))
-#define X_EXT_AUX_SIZE(a, s) ((s) - X_EXT_MAIN_SIZE(a))
-
-#define Y_EXT_MAIN_SIZE(a) (YRAM_YRAM_CHANNEL_COUNT - Y_OFF(a))
-#define Y_EXT_AUX_SIZE(a, s) ((s) - Y_EXT_MAIN_SIZE(a))
-
-#endif
diff --git a/sound/pci/hda/cirrus_scodec.c b/sound/pci/hda/cirrus_scodec.c
deleted file mode 100644
index 3c670207ba30..000000000000
--- a/sound/pci/hda/cirrus_scodec.c
+++ /dev/null
@@ -1,73 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-//
-// Common code for Cirrus side-codecs.
-//
-// Copyright (C) 2021, 2023 Cirrus Logic, Inc. and
-// Cirrus Logic International Semiconductor Ltd.
-
-#include <linux/dev_printk.h>
-#include <linux/gpio/consumer.h>
-#include <linux/module.h>
-
-#include "cirrus_scodec.h"
-
-int cirrus_scodec_get_speaker_id(struct device *dev, int amp_index,
- int num_amps, int fixed_gpio_id)
-{
- struct gpio_desc *speaker_id_desc;
- int speaker_id = -ENOENT;
-
- if (fixed_gpio_id >= 0) {
- dev_dbg(dev, "Found Fixed Speaker ID GPIO (index = %d)\n", fixed_gpio_id);
- speaker_id_desc = gpiod_get_index(dev, NULL, fixed_gpio_id, GPIOD_IN);
- if (IS_ERR(speaker_id_desc)) {
- speaker_id = PTR_ERR(speaker_id_desc);
- return speaker_id;
- }
- speaker_id = gpiod_get_value_cansleep(speaker_id_desc);
- gpiod_put(speaker_id_desc);
- } else {
- int base_index;
- int gpios_per_amp;
- int count;
- int tmp;
- int i;
-
- count = gpiod_count(dev, "spk-id");
- if (count > 0) {
- speaker_id = 0;
- gpios_per_amp = count / num_amps;
- base_index = gpios_per_amp * amp_index;
-
- if (count % num_amps)
- return -EINVAL;
-
- dev_dbg(dev, "Found %d Speaker ID GPIOs per Amp\n", gpios_per_amp);
-
- for (i = 0; i < gpios_per_amp; i++) {
- speaker_id_desc = gpiod_get_index(dev, "spk-id", i + base_index,
- GPIOD_IN);
- if (IS_ERR(speaker_id_desc)) {
- speaker_id = PTR_ERR(speaker_id_desc);
- break;
- }
- tmp = gpiod_get_value_cansleep(speaker_id_desc);
- gpiod_put(speaker_id_desc);
- if (tmp < 0) {
- speaker_id = tmp;
- break;
- }
- speaker_id |= tmp << i;
- }
- }
- }
-
- dev_dbg(dev, "Speaker ID = %d\n", speaker_id);
-
- return speaker_id;
-}
-EXPORT_SYMBOL_NS_GPL(cirrus_scodec_get_speaker_id, "SND_HDA_CIRRUS_SCODEC");
-
-MODULE_DESCRIPTION("HDA Cirrus side-codec library");
-MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
-MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/cirrus_scodec.h b/sound/pci/hda/cirrus_scodec.h
deleted file mode 100644
index ba2041d8ef24..000000000000
--- a/sound/pci/hda/cirrus_scodec.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0
- *
- * Copyright (C) 2023 Cirrus Logic, Inc. and
- * Cirrus Logic International Semiconductor Ltd.
- */
-
-#ifndef CIRRUS_SCODEC_H
-#define CIRRUS_SCODEC_H
-
-int cirrus_scodec_get_speaker_id(struct device *dev, int amp_index,
- int num_amps, int fixed_gpio_id);
-
-#endif /* CIRRUS_SCODEC_H */
diff --git a/sound/pci/hda/cirrus_scodec_test.c b/sound/pci/hda/cirrus_scodec_test.c
deleted file mode 100644
index 93b9cbf1f08a..000000000000
--- a/sound/pci/hda/cirrus_scodec_test.c
+++ /dev/null
@@ -1,332 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-//
-// KUnit test for the Cirrus side-codec library.
-//
-// Copyright (C) 2023 Cirrus Logic, Inc. and
-// Cirrus Logic International Semiconductor Ltd.
-
-#include <kunit/platform_device.h>
-#include <kunit/resource.h>
-#include <kunit/test.h>
-#include <linux/device.h>
-#include <linux/device/faux.h>
-#include <linux/gpio/driver.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-
-#include "cirrus_scodec.h"
-
-KUNIT_DEFINE_ACTION_WRAPPER(faux_device_destroy_wrapper, faux_device_destroy,
- struct faux_device *)
-KUNIT_DEFINE_ACTION_WRAPPER(device_remove_software_node_wrapper,
- device_remove_software_node,
- struct device *)
-
-struct cirrus_scodec_test_gpio {
- unsigned int pin_state;
- struct gpio_chip chip;
-};
-
-struct cirrus_scodec_test_priv {
- struct faux_device *amp_dev;
- struct platform_device *gpio_pdev;
- struct cirrus_scodec_test_gpio *gpio_priv;
-};
-
-static int cirrus_scodec_test_gpio_get_direction(struct gpio_chip *chip,
- unsigned int offset)
-{
- return GPIO_LINE_DIRECTION_IN;
-}
-
-static int cirrus_scodec_test_gpio_direction_in(struct gpio_chip *chip,
- unsigned int offset)
-{
- return 0;
-}
-
-static int cirrus_scodec_test_gpio_get(struct gpio_chip *chip, unsigned int offset)
-{
- struct cirrus_scodec_test_gpio *gpio_priv = gpiochip_get_data(chip);
-
- return !!(gpio_priv->pin_state & BIT(offset));
-}
-
-static int cirrus_scodec_test_gpio_direction_out(struct gpio_chip *chip,
- unsigned int offset, int value)
-{
- return -EOPNOTSUPP;
-}
-
-static int cirrus_scodec_test_gpio_set(struct gpio_chip *chip,
- unsigned int offset, int value)
-{
- return -EOPNOTSUPP;
-}
-
-static int cirrus_scodec_test_gpio_set_config(struct gpio_chip *gc,
- unsigned int offset,
- unsigned long config)
-{
- switch (pinconf_to_config_param(config)) {
- case PIN_CONFIG_OUTPUT:
- case PIN_CONFIG_OUTPUT_ENABLE:
- return -EOPNOTSUPP;
- default:
- return 0;
- }
-}
-
-static const struct gpio_chip cirrus_scodec_test_gpio_chip = {
- .label = "cirrus_scodec_test_gpio",
- .owner = THIS_MODULE,
- .request = gpiochip_generic_request,
- .free = gpiochip_generic_free,
- .get_direction = cirrus_scodec_test_gpio_get_direction,
- .direction_input = cirrus_scodec_test_gpio_direction_in,
- .get = cirrus_scodec_test_gpio_get,
- .direction_output = cirrus_scodec_test_gpio_direction_out,
- .set_rv = cirrus_scodec_test_gpio_set,
- .set_config = cirrus_scodec_test_gpio_set_config,
- .base = -1,
- .ngpio = 32,
-};
-
-static int cirrus_scodec_test_gpio_probe(struct platform_device *pdev)
-{
- struct cirrus_scodec_test_gpio *gpio_priv;
- int ret;
-
- gpio_priv = devm_kzalloc(&pdev->dev, sizeof(*gpio_priv), GFP_KERNEL);
- if (!gpio_priv)
- return -ENOMEM;
-
- /* GPIO core modifies our struct gpio_chip so use a copy */
- gpio_priv->chip = cirrus_scodec_test_gpio_chip;
- ret = devm_gpiochip_add_data(&pdev->dev, &gpio_priv->chip, gpio_priv);
- if (ret)
- return dev_err_probe(&pdev->dev, ret, "Failed to add gpiochip\n");
-
- dev_set_drvdata(&pdev->dev, gpio_priv);
-
- return 0;
-}
-
-static struct platform_driver cirrus_scodec_test_gpio_driver = {
- .driver.name = "cirrus_scodec_test_gpio_drv",
- .driver.owner = THIS_MODULE,
- .probe = cirrus_scodec_test_gpio_probe,
-};
-
-/* software_node referencing the gpio driver */
-static const struct software_node cirrus_scodec_test_gpio_swnode = {
- .name = "cirrus_scodec_test_gpio",
-};
-
-static void cirrus_scodec_test_create_gpio(struct kunit *test)
-{
- struct cirrus_scodec_test_priv *priv = test->priv;
-
- KUNIT_ASSERT_EQ(test, 0,
- kunit_platform_driver_register(test, &cirrus_scodec_test_gpio_driver));
-
- priv->gpio_pdev = kunit_platform_device_alloc(test,
- cirrus_scodec_test_gpio_driver.driver.name,
- PLATFORM_DEVID_NONE);
- KUNIT_ASSERT_NOT_NULL(test, priv->gpio_pdev);
-
- KUNIT_ASSERT_EQ(test, 0, device_add_software_node(&priv->gpio_pdev->dev,
- &cirrus_scodec_test_gpio_swnode));
- KUNIT_ASSERT_EQ(test, 0, kunit_add_action_or_reset(test,
- device_remove_software_node_wrapper,
- &priv->gpio_pdev->dev));
-
- KUNIT_ASSERT_EQ(test, 0, kunit_platform_device_add(test, priv->gpio_pdev));
-
- priv->gpio_priv = dev_get_drvdata(&priv->gpio_pdev->dev);
- KUNIT_ASSERT_NOT_NULL(test, priv->gpio_priv);
-}
-
-static void cirrus_scodec_test_set_gpio_ref_arg(struct software_node_ref_args *arg,
- int gpio_num)
-{
- struct software_node_ref_args template =
- SOFTWARE_NODE_REFERENCE(&cirrus_scodec_test_gpio_swnode, gpio_num, 0);
-
- *arg = template;
-}
-
-static int cirrus_scodec_test_set_spkid_swnode(struct kunit *test,
- struct device *dev,
- struct software_node_ref_args *args,
- int num_args)
-{
- const struct property_entry props_template[] = {
- PROPERTY_ENTRY_REF_ARRAY_LEN("spk-id-gpios", args, num_args),
- { }
- };
- struct property_entry *props;
- struct software_node *node;
-
- node = kunit_kzalloc(test, sizeof(*node), GFP_KERNEL);
- if (!node)
- return -ENOMEM;
-
- props = kunit_kzalloc(test, sizeof(props_template), GFP_KERNEL);
- if (!props)
- return -ENOMEM;
-
- memcpy(props, props_template, sizeof(props_template));
- node->properties = props;
-
- return device_add_software_node(dev, node);
-}
-
-struct cirrus_scodec_test_spkid_param {
- int num_amps;
- int gpios_per_amp;
- int num_amps_sharing;
-};
-
-static void cirrus_scodec_test_spkid_parse(struct kunit *test)
-{
- struct cirrus_scodec_test_priv *priv = test->priv;
- const struct cirrus_scodec_test_spkid_param *param = test->param_value;
- int num_spk_id_refs = param->num_amps * param->gpios_per_amp;
- struct software_node_ref_args *refs;
- struct device *dev = &priv->amp_dev->dev;
- unsigned int v;
- int i, ret;
-
- refs = kunit_kcalloc(test, num_spk_id_refs, sizeof(*refs), GFP_KERNEL);
- KUNIT_ASSERT_NOT_NULL(test, refs);
-
- for (i = 0, v = 0; i < num_spk_id_refs; ) {
- cirrus_scodec_test_set_gpio_ref_arg(&refs[i++], v++);
-
- /*
- * If amps are sharing GPIOs repeat the last set of
- * GPIOs until we've done that number of amps.
- * We have done all GPIOs for an amp when i is a multiple
- * of gpios_per_amp.
- * We have done all amps sharing the same GPIOs when i is
- * a multiple of (gpios_per_amp * num_amps_sharing).
- */
- if (!(i % param->gpios_per_amp) &&
- (i % (param->gpios_per_amp * param->num_amps_sharing)))
- v -= param->gpios_per_amp;
- }
-
- ret = cirrus_scodec_test_set_spkid_swnode(test, dev, refs, num_spk_id_refs);
- KUNIT_EXPECT_EQ_MSG(test, ret, 0, "Failed to add swnode\n");
-
- for (i = 0; i < param->num_amps; ++i) {
- for (v = 0; v < (1 << param->gpios_per_amp); ++v) {
- /* Set only the GPIO bits used by this amp */
- priv->gpio_priv->pin_state =
- v << (param->gpios_per_amp * (i / param->num_amps_sharing));
-
- ret = cirrus_scodec_get_speaker_id(dev, i, param->num_amps, -1);
- KUNIT_EXPECT_EQ_MSG(test, ret, v,
- "get_speaker_id failed amp:%d pin_state:%#x\n",
- i, priv->gpio_priv->pin_state);
- }
- }
-}
-
-static void cirrus_scodec_test_no_spkid(struct kunit *test)
-{
- struct cirrus_scodec_test_priv *priv = test->priv;
- struct device *dev = &priv->amp_dev->dev;
- int ret;
-
- ret = cirrus_scodec_get_speaker_id(dev, 0, 4, -1);
- KUNIT_EXPECT_EQ(test, ret, -ENOENT);
-}
-
-static int cirrus_scodec_test_case_init(struct kunit *test)
-{
- struct cirrus_scodec_test_priv *priv;
-
- priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
-
- test->priv = priv;
-
- /* Create dummy GPIO */
- cirrus_scodec_test_create_gpio(test);
-
- /* Create dummy amp driver dev */
- priv->amp_dev = faux_device_create("cirrus_scodec_test_amp_drv", NULL, NULL);
- KUNIT_ASSERT_NOT_NULL(test, priv->amp_dev);
- KUNIT_ASSERT_EQ(test, 0, kunit_add_action_or_reset(test,
- faux_device_destroy_wrapper,
- priv->amp_dev));
-
- return 0;
-}
-
-static const struct cirrus_scodec_test_spkid_param cirrus_scodec_test_spkid_param_cases[] = {
- { .num_amps = 2, .gpios_per_amp = 1, .num_amps_sharing = 1 },
- { .num_amps = 2, .gpios_per_amp = 2, .num_amps_sharing = 1 },
- { .num_amps = 2, .gpios_per_amp = 3, .num_amps_sharing = 1 },
- { .num_amps = 2, .gpios_per_amp = 4, .num_amps_sharing = 1 },
- { .num_amps = 3, .gpios_per_amp = 1, .num_amps_sharing = 1 },
- { .num_amps = 3, .gpios_per_amp = 2, .num_amps_sharing = 1 },
- { .num_amps = 3, .gpios_per_amp = 3, .num_amps_sharing = 1 },
- { .num_amps = 3, .gpios_per_amp = 4, .num_amps_sharing = 1 },
- { .num_amps = 4, .gpios_per_amp = 1, .num_amps_sharing = 1 },
- { .num_amps = 4, .gpios_per_amp = 2, .num_amps_sharing = 1 },
- { .num_amps = 4, .gpios_per_amp = 3, .num_amps_sharing = 1 },
- { .num_amps = 4, .gpios_per_amp = 4, .num_amps_sharing = 1 },
-
- /* Same GPIO shared by all amps */
- { .num_amps = 2, .gpios_per_amp = 1, .num_amps_sharing = 2 },
- { .num_amps = 2, .gpios_per_amp = 2, .num_amps_sharing = 2 },
- { .num_amps = 2, .gpios_per_amp = 3, .num_amps_sharing = 2 },
- { .num_amps = 2, .gpios_per_amp = 4, .num_amps_sharing = 2 },
- { .num_amps = 3, .gpios_per_amp = 1, .num_amps_sharing = 3 },
- { .num_amps = 3, .gpios_per_amp = 2, .num_amps_sharing = 3 },
- { .num_amps = 3, .gpios_per_amp = 3, .num_amps_sharing = 3 },
- { .num_amps = 3, .gpios_per_amp = 4, .num_amps_sharing = 3 },
- { .num_amps = 4, .gpios_per_amp = 1, .num_amps_sharing = 4 },
- { .num_amps = 4, .gpios_per_amp = 2, .num_amps_sharing = 4 },
- { .num_amps = 4, .gpios_per_amp = 3, .num_amps_sharing = 4 },
- { .num_amps = 4, .gpios_per_amp = 4, .num_amps_sharing = 4 },
-
- /* Two sets of shared GPIOs */
- { .num_amps = 4, .gpios_per_amp = 1, .num_amps_sharing = 2 },
- { .num_amps = 4, .gpios_per_amp = 2, .num_amps_sharing = 2 },
- { .num_amps = 4, .gpios_per_amp = 3, .num_amps_sharing = 2 },
- { .num_amps = 4, .gpios_per_amp = 4, .num_amps_sharing = 2 },
-};
-
-static void cirrus_scodec_test_spkid_param_desc(const struct cirrus_scodec_test_spkid_param *param,
- char *desc)
-{
- snprintf(desc, KUNIT_PARAM_DESC_SIZE, "amps:%d gpios_per_amp:%d num_amps_sharing:%d",
- param->num_amps, param->gpios_per_amp, param->num_amps_sharing);
-}
-
-KUNIT_ARRAY_PARAM(cirrus_scodec_test_spkid, cirrus_scodec_test_spkid_param_cases,
- cirrus_scodec_test_spkid_param_desc);
-
-static struct kunit_case cirrus_scodec_test_cases[] = {
- KUNIT_CASE_PARAM(cirrus_scodec_test_spkid_parse, cirrus_scodec_test_spkid_gen_params),
- KUNIT_CASE(cirrus_scodec_test_no_spkid),
- { } /* terminator */
-};
-
-static struct kunit_suite cirrus_scodec_test_suite = {
- .name = "snd-hda-scodec-cs35l56-test",
- .init = cirrus_scodec_test_case_init,
- .test_cases = cirrus_scodec_test_cases,
-};
-
-kunit_test_suite(cirrus_scodec_test_suite);
-
-MODULE_IMPORT_NS("SND_HDA_CIRRUS_SCODEC");
-MODULE_DESCRIPTION("KUnit test for the Cirrus side-codec library");
-MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
-MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c
deleted file mode 100644
index d5bc81099d0d..000000000000
--- a/sound/pci/hda/cs35l41_hda.c
+++ /dev/null
@@ -1,2087 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// CS35l41 ALSA HDA audio driver
-//
-// Copyright 2021 Cirrus Logic, Inc.
-//
-// Author: Lucas Tanure <tanureal@opensource.cirrus.com>
-
-#include <linux/acpi.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <sound/hda_codec.h>
-#include <sound/soc.h>
-#include <linux/pm_runtime.h>
-#include <linux/spi/spi.h>
-#include <linux/vmalloc.h>
-#include "hda_local.h"
-#include "hda_auto_parser.h"
-#include "hda_jack.h"
-#include "hda_generic.h"
-#include "hda_component.h"
-#include "cs35l41_hda.h"
-#include "cs35l41_hda_property.h"
-
-#define CS35L41_PART "cs35l41"
-
-#define HALO_STATE_DSP_CTL_NAME "HALO_STATE"
-#define HALO_STATE_DSP_CTL_TYPE 5
-#define HALO_STATE_DSP_CTL_ALG 262308
-#define CAL_R_DSP_CTL_NAME "CAL_R"
-#define CAL_STATUS_DSP_CTL_NAME "CAL_STATUS"
-#define CAL_CHECKSUM_DSP_CTL_NAME "CAL_CHECKSUM"
-#define CAL_AMBIENT_DSP_CTL_NAME "CAL_AMBIENT"
-#define CAL_DSP_CTL_TYPE 5
-#define CAL_DSP_CTL_ALG 205
-#define CS35L41_UUID "50d90cdc-3de4-4f18-b528-c7fe3b71f40d"
-#define CS35L41_DSM_GET_MUTE 5
-#define CS35L41_NOTIFY_EVENT 0x91
-#define CS35L41_TUNING_SIG 0x109A4A35
-
-enum cs35l41_tuning_param_types {
- TUNING_PARAM_GAIN,
-};
-
-struct cs35l41_tuning_param_hdr {
- __le32 tuning_index;
- __le32 type;
- __le32 size;
-} __packed;
-
-struct cs35l41_tuning_param {
- struct cs35l41_tuning_param_hdr hdr;
- union {
- __le32 gain;
- };
-} __packed;
-
-struct cs35l41_tuning_params {
- __le32 signature;
- __le32 version;
- __le32 size;
- __le32 num_entries;
- u8 data[];
-} __packed;
-
-/* Firmware calibration controls */
-static const struct cirrus_amp_cal_controls cs35l41_calibration_controls = {
- .alg_id = CAL_DSP_CTL_ALG,
- .mem_region = CAL_DSP_CTL_TYPE,
- .ambient = CAL_AMBIENT_DSP_CTL_NAME,
- .calr = CAL_R_DSP_CTL_NAME,
- .status = CAL_STATUS_DSP_CTL_NAME,
- .checksum = CAL_CHECKSUM_DSP_CTL_NAME,
-};
-
-enum cs35l41_hda_fw_id {
- CS35L41_HDA_FW_SPK_PROT,
- CS35L41_HDA_FW_SPK_CALI,
- CS35L41_HDA_FW_SPK_DIAG,
- CS35L41_HDA_FW_MISC,
- CS35L41_HDA_NUM_FW
-};
-
-static const char * const cs35l41_hda_fw_ids[CS35L41_HDA_NUM_FW] = {
- [CS35L41_HDA_FW_SPK_PROT] = "spk-prot",
- [CS35L41_HDA_FW_SPK_CALI] = "spk-cali",
- [CS35L41_HDA_FW_SPK_DIAG] = "spk-diag",
- [CS35L41_HDA_FW_MISC] = "misc",
-};
-
-static bool firmware_autostart = 1;
-module_param(firmware_autostart, bool, 0444);
-MODULE_PARM_DESC(firmware_autostart, "Allow automatic firmware download on boot"
- "(0=Disable, 1=Enable) (default=1); ");
-
-static const struct reg_sequence cs35l41_hda_config[] = {
- { CS35L41_PLL_CLK_CTRL, 0x00000430 }, // 3072000Hz, BCLK Input, PLL_REFCLK_EN = 1
- { CS35L41_DSP_CLK_CTRL, 0x00000003 }, // DSP CLK EN
- { CS35L41_GLOBAL_CLK_CTRL, 0x00000003 }, // GLOBAL_FS = 48 kHz
- { CS35L41_SP_ENABLES, 0x00010000 }, // ASP_RX1_EN = 1
- { CS35L41_SP_RATE_CTRL, 0x00000021 }, // ASP_BCLK_FREQ = 3.072 MHz
- { CS35L41_SP_FORMAT, 0x20200200 }, // 32 bits RX/TX slots, I2S, clk consumer
- { CS35L41_SP_HIZ_CTRL, 0x00000002 }, // Hi-Z unused
- { CS35L41_SP_TX_WL, 0x00000018 }, // 24 cycles/slot
- { CS35L41_SP_RX_WL, 0x00000018 }, // 24 cycles/slot
- { CS35L41_DAC_PCM1_SRC, 0x00000008 }, // DACPCM1_SRC = ASPRX1
- { CS35L41_ASP_TX1_SRC, 0x00000018 }, // ASPTX1 SRC = VMON
- { CS35L41_ASP_TX2_SRC, 0x00000019 }, // ASPTX2 SRC = IMON
- { CS35L41_ASP_TX3_SRC, 0x00000032 }, // ASPTX3 SRC = ERRVOL
- { CS35L41_ASP_TX4_SRC, 0x00000033 }, // ASPTX4 SRC = CLASSH_TGT
- { CS35L41_DSP1_RX1_SRC, 0x00000008 }, // DSP1RX1 SRC = ASPRX1
- { CS35L41_DSP1_RX2_SRC, 0x00000009 }, // DSP1RX2 SRC = ASPRX2
- { CS35L41_DSP1_RX3_SRC, 0x00000018 }, // DSP1RX3 SRC = VMON
- { CS35L41_DSP1_RX4_SRC, 0x00000019 }, // DSP1RX4 SRC = IMON
- { CS35L41_DSP1_RX5_SRC, 0x00000020 }, // DSP1RX5 SRC = ERRVOL
-};
-
-static const struct reg_sequence cs35l41_hda_config_dsp[] = {
- { CS35L41_PLL_CLK_CTRL, 0x00000430 }, // 3072000Hz, BCLK Input, PLL_REFCLK_EN = 1
- { CS35L41_DSP_CLK_CTRL, 0x00000003 }, // DSP CLK EN
- { CS35L41_GLOBAL_CLK_CTRL, 0x00000003 }, // GLOBAL_FS = 48 kHz
- { CS35L41_SP_ENABLES, 0x00010001 }, // ASP_RX1_EN = 1, ASP_TX1_EN = 1
- { CS35L41_SP_RATE_CTRL, 0x00000021 }, // ASP_BCLK_FREQ = 3.072 MHz
- { CS35L41_SP_FORMAT, 0x20200200 }, // 32 bits RX/TX slots, I2S, clk consumer
- { CS35L41_SP_HIZ_CTRL, 0x00000003 }, // Hi-Z unused/disabled
- { CS35L41_SP_TX_WL, 0x00000018 }, // 24 cycles/slot
- { CS35L41_SP_RX_WL, 0x00000018 }, // 24 cycles/slot
- { CS35L41_DAC_PCM1_SRC, 0x00000032 }, // DACPCM1_SRC = DSP1TX1
- { CS35L41_ASP_TX1_SRC, 0x00000018 }, // ASPTX1 SRC = VMON
- { CS35L41_ASP_TX2_SRC, 0x00000019 }, // ASPTX2 SRC = IMON
- { CS35L41_ASP_TX3_SRC, 0x00000028 }, // ASPTX3 SRC = VPMON
- { CS35L41_ASP_TX4_SRC, 0x00000029 }, // ASPTX4 SRC = VBSTMON
- { CS35L41_DSP1_RX1_SRC, 0x00000008 }, // DSP1RX1 SRC = ASPRX1
- { CS35L41_DSP1_RX2_SRC, 0x00000008 }, // DSP1RX2 SRC = ASPRX1
- { CS35L41_DSP1_RX3_SRC, 0x00000018 }, // DSP1RX3 SRC = VMON
- { CS35L41_DSP1_RX4_SRC, 0x00000019 }, // DSP1RX4 SRC = IMON
- { CS35L41_DSP1_RX6_SRC, 0x00000029 }, // DSP1RX6 SRC = VBSTMON
-};
-
-static const struct reg_sequence cs35l41_hda_unmute[] = {
- { CS35L41_AMP_DIG_VOL_CTRL, 0x00008000 }, // AMP_HPF_PCM_EN = 1, AMP_VOL_PCM 0.0 dB
- { CS35L41_AMP_GAIN_CTRL, 0x00000084 }, // AMP_GAIN_PCM 4.5 dB
-};
-
-static const struct reg_sequence cs35l41_hda_mute[] = {
- { CS35L41_AMP_GAIN_CTRL, 0x00000000 }, // AMP_GAIN_PCM 0.5 dB
- { CS35L41_AMP_DIG_VOL_CTRL, 0x0000A678 }, // AMP_HPF_PCM_EN = 1, AMP_VOL_PCM Mute
-};
-
-static const struct cs_dsp_client_ops client_ops = {
- /* cs_dsp requires the client to provide this even if it is empty */
-};
-
-static int cs35l41_request_tuning_param_file(struct cs35l41_hda *cs35l41, char *tuning_filename,
- const struct firmware **firmware, char **filename,
- const char *ssid)
-{
- int ret = 0;
-
- /* Filename is the same as the tuning file with "cfg" suffix */
- *filename = kasprintf(GFP_KERNEL, "%scfg", tuning_filename);
- if (*filename == NULL)
- return -ENOMEM;
-
- ret = firmware_request_nowarn(firmware, *filename, cs35l41->dev);
- if (ret != 0) {
- dev_dbg(cs35l41->dev, "Failed to request '%s'\n", *filename);
- kfree(*filename);
- *filename = NULL;
- }
-
- return ret;
-}
-
-static int cs35l41_request_firmware_file(struct cs35l41_hda *cs35l41,
- const struct firmware **firmware, char **filename,
- const char *ssid, const char *amp_name,
- int spkid, const char *filetype)
-{
- const char * const dsp_name = cs35l41->cs_dsp.name;
- char *s, c;
- int ret = 0;
-
- if (spkid > -1 && ssid && amp_name)
- *filename = kasprintf(GFP_KERNEL, "cirrus/%s-%s-%s-%s-spkid%d-%s.%s", CS35L41_PART,
- dsp_name, cs35l41_hda_fw_ids[cs35l41->firmware_type],
- ssid, spkid, amp_name, filetype);
- else if (spkid > -1 && ssid)
- *filename = kasprintf(GFP_KERNEL, "cirrus/%s-%s-%s-%s-spkid%d.%s", CS35L41_PART,
- dsp_name, cs35l41_hda_fw_ids[cs35l41->firmware_type],
- ssid, spkid, filetype);
- else if (ssid && amp_name)
- *filename = kasprintf(GFP_KERNEL, "cirrus/%s-%s-%s-%s-%s.%s", CS35L41_PART,
- dsp_name, cs35l41_hda_fw_ids[cs35l41->firmware_type],
- ssid, amp_name, filetype);
- else if (ssid)
- *filename = kasprintf(GFP_KERNEL, "cirrus/%s-%s-%s-%s.%s", CS35L41_PART,
- dsp_name, cs35l41_hda_fw_ids[cs35l41->firmware_type],
- ssid, filetype);
- else
- *filename = kasprintf(GFP_KERNEL, "cirrus/%s-%s-%s.%s", CS35L41_PART,
- dsp_name, cs35l41_hda_fw_ids[cs35l41->firmware_type],
- filetype);
-
- if (*filename == NULL)
- return -ENOMEM;
-
- /*
- * Make sure that filename is lower-case and any non alpha-numeric
- * characters except full stop and '/' are replaced with hyphens.
- */
- s = *filename;
- while (*s) {
- c = *s;
- if (isalnum(c))
- *s = tolower(c);
- else if (c != '.' && c != '/')
- *s = '-';
- s++;
- }
-
- ret = firmware_request_nowarn(firmware, *filename, cs35l41->dev);
- if (ret != 0) {
- dev_dbg(cs35l41->dev, "Failed to request '%s'\n", *filename);
- kfree(*filename);
- *filename = NULL;
- }
-
- return ret;
-}
-
-static int cs35l41_request_firmware_files_spkid(struct cs35l41_hda *cs35l41,
- const struct firmware **wmfw_firmware,
- char **wmfw_filename,
- const struct firmware **coeff_firmware,
- char **coeff_filename)
-{
- int ret;
-
- /* try cirrus/part-dspN-fwtype-sub<-spkidN><-ampname>.wmfw */
- ret = cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_filename,
- cs35l41->acpi_subsystem_id, cs35l41->amp_name,
- cs35l41->speaker_id, "wmfw");
- if (!ret) {
- /* try cirrus/part-dspN-fwtype-sub<-spkidN><-ampname>.bin */
- ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename,
- cs35l41->acpi_subsystem_id, cs35l41->amp_name,
- cs35l41->speaker_id, "bin");
- if (ret)
- goto coeff_err;
-
- return 0;
- }
-
- /* try cirrus/part-dspN-fwtype-sub<-ampname>.wmfw */
- ret = cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_filename,
- cs35l41->acpi_subsystem_id,
- cs35l41->amp_name, -1, "wmfw");
- if (!ret) {
- /* try cirrus/part-dspN-fwtype-sub<-spkidN><-ampname>.bin */
- ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename,
- cs35l41->acpi_subsystem_id, cs35l41->amp_name,
- cs35l41->speaker_id, "bin");
- if (ret)
- goto coeff_err;
-
- return 0;
- }
-
- /* try cirrus/part-dspN-fwtype-sub<-spkidN>.wmfw */
- ret = cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_filename,
- cs35l41->acpi_subsystem_id,
- NULL, cs35l41->speaker_id, "wmfw");
- if (!ret) {
- /* try cirrus/part-dspN-fwtype-sub<-spkidN><-ampname>.bin */
- ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename,
- cs35l41->acpi_subsystem_id,
- cs35l41->amp_name, cs35l41->speaker_id, "bin");
- if (ret)
- /* try cirrus/part-dspN-fwtype-sub<-spkidN>.bin */
- ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware,
- coeff_filename,
- cs35l41->acpi_subsystem_id, NULL,
- cs35l41->speaker_id, "bin");
- if (ret)
- goto coeff_err;
-
- return 0;
- }
-
- /* try cirrus/part-dspN-fwtype-sub.wmfw */
- ret = cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_filename,
- cs35l41->acpi_subsystem_id,
- NULL, -1, "wmfw");
- if (!ret) {
- /* try cirrus/part-dspN-fwtype-sub<-spkidN><-ampname>.bin */
- ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename,
- cs35l41->acpi_subsystem_id, cs35l41->amp_name,
- cs35l41->speaker_id, "bin");
- if (ret)
- /* try cirrus/part-dspN-fwtype-sub<-spkidN>.bin */
- ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware,
- coeff_filename,
- cs35l41->acpi_subsystem_id, NULL,
- cs35l41->speaker_id, "bin");
- if (ret)
- goto coeff_err;
- }
-
- return ret;
-coeff_err:
- release_firmware(*wmfw_firmware);
- kfree(*wmfw_filename);
- return ret;
-}
-
-static int cs35l41_fallback_firmware_file(struct cs35l41_hda *cs35l41,
- const struct firmware **wmfw_firmware,
- char **wmfw_filename,
- const struct firmware **coeff_firmware,
- char **coeff_filename)
-{
- int ret;
-
- /* Handle fallback */
- dev_warn(cs35l41->dev, "Falling back to default firmware.\n");
-
- /* fallback try cirrus/part-dspN-fwtype.wmfw */
- ret = cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_filename,
- NULL, NULL, -1, "wmfw");
- if (ret)
- goto err;
-
- /* fallback try cirrus/part-dspN-fwtype.bin */
- ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename,
- NULL, NULL, -1, "bin");
- if (ret) {
- release_firmware(*wmfw_firmware);
- kfree(*wmfw_filename);
- goto err;
- }
- return 0;
-
-err:
- dev_warn(cs35l41->dev, "Unable to find firmware and tuning\n");
- return ret;
-}
-
-static int cs35l41_request_firmware_files(struct cs35l41_hda *cs35l41,
- const struct firmware **wmfw_firmware,
- char **wmfw_filename,
- const struct firmware **coeff_firmware,
- char **coeff_filename)
-{
- int ret;
-
- if (cs35l41->speaker_id > -1) {
- ret = cs35l41_request_firmware_files_spkid(cs35l41, wmfw_firmware, wmfw_filename,
- coeff_firmware, coeff_filename);
- goto out;
- }
-
- /* try cirrus/part-dspN-fwtype-sub<-ampname>.wmfw */
- ret = cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_filename,
- cs35l41->acpi_subsystem_id,
- cs35l41->amp_name, -1, "wmfw");
- if (!ret) {
- /* try cirrus/part-dspN-fwtype-sub<-ampname>.bin */
- ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename,
- cs35l41->acpi_subsystem_id, cs35l41->amp_name,
- -1, "bin");
- if (ret)
- goto coeff_err;
-
- goto out;
- }
-
- /* try cirrus/part-dspN-fwtype-sub.wmfw */
- ret = cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_filename,
- cs35l41->acpi_subsystem_id,
- NULL, -1, "wmfw");
- if (!ret) {
- /* try cirrus/part-dspN-fwtype-sub<-ampname>.bin */
- ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename,
- cs35l41->acpi_subsystem_id,
- cs35l41->amp_name, -1, "bin");
- if (ret)
- /* try cirrus/part-dspN-fwtype-sub.bin */
- ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename,
- cs35l41->acpi_subsystem_id, NULL, -1,
- "bin");
- if (ret)
- goto coeff_err;
- }
-
-out:
- if (ret)
- /* if all attempts at finding firmware fail, try fallback */
- goto fallback;
-
- return 0;
-
-coeff_err:
- release_firmware(*wmfw_firmware);
- kfree(*wmfw_filename);
-fallback:
- return cs35l41_fallback_firmware_file(cs35l41, wmfw_firmware, wmfw_filename,
- coeff_firmware, coeff_filename);
-}
-
-
-static void cs35l41_hda_apply_calibration(struct cs35l41_hda *cs35l41)
-{
- int ret;
-
- if (!cs35l41->cal_data_valid)
- return;
-
- ret = cs_amp_write_cal_coeffs(&cs35l41->cs_dsp, &cs35l41_calibration_controls,
- &cs35l41->cal_data);
- if (ret < 0)
- dev_warn(cs35l41->dev, "Failed to apply calibration: %d\n", ret);
- else
- dev_info(cs35l41->dev, "Calibration applied: R0=%d\n", cs35l41->cal_data.calR);
-}
-
-static int cs35l41_read_silicon_uid(struct cs35l41_hda *cs35l41, u64 *uid)
-{
- u32 tmp;
- int ret;
-
- ret = regmap_read(cs35l41->regmap, CS35L41_DIE_STS2, &tmp);
- if (ret) {
- dev_err(cs35l41->dev, "Cannot obtain CS35L41_DIE_STS2: %d\n", ret);
- return ret;
- }
-
- *uid = tmp;
- *uid <<= 32;
-
- ret = regmap_read(cs35l41->regmap, CS35L41_DIE_STS1, &tmp);
- if (ret) {
- dev_err(cs35l41->dev, "Cannot obtain CS35L41_DIE_STS1: %d\n", ret);
- return ret;
- }
-
- *uid |= tmp;
-
- dev_dbg(cs35l41->dev, "UniqueID = %#llx\n", *uid);
-
- return 0;
-}
-
-static int cs35l41_get_calibration(struct cs35l41_hda *cs35l41)
-{
- u64 silicon_uid;
- int ret;
-
- ret = cs35l41_read_silicon_uid(cs35l41, &silicon_uid);
- if (ret < 0)
- return ret;
-
- ret = cs_amp_get_efi_calibration_data(cs35l41->dev, silicon_uid,
- cs35l41->index,
- &cs35l41->cal_data);
-
- /* Only return an error status if probe should be aborted */
- if ((ret == -ENOENT) || (ret == -EOVERFLOW))
- return 0;
-
- if (ret < 0)
- return ret;
-
- cs35l41->cal_data_valid = true;
-
- return 0;
-}
-
-
-static void cs35l41_set_default_tuning_params(struct cs35l41_hda *cs35l41)
-{
- cs35l41->tuning_gain = DEFAULT_AMP_GAIN_PCM;
-}
-
-static int cs35l41_read_tuning_params(struct cs35l41_hda *cs35l41, const struct firmware *firmware)
-{
- struct cs35l41_tuning_params *params;
- unsigned int offset = 0;
- unsigned int end;
- int i;
-
- params = (void *)&firmware->data[0];
-
- if (le32_to_cpu(params->size) != firmware->size) {
- dev_err(cs35l41->dev, "Wrong Size for Tuning Param file. Expected %d got %zu\n",
- le32_to_cpu(params->size), firmware->size);
- return -EINVAL;
- }
-
- if (le32_to_cpu(params->version) != 1) {
- dev_err(cs35l41->dev, "Unsupported Tuning Param Version: %d\n",
- le32_to_cpu(params->version));
- return -EINVAL;
- }
-
- if (le32_to_cpu(params->signature) != CS35L41_TUNING_SIG) {
- dev_err(cs35l41->dev,
- "Mismatched Signature for Tuning Param file. Expected %#x got %#x\n",
- CS35L41_TUNING_SIG, le32_to_cpu(params->signature));
- return -EINVAL;
- }
-
- end = firmware->size - sizeof(struct cs35l41_tuning_params);
-
- for (i = 0; i < le32_to_cpu(params->num_entries); i++) {
- struct cs35l41_tuning_param *param;
-
- if ((offset >= end) || ((offset + sizeof(struct cs35l41_tuning_param_hdr)) >= end))
- return -EFAULT;
-
- param = (void *)&params->data[offset];
- offset += le32_to_cpu(param->hdr.size);
-
- if (offset > end)
- return -EFAULT;
-
- switch (le32_to_cpu(param->hdr.type)) {
- case TUNING_PARAM_GAIN:
- cs35l41->tuning_gain = le32_to_cpu(param->gain);
- dev_dbg(cs35l41->dev, "Applying Gain: %d\n", cs35l41->tuning_gain);
- break;
- default:
- break;
- }
- }
-
- return 0;
-}
-
-static int cs35l41_load_tuning_params(struct cs35l41_hda *cs35l41, char *tuning_filename)
-{
- const struct firmware *tuning_param_file = NULL;
- char *tuning_param_filename = NULL;
- int ret;
-
- ret = cs35l41_request_tuning_param_file(cs35l41, tuning_filename, &tuning_param_file,
- &tuning_param_filename, cs35l41->acpi_subsystem_id);
- if (ret) {
- dev_dbg(cs35l41->dev, "Missing Tuning Param for file: %s: %d\n", tuning_filename,
- ret);
- return 0;
- }
-
- ret = cs35l41_read_tuning_params(cs35l41, tuning_param_file);
- if (ret) {
- dev_err(cs35l41->dev, "Error reading Tuning Params from file: %s: %d\n",
- tuning_param_filename, ret);
- /* Reset to default Tuning Parameters */
- cs35l41_set_default_tuning_params(cs35l41);
- }
-
- release_firmware(tuning_param_file);
- kfree(tuning_param_filename);
-
- return ret;
-}
-
-static int cs35l41_init_dsp(struct cs35l41_hda *cs35l41)
-{
- const struct firmware *coeff_firmware = NULL;
- const struct firmware *wmfw_firmware = NULL;
- struct cs_dsp *dsp = &cs35l41->cs_dsp;
- char *coeff_filename = NULL;
- char *wmfw_filename = NULL;
- int ret;
-
- if (!cs35l41->halo_initialized) {
- cs35l41_configure_cs_dsp(cs35l41->dev, cs35l41->regmap, dsp);
- dsp->client_ops = &client_ops;
-
- ret = cs_dsp_halo_init(&cs35l41->cs_dsp);
- if (ret)
- return ret;
- cs35l41->halo_initialized = true;
- }
-
- cs35l41_set_default_tuning_params(cs35l41);
-
- ret = cs35l41_request_firmware_files(cs35l41, &wmfw_firmware, &wmfw_filename,
- &coeff_firmware, &coeff_filename);
- if (ret < 0)
- return ret;
-
- dev_dbg(cs35l41->dev, "Loading WMFW Firmware: %s\n", wmfw_filename);
- if (coeff_filename) {
- dev_dbg(cs35l41->dev, "Loading Coefficient File: %s\n", coeff_filename);
- ret = cs35l41_load_tuning_params(cs35l41, coeff_filename);
- if (ret)
- dev_warn(cs35l41->dev, "Unable to load Tuning Parameters: %d\n", ret);
- } else {
- dev_warn(cs35l41->dev, "No Coefficient File available.\n");
- }
-
- ret = cs_dsp_power_up(dsp, wmfw_firmware, wmfw_filename, coeff_firmware, coeff_filename,
- cs35l41_hda_fw_ids[cs35l41->firmware_type]);
- if (ret)
- goto err;
-
- cs35l41_hda_apply_calibration(cs35l41);
-
-err:
- if (ret)
- cs35l41_set_default_tuning_params(cs35l41);
- release_firmware(wmfw_firmware);
- release_firmware(coeff_firmware);
- kfree(wmfw_filename);
- kfree(coeff_filename);
-
- return ret;
-}
-
-static void cs35l41_shutdown_dsp(struct cs35l41_hda *cs35l41)
-{
- struct cs_dsp *dsp = &cs35l41->cs_dsp;
-
- cs35l41_set_default_tuning_params(cs35l41);
- cs_dsp_stop(dsp);
- cs_dsp_power_down(dsp);
- dev_dbg(cs35l41->dev, "Unloaded Firmware\n");
-}
-
-static void cs35l41_remove_dsp(struct cs35l41_hda *cs35l41)
-{
- struct cs_dsp *dsp = &cs35l41->cs_dsp;
-
- cancel_work_sync(&cs35l41->fw_load_work);
-
- mutex_lock(&cs35l41->fw_mutex);
- cs35l41_shutdown_dsp(cs35l41);
- cs_dsp_remove(dsp);
- cs35l41->halo_initialized = false;
- mutex_unlock(&cs35l41->fw_mutex);
-}
-
-/* Protection release cycle to get the speaker out of Safe-Mode */
-static void cs35l41_error_release(struct device *dev, struct regmap *regmap, unsigned int mask)
-{
- regmap_write(regmap, CS35L41_PROTECT_REL_ERR_IGN, 0);
- regmap_set_bits(regmap, CS35L41_PROTECT_REL_ERR_IGN, mask);
- regmap_clear_bits(regmap, CS35L41_PROTECT_REL_ERR_IGN, mask);
-}
-
-/* Clear all errors to release safe mode. Global Enable must be cleared first. */
-static void cs35l41_irq_release(struct cs35l41_hda *cs35l41)
-{
- cs35l41_error_release(cs35l41->dev, cs35l41->regmap, cs35l41->irq_errors);
- cs35l41->irq_errors = 0;
-}
-
-static void cs35l41_hda_play_start(struct device *dev)
-{
- struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
- struct regmap *reg = cs35l41->regmap;
-
- dev_dbg(dev, "Play (Start)\n");
-
- if (cs35l41->playback_started) {
- dev_dbg(dev, "Playback already started.");
- return;
- }
-
- cs35l41->playback_started = true;
-
- if (cs35l41->cs_dsp.running) {
- regmap_multi_reg_write(reg, cs35l41_hda_config_dsp,
- ARRAY_SIZE(cs35l41_hda_config_dsp));
- if (cs35l41->hw_cfg.bst_type == CS35L41_INT_BOOST)
- regmap_write(reg, CS35L41_DSP1_RX5_SRC, CS35L41_INPUT_SRC_VPMON);
- else
- regmap_write(reg, CS35L41_DSP1_RX5_SRC, CS35L41_INPUT_SRC_VBSTMON);
- regmap_update_bits(reg, CS35L41_PWR_CTRL2,
- CS35L41_VMON_EN_MASK | CS35L41_IMON_EN_MASK,
- 1 << CS35L41_VMON_EN_SHIFT | 1 << CS35L41_IMON_EN_SHIFT);
- cs35l41_set_cspl_mbox_cmd(cs35l41->dev, reg, CSPL_MBOX_CMD_RESUME);
- } else {
- regmap_multi_reg_write(reg, cs35l41_hda_config, ARRAY_SIZE(cs35l41_hda_config));
- }
- regmap_update_bits(reg, CS35L41_PWR_CTRL2, CS35L41_AMP_EN_MASK, 1 << CS35L41_AMP_EN_SHIFT);
- if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST)
- regmap_write(reg, CS35L41_GPIO1_CTRL1, 0x00008001);
-
-}
-
-static void cs35l41_mute(struct device *dev, bool mute)
-{
- struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
- struct regmap *reg = cs35l41->regmap;
- unsigned int amp_gain;
-
- dev_dbg(dev, "Mute(%d:%d) Playback Started: %d\n", mute, cs35l41->mute_override,
- cs35l41->playback_started);
-
- if (cs35l41->playback_started) {
- if (mute || cs35l41->mute_override) {
- dev_dbg(dev, "Muting\n");
- regmap_multi_reg_write(reg, cs35l41_hda_mute, ARRAY_SIZE(cs35l41_hda_mute));
- } else {
- dev_dbg(dev, "Unmuting\n");
- if (cs35l41->cs_dsp.running) {
- dev_dbg(dev, "Using Tuned Gain: %d\n", cs35l41->tuning_gain);
- amp_gain = (cs35l41->tuning_gain << CS35L41_AMP_GAIN_PCM_SHIFT) |
- (DEFAULT_AMP_GAIN_PDM << CS35L41_AMP_GAIN_PDM_SHIFT);
-
- /* AMP_HPF_PCM_EN = 1, AMP_VOL_PCM 0.0 dB */
- regmap_write(reg, CS35L41_AMP_DIG_VOL_CTRL, 0x00008000);
- regmap_write(reg, CS35L41_AMP_GAIN_CTRL, amp_gain);
- } else {
- regmap_multi_reg_write(reg, cs35l41_hda_unmute,
- ARRAY_SIZE(cs35l41_hda_unmute));
- }
- }
- }
-}
-
-static void cs35l41_hda_play_done(struct device *dev)
-{
- struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
- struct regmap *reg = cs35l41->regmap;
-
- dev_dbg(dev, "Play (Complete)\n");
-
- cs35l41_global_enable(dev, reg, cs35l41->hw_cfg.bst_type, 1,
- &cs35l41->cs_dsp);
- cs35l41_mute(dev, false);
-}
-
-static void cs35l41_hda_pause_start(struct device *dev)
-{
- struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
- struct regmap *reg = cs35l41->regmap;
-
- dev_dbg(dev, "Pause (Start)\n");
-
- cs35l41_mute(dev, true);
- cs35l41_global_enable(dev, reg, cs35l41->hw_cfg.bst_type, 0,
- &cs35l41->cs_dsp);
-}
-
-static void cs35l41_hda_pause_done(struct device *dev)
-{
- struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
- struct regmap *reg = cs35l41->regmap;
-
- dev_dbg(dev, "Pause (Complete)\n");
-
- regmap_update_bits(reg, CS35L41_PWR_CTRL2, CS35L41_AMP_EN_MASK, 0 << CS35L41_AMP_EN_SHIFT);
- if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST)
- regmap_write(reg, CS35L41_GPIO1_CTRL1, 0x00000001);
- if (cs35l41->cs_dsp.running) {
- cs35l41_set_cspl_mbox_cmd(dev, reg, CSPL_MBOX_CMD_PAUSE);
- regmap_update_bits(reg, CS35L41_PWR_CTRL2,
- CS35L41_VMON_EN_MASK | CS35L41_IMON_EN_MASK,
- 0 << CS35L41_VMON_EN_SHIFT | 0 << CS35L41_IMON_EN_SHIFT);
- }
- cs35l41_irq_release(cs35l41);
- cs35l41->playback_started = false;
-}
-
-static void cs35l41_hda_pre_playback_hook(struct device *dev, int action)
-{
- struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
-
- switch (action) {
- case HDA_GEN_PCM_ACT_CLEANUP:
- mutex_lock(&cs35l41->fw_mutex);
- cs35l41_hda_pause_start(dev);
- mutex_unlock(&cs35l41->fw_mutex);
- break;
- default:
- break;
- }
-}
-static void cs35l41_hda_playback_hook(struct device *dev, int action)
-{
- struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
-
- switch (action) {
- case HDA_GEN_PCM_ACT_OPEN:
- /*
- * All amps must be resumed before we can start playing back.
- * This ensures, for external boost, that all amps are in AMP_SAFE mode.
- * Do this in HDA_GEN_PCM_ACT_OPEN, since this is run prior to any of the
- * other actions.
- */
- pm_runtime_get_sync(dev);
- break;
- case HDA_GEN_PCM_ACT_PREPARE:
- mutex_lock(&cs35l41->fw_mutex);
- cs35l41_hda_play_start(dev);
- mutex_unlock(&cs35l41->fw_mutex);
- break;
- case HDA_GEN_PCM_ACT_CLEANUP:
- mutex_lock(&cs35l41->fw_mutex);
- cs35l41_hda_pause_done(dev);
- mutex_unlock(&cs35l41->fw_mutex);
- break;
- case HDA_GEN_PCM_ACT_CLOSE:
- mutex_lock(&cs35l41->fw_mutex);
- if (!cs35l41->cs_dsp.running && cs35l41->request_fw_load &&
- !cs35l41->fw_request_ongoing) {
- dev_info(dev, "Requesting Firmware Load after HDA_GEN_PCM_ACT_CLOSE\n");
- cs35l41->fw_request_ongoing = true;
- schedule_work(&cs35l41->fw_load_work);
- }
- mutex_unlock(&cs35l41->fw_mutex);
-
- /*
- * Playback must be finished for all amps before we start runtime suspend.
- * This ensures no amps are playing back when we start putting them to sleep.
- */
- pm_runtime_mark_last_busy(dev);
- pm_runtime_put_autosuspend(dev);
- break;
- default:
- break;
- }
-}
-
-static void cs35l41_hda_post_playback_hook(struct device *dev, int action)
-{
- struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
-
- switch (action) {
- case HDA_GEN_PCM_ACT_PREPARE:
- mutex_lock(&cs35l41->fw_mutex);
- cs35l41_hda_play_done(dev);
- mutex_unlock(&cs35l41->fw_mutex);
- break;
- default:
- break;
- }
-}
-
-static int cs35l41_hda_channel_map(struct device *dev, unsigned int tx_num, unsigned int *tx_slot,
- unsigned int rx_num, unsigned int *rx_slot)
-{
- struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
- static const char * const channel_name[] = { "L", "R" };
-
- if (!cs35l41->amp_name) {
- if (*rx_slot >= ARRAY_SIZE(channel_name))
- return -EINVAL;
-
- cs35l41->amp_name = devm_kasprintf(cs35l41->dev, GFP_KERNEL, "%s%d",
- channel_name[*rx_slot], cs35l41->channel_index);
- if (!cs35l41->amp_name)
- return -ENOMEM;
- }
-
- return cs35l41_set_channels(cs35l41->dev, cs35l41->regmap, tx_num, tx_slot, rx_num,
- rx_slot);
-}
-
-static int cs35l41_verify_id(struct cs35l41_hda *cs35l41, unsigned int *regid, unsigned int *reg_revid)
-{
- unsigned int mtl_revid, chipid;
- int ret;
-
- ret = regmap_read(cs35l41->regmap, CS35L41_DEVID, regid);
- if (ret) {
- dev_err_probe(cs35l41->dev, ret, "Get Device ID failed\n");
- return ret;
- }
-
- ret = regmap_read(cs35l41->regmap, CS35L41_REVID, reg_revid);
- if (ret) {
- dev_err_probe(cs35l41->dev, ret, "Get Revision ID failed\n");
- return ret;
- }
-
- mtl_revid = *reg_revid & CS35L41_MTLREVID_MASK;
-
- chipid = (mtl_revid % 2) ? CS35L41R_CHIP_ID : CS35L41_CHIP_ID;
- if (*regid != chipid) {
- dev_err(cs35l41->dev, "CS35L41 Device ID (%X). Expected ID %X\n", *regid, chipid);
- return -ENODEV;
- }
-
- return 0;
-}
-
-static int cs35l41_ready_for_reset(struct cs35l41_hda *cs35l41)
-{
- mutex_lock(&cs35l41->fw_mutex);
- if (cs35l41->cs_dsp.running) {
- cs35l41->cs_dsp.running = false;
- cs35l41->cs_dsp.booted = false;
- }
- regcache_mark_dirty(cs35l41->regmap);
- mutex_unlock(&cs35l41->fw_mutex);
-
- return 0;
-}
-
-static int cs35l41_system_suspend_prep(struct device *dev)
-{
- struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
-
- dev_dbg(cs35l41->dev, "System Suspend Prepare\n");
-
- if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH) {
- dev_err_once(cs35l41->dev, "System Suspend not supported\n");
- return 0; /* don't block the whole system suspend */
- }
-
- mutex_lock(&cs35l41->fw_mutex);
- if (cs35l41->playback_started)
- cs35l41_hda_pause_start(dev);
- mutex_unlock(&cs35l41->fw_mutex);
-
- return 0;
-}
-
-static int cs35l41_system_suspend(struct device *dev)
-{
- struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
- int ret;
-
- dev_dbg(cs35l41->dev, "System Suspend\n");
-
- if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH) {
- dev_err_once(cs35l41->dev, "System Suspend not supported\n");
- return 0; /* don't block the whole system suspend */
- }
-
- mutex_lock(&cs35l41->fw_mutex);
- if (cs35l41->playback_started)
- cs35l41_hda_pause_done(dev);
- mutex_unlock(&cs35l41->fw_mutex);
-
- ret = pm_runtime_force_suspend(dev);
- if (ret) {
- dev_err(dev, "System Suspend Failed, unable to runtime suspend: %d\n", ret);
- return ret;
- }
-
- /* Shutdown DSP before system suspend */
- ret = cs35l41_ready_for_reset(cs35l41);
- if (ret)
- dev_err(dev, "System Suspend Failed, not ready for Reset: %d\n", ret);
-
- if (cs35l41->reset_gpio) {
- dev_info(cs35l41->dev, "Asserting Reset\n");
- gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
- usleep_range(2000, 2100);
- }
-
- dev_dbg(cs35l41->dev, "System Suspended\n");
-
- return ret;
-}
-
-static int cs35l41_wait_boot_done(struct cs35l41_hda *cs35l41)
-{
- unsigned int int_status;
- int ret;
-
- ret = regmap_read_poll_timeout(cs35l41->regmap, CS35L41_IRQ1_STATUS4, int_status,
- int_status & CS35L41_OTP_BOOT_DONE, 1000, 100000);
- if (ret) {
- dev_err(cs35l41->dev, "Failed waiting for OTP_BOOT_DONE\n");
- return ret;
- }
-
- ret = regmap_read(cs35l41->regmap, CS35L41_IRQ1_STATUS3, &int_status);
- if (ret || (int_status & CS35L41_OTP_BOOT_ERR)) {
- dev_err(cs35l41->dev, "OTP Boot status %x error\n",
- int_status & CS35L41_OTP_BOOT_ERR);
- if (!ret)
- ret = -EIO;
- return ret;
- }
-
- return 0;
-}
-
-static int cs35l41_system_resume(struct device *dev)
-{
- struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
- int ret;
-
- dev_dbg(cs35l41->dev, "System Resume\n");
-
- if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH) {
- dev_err_once(cs35l41->dev, "System Resume not supported\n");
- return 0; /* don't block the whole system resume */
- }
-
- if (cs35l41->reset_gpio) {
- gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
- usleep_range(2000, 2100);
- gpiod_set_value_cansleep(cs35l41->reset_gpio, 1);
- }
-
- usleep_range(2000, 2100);
-
- regcache_cache_only(cs35l41->regmap, false);
-
- regmap_write(cs35l41->regmap, CS35L41_SFT_RESET, CS35L41_SOFTWARE_RESET);
- usleep_range(2000, 2100);
-
- ret = cs35l41_wait_boot_done(cs35l41);
- if (ret)
- return ret;
-
- regcache_cache_only(cs35l41->regmap, true);
-
- ret = pm_runtime_force_resume(dev);
- if (ret) {
- dev_err(dev, "System Resume Failed: Unable to runtime resume: %d\n", ret);
- return ret;
- }
-
- mutex_lock(&cs35l41->fw_mutex);
-
- if (cs35l41->request_fw_load && !cs35l41->fw_request_ongoing) {
- cs35l41->fw_request_ongoing = true;
- schedule_work(&cs35l41->fw_load_work);
- }
- mutex_unlock(&cs35l41->fw_mutex);
-
- return ret;
-}
-
-static int cs35l41_runtime_idle(struct device *dev)
-{
- struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
-
- if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH)
- return -EBUSY; /* suspend not supported yet on this model */
- return 0;
-}
-
-static int cs35l41_runtime_suspend(struct device *dev)
-{
- struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
- int ret = 0;
-
- dev_dbg(cs35l41->dev, "Runtime Suspend\n");
-
- if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH) {
- dev_dbg(cs35l41->dev, "Runtime Suspend not supported\n");
- return 0;
- }
-
- mutex_lock(&cs35l41->fw_mutex);
-
- if (cs35l41->cs_dsp.running) {
- ret = cs35l41_enter_hibernate(cs35l41->dev, cs35l41->regmap,
- cs35l41->hw_cfg.bst_type);
- if (ret)
- goto err;
- } else {
- cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type);
- }
-
- regcache_cache_only(cs35l41->regmap, true);
- regcache_mark_dirty(cs35l41->regmap);
-
-err:
- mutex_unlock(&cs35l41->fw_mutex);
-
- return ret;
-}
-
-static int cs35l41_runtime_resume(struct device *dev)
-{
- struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
- unsigned int regid, reg_revid;
- int ret = 0;
-
- dev_dbg(cs35l41->dev, "Runtime Resume\n");
-
- if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH) {
- dev_dbg(cs35l41->dev, "Runtime Resume not supported\n");
- return 0;
- }
-
- mutex_lock(&cs35l41->fw_mutex);
-
- regcache_cache_only(cs35l41->regmap, false);
-
- if (cs35l41->cs_dsp.running) {
- ret = cs35l41_exit_hibernate(cs35l41->dev, cs35l41->regmap);
- if (ret) {
- dev_warn(cs35l41->dev, "Unable to exit Hibernate.");
- goto err;
- }
- }
-
- ret = cs35l41_verify_id(cs35l41, &regid, &reg_revid);
- if (ret)
- goto err;
-
- /* Test key needs to be unlocked to allow the OTP settings to re-apply */
- cs35l41_test_key_unlock(cs35l41->dev, cs35l41->regmap);
- ret = regcache_sync(cs35l41->regmap);
- cs35l41_test_key_lock(cs35l41->dev, cs35l41->regmap);
- if (ret) {
- dev_err(cs35l41->dev, "Failed to restore register cache: %d\n", ret);
- goto err;
- }
-
- if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST)
- cs35l41_init_boost(cs35l41->dev, cs35l41->regmap, &cs35l41->hw_cfg);
-
- dev_dbg(cs35l41->dev, "CS35L41 Resumed (%x), Revision: %02X\n", regid, reg_revid);
-
-err:
- mutex_unlock(&cs35l41->fw_mutex);
-
- return ret;
-}
-
-static int cs35l41_hda_read_ctl(struct cs_dsp *dsp, const char *name, int type,
- unsigned int alg, void *buf, size_t len)
-{
- int ret;
-
- mutex_lock(&dsp->pwr_lock);
- ret = cs_dsp_coeff_read_ctrl(cs_dsp_get_ctl(dsp, name, type, alg), 0, buf, len);
- mutex_unlock(&dsp->pwr_lock);
-
- return ret;
-}
-
-static int cs35l41_smart_amp(struct cs35l41_hda *cs35l41)
-{
- unsigned int fw_status;
- __be32 halo_sts;
- int ret;
-
- if (cs35l41->bypass_fw) {
- dev_warn(cs35l41->dev, "Bypassing Firmware.\n");
- return 0;
- }
-
- ret = cs35l41_init_dsp(cs35l41);
- if (ret) {
- dev_warn(cs35l41->dev, "Cannot Initialize Firmware. Error: %d\n", ret);
- goto clean_dsp;
- }
-
- ret = cs35l41_write_fs_errata(cs35l41->dev, cs35l41->regmap);
- if (ret) {
- dev_err(cs35l41->dev, "Cannot Write FS Errata: %d\n", ret);
- goto clean_dsp;
- }
-
- ret = cs_dsp_run(&cs35l41->cs_dsp);
- if (ret) {
- dev_err(cs35l41->dev, "Fail to start dsp: %d\n", ret);
- goto clean_dsp;
- }
-
- ret = read_poll_timeout(cs35l41_hda_read_ctl, ret,
- be32_to_cpu(halo_sts) == HALO_STATE_CODE_RUN,
- 1000, 15000, false, &cs35l41->cs_dsp, HALO_STATE_DSP_CTL_NAME,
- HALO_STATE_DSP_CTL_TYPE, HALO_STATE_DSP_CTL_ALG,
- &halo_sts, sizeof(halo_sts));
-
- if (ret) {
- dev_err(cs35l41->dev, "Timeout waiting for HALO Core to start. State: %u\n",
- halo_sts);
- goto clean_dsp;
- }
-
- ret = regmap_read(cs35l41->regmap, CS35L41_DSP_MBOX_2, &fw_status);
- if (ret < 0) {
- dev_err(cs35l41->dev,
- "Failed to read firmware status: %d\n", ret);
- goto clean_dsp;
- }
-
- switch (fw_status) {
- case CSPL_MBOX_STS_RUNNING:
- case CSPL_MBOX_STS_PAUSED:
- break;
- default:
- dev_err(cs35l41->dev, "Firmware status is invalid: %u\n",
- fw_status);
- ret = -EINVAL;
- goto clean_dsp;
- }
-
- ret = cs35l41_set_cspl_mbox_cmd(cs35l41->dev, cs35l41->regmap, CSPL_MBOX_CMD_PAUSE);
- if (ret) {
- dev_err(cs35l41->dev, "Error waiting for DSP to pause: %u\n", ret);
- goto clean_dsp;
- }
-
- dev_info(cs35l41->dev, "Firmware Loaded - Type: %s, Gain: %d\n",
- cs35l41_hda_fw_ids[cs35l41->firmware_type], cs35l41->tuning_gain);
-
- return 0;
-
-clean_dsp:
- cs35l41_shutdown_dsp(cs35l41);
- return ret;
-}
-
-static void cs35l41_load_firmware(struct cs35l41_hda *cs35l41, bool load)
-{
- if (cs35l41->cs_dsp.running && !load) {
- dev_dbg(cs35l41->dev, "Unloading Firmware\n");
- cs35l41_shutdown_dsp(cs35l41);
- } else if (!cs35l41->cs_dsp.running && load) {
- dev_dbg(cs35l41->dev, "Loading Firmware\n");
- cs35l41_smart_amp(cs35l41);
- } else {
- dev_dbg(cs35l41->dev, "Unable to Load firmware.\n");
- }
-}
-
-static int cs35l41_fw_load_ctl_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct cs35l41_hda *cs35l41 = snd_kcontrol_chip(kcontrol);
-
- ucontrol->value.integer.value[0] = cs35l41->request_fw_load;
- return 0;
-}
-
-static int cs35l41_mute_override_ctl_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct cs35l41_hda *cs35l41 = snd_kcontrol_chip(kcontrol);
-
- ucontrol->value.integer.value[0] = cs35l41->mute_override;
- return 0;
-}
-
-static void cs35l41_fw_load_work(struct work_struct *work)
-{
- struct cs35l41_hda *cs35l41 = container_of(work, struct cs35l41_hda, fw_load_work);
-
- pm_runtime_get_sync(cs35l41->dev);
-
- mutex_lock(&cs35l41->fw_mutex);
-
- /* Recheck if playback is ongoing, mutex will block playback during firmware loading */
- if (cs35l41->playback_started)
- dev_err(cs35l41->dev, "Cannot Load/Unload firmware during Playback. Retrying...\n");
- else
- cs35l41_load_firmware(cs35l41, cs35l41->request_fw_load);
-
- cs35l41->fw_request_ongoing = false;
- mutex_unlock(&cs35l41->fw_mutex);
-
- pm_runtime_mark_last_busy(cs35l41->dev);
- pm_runtime_put_autosuspend(cs35l41->dev);
-}
-
-static int cs35l41_fw_load_ctl_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct cs35l41_hda *cs35l41 = snd_kcontrol_chip(kcontrol);
-
- if (cs35l41->request_fw_load == ucontrol->value.integer.value[0])
- return 0;
-
- if (cs35l41->fw_request_ongoing) {
- dev_dbg(cs35l41->dev, "Existing request not complete\n");
- return -EBUSY;
- }
-
- /* Check if playback is ongoing when initial request is made */
- if (cs35l41->playback_started) {
- dev_err(cs35l41->dev, "Cannot Load/Unload firmware during Playback\n");
- return -EBUSY;
- }
-
- cs35l41->fw_request_ongoing = true;
- cs35l41->request_fw_load = ucontrol->value.integer.value[0];
- schedule_work(&cs35l41->fw_load_work);
-
- return 1;
-}
-
-static int cs35l41_fw_type_ctl_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct cs35l41_hda *cs35l41 = snd_kcontrol_chip(kcontrol);
-
- ucontrol->value.enumerated.item[0] = cs35l41->firmware_type;
-
- return 0;
-}
-
-static int cs35l41_fw_type_ctl_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct cs35l41_hda *cs35l41 = snd_kcontrol_chip(kcontrol);
-
- if (ucontrol->value.enumerated.item[0] < CS35L41_HDA_NUM_FW) {
- if (cs35l41->firmware_type != ucontrol->value.enumerated.item[0]) {
- cs35l41->firmware_type = ucontrol->value.enumerated.item[0];
- return 1;
- } else {
- return 0;
- }
- }
-
- return -EINVAL;
-}
-
-static int cs35l41_fw_type_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(cs35l41_hda_fw_ids), cs35l41_hda_fw_ids);
-}
-
-static int cs35l41_create_controls(struct cs35l41_hda *cs35l41)
-{
- char fw_type_ctl_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
- char fw_load_ctl_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
- char mute_override_ctl_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
- struct snd_kcontrol_new fw_type_ctl = {
- .name = fw_type_ctl_name,
- .iface = SNDRV_CTL_ELEM_IFACE_CARD,
- .info = cs35l41_fw_type_ctl_info,
- .get = cs35l41_fw_type_ctl_get,
- .put = cs35l41_fw_type_ctl_put,
- };
- struct snd_kcontrol_new fw_load_ctl = {
- .name = fw_load_ctl_name,
- .iface = SNDRV_CTL_ELEM_IFACE_CARD,
- .info = snd_ctl_boolean_mono_info,
- .get = cs35l41_fw_load_ctl_get,
- .put = cs35l41_fw_load_ctl_put,
- };
- struct snd_kcontrol_new mute_override_ctl = {
- .name = mute_override_ctl_name,
- .iface = SNDRV_CTL_ELEM_IFACE_CARD,
- .info = snd_ctl_boolean_mono_info,
- .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
- .get = cs35l41_mute_override_ctl_get,
- };
- int ret;
-
- scnprintf(fw_type_ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s DSP1 Firmware Type",
- cs35l41->amp_name);
- scnprintf(fw_load_ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s DSP1 Firmware Load",
- cs35l41->amp_name);
- scnprintf(mute_override_ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s Forced Mute Status",
- cs35l41->amp_name);
-
- ret = snd_ctl_add(cs35l41->codec->card, snd_ctl_new1(&fw_type_ctl, cs35l41));
- if (ret) {
- dev_err(cs35l41->dev, "Failed to add KControl %s = %d\n", fw_type_ctl.name, ret);
- return ret;
- }
-
- dev_dbg(cs35l41->dev, "Added Control %s\n", fw_type_ctl.name);
-
- ret = snd_ctl_add(cs35l41->codec->card, snd_ctl_new1(&fw_load_ctl, cs35l41));
- if (ret) {
- dev_err(cs35l41->dev, "Failed to add KControl %s = %d\n", fw_load_ctl.name, ret);
- return ret;
- }
-
- dev_dbg(cs35l41->dev, "Added Control %s\n", fw_load_ctl.name);
-
- ret = snd_ctl_add(cs35l41->codec->card, snd_ctl_new1(&mute_override_ctl, cs35l41));
- if (ret) {
- dev_err(cs35l41->dev, "Failed to add KControl %s = %d\n", mute_override_ctl.name,
- ret);
- return ret;
- }
-
- dev_dbg(cs35l41->dev, "Added Control %s\n", mute_override_ctl.name);
-
- return 0;
-}
-
-static bool cs35l41_dsm_supported(acpi_handle handle, unsigned int commands)
-{
- guid_t guid;
-
- guid_parse(CS35L41_UUID, &guid);
-
- return acpi_check_dsm(handle, &guid, 0, BIT(commands));
-}
-
-static int cs35l41_get_acpi_mute_state(struct cs35l41_hda *cs35l41, acpi_handle handle)
-{
- guid_t guid;
- union acpi_object *ret;
- int mute = -ENODEV;
-
- guid_parse(CS35L41_UUID, &guid);
-
- if (cs35l41_dsm_supported(handle, CS35L41_DSM_GET_MUTE)) {
- ret = acpi_evaluate_dsm(handle, &guid, 0, CS35L41_DSM_GET_MUTE, NULL);
- mute = *ret->buffer.pointer;
- dev_dbg(cs35l41->dev, "CS35L41_DSM_GET_MUTE: %d\n", mute);
- }
-
- dev_dbg(cs35l41->dev, "%s: %d\n", __func__, mute);
-
- return mute;
-}
-
-static void cs35l41_acpi_device_notify(acpi_handle handle, u32 event, struct device *dev)
-{
- struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
- int mute;
-
- if (event != CS35L41_NOTIFY_EVENT)
- return;
-
- mute = cs35l41_get_acpi_mute_state(cs35l41, handle);
- if (mute < 0) {
- dev_warn(cs35l41->dev, "Unable to retrieve mute state: %d\n", mute);
- return;
- }
-
- dev_dbg(cs35l41->dev, "Requesting mute value: %d\n", mute);
- cs35l41->mute_override = (mute > 0);
- cs35l41_mute(cs35l41->dev, cs35l41->mute_override);
-}
-
-static int cs35l41_hda_bind(struct device *dev, struct device *master, void *master_data)
-{
- struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
- struct hda_component_parent *parent = master_data;
- struct hda_component *comp;
- unsigned int sleep_flags;
- int ret = 0;
-
- comp = hda_component_from_index(parent, cs35l41->index);
- if (!comp)
- return -EINVAL;
-
- if (comp->dev)
- return -EBUSY;
-
- pm_runtime_get_sync(dev);
-
- mutex_lock(&cs35l41->fw_mutex);
-
- comp->dev = dev;
- cs35l41->codec = parent->codec;
- if (!cs35l41->acpi_subsystem_id)
- cs35l41->acpi_subsystem_id = kasprintf(GFP_KERNEL, "%.8x",
- cs35l41->codec->core.subsystem_id);
-
- strscpy(comp->name, dev_name(dev), sizeof(comp->name));
-
- cs35l41->firmware_type = CS35L41_HDA_FW_SPK_PROT;
-
- if (firmware_autostart) {
- dev_dbg(cs35l41->dev, "Firmware Autostart.\n");
- cs35l41->request_fw_load = true;
- if (cs35l41_smart_amp(cs35l41) < 0)
- dev_warn(cs35l41->dev, "Cannot Run Firmware, reverting to dsp bypass...\n");
- } else {
- dev_dbg(cs35l41->dev, "Firmware Autostart is disabled.\n");
- }
-
- ret = cs35l41_create_controls(cs35l41);
-
- comp->playback_hook = cs35l41_hda_playback_hook;
- comp->pre_playback_hook = cs35l41_hda_pre_playback_hook;
- comp->post_playback_hook = cs35l41_hda_post_playback_hook;
- comp->acpi_notify = cs35l41_acpi_device_notify;
- comp->adev = cs35l41->dacpi;
-
- comp->acpi_notifications_supported = cs35l41_dsm_supported(acpi_device_handle(comp->adev),
- CS35L41_DSM_GET_MUTE);
-
- cs35l41->mute_override = cs35l41_get_acpi_mute_state(cs35l41,
- acpi_device_handle(cs35l41->dacpi)) > 0;
-
- mutex_unlock(&cs35l41->fw_mutex);
-
- sleep_flags = lock_system_sleep();
- if (!device_link_add(&cs35l41->codec->core.dev, cs35l41->dev, DL_FLAG_STATELESS))
- dev_warn(dev, "Unable to create device link\n");
- unlock_system_sleep(sleep_flags);
-
- pm_runtime_mark_last_busy(dev);
- pm_runtime_put_autosuspend(dev);
-
- dev_info(cs35l41->dev,
- "CS35L41 Bound - SSID: %s, BST: %d, VSPK: %d, CH: %c, FW EN: %d, SPKID: %d\n",
- cs35l41->acpi_subsystem_id, cs35l41->hw_cfg.bst_type,
- cs35l41->hw_cfg.gpio1.func == CS35l41_VSPK_SWITCH,
- cs35l41->hw_cfg.spk_pos ? 'R' : 'L',
- cs35l41->cs_dsp.running, cs35l41->speaker_id);
-
- return ret;
-}
-
-static void cs35l41_hda_unbind(struct device *dev, struct device *master, void *master_data)
-{
- struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
- struct hda_component_parent *parent = master_data;
- struct hda_component *comp;
- unsigned int sleep_flags;
-
- comp = hda_component_from_index(parent, cs35l41->index);
- if (!comp)
- return;
-
- if (comp->dev == dev) {
- sleep_flags = lock_system_sleep();
- device_link_remove(&cs35l41->codec->core.dev, cs35l41->dev);
- unlock_system_sleep(sleep_flags);
- memset(comp, 0, sizeof(*comp));
- }
-}
-
-static const struct component_ops cs35l41_hda_comp_ops = {
- .bind = cs35l41_hda_bind,
- .unbind = cs35l41_hda_unbind,
-};
-
-static irqreturn_t cs35l41_bst_short_err(int irq, void *data)
-{
- struct cs35l41_hda *cs35l41 = data;
-
- dev_crit_ratelimited(cs35l41->dev, "LBST Error\n");
- set_bit(CS35L41_BST_SHORT_ERR_RLS_SHIFT, &cs35l41->irq_errors);
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t cs35l41_bst_dcm_uvp_err(int irq, void *data)
-{
- struct cs35l41_hda *cs35l41 = data;
-
- dev_crit_ratelimited(cs35l41->dev, "DCM VBST Under Voltage Error\n");
- set_bit(CS35L41_BST_UVP_ERR_RLS_SHIFT, &cs35l41->irq_errors);
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t cs35l41_bst_ovp_err(int irq, void *data)
-{
- struct cs35l41_hda *cs35l41 = data;
-
- dev_crit_ratelimited(cs35l41->dev, "VBST Over Voltage error\n");
- set_bit(CS35L41_BST_OVP_ERR_RLS_SHIFT, &cs35l41->irq_errors);
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t cs35l41_temp_err(int irq, void *data)
-{
- struct cs35l41_hda *cs35l41 = data;
-
- dev_crit_ratelimited(cs35l41->dev, "Over temperature error\n");
- set_bit(CS35L41_TEMP_ERR_RLS_SHIFT, &cs35l41->irq_errors);
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t cs35l41_temp_warn(int irq, void *data)
-{
- struct cs35l41_hda *cs35l41 = data;
-
- dev_crit_ratelimited(cs35l41->dev, "Over temperature warning\n");
- set_bit(CS35L41_TEMP_WARN_ERR_RLS_SHIFT, &cs35l41->irq_errors);
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t cs35l41_amp_short(int irq, void *data)
-{
- struct cs35l41_hda *cs35l41 = data;
-
- dev_crit_ratelimited(cs35l41->dev, "Amp short error\n");
- set_bit(CS35L41_AMP_SHORT_ERR_RLS_SHIFT, &cs35l41->irq_errors);
-
- return IRQ_HANDLED;
-}
-
-static const struct cs35l41_irq cs35l41_irqs[] = {
- CS35L41_IRQ(BST_OVP_ERR, "Boost Overvoltage Error", cs35l41_bst_ovp_err),
- CS35L41_IRQ(BST_DCM_UVP_ERR, "Boost Undervoltage Error", cs35l41_bst_dcm_uvp_err),
- CS35L41_IRQ(BST_SHORT_ERR, "Boost Inductor Short Error", cs35l41_bst_short_err),
- CS35L41_IRQ(TEMP_WARN, "Temperature Warning", cs35l41_temp_warn),
- CS35L41_IRQ(TEMP_ERR, "Temperature Error", cs35l41_temp_err),
- CS35L41_IRQ(AMP_SHORT_ERR, "Amp Short", cs35l41_amp_short),
-};
-
-static const struct regmap_irq cs35l41_reg_irqs[] = {
- CS35L41_REG_IRQ(IRQ1_STATUS1, BST_OVP_ERR),
- CS35L41_REG_IRQ(IRQ1_STATUS1, BST_DCM_UVP_ERR),
- CS35L41_REG_IRQ(IRQ1_STATUS1, BST_SHORT_ERR),
- CS35L41_REG_IRQ(IRQ1_STATUS1, TEMP_WARN),
- CS35L41_REG_IRQ(IRQ1_STATUS1, TEMP_ERR),
- CS35L41_REG_IRQ(IRQ1_STATUS1, AMP_SHORT_ERR),
-};
-
-static const struct regmap_irq_chip cs35l41_regmap_irq_chip = {
- .name = "cs35l41 IRQ1 Controller",
- .status_base = CS35L41_IRQ1_STATUS1,
- .mask_base = CS35L41_IRQ1_MASK1,
- .ack_base = CS35L41_IRQ1_STATUS1,
- .num_regs = 4,
- .irqs = cs35l41_reg_irqs,
- .num_irqs = ARRAY_SIZE(cs35l41_reg_irqs),
- .runtime_pm = true,
-};
-
-static void cs35l41_configure_interrupt(struct cs35l41_hda *cs35l41, int irq_pol)
-{
- int irq;
- int ret;
- int i;
-
- if (!cs35l41->irq) {
- dev_warn(cs35l41->dev, "No Interrupt Found");
- goto err;
- }
-
- ret = devm_regmap_add_irq_chip(cs35l41->dev, cs35l41->regmap, cs35l41->irq,
- IRQF_ONESHOT | IRQF_SHARED | irq_pol,
- 0, &cs35l41_regmap_irq_chip, &cs35l41->irq_data);
- if (ret) {
- dev_dbg(cs35l41->dev, "Unable to add IRQ Chip: %d.", ret);
- goto err;
- }
-
- for (i = 0; i < ARRAY_SIZE(cs35l41_irqs); i++) {
- irq = regmap_irq_get_virq(cs35l41->irq_data, cs35l41_irqs[i].irq);
- if (irq < 0) {
- ret = irq;
- dev_dbg(cs35l41->dev, "Unable to map IRQ %s: %d.", cs35l41_irqs[i].name,
- ret);
- goto err;
- }
-
- ret = devm_request_threaded_irq(cs35l41->dev, irq, NULL,
- cs35l41_irqs[i].handler,
- IRQF_ONESHOT | IRQF_SHARED | irq_pol,
- cs35l41_irqs[i].name, cs35l41);
- if (ret) {
- dev_dbg(cs35l41->dev, "Unable to allocate IRQ %s:: %d.",
- cs35l41_irqs[i].name, ret);
- goto err;
- }
- }
- return;
-err:
- dev_warn(cs35l41->dev,
- "IRQ Config Failed. Amp errors may not be recoverable without reboot.");
-}
-
-static int cs35l41_hda_apply_properties(struct cs35l41_hda *cs35l41)
-{
- struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg;
- bool using_irq = false;
- int irq_pol;
- int ret;
-
- if (!cs35l41->hw_cfg.valid)
- return -EINVAL;
-
- ret = cs35l41_init_boost(cs35l41->dev, cs35l41->regmap, hw_cfg);
- if (ret)
- return ret;
-
- if (hw_cfg->gpio1.valid) {
- switch (hw_cfg->gpio1.func) {
- case CS35L41_NOT_USED:
- break;
- case CS35l41_VSPK_SWITCH:
- hw_cfg->gpio1.func = CS35L41_GPIO1_GPIO;
- hw_cfg->gpio1.out_en = true;
- break;
- case CS35l41_SYNC:
- hw_cfg->gpio1.func = CS35L41_GPIO1_MDSYNC;
- break;
- default:
- dev_err(cs35l41->dev, "Invalid function %d for GPIO1\n",
- hw_cfg->gpio1.func);
- return -EINVAL;
- }
- }
-
- if (hw_cfg->gpio2.valid) {
- switch (hw_cfg->gpio2.func) {
- case CS35L41_NOT_USED:
- break;
- case CS35L41_INTERRUPT:
- using_irq = true;
- hw_cfg->gpio2.func = CS35L41_GPIO2_INT_OPEN_DRAIN;
- break;
- default:
- dev_err(cs35l41->dev, "Invalid GPIO2 function %d\n", hw_cfg->gpio2.func);
- return -EINVAL;
- }
- }
-
- irq_pol = cs35l41_gpio_config(cs35l41->regmap, hw_cfg);
-
- if (using_irq)
- cs35l41_configure_interrupt(cs35l41, irq_pol);
-
- return cs35l41_hda_channel_map(cs35l41->dev, 0, NULL, 1, &hw_cfg->spk_pos);
-}
-
-int cs35l41_get_speaker_id(struct device *dev, int amp_index, int num_amps, int fixed_gpio_id)
-{
- struct gpio_desc *speaker_id_desc;
- int speaker_id = -ENODEV;
-
- if (fixed_gpio_id >= 0) {
- dev_dbg(dev, "Found Fixed Speaker ID GPIO (index = %d)\n", fixed_gpio_id);
- speaker_id_desc = gpiod_get_index(dev, NULL, fixed_gpio_id, GPIOD_IN);
- if (IS_ERR(speaker_id_desc)) {
- speaker_id = PTR_ERR(speaker_id_desc);
- return speaker_id;
- }
- speaker_id = gpiod_get_value_cansleep(speaker_id_desc);
- gpiod_put(speaker_id_desc);
- dev_dbg(dev, "Speaker ID = %d\n", speaker_id);
- } else {
- int base_index;
- int gpios_per_amp;
- int count;
- int tmp;
- int i;
-
- count = gpiod_count(dev, "spk-id");
- if (count > 0) {
- speaker_id = 0;
- gpios_per_amp = count / num_amps;
- base_index = gpios_per_amp * amp_index;
-
- if (count % num_amps)
- return -EINVAL;
-
- dev_dbg(dev, "Found %d Speaker ID GPIOs per Amp\n", gpios_per_amp);
-
- for (i = 0; i < gpios_per_amp; i++) {
- speaker_id_desc = gpiod_get_index(dev, "spk-id", i + base_index,
- GPIOD_IN);
- if (IS_ERR(speaker_id_desc)) {
- speaker_id = PTR_ERR(speaker_id_desc);
- break;
- }
- tmp = gpiod_get_value_cansleep(speaker_id_desc);
- gpiod_put(speaker_id_desc);
- if (tmp < 0) {
- speaker_id = tmp;
- break;
- }
- speaker_id |= tmp << i;
- }
- dev_dbg(dev, "Speaker ID = %d\n", speaker_id);
- }
- }
- return speaker_id;
-}
-
-int cs35l41_hda_parse_acpi(struct cs35l41_hda *cs35l41, struct device *physdev, int id)
-{
- struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg;
- u32 values[HDA_MAX_COMPONENTS];
- char *property;
- size_t nval;
- int i, ret;
-
- property = "cirrus,dev-index";
- ret = device_property_count_u32(physdev, property);
- if (ret <= 0)
- goto err;
-
- if (ret > ARRAY_SIZE(values)) {
- ret = -EINVAL;
- goto err;
- }
- nval = ret;
-
- ret = device_property_read_u32_array(physdev, property, values, nval);
- if (ret)
- goto err;
-
- cs35l41->index = -1;
- for (i = 0; i < nval; i++) {
- if (values[i] == id) {
- cs35l41->index = i;
- break;
- }
- }
- if (cs35l41->index == -1) {
- dev_err(cs35l41->dev, "No index found in %s\n", property);
- ret = -ENODEV;
- goto err;
- }
-
- /* To use the same release code for all laptop variants we can't use devm_ version of
- * gpiod_get here, as CLSA010* don't have a fully functional bios with an _DSD node
- */
- cs35l41->reset_gpio = fwnode_gpiod_get_index(acpi_fwnode_handle(cs35l41->dacpi), "reset",
- cs35l41->index, GPIOD_OUT_LOW,
- "cs35l41-reset");
-
- property = "cirrus,speaker-position";
- ret = device_property_read_u32_array(physdev, property, values, nval);
- if (ret)
- goto err;
- hw_cfg->spk_pos = values[cs35l41->index];
-
- cs35l41->channel_index = 0;
- for (i = 0; i < cs35l41->index; i++)
- if (values[i] == hw_cfg->spk_pos)
- cs35l41->channel_index++;
-
- property = "cirrus,gpio1-func";
- ret = device_property_read_u32_array(physdev, property, values, nval);
- if (ret)
- goto err;
- hw_cfg->gpio1.func = values[cs35l41->index];
- hw_cfg->gpio1.valid = true;
-
- property = "cirrus,gpio2-func";
- ret = device_property_read_u32_array(physdev, property, values, nval);
- if (ret)
- goto err;
- hw_cfg->gpio2.func = values[cs35l41->index];
- hw_cfg->gpio2.valid = true;
-
- property = "cirrus,boost-peak-milliamp";
- ret = device_property_read_u32_array(physdev, property, values, nval);
- if (ret == 0)
- hw_cfg->bst_ipk = values[cs35l41->index];
- else
- hw_cfg->bst_ipk = -1;
-
- property = "cirrus,boost-ind-nanohenry";
- ret = device_property_read_u32_array(physdev, property, values, nval);
- if (ret == 0)
- hw_cfg->bst_ind = values[cs35l41->index];
- else
- hw_cfg->bst_ind = -1;
-
- property = "cirrus,boost-cap-microfarad";
- ret = device_property_read_u32_array(physdev, property, values, nval);
- if (ret == 0)
- hw_cfg->bst_cap = values[cs35l41->index];
- else
- hw_cfg->bst_cap = -1;
-
- cs35l41->speaker_id = cs35l41_get_speaker_id(physdev, cs35l41->index, nval, -1);
-
- if (hw_cfg->bst_ind > 0 || hw_cfg->bst_cap > 0 || hw_cfg->bst_ipk > 0)
- hw_cfg->bst_type = CS35L41_INT_BOOST;
- else
- hw_cfg->bst_type = CS35L41_EXT_BOOST;
-
- hw_cfg->valid = true;
-
- return 0;
-err:
- dev_err(cs35l41->dev, "Failed property %s: %d\n", property, ret);
- hw_cfg->valid = false;
- hw_cfg->gpio1.valid = false;
- hw_cfg->gpio2.valid = false;
- acpi_dev_put(cs35l41->dacpi);
-
- return ret;
-}
-
-static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, int id)
-{
- struct acpi_device *adev;
- struct device *physdev;
- struct spi_device *spi;
- const char *sub;
- int ret;
-
- adev = acpi_dev_get_first_match_dev(hid, NULL, -1);
- if (!adev) {
- dev_err(cs35l41->dev, "Failed to find an ACPI device for %s\n", hid);
- return -ENODEV;
- }
-
- cs35l41->dacpi = adev;
- physdev = get_device(acpi_get_first_physical_node(adev));
-
- sub = acpi_get_subsystem_id(ACPI_HANDLE(physdev));
- if (IS_ERR(sub))
- sub = NULL;
- cs35l41->acpi_subsystem_id = sub;
-
- ret = cs35l41_add_dsd_properties(cs35l41, physdev, id, hid);
- if (!ret) {
- dev_info(cs35l41->dev, "Using extra _DSD properties, bypassing _DSD in ACPI\n");
- goto out;
- }
-
- ret = cs35l41_hda_parse_acpi(cs35l41, physdev, id);
- if (ret) {
- put_device(physdev);
- return ret;
- }
-out:
- put_device(physdev);
-
- cs35l41->bypass_fw = false;
- if (cs35l41->control_bus == SPI) {
- spi = to_spi_device(cs35l41->dev);
- if (spi->max_speed_hz < CS35L41_MAX_ACCEPTABLE_SPI_SPEED_HZ) {
- dev_warn(cs35l41->dev,
- "SPI speed is too slow to support firmware download: %d Hz.\n",
- spi->max_speed_hz);
- cs35l41->bypass_fw = true;
- }
- }
-
- return 0;
-}
-
-int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq,
- struct regmap *regmap, enum control_bus control_bus)
-{
- unsigned int regid, reg_revid;
- struct cs35l41_hda *cs35l41;
- int ret;
-
- BUILD_BUG_ON(ARRAY_SIZE(cs35l41_irqs) != ARRAY_SIZE(cs35l41_reg_irqs));
- BUILD_BUG_ON(ARRAY_SIZE(cs35l41_irqs) != CS35L41_NUM_IRQ);
-
- if (IS_ERR(regmap))
- return PTR_ERR(regmap);
-
- cs35l41 = devm_kzalloc(dev, sizeof(*cs35l41), GFP_KERNEL);
- if (!cs35l41)
- return -ENOMEM;
-
- cs35l41->dev = dev;
- cs35l41->irq = irq;
- cs35l41->regmap = regmap;
- cs35l41->control_bus = control_bus;
- dev_set_drvdata(dev, cs35l41);
-
- ret = cs35l41_hda_read_acpi(cs35l41, device_name, id);
- if (ret)
- return dev_err_probe(cs35l41->dev, ret, "Platform not supported\n");
-
- if (IS_ERR(cs35l41->reset_gpio)) {
- ret = PTR_ERR(cs35l41->reset_gpio);
- cs35l41->reset_gpio = NULL;
- if (ret == -EBUSY) {
- dev_info(cs35l41->dev, "Reset line busy, assuming shared reset\n");
- } else {
- dev_err_probe(cs35l41->dev, ret, "Failed to get reset GPIO\n");
- goto err;
- }
- }
- if (cs35l41->reset_gpio) {
- gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
- usleep_range(2000, 2100);
- gpiod_set_value_cansleep(cs35l41->reset_gpio, 1);
- }
-
- usleep_range(2000, 2100);
- regmap_write(cs35l41->regmap, CS35L41_SFT_RESET, CS35L41_SOFTWARE_RESET);
- usleep_range(2000, 2100);
-
- ret = cs35l41_wait_boot_done(cs35l41);
- if (ret)
- goto err;
-
- ret = cs35l41_verify_id(cs35l41, &regid, &reg_revid);
- if (ret)
- goto err;
-
- ret = cs35l41_test_key_unlock(cs35l41->dev, cs35l41->regmap);
- if (ret)
- goto err;
-
- ret = cs35l41_register_errata_patch(cs35l41->dev, cs35l41->regmap, reg_revid);
- if (ret)
- goto err;
-
- ret = cs35l41_otp_unpack(cs35l41->dev, cs35l41->regmap);
- if (ret) {
- dev_err_probe(cs35l41->dev, ret, "OTP Unpack failed\n");
- goto err;
- }
-
- ret = cs35l41_test_key_lock(cs35l41->dev, cs35l41->regmap);
- if (ret)
- goto err;
-
- ret = cs35l41_get_calibration(cs35l41);
- if (ret && ret != -ENOENT)
- goto err;
-
- cs35l41_mute(cs35l41->dev, true);
-
- INIT_WORK(&cs35l41->fw_load_work, cs35l41_fw_load_work);
- mutex_init(&cs35l41->fw_mutex);
-
- pm_runtime_set_autosuspend_delay(cs35l41->dev, 3000);
- pm_runtime_use_autosuspend(cs35l41->dev);
- pm_runtime_mark_last_busy(cs35l41->dev);
- pm_runtime_set_active(cs35l41->dev);
- pm_runtime_get_noresume(cs35l41->dev);
- pm_runtime_enable(cs35l41->dev);
-
- ret = cs35l41_hda_apply_properties(cs35l41);
- if (ret)
- goto err_pm;
-
- pm_runtime_put_autosuspend(cs35l41->dev);
-
- ret = component_add(cs35l41->dev, &cs35l41_hda_comp_ops);
- if (ret) {
- dev_err_probe(cs35l41->dev, ret, "Register component failed\n");
- goto err_pm;
- }
-
- dev_info(cs35l41->dev, "Cirrus Logic CS35L41 (%x), Revision: %02X\n", regid, reg_revid);
-
- return 0;
-
-err_pm:
- pm_runtime_dont_use_autosuspend(cs35l41->dev);
- pm_runtime_disable(cs35l41->dev);
- pm_runtime_put_noidle(cs35l41->dev);
-
-err:
- if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type))
- gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
- gpiod_put(cs35l41->reset_gpio);
- gpiod_put(cs35l41->cs_gpio);
- acpi_dev_put(cs35l41->dacpi);
- kfree(cs35l41->acpi_subsystem_id);
-
- return ret;
-}
-EXPORT_SYMBOL_NS_GPL(cs35l41_hda_probe, "SND_HDA_SCODEC_CS35L41");
-
-void cs35l41_hda_remove(struct device *dev)
-{
- struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
-
- component_del(cs35l41->dev, &cs35l41_hda_comp_ops);
-
- pm_runtime_get_sync(cs35l41->dev);
- pm_runtime_dont_use_autosuspend(cs35l41->dev);
- pm_runtime_disable(cs35l41->dev);
-
- if (cs35l41->halo_initialized)
- cs35l41_remove_dsp(cs35l41);
-
- acpi_dev_put(cs35l41->dacpi);
-
- pm_runtime_put_noidle(cs35l41->dev);
-
- if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type))
- gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
- gpiod_put(cs35l41->reset_gpio);
- gpiod_put(cs35l41->cs_gpio);
- kfree(cs35l41->acpi_subsystem_id);
-}
-EXPORT_SYMBOL_NS_GPL(cs35l41_hda_remove, "SND_HDA_SCODEC_CS35L41");
-
-const struct dev_pm_ops cs35l41_hda_pm_ops = {
- RUNTIME_PM_OPS(cs35l41_runtime_suspend, cs35l41_runtime_resume,
- cs35l41_runtime_idle)
- .prepare = cs35l41_system_suspend_prep,
- SYSTEM_SLEEP_PM_OPS(cs35l41_system_suspend, cs35l41_system_resume)
-};
-EXPORT_SYMBOL_NS_GPL(cs35l41_hda_pm_ops, "SND_HDA_SCODEC_CS35L41");
-
-MODULE_DESCRIPTION("CS35L41 HDA Driver");
-MODULE_IMPORT_NS("SND_SOC_CS_AMP_LIB");
-MODULE_AUTHOR("Lucas Tanure, Cirrus Logic Inc, <tanureal@opensource.cirrus.com>");
-MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS("FW_CS_DSP");
diff --git a/sound/pci/hda/cs35l41_hda.h b/sound/pci/hda/cs35l41_hda.h
deleted file mode 100644
index c730b3351589..000000000000
--- a/sound/pci/hda/cs35l41_hda.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0
- *
- * CS35L41 ALSA HDA audio driver
- *
- * Copyright 2021 Cirrus Logic, Inc.
- *
- * Author: Lucas Tanure <tanureal@opensource.cirrus.com>
- */
-
-#ifndef __CS35L41_HDA_H__
-#define __CS35L41_HDA_H__
-
-#include <linux/acpi.h>
-#include <linux/efi.h>
-#include <linux/regulator/consumer.h>
-#include <linux/gpio/consumer.h>
-#include <linux/device.h>
-#include <sound/cs35l41.h>
-#include <sound/cs-amp-lib.h>
-
-#include <linux/firmware/cirrus/cs_dsp.h>
-#include <linux/firmware/cirrus/wmfw.h>
-
-#define CS35L41_MAX_ACCEPTABLE_SPI_SPEED_HZ 1000000
-#define DEFAULT_AMP_GAIN_PCM 17 /* 17.5dB Gain */
-#define DEFAULT_AMP_GAIN_PDM 19 /* 19.5dB Gain */
-
-struct cs35l41_amp_cal_data {
- u32 calTarget[2];
- u32 calTime[2];
- s8 calAmbient;
- u8 calStatus;
- u16 calR;
-} __packed;
-
-struct cs35l41_amp_efi_data {
- u32 size;
- u32 count;
- struct cs35l41_amp_cal_data data[];
-} __packed;
-
-enum cs35l41_hda_spk_pos {
- CS35L41_LEFT,
- CS35L41_RIGHT,
-};
-
-enum cs35l41_hda_gpio_function {
- CS35L41_NOT_USED,
- CS35l41_VSPK_SWITCH,
- CS35L41_INTERRUPT,
- CS35l41_SYNC,
-};
-
-enum control_bus {
- I2C,
- SPI
-};
-
-struct cs35l41_hda {
- struct device *dev;
- struct regmap *regmap;
- struct gpio_desc *reset_gpio;
- struct gpio_desc *cs_gpio;
- struct cs35l41_hw_cfg hw_cfg;
- struct hda_codec *codec;
-
- int irq;
- int index;
- int channel_index;
- unsigned volatile long irq_errors;
- const char *amp_name;
- const char *acpi_subsystem_id;
- int firmware_type;
- int speaker_id;
- struct mutex fw_mutex;
- struct work_struct fw_load_work;
-
- struct regmap_irq_chip_data *irq_data;
- bool firmware_running;
- bool request_fw_load;
- bool fw_request_ongoing;
- bool halo_initialized;
- bool playback_started;
- struct cs_dsp cs_dsp;
- struct acpi_device *dacpi;
- bool mute_override;
- enum control_bus control_bus;
- bool bypass_fw;
- unsigned int tuning_gain;
- struct cirrus_amp_cal_data cal_data;
- bool cal_data_valid;
-
-};
-
-enum halo_state {
- HALO_STATE_CODE_INIT_DOWNLOAD = 0,
- HALO_STATE_CODE_START,
- HALO_STATE_CODE_RUN
-};
-
-extern const struct dev_pm_ops cs35l41_hda_pm_ops;
-
-int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq,
- struct regmap *regmap, enum control_bus control_bus);
-void cs35l41_hda_remove(struct device *dev);
-int cs35l41_get_speaker_id(struct device *dev, int amp_index, int num_amps, int fixed_gpio_id);
-int cs35l41_hda_parse_acpi(struct cs35l41_hda *cs35l41, struct device *physdev, int id);
-
-#endif /*__CS35L41_HDA_H__*/
diff --git a/sound/pci/hda/cs35l41_hda_i2c.c b/sound/pci/hda/cs35l41_hda_i2c.c
deleted file mode 100644
index e77495413c21..000000000000
--- a/sound/pci/hda/cs35l41_hda_i2c.c
+++ /dev/null
@@ -1,69 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// CS35l41 HDA I2C driver
-//
-// Copyright 2021 Cirrus Logic, Inc.
-//
-// Author: Lucas Tanure <tanureal@opensource.cirrus.com>
-
-#include <linux/mod_devicetable.h>
-#include <linux/module.h>
-#include <linux/i2c.h>
-
-#include "cs35l41_hda.h"
-
-static int cs35l41_hda_i2c_probe(struct i2c_client *clt)
-{
- const char *device_name;
-
- /*
- * Compare against the device name so it works for SPI, normal ACPI
- * and for ACPI by serial-multi-instantiate matching cases.
- */
- if (strstr(dev_name(&clt->dev), "CLSA0100"))
- device_name = "CLSA0100";
- else if (strstr(dev_name(&clt->dev), "CLSA0101"))
- device_name = "CLSA0101";
- else if (strstr(dev_name(&clt->dev), "CSC3551"))
- device_name = "CSC3551";
- else
- return -ENODEV;
-
- return cs35l41_hda_probe(&clt->dev, device_name, clt->addr, clt->irq,
- devm_regmap_init_i2c(clt, &cs35l41_regmap_i2c), I2C);
-}
-
-static void cs35l41_hda_i2c_remove(struct i2c_client *clt)
-{
- cs35l41_hda_remove(&clt->dev);
-}
-
-static const struct i2c_device_id cs35l41_hda_i2c_id[] = {
- { "cs35l41-hda" },
- {}
-};
-
-static const struct acpi_device_id cs35l41_acpi_hda_match[] = {
- {"CLSA0100", 0 },
- {"CLSA0101", 0 },
- {"CSC3551", 0 },
- {}
-};
-MODULE_DEVICE_TABLE(acpi, cs35l41_acpi_hda_match);
-
-static struct i2c_driver cs35l41_i2c_driver = {
- .driver = {
- .name = "cs35l41-hda",
- .acpi_match_table = cs35l41_acpi_hda_match,
- .pm = &cs35l41_hda_pm_ops,
- },
- .id_table = cs35l41_hda_i2c_id,
- .probe = cs35l41_hda_i2c_probe,
- .remove = cs35l41_hda_i2c_remove,
-};
-module_i2c_driver(cs35l41_i2c_driver);
-
-MODULE_DESCRIPTION("HDA CS35L41 driver");
-MODULE_IMPORT_NS("SND_HDA_SCODEC_CS35L41");
-MODULE_AUTHOR("Lucas Tanure <tanureal@opensource.cirrus.com>");
-MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/cs35l41_hda_property.c b/sound/pci/hda/cs35l41_hda_property.c
deleted file mode 100644
index d8249d997c2a..000000000000
--- a/sound/pci/hda/cs35l41_hda_property.c
+++ /dev/null
@@ -1,578 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// CS35L41 ALSA HDA Property driver
-//
-// Copyright 2023 Cirrus Logic, Inc.
-//
-// Author: Stefan Binding <sbinding@opensource.cirrus.com>
-
-#include <linux/acpi.h>
-#include <linux/gpio/consumer.h>
-#include <linux/string.h>
-#include "cs35l41_hda_property.h"
-#include <linux/spi/spi.h>
-
-#define MAX_AMPS 4
-
-struct cs35l41_config {
- const char *ssid;
- int num_amps;
- enum {
- INTERNAL,
- EXTERNAL
- } boost_type;
- u8 channel[MAX_AMPS];
- int reset_gpio_index; /* -1 if no reset gpio */
- int spkid_gpio_index; /* -1 if no spkid gpio */
- int cs_gpio_index; /* -1 if no cs gpio, or cs-gpios already exists, max num amps == 2 */
- int boost_ind_nanohenry; /* Required if boost_type == Internal */
- int boost_peak_milliamp; /* Required if boost_type == Internal */
- int boost_cap_microfarad; /* Required if boost_type == Internal */
-};
-
-static const struct cs35l41_config cs35l41_config_table[] = {
- { "10251826", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 },
- { "1025182C", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 },
- { "10251844", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 },
- { "10280B27", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
- { "10280B28", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
- { "10280BEB", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 0, 0, 0 },
- { "10280C4D", 4, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, CS35L41_LEFT, CS35L41_RIGHT }, 0, 1, -1, 1000, 4500, 24 },
-/*
- * Device 103C89C6 does have _DSD, however it is setup to use the wrong boost type.
- * We can override the _DSD to correct the boost type here.
- * Since this laptop has valid ACPI, we do not need to handle cs-gpios, since that already exists
- * in the ACPI. The Reset GPIO is also valid, so we can use the Reset defined in _DSD.
- */
- { "103C89C6", 2, INTERNAL, { CS35L41_RIGHT, CS35L41_LEFT, 0, 0 }, -1, -1, -1, 1000, 4500, 24 },
- { "103C8A28", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 },
- { "103C8A29", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 },
- { "103C8A2A", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 },
- { "103C8A2B", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 },
- { "103C8A2C", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 },
- { "103C8A2D", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 },
- { "103C8A2E", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 },
- { "103C8A30", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 },
- { "103C8A31", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 },
- { "103C8A6E", 4, EXTERNAL, { CS35L41_LEFT, CS35L41_LEFT, CS35L41_RIGHT, CS35L41_RIGHT }, 0, -1, -1, 0, 0, 0 },
- { "103C8BB3", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 },
- { "103C8BB4", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 },
- { "103C8BDD", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 },
- { "103C8BDE", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 },
- { "103C8BDF", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 },
- { "103C8BE0", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 },
- { "103C8BE1", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 },
- { "103C8BE2", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 },
- { "103C8BE3", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 },
- { "103C8BE5", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 },
- { "103C8BE6", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 },
- { "103C8BE7", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 },
- { "103C8BE8", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 },
- { "103C8BE9", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 },
- { "103C8B3A", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 },
- { "103C8C15", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4000, 24 },
- { "103C8C16", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4000, 24 },
- { "103C8C17", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4000, 24 },
- { "103C8C4D", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 },
- { "103C8C4E", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 },
- { "103C8C4F", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 },
- { "103C8C50", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 },
- { "103C8C51", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 },
- { "103C8CDD", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4100, 24 },
- { "103C8CDE", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 3900, 24 },
- { "104312AF", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
- { "10431433", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 },
- { "10431463", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 },
- { "10431473", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 1000, 4500, 24 },
- { "10431483", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 1000, 4500, 24 },
- { "10431493", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
- { "104314D3", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
- { "104314E3", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 },
- { "10431503", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 },
- { "10431533", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 },
- { "10431573", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
- { "10431663", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 1000, 4500, 24 },
- { "10431683", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
- { "104316A3", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 },
- { "104316D3", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 },
- { "104316F3", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 },
- { "104317F3", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 },
- { "10431863", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
- { "104318D3", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
- { "10431A83", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 },
- { "10431B93", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
- { "10431C9F", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
- { "10431CAF", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
- { "10431CCF", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
- { "10431CDF", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
- { "10431CEF", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
- { "10431D1F", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 },
- { "10431DA2", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 },
- { "10431E02", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 },
- { "10431E12", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
- { "10431EE2", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 },
- { "10431F12", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 },
- { "10431F1F", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 0, 0, 0 },
- { "10431F62", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 },
- { "10433A20", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
- { "10433A30", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
- { "10433A40", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
- { "10433A50", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
- { "10433A60", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
- { "17AA3865", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 },
- { "17AA3866", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 },
- { "17AA386E", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 2, -1, 0, 0, 0 },
- { "17AA386F", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 },
- { "17AA3877", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 },
- { "17AA3878", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 },
- { "17AA38A9", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 2, -1, 0, 0, 0 },
- { "17AA38AB", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 2, -1, 0, 0, 0 },
- { "17AA38B4", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
- { "17AA38B5", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
- { "17AA38B6", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
- { "17AA38B7", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
- { "17AA38C7", 4, INTERNAL, { CS35L41_RIGHT, CS35L41_LEFT, CS35L41_RIGHT, CS35L41_LEFT }, 0, 2, -1, 1000, 4500, 24 },
- { "17AA38C8", 4, INTERNAL, { CS35L41_RIGHT, CS35L41_LEFT, CS35L41_RIGHT, CS35L41_LEFT }, 0, 2, -1, 1000, 4500, 24 },
- { "17AA38F9", 2, EXTERNAL, { CS35L41_RIGHT, CS35L41_LEFT, 0, 0 }, 0, 2, -1, 0, 0, 0 },
- { "17AA38FA", 2, EXTERNAL, { CS35L41_RIGHT, CS35L41_LEFT, 0, 0 }, 0, 2, -1, 0, 0, 0 },
- {}
-};
-
-static int cs35l41_add_gpios(struct cs35l41_hda *cs35l41, struct device *physdev, int reset_gpio,
- int spkid_gpio, int cs_gpio_index, int num_amps)
-{
- struct acpi_gpio_mapping *gpio_mapping = NULL;
- struct acpi_gpio_params *reset_gpio_params = NULL;
- struct acpi_gpio_params *spkid_gpio_params = NULL;
- struct acpi_gpio_params *cs_gpio_params = NULL;
- unsigned int num_entries = 0;
- unsigned int reset_index, spkid_index, csgpio_index;
- int i;
-
- /*
- * GPIO Mapping only needs to be done once, since it would be available for subsequent amps
- */
- if (cs35l41->dacpi->driver_gpios)
- return 0;
-
- if (reset_gpio >= 0) {
- reset_index = num_entries;
- num_entries++;
- }
-
- if (spkid_gpio >= 0) {
- spkid_index = num_entries;
- num_entries++;
- }
-
- if ((cs_gpio_index >= 0) && (num_amps == 2)) {
- csgpio_index = num_entries;
- num_entries++;
- }
-
- if (!num_entries)
- return 0;
-
- /* must include termination entry */
- num_entries++;
-
- gpio_mapping = devm_kcalloc(physdev, num_entries, sizeof(struct acpi_gpio_mapping),
- GFP_KERNEL);
-
- if (!gpio_mapping)
- goto err;
-
- if (reset_gpio >= 0) {
- gpio_mapping[reset_index].name = "reset-gpios";
- reset_gpio_params = devm_kcalloc(physdev, num_amps, sizeof(struct acpi_gpio_params),
- GFP_KERNEL);
- if (!reset_gpio_params)
- goto err;
-
- for (i = 0; i < num_amps; i++)
- reset_gpio_params[i].crs_entry_index = reset_gpio;
-
- gpio_mapping[reset_index].data = reset_gpio_params;
- gpio_mapping[reset_index].size = num_amps;
- }
-
- if (spkid_gpio >= 0) {
- gpio_mapping[spkid_index].name = "spk-id-gpios";
- spkid_gpio_params = devm_kcalloc(physdev, num_amps, sizeof(struct acpi_gpio_params),
- GFP_KERNEL);
- if (!spkid_gpio_params)
- goto err;
-
- for (i = 0; i < num_amps; i++)
- spkid_gpio_params[i].crs_entry_index = spkid_gpio;
-
- gpio_mapping[spkid_index].data = spkid_gpio_params;
- gpio_mapping[spkid_index].size = num_amps;
- }
-
- if ((cs_gpio_index >= 0) && (num_amps == 2)) {
- gpio_mapping[csgpio_index].name = "cs-gpios";
- /* only one GPIO CS is supported without using _DSD, obtained using index 0 */
- cs_gpio_params = devm_kzalloc(physdev, sizeof(struct acpi_gpio_params), GFP_KERNEL);
- if (!cs_gpio_params)
- goto err;
-
- cs_gpio_params->crs_entry_index = cs_gpio_index;
-
- gpio_mapping[csgpio_index].data = cs_gpio_params;
- gpio_mapping[csgpio_index].size = 1;
- }
-
- return devm_acpi_dev_add_driver_gpios(physdev, gpio_mapping);
-err:
- devm_kfree(physdev, gpio_mapping);
- devm_kfree(physdev, reset_gpio_params);
- devm_kfree(physdev, spkid_gpio_params);
- devm_kfree(physdev, cs_gpio_params);
- return -ENOMEM;
-}
-
-static int generic_dsd_config(struct cs35l41_hda *cs35l41, struct device *physdev, int id,
- const char *hid)
-{
- struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg;
- const struct cs35l41_config *cfg;
- struct gpio_desc *cs_gpiod;
- struct spi_device *spi;
- bool dsd_found;
- int ret;
- int i;
-
- for (cfg = cs35l41_config_table; cfg->ssid; cfg++) {
- if (!strcasecmp(cfg->ssid, cs35l41->acpi_subsystem_id))
- break;
- }
-
- if (!cfg->ssid)
- return -ENOENT;
-
- if (!cs35l41->dacpi || cs35l41->dacpi != ACPI_COMPANION(physdev)) {
- dev_err(cs35l41->dev, "ACPI Device does not match, cannot override _DSD.\n");
- return -ENODEV;
- }
-
- dev_info(cs35l41->dev, "Adding DSD properties for %s\n", cs35l41->acpi_subsystem_id);
-
- dsd_found = acpi_dev_has_props(cs35l41->dacpi);
-
- if (!dsd_found) {
- ret = cs35l41_add_gpios(cs35l41, physdev, cfg->reset_gpio_index,
- cfg->spkid_gpio_index, cfg->cs_gpio_index,
- cfg->num_amps);
- if (ret) {
- dev_err(cs35l41->dev, "Error adding GPIO mapping: %d\n", ret);
- return ret;
- }
- } else if (cfg->reset_gpio_index >= 0 || cfg->spkid_gpio_index >= 0) {
- dev_warn(cs35l41->dev, "Cannot add Reset/Speaker ID/SPI CS GPIO Mapping, "
- "_DSD already exists.\n");
- }
-
- if (cs35l41->control_bus == SPI) {
- cs35l41->index = id;
-
- /*
- * Manually set the Chip Select for the second amp <cs_gpio_index> in the node.
- * This is only supported for systems with 2 amps, since we cannot expand the
- * default number of chip selects without using cs-gpios
- * The CS GPIO must be set high prior to communicating with the first amp (which
- * uses a native chip select), to ensure the second amp does not clash with the
- * first.
- */
- if (IS_ENABLED(CONFIG_SPI) && cfg->cs_gpio_index >= 0) {
- spi = to_spi_device(cs35l41->dev);
-
- if (cfg->num_amps != 2) {
- dev_warn(cs35l41->dev,
- "Cannot update SPI CS, Number of Amps (%d) != 2\n",
- cfg->num_amps);
- } else if (dsd_found) {
- dev_warn(cs35l41->dev,
- "Cannot update SPI CS, _DSD already exists.\n");
- } else {
- /*
- * This is obtained using driver_gpios, since only one GPIO for CS
- * exists, this can be obtained using index 0.
- */
- cs_gpiod = gpiod_get_index(physdev, "cs", 0, GPIOD_OUT_LOW);
- if (IS_ERR(cs_gpiod)) {
- dev_err(cs35l41->dev,
- "Unable to get Chip Select GPIO descriptor\n");
- return PTR_ERR(cs_gpiod);
- }
- if (id == 1) {
- spi_set_csgpiod(spi, 0, cs_gpiod);
- cs35l41->cs_gpio = cs_gpiod;
- } else {
- gpiod_set_value_cansleep(cs_gpiod, true);
- gpiod_put(cs_gpiod);
- }
- spi_setup(spi);
- }
- }
- } else {
- if (cfg->num_amps > 2)
- /*
- * i2c addresses for 3/4 amps are used in order: 0x40, 0x41, 0x42, 0x43,
- * subtracting 0x40 would give zero-based index
- */
- cs35l41->index = id - 0x40;
- else
- /* i2c addr 0x40 for first amp (always), 0x41/0x42 for 2nd amp */
- cs35l41->index = id == 0x40 ? 0 : 1;
- }
-
- cs35l41->reset_gpio = fwnode_gpiod_get_index(acpi_fwnode_handle(cs35l41->dacpi), "reset",
- cs35l41->index, GPIOD_OUT_LOW,
- "cs35l41-reset");
- cs35l41->speaker_id = cs35l41_get_speaker_id(physdev, cs35l41->index, cfg->num_amps, -1);
-
- hw_cfg->spk_pos = cfg->channel[cs35l41->index];
-
- cs35l41->channel_index = 0;
- for (i = 0; i < cs35l41->index; i++)
- if (cfg->channel[i] == hw_cfg->spk_pos)
- cs35l41->channel_index++;
-
- if (cfg->boost_type == INTERNAL) {
- hw_cfg->bst_type = CS35L41_INT_BOOST;
- hw_cfg->bst_ind = cfg->boost_ind_nanohenry;
- hw_cfg->bst_ipk = cfg->boost_peak_milliamp;
- hw_cfg->bst_cap = cfg->boost_cap_microfarad;
- hw_cfg->gpio1.func = CS35L41_NOT_USED;
- hw_cfg->gpio1.valid = true;
- } else {
- hw_cfg->bst_type = CS35L41_EXT_BOOST;
- hw_cfg->bst_ind = -1;
- hw_cfg->bst_ipk = -1;
- hw_cfg->bst_cap = -1;
- hw_cfg->gpio1.func = CS35l41_VSPK_SWITCH;
- hw_cfg->gpio1.valid = true;
- }
-
- hw_cfg->gpio2.func = CS35L41_INTERRUPT;
- hw_cfg->gpio2.valid = true;
- hw_cfg->valid = true;
-
- return 0;
-}
-
-/*
- * Systems 103C8C66, 103C8C67, 103C8C68, 103C8C6A use a dual speaker id system - each speaker has
- * its own speaker id.
- */
-static int hp_i2c_int_2amp_dual_spkid(struct cs35l41_hda *cs35l41, struct device *physdev, int id,
- const char *hid)
-{
- struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg;
-
- /* If _DSD exists for this laptop, we cannot support it through here */
- if (acpi_dev_has_props(cs35l41->dacpi))
- return -ENOENT;
-
- /* check I2C address to assign the index */
- cs35l41->index = id == 0x40 ? 0 : 1;
- cs35l41->channel_index = 0;
- cs35l41->reset_gpio = gpiod_get_index(physdev, NULL, 0, GPIOD_OUT_HIGH);
- if (cs35l41->index == 0)
- cs35l41->speaker_id = cs35l41_get_speaker_id(physdev, 0, 0, 1);
- else
- cs35l41->speaker_id = cs35l41_get_speaker_id(physdev, 0, 0, 2);
- hw_cfg->spk_pos = cs35l41->index;
- hw_cfg->gpio2.func = CS35L41_INTERRUPT;
- hw_cfg->gpio2.valid = true;
- hw_cfg->valid = true;
-
- hw_cfg->bst_type = CS35L41_INT_BOOST;
- hw_cfg->bst_ind = 1000;
- hw_cfg->bst_ipk = 4100;
- hw_cfg->bst_cap = 24;
- hw_cfg->gpio1.func = CS35L41_NOT_USED;
- hw_cfg->gpio1.valid = true;
-
- return 0;
-}
-
-/*
- * Device CLSA010(0/1) doesn't have _DSD so a gpiod_get by the label reset won't work.
- * And devices created by serial-multi-instantiate don't have their device struct
- * pointing to the correct fwnode, so acpi_dev must be used here.
- * And devm functions expect that the device requesting the resource has the correct
- * fwnode.
- */
-static int lenovo_legion_no_acpi(struct cs35l41_hda *cs35l41, struct device *physdev, int id,
- const char *hid)
-{
- struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg;
-
- /* check I2C address to assign the index */
- cs35l41->index = id == 0x40 ? 0 : 1;
- cs35l41->channel_index = 0;
- cs35l41->reset_gpio = gpiod_get_index(physdev, NULL, 0, GPIOD_OUT_HIGH);
- cs35l41->speaker_id = cs35l41_get_speaker_id(physdev, 0, 0, 2);
- hw_cfg->spk_pos = cs35l41->index;
- hw_cfg->gpio2.func = CS35L41_INTERRUPT;
- hw_cfg->gpio2.valid = true;
- hw_cfg->valid = true;
-
- if (strcmp(hid, "CLSA0100") == 0) {
- hw_cfg->bst_type = CS35L41_EXT_BOOST_NO_VSPK_SWITCH;
- } else if (strcmp(hid, "CLSA0101") == 0) {
- hw_cfg->bst_type = CS35L41_EXT_BOOST;
- hw_cfg->gpio1.func = CS35l41_VSPK_SWITCH;
- hw_cfg->gpio1.valid = true;
- }
-
- return 0;
-}
-
-static int missing_speaker_id_gpio2(struct cs35l41_hda *cs35l41, struct device *physdev, int id,
- const char *hid)
-{
- int ret;
-
- ret = cs35l41_add_gpios(cs35l41, physdev, -1, 2, -1, 2);
- if (ret) {
- dev_err(cs35l41->dev, "Error adding GPIO mapping: %d\n", ret);
- return ret;
- }
-
- return cs35l41_hda_parse_acpi(cs35l41, physdev, id);
-}
-
-struct cs35l41_prop_model {
- const char *hid;
- const char *ssid;
- int (*add_prop)(struct cs35l41_hda *cs35l41, struct device *physdev, int id,
- const char *hid);
-};
-
-static const struct cs35l41_prop_model cs35l41_prop_model_table[] = {
- { "CLSA0100", NULL, lenovo_legion_no_acpi },
- { "CLSA0101", NULL, lenovo_legion_no_acpi },
- { "CSC3551", "10251826", generic_dsd_config },
- { "CSC3551", "1025182C", generic_dsd_config },
- { "CSC3551", "10251844", generic_dsd_config },
- { "CSC3551", "10280B27", generic_dsd_config },
- { "CSC3551", "10280B28", generic_dsd_config },
- { "CSC3551", "10280BEB", generic_dsd_config },
- { "CSC3551", "10280C4D", generic_dsd_config },
- { "CSC3551", "103C89C6", generic_dsd_config },
- { "CSC3551", "103C8A28", generic_dsd_config },
- { "CSC3551", "103C8A29", generic_dsd_config },
- { "CSC3551", "103C8A2A", generic_dsd_config },
- { "CSC3551", "103C8A2B", generic_dsd_config },
- { "CSC3551", "103C8A2C", generic_dsd_config },
- { "CSC3551", "103C8A2D", generic_dsd_config },
- { "CSC3551", "103C8A2E", generic_dsd_config },
- { "CSC3551", "103C8A30", generic_dsd_config },
- { "CSC3551", "103C8A31", generic_dsd_config },
- { "CSC3551", "103C8A6E", generic_dsd_config },
- { "CSC3551", "103C8BB3", generic_dsd_config },
- { "CSC3551", "103C8BB4", generic_dsd_config },
- { "CSC3551", "103C8BDD", generic_dsd_config },
- { "CSC3551", "103C8BDE", generic_dsd_config },
- { "CSC3551", "103C8BDF", generic_dsd_config },
- { "CSC3551", "103C8BE0", generic_dsd_config },
- { "CSC3551", "103C8BE1", generic_dsd_config },
- { "CSC3551", "103C8BE2", generic_dsd_config },
- { "CSC3551", "103C8BE3", generic_dsd_config },
- { "CSC3551", "103C8BE5", generic_dsd_config },
- { "CSC3551", "103C8BE6", generic_dsd_config },
- { "CSC3551", "103C8BE7", generic_dsd_config },
- { "CSC3551", "103C8BE8", generic_dsd_config },
- { "CSC3551", "103C8BE9", generic_dsd_config },
- { "CSC3551", "103C8B3A", generic_dsd_config },
- { "CSC3551", "103C8C15", generic_dsd_config },
- { "CSC3551", "103C8C16", generic_dsd_config },
- { "CSC3551", "103C8C17", generic_dsd_config },
- { "CSC3551", "103C8C4D", generic_dsd_config },
- { "CSC3551", "103C8C4E", generic_dsd_config },
- { "CSC3551", "103C8C4F", generic_dsd_config },
- { "CSC3551", "103C8C50", generic_dsd_config },
- { "CSC3551", "103C8C51", generic_dsd_config },
- { "CSC3551", "103C8C66", hp_i2c_int_2amp_dual_spkid },
- { "CSC3551", "103C8C67", hp_i2c_int_2amp_dual_spkid },
- { "CSC3551", "103C8C68", hp_i2c_int_2amp_dual_spkid },
- { "CSC3551", "103C8C6A", hp_i2c_int_2amp_dual_spkid },
- { "CSC3551", "103C8CDD", generic_dsd_config },
- { "CSC3551", "103C8CDE", generic_dsd_config },
- { "CSC3551", "104312AF", generic_dsd_config },
- { "CSC3551", "10431433", generic_dsd_config },
- { "CSC3551", "10431463", generic_dsd_config },
- { "CSC3551", "10431473", generic_dsd_config },
- { "CSC3551", "10431483", generic_dsd_config },
- { "CSC3551", "10431493", generic_dsd_config },
- { "CSC3551", "104314D3", generic_dsd_config },
- { "CSC3551", "104314E3", generic_dsd_config },
- { "CSC3551", "10431503", generic_dsd_config },
- { "CSC3551", "10431533", generic_dsd_config },
- { "CSC3551", "10431573", generic_dsd_config },
- { "CSC3551", "10431663", generic_dsd_config },
- { "CSC3551", "10431683", generic_dsd_config },
- { "CSC3551", "104316A3", generic_dsd_config },
- { "CSC3551", "104316D3", generic_dsd_config },
- { "CSC3551", "104316F3", generic_dsd_config },
- { "CSC3551", "104317F3", generic_dsd_config },
- { "CSC3551", "10431863", generic_dsd_config },
- { "CSC3551", "104318D3", generic_dsd_config },
- { "CSC3551", "10431A63", missing_speaker_id_gpio2 },
- { "CSC3551", "10431A83", generic_dsd_config },
- { "CSC3551", "10431B93", generic_dsd_config },
- { "CSC3551", "10431C9F", generic_dsd_config },
- { "CSC3551", "10431CAF", generic_dsd_config },
- { "CSC3551", "10431CCF", generic_dsd_config },
- { "CSC3551", "10431CDF", generic_dsd_config },
- { "CSC3551", "10431CEF", generic_dsd_config },
- { "CSC3551", "10431D1F", generic_dsd_config },
- { "CSC3551", "10431DA2", generic_dsd_config },
- { "CSC3551", "10431E02", generic_dsd_config },
- { "CSC3551", "10431E12", generic_dsd_config },
- { "CSC3551", "10431EE2", generic_dsd_config },
- { "CSC3551", "10431F12", generic_dsd_config },
- { "CSC3551", "10431F1F", generic_dsd_config },
- { "CSC3551", "10431F62", generic_dsd_config },
- { "CSC3551", "10433A20", generic_dsd_config },
- { "CSC3551", "10433A30", generic_dsd_config },
- { "CSC3551", "10433A40", generic_dsd_config },
- { "CSC3551", "10433A50", generic_dsd_config },
- { "CSC3551", "10433A60", generic_dsd_config },
- { "CSC3551", "17AA3865", generic_dsd_config },
- { "CSC3551", "17AA3866", generic_dsd_config },
- { "CSC3551", "17AA386E", generic_dsd_config },
- { "CSC3551", "17AA386F", generic_dsd_config },
- { "CSC3551", "17AA3877", generic_dsd_config },
- { "CSC3551", "17AA3878", generic_dsd_config },
- { "CSC3551", "17AA38A9", generic_dsd_config },
- { "CSC3551", "17AA38AB", generic_dsd_config },
- { "CSC3551", "17AA38B4", generic_dsd_config },
- { "CSC3551", "17AA38B5", generic_dsd_config },
- { "CSC3551", "17AA38B6", generic_dsd_config },
- { "CSC3551", "17AA38B7", generic_dsd_config },
- { "CSC3551", "17AA38C7", generic_dsd_config },
- { "CSC3551", "17AA38C8", generic_dsd_config },
- { "CSC3551", "17AA38F9", generic_dsd_config },
- { "CSC3551", "17AA38FA", generic_dsd_config },
- {}
-};
-
-int cs35l41_add_dsd_properties(struct cs35l41_hda *cs35l41, struct device *physdev, int id,
- const char *hid)
-{
- const struct cs35l41_prop_model *model;
-
- for (model = cs35l41_prop_model_table; model->hid; model++) {
- if (!strcmp(model->hid, hid) &&
- (!model->ssid ||
- (cs35l41->acpi_subsystem_id &&
- !strcasecmp(model->ssid, cs35l41->acpi_subsystem_id))))
- return model->add_prop(cs35l41, physdev, id, hid);
- }
-
- return -ENOENT;
-}
diff --git a/sound/pci/hda/cs35l41_hda_property.h b/sound/pci/hda/cs35l41_hda_property.h
deleted file mode 100644
index fd834042e2fd..000000000000
--- a/sound/pci/hda/cs35l41_hda_property.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0
- *
- * CS35L41 ALSA HDA Property driver
- *
- * Copyright 2023 Cirrus Logic, Inc.
- *
- * Author: Stefan Binding <sbinding@opensource.cirrus.com>
- */
-
-#ifndef CS35L41_HDA_PROP_H
-#define CS35L41_HDA_PROP_H
-
-#include <linux/device.h>
-#include "cs35l41_hda.h"
-
-int cs35l41_add_dsd_properties(struct cs35l41_hda *cs35l41, struct device *physdev, int id,
- const char *hid);
-#endif /* CS35L41_HDA_PROP_H */
diff --git a/sound/pci/hda/cs35l41_hda_spi.c b/sound/pci/hda/cs35l41_hda_spi.c
deleted file mode 100644
index 2acbaf8467a0..000000000000
--- a/sound/pci/hda/cs35l41_hda_spi.c
+++ /dev/null
@@ -1,64 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// CS35l41 HDA SPI driver
-//
-// Copyright 2021 Cirrus Logic, Inc.
-//
-// Author: Lucas Tanure <tanureal@opensource.cirrus.com>
-
-#include <linux/mod_devicetable.h>
-#include <linux/module.h>
-#include <linux/spi/spi.h>
-
-#include "cs35l41_hda.h"
-
-static int cs35l41_hda_spi_probe(struct spi_device *spi)
-{
- const char *device_name;
-
- /*
- * Compare against the device name so it works for SPI, normal ACPI
- * and for ACPI by serial-multi-instantiate matching cases.
- */
- if (strstr(dev_name(&spi->dev), "CSC3551"))
- device_name = "CSC3551";
- else
- return -ENODEV;
-
- return cs35l41_hda_probe(&spi->dev, device_name, spi_get_chipselect(spi, 0), spi->irq,
- devm_regmap_init_spi(spi, &cs35l41_regmap_spi), SPI);
-}
-
-static void cs35l41_hda_spi_remove(struct spi_device *spi)
-{
- cs35l41_hda_remove(&spi->dev);
-}
-
-static const struct spi_device_id cs35l41_hda_spi_id[] = {
- { "cs35l41-hda", 0 },
- {}
-};
-MODULE_DEVICE_TABLE(spi, cs35l41_hda_spi_id);
-
-static const struct acpi_device_id cs35l41_acpi_hda_match[] = {
- { "CSC3551", 0 },
- {}
-};
-MODULE_DEVICE_TABLE(acpi, cs35l41_acpi_hda_match);
-
-static struct spi_driver cs35l41_spi_driver = {
- .driver = {
- .name = "cs35l41-hda",
- .acpi_match_table = cs35l41_acpi_hda_match,
- .pm = &cs35l41_hda_pm_ops,
- },
- .id_table = cs35l41_hda_spi_id,
- .probe = cs35l41_hda_spi_probe,
- .remove = cs35l41_hda_spi_remove,
-};
-module_spi_driver(cs35l41_spi_driver);
-
-MODULE_DESCRIPTION("HDA CS35L41 driver");
-MODULE_IMPORT_NS("SND_HDA_SCODEC_CS35L41");
-MODULE_AUTHOR("Lucas Tanure <tanureal@opensource.cirrus.com>");
-MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/cs35l56_hda.c b/sound/pci/hda/cs35l56_hda.c
deleted file mode 100644
index 3f2fd32f4ad9..000000000000
--- a/sound/pci/hda/cs35l56_hda.c
+++ /dev/null
@@ -1,1124 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-//
-// HDA audio driver for Cirrus Logic CS35L56 smart amp
-//
-// Copyright (C) 2023 Cirrus Logic, Inc. and
-// Cirrus Logic International Semiconductor Ltd.
-//
-
-#include <linux/acpi.h>
-#include <linux/debugfs.h>
-#include <linux/gpio/consumer.h>
-#include <linux/module.h>
-#include <linux/pm_runtime.h>
-#include <linux/regmap.h>
-#include <linux/slab.h>
-#include <sound/core.h>
-#include <sound/cs-amp-lib.h>
-#include <sound/hda_codec.h>
-#include <sound/tlv.h>
-#include "cirrus_scodec.h"
-#include "cs35l56_hda.h"
-#include "hda_component.h"
-#include "hda_generic.h"
-
- /*
- * The cs35l56_hda_dai_config[] reg sequence configures the device as
- * ASP1_BCLK_FREQ = 3.072 MHz
- * ASP1_RX_WIDTH = 32 cycles per slot, ASP1_TX_WIDTH = 32 cycles per slot, ASP1_FMT = I2S
- * ASP1_DOUT_HIZ_CONTROL = Hi-Z during unused timeslots
- * ASP1_RX_WL = 24 bits per sample
- * ASP1_TX_WL = 24 bits per sample
- * ASP1_RXn_EN 1..3 and ASP1_TXn_EN 1..4 disabled
- *
- * Override any Windows-specific mixer settings applied by the firmware.
- */
-static const struct reg_sequence cs35l56_hda_dai_config[] = {
- { CS35L56_ASP1_CONTROL1, 0x00000021 },
- { CS35L56_ASP1_CONTROL2, 0x20200200 },
- { CS35L56_ASP1_CONTROL3, 0x00000003 },
- { CS35L56_ASP1_FRAME_CONTROL1, 0x03020100 },
- { CS35L56_ASP1_FRAME_CONTROL5, 0x00020100 },
- { CS35L56_ASP1_DATA_CONTROL5, 0x00000018 },
- { CS35L56_ASP1_DATA_CONTROL1, 0x00000018 },
- { CS35L56_ASP1_ENABLES1, 0x00000000 },
- { CS35L56_ASP1TX1_INPUT, 0x00000018 },
- { CS35L56_ASP1TX2_INPUT, 0x00000019 },
- { CS35L56_ASP1TX3_INPUT, 0x00000020 },
- { CS35L56_ASP1TX4_INPUT, 0x00000028 },
-
-};
-
-static void cs35l56_hda_wait_dsp_ready(struct cs35l56_hda *cs35l56)
-{
- /* Wait for patching to complete */
- flush_work(&cs35l56->dsp_work);
-}
-
-static void cs35l56_hda_play(struct cs35l56_hda *cs35l56)
-{
- unsigned int val;
- int ret;
-
- cs35l56_hda_wait_dsp_ready(cs35l56);
-
- pm_runtime_get_sync(cs35l56->base.dev);
- ret = cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_AUDIO_PLAY);
- if (ret == 0) {
- /* Wait for firmware to enter PS0 power state */
- ret = regmap_read_poll_timeout(cs35l56->base.regmap,
- cs35l56->base.fw_reg->transducer_actual_ps,
- val, (val == CS35L56_PS0),
- CS35L56_PS0_POLL_US,
- CS35L56_PS0_TIMEOUT_US);
- if (ret)
- dev_warn(cs35l56->base.dev, "PS0 wait failed: %d\n", ret);
- }
- regmap_set_bits(cs35l56->base.regmap, CS35L56_ASP1_ENABLES1,
- BIT(CS35L56_ASP_RX1_EN_SHIFT) | BIT(CS35L56_ASP_RX2_EN_SHIFT) |
- cs35l56->asp_tx_mask);
- cs35l56->playing = true;
-}
-
-static void cs35l56_hda_pause(struct cs35l56_hda *cs35l56)
-{
- cs35l56->playing = false;
- cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_AUDIO_PAUSE);
- regmap_clear_bits(cs35l56->base.regmap, CS35L56_ASP1_ENABLES1,
- BIT(CS35L56_ASP_RX1_EN_SHIFT) | BIT(CS35L56_ASP_RX2_EN_SHIFT) |
- BIT(CS35L56_ASP_TX1_EN_SHIFT) | BIT(CS35L56_ASP_TX2_EN_SHIFT) |
- BIT(CS35L56_ASP_TX3_EN_SHIFT) | BIT(CS35L56_ASP_TX4_EN_SHIFT));
-
- pm_runtime_mark_last_busy(cs35l56->base.dev);
- pm_runtime_put_autosuspend(cs35l56->base.dev);
-}
-
-static void cs35l56_hda_playback_hook(struct device *dev, int action)
-{
- struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev);
-
- dev_dbg(cs35l56->base.dev, "%s()%d: action: %d\n", __func__, __LINE__, action);
-
- switch (action) {
- case HDA_GEN_PCM_ACT_PREPARE:
- if (cs35l56->playing)
- break;
-
- /* If we're suspended: flag that resume should start playback */
- if (cs35l56->suspended) {
- cs35l56->playing = true;
- break;
- }
-
- cs35l56_hda_play(cs35l56);
- break;
- case HDA_GEN_PCM_ACT_CLEANUP:
- if (!cs35l56->playing)
- break;
-
- cs35l56_hda_pause(cs35l56);
- break;
- default:
- break;
- }
-}
-
-static int cs35l56_hda_runtime_suspend(struct device *dev)
-{
- struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev);
-
- if (cs35l56->cs_dsp.booted)
- cs_dsp_stop(&cs35l56->cs_dsp);
-
- return cs35l56_runtime_suspend_common(&cs35l56->base);
-}
-
-static int cs35l56_hda_runtime_resume(struct device *dev)
-{
- struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev);
- int ret;
-
- ret = cs35l56_runtime_resume_common(&cs35l56->base, false);
- if (ret < 0)
- return ret;
-
- if (cs35l56->cs_dsp.booted) {
- ret = cs_dsp_run(&cs35l56->cs_dsp);
- if (ret) {
- dev_dbg(cs35l56->base.dev, "%s: cs_dsp_run ret %d\n", __func__, ret);
- goto err;
- }
- }
-
- return 0;
-
-err:
- cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_ALLOW_AUTO_HIBERNATE);
- regmap_write(cs35l56->base.regmap, CS35L56_DSP_VIRTUAL1_MBOX_1,
- CS35L56_MBOX_CMD_HIBERNATE_NOW);
-
- regcache_cache_only(cs35l56->base.regmap, true);
-
- return ret;
-}
-
-static int cs35l56_hda_mixer_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = CS35L56_NUM_INPUT_SRC;
- if (uinfo->value.enumerated.item >= CS35L56_NUM_INPUT_SRC)
- uinfo->value.enumerated.item = CS35L56_NUM_INPUT_SRC - 1;
- strscpy(uinfo->value.enumerated.name, cs35l56_tx_input_texts[uinfo->value.enumerated.item],
- sizeof(uinfo->value.enumerated.name));
-
- return 0;
-}
-
-static int cs35l56_hda_mixer_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct cs35l56_hda *cs35l56 = snd_kcontrol_chip(kcontrol);
- unsigned int reg_val;
- int i;
-
- cs35l56_hda_wait_dsp_ready(cs35l56);
-
- regmap_read(cs35l56->base.regmap, kcontrol->private_value, &reg_val);
- reg_val &= CS35L56_ASP_TXn_SRC_MASK;
-
- for (i = 0; i < CS35L56_NUM_INPUT_SRC; ++i) {
- if (cs35l56_tx_input_values[i] == reg_val) {
- ucontrol->value.enumerated.item[0] = i;
- break;
- }
- }
-
- return 0;
-}
-
-static int cs35l56_hda_mixer_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct cs35l56_hda *cs35l56 = snd_kcontrol_chip(kcontrol);
- unsigned int item = ucontrol->value.enumerated.item[0];
- bool changed;
-
- if (item >= CS35L56_NUM_INPUT_SRC)
- return -EINVAL;
-
- cs35l56_hda_wait_dsp_ready(cs35l56);
-
- regmap_update_bits_check(cs35l56->base.regmap, kcontrol->private_value,
- CS35L56_INPUT_MASK, cs35l56_tx_input_values[item],
- &changed);
-
- return changed;
-}
-
-static int cs35l56_hda_posture_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = 1;
- uinfo->value.integer.min = CS35L56_MAIN_POSTURE_MIN;
- uinfo->value.integer.max = CS35L56_MAIN_POSTURE_MAX;
- return 0;
-}
-
-static int cs35l56_hda_posture_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct cs35l56_hda *cs35l56 = snd_kcontrol_chip(kcontrol);
- unsigned int pos;
- int ret;
-
- cs35l56_hda_wait_dsp_ready(cs35l56);
-
- ret = regmap_read(cs35l56->base.regmap,
- cs35l56->base.fw_reg->posture_number, &pos);
- if (ret)
- return ret;
-
- ucontrol->value.integer.value[0] = pos;
-
- return 0;
-}
-
-static int cs35l56_hda_posture_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct cs35l56_hda *cs35l56 = snd_kcontrol_chip(kcontrol);
- unsigned long pos = ucontrol->value.integer.value[0];
- bool changed;
- int ret;
-
- if ((pos < CS35L56_MAIN_POSTURE_MIN) ||
- (pos > CS35L56_MAIN_POSTURE_MAX))
- return -EINVAL;
-
- cs35l56_hda_wait_dsp_ready(cs35l56);
-
- ret = regmap_update_bits_check(cs35l56->base.regmap, cs35l56->base.fw_reg->posture_number,
- CS35L56_MAIN_POSTURE_MASK, pos, &changed);
- if (ret)
- return ret;
-
- return changed;
-}
-
-static const struct {
- const char *name;
- unsigned int reg;
-} cs35l56_hda_mixer_controls[] = {
- { "ASP1 TX1 Source", CS35L56_ASP1TX1_INPUT },
- { "ASP1 TX2 Source", CS35L56_ASP1TX2_INPUT },
- { "ASP1 TX3 Source", CS35L56_ASP1TX3_INPUT },
- { "ASP1 TX4 Source", CS35L56_ASP1TX4_INPUT },
-};
-
-static const DECLARE_TLV_DB_SCALE(cs35l56_hda_vol_tlv, -10000, 25, 0);
-
-static int cs35l56_hda_vol_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = 1;
- uinfo->value.integer.step = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = CS35L56_MAIN_RENDER_USER_VOLUME_MAX -
- CS35L56_MAIN_RENDER_USER_VOLUME_MIN;
-
- return 0;
-}
-
-static int cs35l56_hda_vol_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct cs35l56_hda *cs35l56 = snd_kcontrol_chip(kcontrol);
- unsigned int raw_vol;
- int vol;
- int ret;
-
- cs35l56_hda_wait_dsp_ready(cs35l56);
-
- ret = regmap_read(cs35l56->base.regmap, cs35l56->base.fw_reg->user_volume, &raw_vol);
-
- if (ret)
- return ret;
-
- vol = (s16)(raw_vol & 0xFFFF);
- vol >>= CS35L56_MAIN_RENDER_USER_VOLUME_SHIFT;
-
- if (vol & BIT(CS35L56_MAIN_RENDER_USER_VOLUME_SIGNBIT))
- vol |= ~((int)(BIT(CS35L56_MAIN_RENDER_USER_VOLUME_SIGNBIT) - 1));
-
- ucontrol->value.integer.value[0] = vol - CS35L56_MAIN_RENDER_USER_VOLUME_MIN;
-
- return 0;
-}
-
-static int cs35l56_hda_vol_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct cs35l56_hda *cs35l56 = snd_kcontrol_chip(kcontrol);
- long vol = ucontrol->value.integer.value[0];
- unsigned int raw_vol;
- bool changed;
- int ret;
-
- if ((vol < 0) || (vol > (CS35L56_MAIN_RENDER_USER_VOLUME_MAX -
- CS35L56_MAIN_RENDER_USER_VOLUME_MIN)))
- return -EINVAL;
-
- raw_vol = (vol + CS35L56_MAIN_RENDER_USER_VOLUME_MIN) <<
- CS35L56_MAIN_RENDER_USER_VOLUME_SHIFT;
-
- cs35l56_hda_wait_dsp_ready(cs35l56);
-
- ret = regmap_update_bits_check(cs35l56->base.regmap, cs35l56->base.fw_reg->user_volume,
- CS35L56_MAIN_RENDER_USER_VOLUME_MASK, raw_vol, &changed);
- if (ret)
- return ret;
-
- return changed;
-}
-
-static void cs35l56_hda_create_controls(struct cs35l56_hda *cs35l56)
-{
- struct snd_kcontrol_new ctl_template = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
- .info = cs35l56_hda_posture_info,
- .get = cs35l56_hda_posture_get,
- .put = cs35l56_hda_posture_put,
- };
- char name[64];
- int i;
-
- snprintf(name, sizeof(name), "%s Posture Number", cs35l56->amp_name);
- ctl_template.name = name;
- cs35l56->posture_ctl = snd_ctl_new1(&ctl_template, cs35l56);
- if (snd_ctl_add(cs35l56->codec->card, cs35l56->posture_ctl))
- dev_err(cs35l56->base.dev, "Failed to add KControl: %s\n", ctl_template.name);
-
- /* Mixer controls */
- ctl_template.info = cs35l56_hda_mixer_info;
- ctl_template.get = cs35l56_hda_mixer_get;
- ctl_template.put = cs35l56_hda_mixer_put;
-
- BUILD_BUG_ON(ARRAY_SIZE(cs35l56->mixer_ctl) != ARRAY_SIZE(cs35l56_hda_mixer_controls));
-
- for (i = 0; i < ARRAY_SIZE(cs35l56_hda_mixer_controls); ++i) {
- snprintf(name, sizeof(name), "%s %s", cs35l56->amp_name,
- cs35l56_hda_mixer_controls[i].name);
- ctl_template.private_value = cs35l56_hda_mixer_controls[i].reg;
- cs35l56->mixer_ctl[i] = snd_ctl_new1(&ctl_template, cs35l56);
- if (snd_ctl_add(cs35l56->codec->card, cs35l56->mixer_ctl[i])) {
- dev_err(cs35l56->base.dev, "Failed to add KControl: %s\n",
- ctl_template.name);
- }
- }
-
- ctl_template.info = cs35l56_hda_vol_info;
- ctl_template.get = cs35l56_hda_vol_get;
- ctl_template.put = cs35l56_hda_vol_put;
- ctl_template.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ);
- ctl_template.tlv.p = cs35l56_hda_vol_tlv;
- snprintf(name, sizeof(name), "%s Speaker Playback Volume", cs35l56->amp_name);
- ctl_template.name = name;
- cs35l56->volume_ctl = snd_ctl_new1(&ctl_template, cs35l56);
- if (snd_ctl_add(cs35l56->codec->card, cs35l56->volume_ctl))
- dev_err(cs35l56->base.dev, "Failed to add KControl: %s\n", ctl_template.name);
-}
-
-static void cs35l56_hda_remove_controls(struct cs35l56_hda *cs35l56)
-{
- int i;
-
- for (i = ARRAY_SIZE(cs35l56->mixer_ctl) - 1; i >= 0; i--)
- snd_ctl_remove(cs35l56->codec->card, cs35l56->mixer_ctl[i]);
-
- snd_ctl_remove(cs35l56->codec->card, cs35l56->posture_ctl);
- snd_ctl_remove(cs35l56->codec->card, cs35l56->volume_ctl);
-}
-
-static const struct cs_dsp_client_ops cs35l56_hda_client_ops = {
- /* cs_dsp requires the client to provide this even if it is empty */
-};
-
-static int cs35l56_hda_request_firmware_file(struct cs35l56_hda *cs35l56,
- const struct firmware **firmware, char **filename,
- const char *base_name, const char *system_name,
- const char *amp_name,
- const char *filetype)
-{
- char *s, c;
- int ret = 0;
-
- if (system_name && amp_name)
- *filename = kasprintf(GFP_KERNEL, "%s-%s-%s.%s", base_name,
- system_name, amp_name, filetype);
- else if (system_name)
- *filename = kasprintf(GFP_KERNEL, "%s-%s.%s", base_name,
- system_name, filetype);
- else
- *filename = kasprintf(GFP_KERNEL, "%s.%s", base_name, filetype);
-
- if (!*filename)
- return -ENOMEM;
-
- /*
- * Make sure that filename is lower-case and any non alpha-numeric
- * characters except full stop and forward slash are replaced with
- * hyphens.
- */
- s = *filename;
- while (*s) {
- c = *s;
- if (isalnum(c))
- *s = tolower(c);
- else if (c != '.' && c != '/')
- *s = '-';
- s++;
- }
-
- ret = firmware_request_nowarn(firmware, *filename, cs35l56->base.dev);
- if (ret) {
- dev_dbg(cs35l56->base.dev, "Failed to request '%s'\n", *filename);
- kfree(*filename);
- *filename = NULL;
- return ret;
- }
-
- dev_dbg(cs35l56->base.dev, "Found '%s'\n", *filename);
-
- return 0;
-}
-
-static void cs35l56_hda_request_firmware_files(struct cs35l56_hda *cs35l56,
- unsigned int preloaded_fw_ver,
- const struct firmware **wmfw_firmware,
- char **wmfw_filename,
- const struct firmware **coeff_firmware,
- char **coeff_filename)
-{
- const char *system_name = cs35l56->system_name;
- const char *amp_name = cs35l56->amp_name;
- char base_name[37];
- int ret;
-
- if (preloaded_fw_ver) {
- snprintf(base_name, sizeof(base_name),
- "cirrus/cs35l%02x-%02x%s-%06x-dsp1-misc",
- cs35l56->base.type,
- cs35l56->base.rev,
- cs35l56->base.secured ? "-s" : "",
- preloaded_fw_ver & 0xffffff);
- } else {
- snprintf(base_name, sizeof(base_name),
- "cirrus/cs35l%02x-%02x%s-dsp1-misc",
- cs35l56->base.type,
- cs35l56->base.rev,
- cs35l56->base.secured ? "-s" : "");
- }
-
- if (system_name && amp_name) {
- if (!cs35l56_hda_request_firmware_file(cs35l56, wmfw_firmware, wmfw_filename,
- base_name, system_name, amp_name, "wmfw")) {
- cs35l56_hda_request_firmware_file(cs35l56, coeff_firmware, coeff_filename,
- base_name, system_name, amp_name, "bin");
- return;
- }
- }
-
- if (system_name) {
- if (!cs35l56_hda_request_firmware_file(cs35l56, wmfw_firmware, wmfw_filename,
- base_name, system_name, NULL, "wmfw")) {
- if (amp_name)
- cs35l56_hda_request_firmware_file(cs35l56,
- coeff_firmware, coeff_filename,
- base_name, system_name,
- amp_name, "bin");
- if (!*coeff_firmware)
- cs35l56_hda_request_firmware_file(cs35l56,
- coeff_firmware, coeff_filename,
- base_name, system_name,
- NULL, "bin");
- return;
- }
-
- /*
- * Check for system-specific bin files without wmfw before
- * falling back to generic firmware
- */
- if (amp_name)
- cs35l56_hda_request_firmware_file(cs35l56, coeff_firmware, coeff_filename,
- base_name, system_name, amp_name, "bin");
- if (!*coeff_firmware)
- cs35l56_hda_request_firmware_file(cs35l56, coeff_firmware, coeff_filename,
- base_name, system_name, NULL, "bin");
-
- if (*coeff_firmware)
- return;
- }
-
- ret = cs35l56_hda_request_firmware_file(cs35l56, wmfw_firmware, wmfw_filename,
- base_name, NULL, NULL, "wmfw");
- if (!ret) {
- cs35l56_hda_request_firmware_file(cs35l56, coeff_firmware, coeff_filename,
- base_name, NULL, NULL, "bin");
- return;
- }
-
- if (!*coeff_firmware)
- cs35l56_hda_request_firmware_file(cs35l56, coeff_firmware, coeff_filename,
- base_name, NULL, NULL, "bin");
-}
-
-static void cs35l56_hda_release_firmware_files(const struct firmware *wmfw_firmware,
- char *wmfw_filename,
- const struct firmware *coeff_firmware,
- char *coeff_filename)
-{
- release_firmware(wmfw_firmware);
- kfree(wmfw_filename);
-
- release_firmware(coeff_firmware);
- kfree(coeff_filename);
-}
-
-static void cs35l56_hda_apply_calibration(struct cs35l56_hda *cs35l56)
-{
- int ret;
-
- if (!cs35l56->base.cal_data_valid || cs35l56->base.secured)
- return;
-
- ret = cs_amp_write_cal_coeffs(&cs35l56->cs_dsp,
- &cs35l56_calibration_controls,
- &cs35l56->base.cal_data);
- if (ret < 0)
- dev_warn(cs35l56->base.dev, "Failed to write calibration: %d\n", ret);
- else
- dev_info(cs35l56->base.dev, "Calibration applied\n");
-}
-
-static void cs35l56_hda_fw_load(struct cs35l56_hda *cs35l56)
-{
- const struct firmware *coeff_firmware = NULL;
- const struct firmware *wmfw_firmware = NULL;
- char *coeff_filename = NULL;
- char *wmfw_filename = NULL;
- unsigned int preloaded_fw_ver;
- bool firmware_missing;
- int ret;
-
- /*
- * Prepare for a new DSP power-up. If the DSP has had firmware
- * downloaded previously then it needs to be powered down so that it
- * can be updated.
- */
- if (cs35l56->base.fw_patched)
- cs_dsp_power_down(&cs35l56->cs_dsp);
-
- cs35l56->base.fw_patched = false;
-
- ret = pm_runtime_resume_and_get(cs35l56->base.dev);
- if (ret < 0) {
- dev_err(cs35l56->base.dev, "Failed to resume and get %d\n", ret);
- return;
- }
-
- /*
- * The firmware can only be upgraded if it is currently running
- * from the built-in ROM. If not, the wmfw/bin must be for the
- * version of firmware that is running on the chip.
- */
- ret = cs35l56_read_prot_status(&cs35l56->base, &firmware_missing, &preloaded_fw_ver);
- if (ret)
- goto err_pm_put;
-
- if (firmware_missing)
- preloaded_fw_ver = 0;
-
- cs35l56_hda_request_firmware_files(cs35l56, preloaded_fw_ver,
- &wmfw_firmware, &wmfw_filename,
- &coeff_firmware, &coeff_filename);
-
- /*
- * If the BIOS didn't patch the firmware a bin file is mandatory to
- * enable the ASP·
- */
- if (!coeff_firmware && firmware_missing) {
- dev_err(cs35l56->base.dev, ".bin file required but not found\n");
- goto err_fw_release;
- }
-
- mutex_lock(&cs35l56->base.irq_lock);
-
- /*
- * If the firmware hasn't been patched it must be shutdown before
- * doing a full patch and reset afterwards. If it is already
- * running a patched version the firmware files only contain
- * tunings and we can use the lower cost reinit sequence instead.
- */
- if (firmware_missing && (wmfw_firmware || coeff_firmware)) {
- ret = cs35l56_firmware_shutdown(&cs35l56->base);
- if (ret)
- goto err;
- }
-
- ret = cs_dsp_power_up(&cs35l56->cs_dsp, wmfw_firmware, wmfw_filename,
- coeff_firmware, coeff_filename, "misc");
- if (ret) {
- dev_dbg(cs35l56->base.dev, "%s: cs_dsp_power_up ret %d\n", __func__, ret);
- goto err;
- }
-
- if (wmfw_filename)
- dev_dbg(cs35l56->base.dev, "Loaded WMFW Firmware: %s\n", wmfw_filename);
-
- if (coeff_filename)
- dev_dbg(cs35l56->base.dev, "Loaded Coefficients: %s\n", coeff_filename);
-
- /* If we downloaded firmware, reset the device and wait for it to boot */
- if (firmware_missing && (wmfw_firmware || coeff_firmware)) {
- cs35l56_system_reset(&cs35l56->base, false);
- regcache_mark_dirty(cs35l56->base.regmap);
- ret = cs35l56_wait_for_firmware_boot(&cs35l56->base);
- if (ret)
- goto err_powered_up;
-
- regcache_cache_only(cs35l56->base.regmap, false);
- }
-
- /* Disable auto-hibernate so that runtime_pm has control */
- ret = cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE);
- if (ret)
- goto err_powered_up;
-
- regcache_sync(cs35l56->base.regmap);
-
- regmap_clear_bits(cs35l56->base.regmap,
- cs35l56->base.fw_reg->prot_sts,
- CS35L56_FIRMWARE_MISSING);
- cs35l56->base.fw_patched = true;
-
- ret = cs_dsp_run(&cs35l56->cs_dsp);
- if (ret)
- dev_dbg(cs35l56->base.dev, "%s: cs_dsp_run ret %d\n", __func__, ret);
-
- cs35l56_hda_apply_calibration(cs35l56);
- ret = cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_AUDIO_REINIT);
- if (ret)
- cs_dsp_stop(&cs35l56->cs_dsp);
-
- cs35l56_log_tuning(&cs35l56->base, &cs35l56->cs_dsp);
-
-err_powered_up:
- if (!cs35l56->base.fw_patched)
- cs_dsp_power_down(&cs35l56->cs_dsp);
-err:
- mutex_unlock(&cs35l56->base.irq_lock);
-err_fw_release:
- cs35l56_hda_release_firmware_files(wmfw_firmware, wmfw_filename,
- coeff_firmware, coeff_filename);
-err_pm_put:
- pm_runtime_put(cs35l56->base.dev);
-}
-
-static void cs35l56_hda_dsp_work(struct work_struct *work)
-{
- struct cs35l56_hda *cs35l56 = container_of(work, struct cs35l56_hda, dsp_work);
-
- cs35l56_hda_fw_load(cs35l56);
-}
-
-static int cs35l56_hda_bind(struct device *dev, struct device *master, void *master_data)
-{
- struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev);
- struct hda_component_parent *parent = master_data;
- struct hda_component *comp;
-
- comp = hda_component_from_index(parent, cs35l56->index);
- if (!comp)
- return -EINVAL;
-
- if (comp->dev)
- return -EBUSY;
-
- comp->dev = dev;
- cs35l56->codec = parent->codec;
- strscpy(comp->name, dev_name(dev), sizeof(comp->name));
- comp->playback_hook = cs35l56_hda_playback_hook;
-
- queue_work(system_long_wq, &cs35l56->dsp_work);
-
- cs35l56_hda_create_controls(cs35l56);
-
-#if IS_ENABLED(CONFIG_SND_DEBUG)
- cs35l56->debugfs_root = debugfs_create_dir(dev_name(cs35l56->base.dev), sound_debugfs_root);
- cs_dsp_init_debugfs(&cs35l56->cs_dsp, cs35l56->debugfs_root);
-#endif
-
- dev_dbg(cs35l56->base.dev, "Bound\n");
-
- return 0;
-}
-
-static void cs35l56_hda_unbind(struct device *dev, struct device *master, void *master_data)
-{
- struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev);
- struct hda_component_parent *parent = master_data;
- struct hda_component *comp;
-
- cancel_work_sync(&cs35l56->dsp_work);
-
- cs35l56_hda_remove_controls(cs35l56);
-
-#if IS_ENABLED(CONFIG_SND_DEBUG)
- cs_dsp_cleanup_debugfs(&cs35l56->cs_dsp);
- debugfs_remove_recursive(cs35l56->debugfs_root);
-#endif
-
- if (cs35l56->base.fw_patched)
- cs_dsp_power_down(&cs35l56->cs_dsp);
-
- comp = hda_component_from_index(parent, cs35l56->index);
- if (comp && (comp->dev == dev))
- memset(comp, 0, sizeof(*comp));
-
- cs35l56->codec = NULL;
-
- dev_dbg(cs35l56->base.dev, "Unbound\n");
-}
-
-static const struct component_ops cs35l56_hda_comp_ops = {
- .bind = cs35l56_hda_bind,
- .unbind = cs35l56_hda_unbind,
-};
-
-static int cs35l56_hda_system_suspend(struct device *dev)
-{
- struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev);
-
- cs35l56_hda_wait_dsp_ready(cs35l56);
-
- if (cs35l56->playing)
- cs35l56_hda_pause(cs35l56);
-
- cs35l56->suspended = true;
-
- /*
- * The interrupt line is normally shared, but after we start suspending
- * we can't check if our device is the source of an interrupt, and can't
- * clear it. Prevent this race by temporarily disabling the parent irq
- * until we reach _no_irq.
- */
- if (cs35l56->base.irq)
- disable_irq(cs35l56->base.irq);
-
- return pm_runtime_force_suspend(dev);
-}
-
-static int cs35l56_hda_system_suspend_late(struct device *dev)
-{
- struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev);
-
- /*
- * RESET is usually shared by all amps so it must not be asserted until
- * all driver instances have done their suspend() stage.
- */
- if (cs35l56->base.reset_gpio) {
- gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0);
- cs35l56_wait_min_reset_pulse();
- }
-
- return 0;
-}
-
-static int cs35l56_hda_system_suspend_no_irq(struct device *dev)
-{
- struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev);
-
- /* Handlers are now disabled so the parent IRQ can safely be re-enabled. */
- if (cs35l56->base.irq)
- enable_irq(cs35l56->base.irq);
-
- return 0;
-}
-
-static int cs35l56_hda_system_resume_no_irq(struct device *dev)
-{
- struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev);
-
- /*
- * WAKE interrupts unmask if the CS35L56 hibernates, which can cause
- * spurious interrupts, and the interrupt line is normally shared.
- * We can't check if our device is the source of an interrupt, and can't
- * clear it, until it has fully resumed. Prevent this race by temporarily
- * disabling the parent irq until we complete resume().
- */
- if (cs35l56->base.irq)
- disable_irq(cs35l56->base.irq);
-
- return 0;
-}
-
-static int cs35l56_hda_system_resume_early(struct device *dev)
-{
- struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev);
-
- /* Ensure a spec-compliant RESET pulse. */
- if (cs35l56->base.reset_gpio) {
- gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0);
- cs35l56_wait_min_reset_pulse();
-
- /* Release shared RESET before drivers start resume(). */
- gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 1);
- cs35l56_wait_control_port_ready();
- }
-
- return 0;
-}
-
-static int cs35l56_hda_system_resume(struct device *dev)
-{
- struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev);
- int ret;
-
- /* Undo pm_runtime_force_suspend() before re-enabling the irq */
- ret = pm_runtime_force_resume(dev);
- if (cs35l56->base.irq)
- enable_irq(cs35l56->base.irq);
-
- if (ret)
- return ret;
-
- cs35l56->suspended = false;
-
- if (!cs35l56->codec)
- return 0;
-
- ret = cs35l56_is_fw_reload_needed(&cs35l56->base);
- dev_dbg(cs35l56->base.dev, "fw_reload_needed: %d\n", ret);
- if (ret > 0)
- queue_work(system_long_wq, &cs35l56->dsp_work);
-
- if (cs35l56->playing)
- cs35l56_hda_play(cs35l56);
-
- return 0;
-}
-
-static int cs35l56_hda_read_acpi(struct cs35l56_hda *cs35l56, int hid, int id)
-{
- u32 values[HDA_MAX_COMPONENTS];
- char hid_string[8];
- struct acpi_device *adev;
- const char *property, *sub;
- size_t nval;
- int i, ret;
-
- /*
- * ACPI_COMPANION isn't available when this driver was instantiated by
- * the serial-multi-instantiate driver, so lookup the node by HID
- */
- if (!ACPI_COMPANION(cs35l56->base.dev)) {
- snprintf(hid_string, sizeof(hid_string), "CSC%04X", hid);
- adev = acpi_dev_get_first_match_dev(hid_string, NULL, -1);
- if (!adev) {
- dev_err(cs35l56->base.dev, "Failed to find an ACPI device for %s\n",
- dev_name(cs35l56->base.dev));
- return -ENODEV;
- }
- ACPI_COMPANION_SET(cs35l56->base.dev, adev);
- }
-
- property = "cirrus,dev-index";
- ret = device_property_count_u32(cs35l56->base.dev, property);
- if (ret <= 0)
- goto err;
-
- if (ret > ARRAY_SIZE(values)) {
- ret = -EINVAL;
- goto err;
- }
- nval = ret;
-
- ret = device_property_read_u32_array(cs35l56->base.dev, property, values, nval);
- if (ret)
- goto err;
-
- cs35l56->index = -1;
- for (i = 0; i < nval; i++) {
- if (values[i] == id) {
- cs35l56->index = i;
- break;
- }
- }
- /*
- * It's not an error for the ID to be missing: for I2C there can be
- * an alias address that is not a real device. So reject silently.
- */
- if (cs35l56->index == -1) {
- dev_dbg(cs35l56->base.dev, "No index found in %s\n", property);
- ret = -ENODEV;
- goto err;
- }
-
- sub = acpi_get_subsystem_id(ACPI_HANDLE(cs35l56->base.dev));
-
- if (IS_ERR(sub)) {
- dev_info(cs35l56->base.dev,
- "Read ACPI _SUB failed(%ld): fallback to generic firmware\n",
- PTR_ERR(sub));
- } else {
- ret = cirrus_scodec_get_speaker_id(cs35l56->base.dev, cs35l56->index, nval, -1);
- if (ret == -ENOENT) {
- cs35l56->system_name = sub;
- } else if (ret >= 0) {
- cs35l56->system_name = kasprintf(GFP_KERNEL, "%s-spkid%d", sub, ret);
- kfree(sub);
- if (!cs35l56->system_name)
- return -ENOMEM;
- } else {
- return ret;
- }
- }
-
- cs35l56->base.reset_gpio = devm_gpiod_get_index_optional(cs35l56->base.dev,
- "reset",
- cs35l56->index,
- GPIOD_OUT_LOW);
- if (IS_ERR(cs35l56->base.reset_gpio)) {
- ret = PTR_ERR(cs35l56->base.reset_gpio);
-
- /*
- * If RESET is shared the first amp to probe will grab the reset
- * line and reset all the amps
- */
- if (ret != -EBUSY)
- return dev_err_probe(cs35l56->base.dev, ret, "Failed to get reset GPIO\n");
-
- dev_info(cs35l56->base.dev, "Reset GPIO busy, assume shared reset\n");
- cs35l56->base.reset_gpio = NULL;
- }
-
- return 0;
-
-err:
- if (ret != -ENODEV)
- dev_err(cs35l56->base.dev, "Failed property %s: %d\n", property, ret);
-
- return ret;
-}
-
-int cs35l56_hda_common_probe(struct cs35l56_hda *cs35l56, int hid, int id)
-{
- int ret;
-
- mutex_init(&cs35l56->base.irq_lock);
- dev_set_drvdata(cs35l56->base.dev, cs35l56);
-
- INIT_WORK(&cs35l56->dsp_work, cs35l56_hda_dsp_work);
-
- ret = cs35l56_hda_read_acpi(cs35l56, hid, id);
- if (ret)
- goto err;
-
- cs35l56->amp_name = devm_kasprintf(cs35l56->base.dev, GFP_KERNEL, "AMP%d",
- cs35l56->index + 1);
- if (!cs35l56->amp_name) {
- ret = -ENOMEM;
- goto err;
- }
-
- cs35l56->base.cal_index = -1;
-
- cs35l56_init_cs_dsp(&cs35l56->base, &cs35l56->cs_dsp);
- cs35l56->cs_dsp.client_ops = &cs35l56_hda_client_ops;
-
- if (cs35l56->base.reset_gpio) {
- dev_dbg(cs35l56->base.dev, "Hard reset\n");
-
- /*
- * The GPIOD_OUT_LOW to *_gpiod_get_*() will be ignored if the
- * ACPI defines a different default state. So explicitly set low.
- */
- gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0);
- cs35l56_wait_min_reset_pulse();
- gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 1);
- }
-
- ret = cs35l56_hw_init(&cs35l56->base);
- if (ret < 0)
- goto err;
-
- /* Reset the device and wait for it to boot */
- cs35l56_system_reset(&cs35l56->base, false);
- ret = cs35l56_wait_for_firmware_boot(&cs35l56->base);
- if (ret)
- goto err;
-
- regcache_cache_only(cs35l56->base.regmap, false);
-
- ret = cs35l56_set_patch(&cs35l56->base);
- if (ret)
- goto err;
-
- regcache_mark_dirty(cs35l56->base.regmap);
- regcache_sync(cs35l56->base.regmap);
-
- /* Disable auto-hibernate so that runtime_pm has control */
- ret = cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE);
- if (ret)
- goto err;
-
- ret = cs35l56_get_calibration(&cs35l56->base);
- if (ret)
- goto err;
-
- ret = cs_dsp_halo_init(&cs35l56->cs_dsp);
- if (ret) {
- dev_err_probe(cs35l56->base.dev, ret, "cs_dsp_halo_init failed\n");
- goto err;
- }
-
- dev_info(cs35l56->base.dev, "DSP system name: '%s', amp name: '%s'\n",
- cs35l56->system_name, cs35l56->amp_name);
-
- regmap_multi_reg_write(cs35l56->base.regmap, cs35l56_hda_dai_config,
- ARRAY_SIZE(cs35l56_hda_dai_config));
-
- /*
- * By default only enable one ASP1TXn, where n=amplifier index,
- * This prevents multiple amps trying to drive the same slot.
- */
- cs35l56->asp_tx_mask = BIT(cs35l56->index);
-
- pm_runtime_set_autosuspend_delay(cs35l56->base.dev, 3000);
- pm_runtime_use_autosuspend(cs35l56->base.dev);
- pm_runtime_set_active(cs35l56->base.dev);
- pm_runtime_mark_last_busy(cs35l56->base.dev);
- pm_runtime_enable(cs35l56->base.dev);
-
- cs35l56->base.init_done = true;
-
- ret = component_add(cs35l56->base.dev, &cs35l56_hda_comp_ops);
- if (ret) {
- dev_err(cs35l56->base.dev, "Register component failed: %d\n", ret);
- goto pm_err;
- }
-
- return 0;
-
-pm_err:
- pm_runtime_disable(cs35l56->base.dev);
- cs_dsp_remove(&cs35l56->cs_dsp);
-err:
- gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0);
-
- return ret;
-}
-EXPORT_SYMBOL_NS_GPL(cs35l56_hda_common_probe, "SND_HDA_SCODEC_CS35L56");
-
-void cs35l56_hda_remove(struct device *dev)
-{
- struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev);
-
- component_del(cs35l56->base.dev, &cs35l56_hda_comp_ops);
-
- pm_runtime_dont_use_autosuspend(cs35l56->base.dev);
- pm_runtime_get_sync(cs35l56->base.dev);
- pm_runtime_disable(cs35l56->base.dev);
-
- cs_dsp_remove(&cs35l56->cs_dsp);
-
- kfree(cs35l56->system_name);
- pm_runtime_put_noidle(cs35l56->base.dev);
-
- gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0);
-}
-EXPORT_SYMBOL_NS_GPL(cs35l56_hda_remove, "SND_HDA_SCODEC_CS35L56");
-
-const struct dev_pm_ops cs35l56_hda_pm_ops = {
- RUNTIME_PM_OPS(cs35l56_hda_runtime_suspend, cs35l56_hda_runtime_resume, NULL)
- SYSTEM_SLEEP_PM_OPS(cs35l56_hda_system_suspend, cs35l56_hda_system_resume)
- LATE_SYSTEM_SLEEP_PM_OPS(cs35l56_hda_system_suspend_late,
- cs35l56_hda_system_resume_early)
- NOIRQ_SYSTEM_SLEEP_PM_OPS(cs35l56_hda_system_suspend_no_irq,
- cs35l56_hda_system_resume_no_irq)
-};
-EXPORT_SYMBOL_NS_GPL(cs35l56_hda_pm_ops, "SND_HDA_SCODEC_CS35L56");
-
-MODULE_DESCRIPTION("CS35L56 HDA Driver");
-MODULE_IMPORT_NS("FW_CS_DSP");
-MODULE_IMPORT_NS("SND_HDA_CIRRUS_SCODEC");
-MODULE_IMPORT_NS("SND_SOC_CS35L56_SHARED");
-MODULE_IMPORT_NS("SND_SOC_CS_AMP_LIB");
-MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
-MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>");
-MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/cs35l56_hda.h b/sound/pci/hda/cs35l56_hda.h
deleted file mode 100644
index 38d94fb213a5..000000000000
--- a/sound/pci/hda/cs35l56_hda.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only
- *
- * HDA audio driver for Cirrus Logic CS35L56 smart amp
- *
- * Copyright (C) 2023 Cirrus Logic, Inc. and
- * Cirrus Logic International Semiconductor Ltd.
- */
-
-#ifndef __CS35L56_HDA_H__
-#define __CS35L56_HDA_H__
-
-#include <linux/device.h>
-#include <linux/gpio/consumer.h>
-#include <linux/firmware/cirrus/cs_dsp.h>
-#include <linux/firmware/cirrus/wmfw.h>
-#include <linux/regulator/consumer.h>
-#include <linux/workqueue.h>
-#include <sound/cs35l56.h>
-
-struct dentry;
-
-struct cs35l56_hda {
- struct cs35l56_base base;
- struct hda_codec *codec;
- struct work_struct dsp_work;
-
- int index;
- const char *system_name;
- const char *amp_name;
-
- struct cs_dsp cs_dsp;
- bool playing;
- bool suspended;
- u8 asp_tx_mask;
-
- struct snd_kcontrol *posture_ctl;
- struct snd_kcontrol *volume_ctl;
- struct snd_kcontrol *mixer_ctl[4];
-
-#if IS_ENABLED(CONFIG_SND_DEBUG)
- struct dentry *debugfs_root;
-#endif
-};
-
-extern const struct dev_pm_ops cs35l56_hda_pm_ops;
-
-int cs35l56_hda_common_probe(struct cs35l56_hda *cs35l56, int hid, int id);
-void cs35l56_hda_remove(struct device *dev);
-
-#endif /*__CS35L56_HDA_H__*/
diff --git a/sound/pci/hda/cs35l56_hda_i2c.c b/sound/pci/hda/cs35l56_hda_i2c.c
deleted file mode 100644
index d10209e4eddd..000000000000
--- a/sound/pci/hda/cs35l56_hda_i2c.c
+++ /dev/null
@@ -1,87 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-//
-// CS35L56 HDA audio driver I2C binding
-//
-// Copyright (C) 2023 Cirrus Logic, Inc. and
-// Cirrus Logic International Semiconductor Ltd.
-
-#include <linux/i2c.h>
-#include <linux/module.h>
-#include <linux/regmap.h>
-
-#include "cs35l56_hda.h"
-
-static int cs35l56_hda_i2c_probe(struct i2c_client *clt)
-{
- const struct i2c_device_id *id = i2c_client_get_device_id(clt);
- struct cs35l56_hda *cs35l56;
- int ret;
-
- cs35l56 = devm_kzalloc(&clt->dev, sizeof(*cs35l56), GFP_KERNEL);
- if (!cs35l56)
- return -ENOMEM;
-
- cs35l56->base.dev = &clt->dev;
-
-#ifdef CS35L56_WAKE_HOLD_TIME_US
- cs35l56->base.can_hibernate = true;
-#endif
-
- cs35l56->base.fw_reg = &cs35l56_fw_reg;
-
- cs35l56->base.regmap = devm_regmap_init_i2c(clt, &cs35l56_regmap_i2c);
- if (IS_ERR(cs35l56->base.regmap)) {
- ret = PTR_ERR(cs35l56->base.regmap);
- dev_err(cs35l56->base.dev, "Failed to allocate register map: %d\n",
- ret);
- return ret;
- }
-
- ret = cs35l56_hda_common_probe(cs35l56, id->driver_data, clt->addr);
- if (ret)
- return ret;
- ret = cs35l56_irq_request(&cs35l56->base, clt->irq);
- if (ret < 0)
- cs35l56_hda_remove(cs35l56->base.dev);
-
- return ret;
-}
-
-static void cs35l56_hda_i2c_remove(struct i2c_client *clt)
-{
- cs35l56_hda_remove(&clt->dev);
-}
-
-static const struct i2c_device_id cs35l56_hda_i2c_id[] = {
- { "cs35l54-hda", 0x3554 },
- { "cs35l56-hda", 0x3556 },
- { "cs35l57-hda", 0x3557 },
- {}
-};
-
-static const struct acpi_device_id cs35l56_acpi_hda_match[] = {
- { "CSC3554", 0 },
- { "CSC3556", 0 },
- { "CSC3557", 0 },
- {}
-};
-MODULE_DEVICE_TABLE(acpi, cs35l56_acpi_hda_match);
-
-static struct i2c_driver cs35l56_hda_i2c_driver = {
- .driver = {
- .name = "cs35l56-hda",
- .acpi_match_table = cs35l56_acpi_hda_match,
- .pm = &cs35l56_hda_pm_ops,
- },
- .id_table = cs35l56_hda_i2c_id,
- .probe = cs35l56_hda_i2c_probe,
- .remove = cs35l56_hda_i2c_remove,
-};
-module_i2c_driver(cs35l56_hda_i2c_driver);
-
-MODULE_DESCRIPTION("HDA CS35L56 I2C driver");
-MODULE_IMPORT_NS("SND_HDA_SCODEC_CS35L56");
-MODULE_IMPORT_NS("SND_SOC_CS35L56_SHARED");
-MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
-MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>");
-MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/cs35l56_hda_spi.c b/sound/pci/hda/cs35l56_hda_spi.c
deleted file mode 100644
index f57533d3d728..000000000000
--- a/sound/pci/hda/cs35l56_hda_spi.c
+++ /dev/null
@@ -1,90 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-//
-// CS35L56 HDA audio driver SPI binding
-//
-// Copyright (C) 2023 Cirrus Logic, Inc. and
-// Cirrus Logic International Semiconductor Ltd.
-
-#include <linux/module.h>
-#include <linux/regmap.h>
-#include <linux/spi/spi.h>
-
-#include "cs35l56_hda.h"
-
-static int cs35l56_hda_spi_probe(struct spi_device *spi)
-{
- const struct spi_device_id *id = spi_get_device_id(spi);
- struct cs35l56_hda *cs35l56;
- int ret;
-
- cs35l56 = devm_kzalloc(&spi->dev, sizeof(*cs35l56), GFP_KERNEL);
- if (!cs35l56)
- return -ENOMEM;
-
- cs35l56->base.dev = &spi->dev;
- ret = cs35l56_init_config_for_spi(&cs35l56->base, spi);
- if (ret)
- return ret;
-
-#ifdef CS35L56_WAKE_HOLD_TIME_US
- cs35l56->base.can_hibernate = true;
-#endif
-
- cs35l56->base.fw_reg = &cs35l56_fw_reg;
-
- cs35l56->base.regmap = devm_regmap_init_spi(spi, &cs35l56_regmap_spi);
- if (IS_ERR(cs35l56->base.regmap)) {
- ret = PTR_ERR(cs35l56->base.regmap);
- dev_err(cs35l56->base.dev, "Failed to allocate register map: %d\n",
- ret);
- return ret;
- }
-
- ret = cs35l56_hda_common_probe(cs35l56, id->driver_data, spi_get_chipselect(spi, 0));
- if (ret)
- return ret;
- ret = cs35l56_irq_request(&cs35l56->base, spi->irq);
- if (ret < 0)
- cs35l56_hda_remove(cs35l56->base.dev);
-
- return ret;
-}
-
-static void cs35l56_hda_spi_remove(struct spi_device *spi)
-{
- cs35l56_hda_remove(&spi->dev);
-}
-
-static const struct spi_device_id cs35l56_hda_spi_id[] = {
- { "cs35l54-hda", 0x3554 },
- { "cs35l56-hda", 0x3556 },
- { "cs35l57-hda", 0x3557 },
- {}
-};
-
-static const struct acpi_device_id cs35l56_acpi_hda_match[] = {
- { "CSC3554", 0 },
- { "CSC3556", 0 },
- { "CSC3557", 0 },
- {}
-};
-MODULE_DEVICE_TABLE(acpi, cs35l56_acpi_hda_match);
-
-static struct spi_driver cs35l56_hda_spi_driver = {
- .driver = {
- .name = "cs35l56-hda",
- .acpi_match_table = cs35l56_acpi_hda_match,
- .pm = &cs35l56_hda_pm_ops,
- },
- .id_table = cs35l56_hda_spi_id,
- .probe = cs35l56_hda_spi_probe,
- .remove = cs35l56_hda_spi_remove,
-};
-module_spi_driver(cs35l56_hda_spi_driver);
-
-MODULE_DESCRIPTION("HDA CS35L56 SPI driver");
-MODULE_IMPORT_NS("SND_HDA_SCODEC_CS35L56");
-MODULE_IMPORT_NS("SND_SOC_CS35L56_SHARED");
-MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
-MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>");
-MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/hda_acpi.c b/sound/pci/hda/hda_acpi.c
deleted file mode 100644
index 505cc97e0ee9..000000000000
--- a/sound/pci/hda/hda_acpi.c
+++ /dev/null
@@ -1,325 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * ALSA driver for ACPI-based HDA Controllers.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/acpi.h>
-
-#include <sound/hda_codec.h>
-
-#include "hda_controller.h"
-
-struct hda_acpi {
- struct azx azx;
- struct snd_card *card;
- struct platform_device *pdev;
- void __iomem *regs;
- struct work_struct probe_work;
- const struct hda_data *data;
-};
-
-/**
- * struct hda_data - Optional device-specific data
- * @short_name: Used for the ALSA card name; defaults to KBUILD_MODNAME
- * @long_name: Used for longer description; defaults to short_name
- * @flags: Passed to &azx->driver_caps
- *
- * A pointer to a record of this type may be stored in the
- * &acpi_device_id->driver_data field of an ACPI match table entry in order to
- * customize the naming and behavior of a particular device. All fields are
- * optional and sensible defaults will be selected in their absence.
- */
-struct hda_data {
- const char *short_name;
- const char *long_name;
- unsigned long flags;
-};
-
-static int hda_acpi_dev_disconnect(struct snd_device *device)
-{
- struct azx *chip = device->device_data;
-
- chip->bus.shutdown = 1;
- return 0;
-}
-
-static int hda_acpi_dev_free(struct snd_device *device)
-{
- struct azx *azx = device->device_data;
- struct hda_acpi *hda = container_of(azx, struct hda_acpi, azx);
-
- cancel_work_sync(&hda->probe_work);
- if (azx_bus(azx)->chip_init) {
- azx_stop_all_streams(azx);
- azx_stop_chip(azx);
- }
-
- azx_free_stream_pages(azx);
- azx_free_streams(azx);
- snd_hdac_bus_exit(azx_bus(azx));
-
- return 0;
-}
-
-static int hda_acpi_init(struct hda_acpi *hda)
-{
- struct hdac_bus *bus = azx_bus(&hda->azx);
- struct snd_card *card = hda->azx.card;
- struct device *dev = &hda->pdev->dev;
- struct azx *azx = &hda->azx;
- struct resource *res;
- unsigned short gcap;
- const char *sname, *lname;
- int err, irq;
-
- /* The base address for the HDA registers and the interrupt are wrapped
- * in an ACPI _CRS object which can be parsed by platform_get_irq() and
- * devm_platform_get_and_ioremap_resource()
- */
-
- irq = platform_get_irq(hda->pdev, 0);
- if (irq < 0)
- return irq;
-
- hda->regs = devm_platform_get_and_ioremap_resource(hda->pdev, 0, &res);
- if (IS_ERR(hda->regs))
- return PTR_ERR(hda->regs);
-
- bus->remap_addr = hda->regs;
- bus->addr = res->start;
-
- err = devm_request_irq(dev, irq, azx_interrupt,
- IRQF_SHARED, KBUILD_MODNAME, azx);
- if (err) {
- dev_err(dev, "unable to request IRQ %d, disabling device\n",
- irq);
- return err;
- }
- bus->irq = irq;
- bus->dma_stop_delay = 100;
- card->sync_irq = bus->irq;
-
- gcap = azx_readw(azx, GCAP);
- dev_dbg(dev, "chipset global capabilities = 0x%x\n", gcap);
-
- azx->align_buffer_size = 1;
-
- azx->capture_streams = (gcap >> 8) & 0x0f;
- azx->playback_streams = (gcap >> 12) & 0x0f;
-
- azx->capture_index_offset = 0;
- azx->playback_index_offset = azx->capture_streams;
- azx->num_streams = azx->playback_streams + azx->capture_streams;
-
- err = azx_init_streams(azx);
- if (err < 0) {
- dev_err(dev, "failed to initialize streams: %d\n", err);
- return err;
- }
-
- err = azx_alloc_stream_pages(azx);
- if (err < 0) {
- dev_err(dev, "failed to allocate stream pages: %d\n", err);
- return err;
- }
-
- azx_init_chip(azx, 1);
-
- if (!bus->codec_mask) {
- dev_err(dev, "no codecs found!\n");
- return -ENODEV;
- }
-
- strscpy(card->driver, "hda-acpi");
-
- sname = hda->data->short_name ? hda->data->short_name : KBUILD_MODNAME;
-
- if (strlen(sname) > sizeof(card->shortname))
- dev_info(dev, "truncating shortname for card %s\n", sname);
- strscpy(card->shortname, sname);
-
- lname = hda->data->long_name ? hda->data->long_name : sname;
-
- snprintf(card->longname, sizeof(card->longname),
- "%s at 0x%lx irq %i", lname, bus->addr, bus->irq);
-
- return 0;
-}
-
-static void hda_acpi_probe_work(struct work_struct *work)
-{
- struct hda_acpi *hda = container_of(work, struct hda_acpi, probe_work);
- struct azx *chip = &hda->azx;
- int err;
-
- err = hda_acpi_init(hda);
- if (err < 0)
- return;
-
- err = azx_probe_codecs(chip, 8);
- if (err < 0)
- return;
-
- err = azx_codec_configure(chip);
- if (err < 0)
- return;
-
- err = snd_card_register(chip->card);
- if (err < 0)
- return;
-
- chip->running = 1;
-}
-
-static int hda_acpi_create(struct hda_acpi *hda)
-{
- static const struct snd_device_ops ops = {
- .dev_disconnect = hda_acpi_dev_disconnect,
- .dev_free = hda_acpi_dev_free,
- };
- static const struct hda_controller_ops null_ops;
- struct azx *azx = &hda->azx;
- int err;
-
- mutex_init(&azx->open_mutex);
- azx->card = hda->card;
- INIT_LIST_HEAD(&azx->pcm_list);
-
- azx->ops = &null_ops;
- azx->driver_caps = hda->data->flags;
- azx->driver_type = hda->data->flags & 0xff;
- azx->codec_probe_mask = -1;
-
- err = azx_bus_init(azx, NULL);
- if (err < 0)
- return err;
-
- err = snd_device_new(hda->card, SNDRV_DEV_LOWLEVEL, &hda->azx, &ops);
- if (err < 0) {
- dev_err(&hda->pdev->dev, "Error creating device\n");
- return err;
- }
-
- return 0;
-}
-
-static int hda_acpi_probe(struct platform_device *pdev)
-{
- struct hda_acpi *hda;
- int err;
-
- hda = devm_kzalloc(&pdev->dev, sizeof(*hda), GFP_KERNEL);
- if (!hda)
- return -ENOMEM;
-
- hda->pdev = pdev;
- hda->data = acpi_device_get_match_data(&pdev->dev);
-
- /* Fall back to defaults if the table didn't have a *struct hda_data */
- if (!hda->data)
- hda->data = devm_kzalloc(&pdev->dev, sizeof(*hda->data),
- GFP_KERNEL);
- if (!hda->data)
- return -ENOMEM;
-
- err = snd_card_new(&pdev->dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
- THIS_MODULE, 0, &hda->card);
- if (err < 0) {
- dev_err(&pdev->dev, "Error creating card!\n");
- return err;
- }
-
- INIT_WORK(&hda->probe_work, hda_acpi_probe_work);
-
- err = hda_acpi_create(hda);
- if (err < 0)
- goto out_free;
- hda->card->private_data = &hda->azx;
-
- dev_set_drvdata(&pdev->dev, hda->card);
-
- schedule_work(&hda->probe_work);
-
- return 0;
-
-out_free:
- snd_card_free(hda->card);
- return err;
-}
-
-static void hda_acpi_remove(struct platform_device *pdev)
-{
- snd_card_free(dev_get_drvdata(&pdev->dev));
-}
-
-static void hda_acpi_shutdown(struct platform_device *pdev)
-{
- struct snd_card *card = dev_get_drvdata(&pdev->dev);
- struct azx *chip;
-
- if (!card)
- return;
- chip = card->private_data;
- if (chip && chip->running)
- azx_stop_chip(chip);
-}
-
-static int hda_acpi_suspend(struct device *dev)
-{
- struct snd_card *card = dev_get_drvdata(dev);
- int rc;
-
- rc = pm_runtime_force_suspend(dev);
- if (rc < 0)
- return rc;
- snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
-
- return 0;
-}
-
-static int hda_acpi_resume(struct device *dev)
-{
- struct snd_card *card = dev_get_drvdata(dev);
- int rc;
-
- rc = pm_runtime_force_resume(dev);
- if (rc < 0)
- return rc;
- snd_power_change_state(card, SNDRV_CTL_POWER_D0);
-
- return 0;
-}
-
-static const struct dev_pm_ops hda_acpi_pm = {
- SYSTEM_SLEEP_PM_OPS(hda_acpi_suspend, hda_acpi_resume)
-};
-
-static const struct hda_data nvidia_hda_data = {
- .short_name = "NVIDIA",
- .long_name = "NVIDIA HDA Controller",
- .flags = AZX_DCAPS_CORBRP_SELF_CLEAR,
-};
-
-static const struct acpi_device_id hda_acpi_match[] = {
- { .id = "NVDA2014", .driver_data = (uintptr_t) &nvidia_hda_data },
- { .id = "NVDA2015", .driver_data = (uintptr_t) &nvidia_hda_data },
- {},
-};
-MODULE_DEVICE_TABLE(acpi, hda_acpi_match);
-
-static struct platform_driver hda_acpi_platform_driver = {
- .driver = {
- .name = KBUILD_MODNAME,
- .pm = &hda_acpi_pm,
- .acpi_match_table = hda_acpi_match,
- },
- .probe = hda_acpi_probe,
- .remove = hda_acpi_remove,
- .shutdown = hda_acpi_shutdown,
-};
-module_platform_driver(hda_acpi_platform_driver);
-
-MODULE_DESCRIPTION("Driver for ACPI-based HDA Controllers");
-MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c
deleted file mode 100644
index 8923813ce424..000000000000
--- a/sound/pci/hda/hda_auto_parser.c
+++ /dev/null
@@ -1,1104 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * BIOS auto-parser helper functions for HD-audio
- *
- * Copyright (c) 2012 Takashi Iwai <tiwai@suse.de>
- */
-
-#include <linux/slab.h>
-#include <linux/export.h>
-#include <linux/sort.h>
-#include <sound/core.h>
-#include <sound/hda_codec.h>
-#include "hda_local.h"
-#include "hda_auto_parser.h"
-
-/*
- * Helper for automatic pin configuration
- */
-
-static int is_in_nid_list(hda_nid_t nid, const hda_nid_t *list)
-{
- for (; *list; list++)
- if (*list == nid)
- return 1;
- return 0;
-}
-
-/* a pair of input pin and its sequence */
-struct auto_out_pin {
- hda_nid_t pin;
- short seq;
-};
-
-static int compare_seq(const void *ap, const void *bp)
-{
- const struct auto_out_pin *a = ap;
- const struct auto_out_pin *b = bp;
- return (int)(a->seq - b->seq);
-}
-
-/*
- * Sort an associated group of pins according to their sequence numbers.
- * then store it to a pin array.
- */
-static void sort_pins_by_sequence(hda_nid_t *pins, struct auto_out_pin *list,
- int num_pins)
-{
- int i;
- sort(list, num_pins, sizeof(list[0]), compare_seq, NULL);
- for (i = 0; i < num_pins; i++)
- pins[i] = list[i].pin;
-}
-
-
-/* add the found input-pin to the cfg->inputs[] table */
-static void add_auto_cfg_input_pin(struct hda_codec *codec, struct auto_pin_cfg *cfg,
- hda_nid_t nid, int type)
-{
- if (cfg->num_inputs < AUTO_CFG_MAX_INS) {
- cfg->inputs[cfg->num_inputs].pin = nid;
- cfg->inputs[cfg->num_inputs].type = type;
- cfg->inputs[cfg->num_inputs].has_boost_on_pin =
- nid_has_volume(codec, nid, HDA_INPUT);
- cfg->num_inputs++;
- }
-}
-
-static int compare_input_type(const void *ap, const void *bp)
-{
- const struct auto_pin_cfg_item *a = ap;
- const struct auto_pin_cfg_item *b = bp;
- if (a->type != b->type)
- return (int)(a->type - b->type);
-
- /* If has both hs_mic and hp_mic, pick the hs_mic ahead of hp_mic. */
- if (a->is_headset_mic && b->is_headphone_mic)
- return -1; /* don't swap */
- else if (a->is_headphone_mic && b->is_headset_mic)
- return 1; /* swap */
-
- /* In case one has boost and the other one has not,
- pick the one with boost first. */
- if (a->has_boost_on_pin != b->has_boost_on_pin)
- return (int)(b->has_boost_on_pin - a->has_boost_on_pin);
-
- /* Keep the original order */
- return a->order - b->order;
-}
-
-/* Reorder the surround channels
- * ALSA sequence is front/surr/clfe/side
- * HDA sequence is:
- * 4-ch: front/surr => OK as it is
- * 6-ch: front/clfe/surr
- * 8-ch: front/clfe/rear/side|fc
- */
-static void reorder_outputs(unsigned int nums, hda_nid_t *pins)
-{
- switch (nums) {
- case 3:
- case 4:
- swap(pins[1], pins[2]);
- break;
- }
-}
-
-/* check whether the given pin has a proper pin I/O capability bit */
-static bool check_pincap_validity(struct hda_codec *codec, hda_nid_t pin,
- unsigned int dev)
-{
- unsigned int pincap = snd_hda_query_pin_caps(codec, pin);
-
- /* some old hardware don't return the proper pincaps */
- if (!pincap)
- return true;
-
- switch (dev) {
- case AC_JACK_LINE_OUT:
- case AC_JACK_SPEAKER:
- case AC_JACK_HP_OUT:
- case AC_JACK_SPDIF_OUT:
- case AC_JACK_DIG_OTHER_OUT:
- return !!(pincap & AC_PINCAP_OUT);
- default:
- return !!(pincap & AC_PINCAP_IN);
- }
-}
-
-static bool can_be_headset_mic(struct hda_codec *codec,
- struct auto_pin_cfg_item *item,
- int seq_number)
-{
- int attr;
- unsigned int def_conf;
- if (item->type != AUTO_PIN_MIC)
- return false;
-
- if (item->is_headset_mic || item->is_headphone_mic)
- return false; /* Already assigned */
-
- def_conf = snd_hda_codec_get_pincfg(codec, item->pin);
- attr = snd_hda_get_input_pin_attr(def_conf);
- if (attr <= INPUT_PIN_ATTR_DOCK)
- return false;
-
- if (seq_number >= 0) {
- int seq = get_defcfg_sequence(def_conf);
- if (seq != seq_number)
- return false;
- }
-
- return true;
-}
-
-/*
- * Parse all pin widgets and store the useful pin nids to cfg
- *
- * The number of line-outs or any primary output is stored in line_outs,
- * and the corresponding output pins are assigned to line_out_pins[],
- * in the order of front, rear, CLFE, side, ...
- *
- * If more extra outputs (speaker and headphone) are found, the pins are
- * assisnged to hp_pins[] and speaker_pins[], respectively. If no line-out jack
- * is detected, one of speaker of HP pins is assigned as the primary
- * output, i.e. to line_out_pins[0]. So, line_outs is always positive
- * if any analog output exists.
- *
- * The analog input pins are assigned to inputs array.
- * The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
- * respectively.
- */
-int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
- struct auto_pin_cfg *cfg,
- const hda_nid_t *ignore_nids,
- unsigned int cond_flags)
-{
- hda_nid_t nid;
- short seq, assoc_line_out;
- struct auto_out_pin line_out[ARRAY_SIZE(cfg->line_out_pins)];
- struct auto_out_pin speaker_out[ARRAY_SIZE(cfg->speaker_pins)];
- struct auto_out_pin hp_out[ARRAY_SIZE(cfg->hp_pins)];
- int i;
-
- if (!snd_hda_get_int_hint(codec, "parser_flags", &i))
- cond_flags = i;
-
- memset(cfg, 0, sizeof(*cfg));
-
- memset(line_out, 0, sizeof(line_out));
- memset(speaker_out, 0, sizeof(speaker_out));
- memset(hp_out, 0, sizeof(hp_out));
- assoc_line_out = 0;
-
- for_each_hda_codec_node(nid, codec) {
- unsigned int wid_caps = get_wcaps(codec, nid);
- unsigned int wid_type = get_wcaps_type(wid_caps);
- unsigned int def_conf;
- short assoc, loc, conn, dev;
-
- /* read all default configuration for pin complex */
- if (wid_type != AC_WID_PIN)
- continue;
- /* ignore the given nids (e.g. pc-beep returns error) */
- if (ignore_nids && is_in_nid_list(nid, ignore_nids))
- continue;
-
- def_conf = snd_hda_codec_get_pincfg(codec, nid);
- conn = get_defcfg_connect(def_conf);
- if (conn == AC_JACK_PORT_NONE)
- continue;
- loc = get_defcfg_location(def_conf);
- dev = get_defcfg_device(def_conf);
-
- /* workaround for buggy BIOS setups */
- if (dev == AC_JACK_LINE_OUT) {
- if (conn == AC_JACK_PORT_FIXED ||
- conn == AC_JACK_PORT_BOTH)
- dev = AC_JACK_SPEAKER;
- }
-
- if (!check_pincap_validity(codec, nid, dev))
- continue;
-
- switch (dev) {
- case AC_JACK_LINE_OUT:
- seq = get_defcfg_sequence(def_conf);
- assoc = get_defcfg_association(def_conf);
-
- if (!(wid_caps & AC_WCAP_STEREO))
- if (!cfg->mono_out_pin)
- cfg->mono_out_pin = nid;
- if (!assoc)
- continue;
- if (!assoc_line_out)
- assoc_line_out = assoc;
- else if (assoc_line_out != assoc) {
- codec_info(codec,
- "ignore pin 0x%x with mismatching assoc# 0x%x vs 0x%x\n",
- nid, assoc, assoc_line_out);
- continue;
- }
- if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins)) {
- codec_info(codec,
- "ignore pin 0x%x, too many assigned pins\n",
- nid);
- continue;
- }
- line_out[cfg->line_outs].pin = nid;
- line_out[cfg->line_outs].seq = seq;
- cfg->line_outs++;
- break;
- case AC_JACK_SPEAKER:
- seq = get_defcfg_sequence(def_conf);
- assoc = get_defcfg_association(def_conf);
- if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins)) {
- codec_info(codec,
- "ignore pin 0x%x, too many assigned pins\n",
- nid);
- continue;
- }
- speaker_out[cfg->speaker_outs].pin = nid;
- speaker_out[cfg->speaker_outs].seq = (assoc << 4) | seq;
- cfg->speaker_outs++;
- break;
- case AC_JACK_HP_OUT:
- seq = get_defcfg_sequence(def_conf);
- assoc = get_defcfg_association(def_conf);
- if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins)) {
- codec_info(codec,
- "ignore pin 0x%x, too many assigned pins\n",
- nid);
- continue;
- }
- hp_out[cfg->hp_outs].pin = nid;
- hp_out[cfg->hp_outs].seq = (assoc << 4) | seq;
- cfg->hp_outs++;
- break;
- case AC_JACK_MIC_IN:
- add_auto_cfg_input_pin(codec, cfg, nid, AUTO_PIN_MIC);
- break;
- case AC_JACK_LINE_IN:
- add_auto_cfg_input_pin(codec, cfg, nid, AUTO_PIN_LINE_IN);
- break;
- case AC_JACK_CD:
- add_auto_cfg_input_pin(codec, cfg, nid, AUTO_PIN_CD);
- break;
- case AC_JACK_AUX:
- add_auto_cfg_input_pin(codec, cfg, nid, AUTO_PIN_AUX);
- break;
- case AC_JACK_SPDIF_OUT:
- case AC_JACK_DIG_OTHER_OUT:
- if (cfg->dig_outs >= ARRAY_SIZE(cfg->dig_out_pins)) {
- codec_info(codec,
- "ignore pin 0x%x, too many assigned pins\n",
- nid);
- continue;
- }
- cfg->dig_out_pins[cfg->dig_outs] = nid;
- cfg->dig_out_type[cfg->dig_outs] =
- (loc == AC_JACK_LOC_HDMI) ?
- HDA_PCM_TYPE_HDMI : HDA_PCM_TYPE_SPDIF;
- cfg->dig_outs++;
- break;
- case AC_JACK_SPDIF_IN:
- case AC_JACK_DIG_OTHER_IN:
- cfg->dig_in_pin = nid;
- if (loc == AC_JACK_LOC_HDMI)
- cfg->dig_in_type = HDA_PCM_TYPE_HDMI;
- else
- cfg->dig_in_type = HDA_PCM_TYPE_SPDIF;
- break;
- }
- }
-
- /* Find a pin that could be a headset or headphone mic */
- if (cond_flags & HDA_PINCFG_HEADSET_MIC || cond_flags & HDA_PINCFG_HEADPHONE_MIC) {
- bool hsmic = !!(cond_flags & HDA_PINCFG_HEADSET_MIC);
- bool hpmic = !!(cond_flags & HDA_PINCFG_HEADPHONE_MIC);
- for (i = 0; (hsmic || hpmic) && (i < cfg->num_inputs); i++)
- if (hsmic && can_be_headset_mic(codec, &cfg->inputs[i], 0xc)) {
- cfg->inputs[i].is_headset_mic = 1;
- hsmic = false;
- } else if (hpmic && can_be_headset_mic(codec, &cfg->inputs[i], 0xd)) {
- cfg->inputs[i].is_headphone_mic = 1;
- hpmic = false;
- }
-
- /* If we didn't find our sequence number mark, fall back to any sequence number */
- for (i = 0; (hsmic || hpmic) && (i < cfg->num_inputs); i++) {
- if (!can_be_headset_mic(codec, &cfg->inputs[i], -1))
- continue;
- if (hsmic) {
- cfg->inputs[i].is_headset_mic = 1;
- hsmic = false;
- } else if (hpmic) {
- cfg->inputs[i].is_headphone_mic = 1;
- hpmic = false;
- }
- }
-
- if (hsmic)
- codec_dbg(codec, "Told to look for a headset mic, but didn't find any.\n");
- if (hpmic)
- codec_dbg(codec, "Told to look for a headphone mic, but didn't find any.\n");
- }
-
- /* FIX-UP:
- * If no line-out is defined but multiple HPs are found,
- * some of them might be the real line-outs.
- */
- if (!cfg->line_outs && cfg->hp_outs > 1 &&
- !(cond_flags & HDA_PINCFG_NO_HP_FIXUP)) {
- i = 0;
- while (i < cfg->hp_outs) {
- /* The real HPs should have the sequence 0x0f */
- if ((hp_out[i].seq & 0x0f) == 0x0f) {
- i++;
- continue;
- }
- /* Move it to the line-out table */
- line_out[cfg->line_outs++] = hp_out[i];
- cfg->hp_outs--;
- memmove(hp_out + i, hp_out + i + 1,
- sizeof(hp_out[0]) * (cfg->hp_outs - i));
- }
- memset(hp_out + cfg->hp_outs, 0,
- sizeof(hp_out[0]) * (AUTO_CFG_MAX_OUTS - cfg->hp_outs));
- if (!cfg->hp_outs)
- cfg->line_out_type = AUTO_PIN_HP_OUT;
-
- }
-
- /* sort by sequence */
- sort_pins_by_sequence(cfg->line_out_pins, line_out, cfg->line_outs);
- sort_pins_by_sequence(cfg->speaker_pins, speaker_out,
- cfg->speaker_outs);
- sort_pins_by_sequence(cfg->hp_pins, hp_out, cfg->hp_outs);
-
- /*
- * FIX-UP: if no line-outs are detected, try to use speaker or HP pin
- * as a primary output
- */
- if (!cfg->line_outs &&
- !(cond_flags & HDA_PINCFG_NO_LO_FIXUP)) {
- if (cfg->speaker_outs) {
- cfg->line_outs = cfg->speaker_outs;
- memcpy(cfg->line_out_pins, cfg->speaker_pins,
- sizeof(cfg->speaker_pins));
- cfg->speaker_outs = 0;
- memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
- cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
- } else if (cfg->hp_outs) {
- cfg->line_outs = cfg->hp_outs;
- memcpy(cfg->line_out_pins, cfg->hp_pins,
- sizeof(cfg->hp_pins));
- cfg->hp_outs = 0;
- memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
- cfg->line_out_type = AUTO_PIN_HP_OUT;
- }
- }
-
- reorder_outputs(cfg->line_outs, cfg->line_out_pins);
- reorder_outputs(cfg->hp_outs, cfg->hp_pins);
- reorder_outputs(cfg->speaker_outs, cfg->speaker_pins);
-
- /* sort inputs in the order of AUTO_PIN_* type */
- for (i = 0; i < cfg->num_inputs; i++)
- cfg->inputs[i].order = i;
- sort(cfg->inputs, cfg->num_inputs, sizeof(cfg->inputs[0]),
- compare_input_type, NULL);
-
- /*
- * debug prints of the parsed results
- */
- codec_info(codec, "autoconfig for %s: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x) type:%s\n",
- codec->core.chip_name, cfg->line_outs, cfg->line_out_pins[0],
- cfg->line_out_pins[1], cfg->line_out_pins[2],
- cfg->line_out_pins[3], cfg->line_out_pins[4],
- cfg->line_out_type == AUTO_PIN_HP_OUT ? "hp" :
- (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT ?
- "speaker" : "line"));
- codec_info(codec, " speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
- cfg->speaker_outs, cfg->speaker_pins[0],
- cfg->speaker_pins[1], cfg->speaker_pins[2],
- cfg->speaker_pins[3], cfg->speaker_pins[4]);
- codec_info(codec, " hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
- cfg->hp_outs, cfg->hp_pins[0],
- cfg->hp_pins[1], cfg->hp_pins[2],
- cfg->hp_pins[3], cfg->hp_pins[4]);
- codec_info(codec, " mono: mono_out=0x%x\n", cfg->mono_out_pin);
- if (cfg->dig_outs)
- codec_info(codec, " dig-out=0x%x/0x%x\n",
- cfg->dig_out_pins[0], cfg->dig_out_pins[1]);
- codec_info(codec, " inputs:\n");
- for (i = 0; i < cfg->num_inputs; i++) {
- codec_info(codec, " %s=0x%x\n",
- hda_get_autocfg_input_label(codec, cfg, i),
- cfg->inputs[i].pin);
- }
- if (cfg->dig_in_pin)
- codec_info(codec, " dig-in=0x%x\n", cfg->dig_in_pin);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_parse_pin_defcfg);
-
-/**
- * snd_hda_get_input_pin_attr - Get the input pin attribute from pin config
- * @def_conf: pin configuration value
- *
- * Guess the input pin attribute (INPUT_PIN_ATTR_XXX) from the given
- * default pin configuration value.
- */
-int snd_hda_get_input_pin_attr(unsigned int def_conf)
-{
- unsigned int loc = get_defcfg_location(def_conf);
- unsigned int conn = get_defcfg_connect(def_conf);
- if (conn == AC_JACK_PORT_NONE)
- return INPUT_PIN_ATTR_UNUSED;
- /* Windows may claim the internal mic to be BOTH, too */
- if (conn == AC_JACK_PORT_FIXED || conn == AC_JACK_PORT_BOTH)
- return INPUT_PIN_ATTR_INT;
- if ((loc & 0x30) == AC_JACK_LOC_INTERNAL)
- return INPUT_PIN_ATTR_INT;
- if ((loc & 0x30) == AC_JACK_LOC_SEPARATE)
- return INPUT_PIN_ATTR_DOCK;
- if (loc == AC_JACK_LOC_REAR)
- return INPUT_PIN_ATTR_REAR;
- if (loc == AC_JACK_LOC_FRONT)
- return INPUT_PIN_ATTR_FRONT;
- return INPUT_PIN_ATTR_NORMAL;
-}
-EXPORT_SYMBOL_GPL(snd_hda_get_input_pin_attr);
-
-/**
- * hda_get_input_pin_label - Give a label for the given input pin
- * @codec: the HDA codec
- * @item: ping config item to refer
- * @pin: the pin NID
- * @check_location: flag to add the jack location prefix
- *
- * When @check_location is true, the function checks the pin location
- * for mic and line-in pins, and set an appropriate prefix like "Front",
- * "Rear", "Internal".
- */
-static const char *hda_get_input_pin_label(struct hda_codec *codec,
- const struct auto_pin_cfg_item *item,
- hda_nid_t pin, bool check_location)
-{
- unsigned int def_conf;
- static const char * const mic_names[] = {
- "Internal Mic", "Dock Mic", "Mic", "Rear Mic", "Front Mic"
- };
- int attr;
-
- def_conf = snd_hda_codec_get_pincfg(codec, pin);
-
- switch (get_defcfg_device(def_conf)) {
- case AC_JACK_MIC_IN:
- if (item && item->is_headset_mic)
- return "Headset Mic";
- if (item && item->is_headphone_mic)
- return "Headphone Mic";
- if (!check_location)
- return "Mic";
- attr = snd_hda_get_input_pin_attr(def_conf);
- if (!attr)
- return "None";
- return mic_names[attr - 1];
- case AC_JACK_LINE_IN:
- if (!check_location)
- return "Line";
- attr = snd_hda_get_input_pin_attr(def_conf);
- if (!attr)
- return "None";
- if (attr == INPUT_PIN_ATTR_DOCK)
- return "Dock Line";
- return "Line";
- case AC_JACK_AUX:
- return "Aux";
- case AC_JACK_CD:
- return "CD";
- case AC_JACK_SPDIF_IN:
- return "SPDIF In";
- case AC_JACK_DIG_OTHER_IN:
- return "Digital In";
- case AC_JACK_HP_OUT:
- return "Headphone Mic";
- default:
- return "Misc";
- }
-}
-
-/* Check whether the location prefix needs to be added to the label.
- * If all mic-jacks are in the same location (e.g. rear panel), we don't
- * have to put "Front" prefix to each label. In such a case, returns false.
- */
-static int check_mic_location_need(struct hda_codec *codec,
- const struct auto_pin_cfg *cfg,
- int input)
-{
- unsigned int defc;
- int i, attr, attr2;
-
- defc = snd_hda_codec_get_pincfg(codec, cfg->inputs[input].pin);
- attr = snd_hda_get_input_pin_attr(defc);
- /* for internal or docking mics, we need locations */
- if (attr <= INPUT_PIN_ATTR_NORMAL)
- return 1;
-
- attr = 0;
- for (i = 0; i < cfg->num_inputs; i++) {
- defc = snd_hda_codec_get_pincfg(codec, cfg->inputs[i].pin);
- attr2 = snd_hda_get_input_pin_attr(defc);
- if (attr2 >= INPUT_PIN_ATTR_NORMAL) {
- if (attr && attr != attr2)
- return 1; /* different locations found */
- attr = attr2;
- }
- }
- return 0;
-}
-
-/**
- * hda_get_autocfg_input_label - Get a label for the given input
- * @codec: the HDA codec
- * @cfg: the parsed pin configuration
- * @input: the input index number
- *
- * Get a label for the given input pin defined by the autocfg item.
- * Unlike hda_get_input_pin_label(), this function checks all inputs
- * defined in autocfg and avoids the redundant mic/line prefix as much as
- * possible.
- */
-const char *hda_get_autocfg_input_label(struct hda_codec *codec,
- const struct auto_pin_cfg *cfg,
- int input)
-{
- int type = cfg->inputs[input].type;
- int has_multiple_pins = 0;
-
- if ((input > 0 && cfg->inputs[input - 1].type == type) ||
- (input < cfg->num_inputs - 1 && cfg->inputs[input + 1].type == type))
- has_multiple_pins = 1;
- if (has_multiple_pins && type == AUTO_PIN_MIC)
- has_multiple_pins &= check_mic_location_need(codec, cfg, input);
- has_multiple_pins |= codec->force_pin_prefix;
- return hda_get_input_pin_label(codec, &cfg->inputs[input],
- cfg->inputs[input].pin,
- has_multiple_pins);
-}
-EXPORT_SYMBOL_GPL(hda_get_autocfg_input_label);
-
-/* return the position of NID in the list, or -1 if not found */
-static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
-{
- int i;
- for (i = 0; i < nums; i++)
- if (list[i] == nid)
- return i;
- return -1;
-}
-
-/* get a unique suffix or an index number */
-static const char *check_output_sfx(hda_nid_t nid, const hda_nid_t *pins,
- int num_pins, int *indexp)
-{
- static const char * const channel_sfx[] = {
- " Front", " Surround", " CLFE", " Side"
- };
- int i;
-
- i = find_idx_in_nid_list(nid, pins, num_pins);
- if (i < 0)
- return NULL;
- if (num_pins == 1)
- return "";
- if (num_pins > ARRAY_SIZE(channel_sfx)) {
- if (indexp)
- *indexp = i;
- return "";
- }
- return channel_sfx[i];
-}
-
-static const char *check_output_pfx(struct hda_codec *codec, hda_nid_t nid)
-{
- unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);
- int attr = snd_hda_get_input_pin_attr(def_conf);
-
- /* check the location */
- switch (attr) {
- case INPUT_PIN_ATTR_DOCK:
- return "Dock ";
- case INPUT_PIN_ATTR_FRONT:
- return "Front ";
- }
- return "";
-}
-
-static int get_hp_label_index(struct hda_codec *codec, hda_nid_t nid,
- const hda_nid_t *pins, int num_pins)
-{
- int i, j, idx = 0;
-
- const char *pfx = check_output_pfx(codec, nid);
-
- i = find_idx_in_nid_list(nid, pins, num_pins);
- if (i < 0)
- return -1;
- for (j = 0; j < i; j++)
- if (pfx == check_output_pfx(codec, pins[j]))
- idx++;
-
- return idx;
-}
-
-static int fill_audio_out_name(struct hda_codec *codec, hda_nid_t nid,
- const struct auto_pin_cfg *cfg,
- const char *name, char *label, int maxlen,
- int *indexp)
-{
- unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);
- int attr = snd_hda_get_input_pin_attr(def_conf);
- const char *pfx, *sfx = "";
-
- /* handle as a speaker if it's a fixed line-out */
- if (!strcmp(name, "Line Out") && attr == INPUT_PIN_ATTR_INT)
- name = "Speaker";
- pfx = check_output_pfx(codec, nid);
-
- if (cfg) {
- /* try to give a unique suffix if needed */
- sfx = check_output_sfx(nid, cfg->line_out_pins, cfg->line_outs,
- indexp);
- if (!sfx)
- sfx = check_output_sfx(nid, cfg->speaker_pins, cfg->speaker_outs,
- indexp);
- if (!sfx) {
- /* don't add channel suffix for Headphone controls */
- int idx = get_hp_label_index(codec, nid, cfg->hp_pins,
- cfg->hp_outs);
- if (idx >= 0 && indexp)
- *indexp = idx;
- sfx = "";
- }
- }
- snprintf(label, maxlen, "%s%s%s", pfx, name, sfx);
- return 1;
-}
-
-#define is_hdmi_cfg(conf) \
- (get_defcfg_location(conf) == AC_JACK_LOC_HDMI)
-
-/**
- * snd_hda_get_pin_label - Get a label for the given I/O pin
- * @codec: the HDA codec
- * @nid: pin NID
- * @cfg: the parsed pin configuration
- * @label: the string buffer to store
- * @maxlen: the max length of string buffer (including termination)
- * @indexp: the pointer to return the index number (for multiple ctls)
- *
- * Get a label for the given pin. This function works for both input and
- * output pins. When @cfg is given as non-NULL, the function tries to get
- * an optimized label using hda_get_autocfg_input_label().
- *
- * This function tries to give a unique label string for the pin as much as
- * possible. For example, when the multiple line-outs are present, it adds
- * the channel suffix like "Front", "Surround", etc (only when @cfg is given).
- * If no unique name with a suffix is available and @indexp is non-NULL, the
- * index number is stored in the pointer.
- */
-int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid,
- const struct auto_pin_cfg *cfg,
- char *label, int maxlen, int *indexp)
-{
- unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);
- const char *name = NULL;
- int i;
- bool hdmi;
-
- if (indexp)
- *indexp = 0;
- if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
- return 0;
-
- switch (get_defcfg_device(def_conf)) {
- case AC_JACK_LINE_OUT:
- return fill_audio_out_name(codec, nid, cfg, "Line Out",
- label, maxlen, indexp);
- case AC_JACK_SPEAKER:
- return fill_audio_out_name(codec, nid, cfg, "Speaker",
- label, maxlen, indexp);
- case AC_JACK_HP_OUT:
- return fill_audio_out_name(codec, nid, cfg, "Headphone",
- label, maxlen, indexp);
- case AC_JACK_SPDIF_OUT:
- case AC_JACK_DIG_OTHER_OUT:
- hdmi = is_hdmi_cfg(def_conf);
- name = hdmi ? "HDMI" : "SPDIF";
- if (cfg && indexp)
- for (i = 0; i < cfg->dig_outs; i++) {
- hda_nid_t pin = cfg->dig_out_pins[i];
- unsigned int c;
- if (pin == nid)
- break;
- c = snd_hda_codec_get_pincfg(codec, pin);
- if (hdmi == is_hdmi_cfg(c))
- (*indexp)++;
- }
- break;
- default:
- if (cfg) {
- for (i = 0; i < cfg->num_inputs; i++) {
- if (cfg->inputs[i].pin != nid)
- continue;
- name = hda_get_autocfg_input_label(codec, cfg, i);
- if (name)
- break;
- }
- }
- if (!name)
- name = hda_get_input_pin_label(codec, NULL, nid, true);
- break;
- }
- if (!name)
- return 0;
- strscpy(label, name, maxlen);
- return 1;
-}
-EXPORT_SYMBOL_GPL(snd_hda_get_pin_label);
-
-/**
- * snd_hda_add_verbs - Add verbs to the init list
- * @codec: the HDA codec
- * @list: zero-terminated verb list to add
- *
- * Append the given verb list to the execution list. The verbs will be
- * performed at init and resume time via snd_hda_apply_verbs().
- */
-int snd_hda_add_verbs(struct hda_codec *codec,
- const struct hda_verb *list)
-{
- const struct hda_verb **v;
- v = snd_array_new(&codec->verbs);
- if (!v)
- return -ENOMEM;
- *v = list;
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_add_verbs);
-
-/**
- * snd_hda_apply_verbs - Execute the init verb lists
- * @codec: the HDA codec
- */
-void snd_hda_apply_verbs(struct hda_codec *codec)
-{
- const struct hda_verb **v;
- int i;
-
- snd_array_for_each(&codec->verbs, i, v)
- snd_hda_sequence_write(codec, *v);
-}
-EXPORT_SYMBOL_GPL(snd_hda_apply_verbs);
-
-/**
- * snd_hda_apply_pincfgs - Set each pin config in the given list
- * @codec: the HDA codec
- * @cfg: NULL-terminated pin config table
- */
-void snd_hda_apply_pincfgs(struct hda_codec *codec,
- const struct hda_pintbl *cfg)
-{
- for (; cfg->nid; cfg++)
- snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val);
-}
-EXPORT_SYMBOL_GPL(snd_hda_apply_pincfgs);
-
-static void set_pin_targets(struct hda_codec *codec,
- const struct hda_pintbl *cfg)
-{
- for (; cfg->nid; cfg++)
- snd_hda_set_pin_ctl_cache(codec, cfg->nid, cfg->val);
-}
-
-void __snd_hda_apply_fixup(struct hda_codec *codec, int id, int action, int depth)
-{
- const char *modelname = codec->fixup_name;
-
- while (id >= 0) {
- const struct hda_fixup *fix = codec->fixup_list + id;
-
- if (++depth > 10)
- break;
- if (fix->chained_before)
- __snd_hda_apply_fixup(codec, fix->chain_id, action, depth + 1);
-
- switch (fix->type) {
- case HDA_FIXUP_PINS:
- if (action != HDA_FIXUP_ACT_PRE_PROBE || !fix->v.pins)
- break;
- codec_dbg(codec, "%s: Apply pincfg for %s\n",
- codec->core.chip_name, modelname);
- snd_hda_apply_pincfgs(codec, fix->v.pins);
- break;
- case HDA_FIXUP_VERBS:
- if (action != HDA_FIXUP_ACT_PROBE || !fix->v.verbs)
- break;
- codec_dbg(codec, "%s: Apply fix-verbs for %s\n",
- codec->core.chip_name, modelname);
- snd_hda_add_verbs(codec, fix->v.verbs);
- break;
- case HDA_FIXUP_FUNC:
- if (!fix->v.func)
- break;
- codec_dbg(codec, "%s: Apply fix-func for %s\n",
- codec->core.chip_name, modelname);
- fix->v.func(codec, fix, action);
- break;
- case HDA_FIXUP_PINCTLS:
- if (action != HDA_FIXUP_ACT_PROBE || !fix->v.pins)
- break;
- codec_dbg(codec, "%s: Apply pinctl for %s\n",
- codec->core.chip_name, modelname);
- set_pin_targets(codec, fix->v.pins);
- break;
- default:
- codec_err(codec, "%s: Invalid fixup type %d\n",
- codec->core.chip_name, fix->type);
- break;
- }
- if (!fix->chained || fix->chained_before)
- break;
- id = fix->chain_id;
- }
-}
-EXPORT_SYMBOL_GPL(__snd_hda_apply_fixup);
-
-/**
- * snd_hda_apply_fixup - Apply the fixup chain with the given action
- * @codec: the HDA codec
- * @action: fixup action (HDA_FIXUP_ACT_XXX)
- */
-void snd_hda_apply_fixup(struct hda_codec *codec, int action)
-{
- if (codec->fixup_list)
- __snd_hda_apply_fixup(codec, codec->fixup_id, action, 0);
-}
-EXPORT_SYMBOL_GPL(snd_hda_apply_fixup);
-
-#define IGNORE_SEQ_ASSOC (~(AC_DEFCFG_SEQUENCE | AC_DEFCFG_DEF_ASSOC))
-
-static bool pin_config_match(struct hda_codec *codec,
- const struct hda_pintbl *pins,
- bool match_all_pins)
-{
- const struct hda_pincfg *pin;
- int i;
-
- snd_array_for_each(&codec->init_pins, i, pin) {
- hda_nid_t nid = pin->nid;
- u32 cfg = pin->cfg;
- const struct hda_pintbl *t_pins;
- int found;
-
- t_pins = pins;
- found = 0;
- for (; t_pins->nid; t_pins++) {
- if (t_pins->nid == nid) {
- found = 1;
- if ((t_pins->val & IGNORE_SEQ_ASSOC) == (cfg & IGNORE_SEQ_ASSOC))
- break;
- else if ((cfg & 0xf0000000) == 0x40000000 && (t_pins->val & 0xf0000000) == 0x40000000)
- break;
- else
- return false;
- }
- }
- if (match_all_pins &&
- !found && (cfg & 0xf0000000) != 0x40000000)
- return false;
- }
-
- return true;
-}
-
-/**
- * snd_hda_pick_pin_fixup - Pick up a fixup matching with the pin quirk list
- * @codec: the HDA codec
- * @pin_quirk: zero-terminated pin quirk list
- * @fixlist: the fixup list
- * @match_all_pins: all valid pins must match with the table entries
- */
-void snd_hda_pick_pin_fixup(struct hda_codec *codec,
- const struct snd_hda_pin_quirk *pin_quirk,
- const struct hda_fixup *fixlist,
- bool match_all_pins)
-{
- const struct snd_hda_pin_quirk *pq;
- const char *name = NULL;
-
- if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET)
- return;
-
- for (pq = pin_quirk; pq->subvendor; pq++) {
- if ((codec->core.subsystem_id & 0xffff0000) != (pq->subvendor << 16))
- continue;
- if (codec->core.vendor_id != pq->codec)
- continue;
- if (pin_config_match(codec, pq->pins, match_all_pins)) {
- codec->fixup_id = pq->value;
-#ifdef CONFIG_SND_DEBUG_VERBOSE
- codec->fixup_name = pq->name;
- name = pq->name;
-#endif
- codec_info(codec, "%s: picked fixup %s (pin match)\n",
- codec->core.chip_name, name ? name : "");
- codec->fixup_list = fixlist;
- return;
- }
- }
-}
-EXPORT_SYMBOL_GPL(snd_hda_pick_pin_fixup);
-
-/* check whether the given quirk entry matches with vendor/device pair */
-static bool hda_quirk_match(u16 vendor, u16 device, const struct hda_quirk *q)
-{
- if (q->subvendor != vendor)
- return false;
- return !q->subdevice ||
- (device & q->subdevice_mask) == q->subdevice;
-}
-
-/* look through the quirk list and return the matching entry */
-static const struct hda_quirk *
-hda_quirk_lookup_id(u16 vendor, u16 device, const struct hda_quirk *list)
-{
- const struct hda_quirk *q;
-
- for (q = list; q->subvendor || q->subdevice; q++) {
- if (hda_quirk_match(vendor, device, q))
- return q;
- }
- return NULL;
-}
-
-/**
- * snd_hda_pick_fixup - Pick up a fixup matching with PCI/codec SSID or model string
- * @codec: the HDA codec
- * @models: NULL-terminated model string list
- * @quirk: zero-terminated PCI/codec SSID quirk list
- * @fixlist: the fixup list
- *
- * Pick up a fixup entry matching with the given model string or SSID.
- * If a fixup was already set beforehand, the function doesn't do anything.
- * When a special model string "nofixup" is given, also no fixup is applied.
- *
- * The function tries to find the matching model name at first, if given.
- * If the model string contains the SSID alias, try to look up with the given
- * alias ID.
- * If nothing matched, try to look up the PCI SSID.
- * If still nothing matched, try to look up the codec SSID.
- */
-void snd_hda_pick_fixup(struct hda_codec *codec,
- const struct hda_model_fixup *models,
- const struct hda_quirk *quirk,
- const struct hda_fixup *fixlist)
-{
- const struct hda_quirk *q;
- int id = HDA_FIXUP_ID_NOT_SET;
- const char *name = NULL;
- const char *type = NULL;
- unsigned int vendor, device;
- u16 pci_vendor, pci_device;
- u16 codec_vendor, codec_device;
-
- if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET)
- return;
-
- /* when model=nofixup is given, don't pick up any fixups */
- if (codec->modelname && !strcmp(codec->modelname, "nofixup")) {
- id = HDA_FIXUP_ID_NO_FIXUP;
- fixlist = NULL;
- codec_info(codec, "%s: picked no fixup (nofixup specified)\n",
- codec->core.chip_name);
- goto found;
- }
-
- /* match with the model name string */
- if (codec->modelname && models) {
- while (models->name) {
- if (!strcmp(codec->modelname, models->name)) {
- id = models->id;
- name = models->name;
- codec_info(codec, "%s: picked fixup %s (model specified)\n",
- codec->core.chip_name, name);
- goto found;
- }
- models++;
- }
- }
-
- if (!quirk)
- return;
-
- if (codec->bus->pci) {
- pci_vendor = codec->bus->pci->subsystem_vendor;
- pci_device = codec->bus->pci->subsystem_device;
- }
-
- codec_vendor = codec->core.subsystem_id >> 16;
- codec_device = codec->core.subsystem_id & 0xffff;
-
- /* match with the SSID alias given by the model string "XXXX:YYYY" */
- if (codec->modelname &&
- sscanf(codec->modelname, "%04x:%04x", &vendor, &device) == 2) {
- q = hda_quirk_lookup_id(vendor, device, quirk);
- if (q) {
- type = "alias SSID";
- goto found_device;
- }
- }
-
- /* match primarily with the PCI SSID */
- for (q = quirk; q->subvendor || q->subdevice; q++) {
- /* if the entry is specific to codec SSID, check with it */
- if (!codec->bus->pci || q->match_codec_ssid) {
- if (hda_quirk_match(codec_vendor, codec_device, q)) {
- type = "codec SSID";
- goto found_device;
- }
- } else {
- if (hda_quirk_match(pci_vendor, pci_device, q)) {
- type = "PCI SSID";
- goto found_device;
- }
- }
- }
-
- /* match with the codec SSID */
- q = hda_quirk_lookup_id(codec_vendor, codec_device, quirk);
- if (q) {
- type = "codec SSID";
- goto found_device;
- }
-
- return; /* no matching */
-
- found_device:
- id = q->value;
-#ifdef CONFIG_SND_DEBUG_VERBOSE
- name = q->name;
-#endif
- codec_info(codec, "%s: picked fixup %s for %s %04x:%04x\n",
- codec->core.chip_name, name ? name : "",
- type, q->subvendor, q->subdevice);
- found:
- codec->fixup_id = id;
- codec->fixup_list = fixlist;
- codec->fixup_name = name;
-}
-EXPORT_SYMBOL_GPL(snd_hda_pick_fixup);
diff --git a/sound/pci/hda/hda_auto_parser.h b/sound/pci/hda/hda_auto_parser.h
deleted file mode 100644
index 87af3d8c02f7..000000000000
--- a/sound/pci/hda/hda_auto_parser.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * BIOS auto-parser helper functions for HD-audio
- *
- * Copyright (c) 2012 Takashi Iwai <tiwai@suse.de>
- */
-
-#ifndef __SOUND_HDA_AUTO_PARSER_H
-#define __SOUND_HDA_AUTO_PARSER_H
-
-#include "hda_local.h"
-
-/*
- * Helper for automatic pin configuration
- */
-
-enum {
- AUTO_PIN_MIC,
- AUTO_PIN_LINE_IN,
- AUTO_PIN_CD,
- AUTO_PIN_AUX,
- AUTO_PIN_LAST
-};
-
-enum {
- AUTO_PIN_LINE_OUT,
- AUTO_PIN_SPEAKER_OUT,
- AUTO_PIN_HP_OUT
-};
-
-#define AUTO_CFG_MAX_OUTS HDA_MAX_OUTS
-#define AUTO_CFG_MAX_INS 18
-
-struct auto_pin_cfg_item {
- hda_nid_t pin;
- int type;
- unsigned int is_headset_mic:1;
- unsigned int is_headphone_mic:1; /* Mic-only in headphone jack */
- unsigned int has_boost_on_pin:1;
- int order;
-};
-
-struct auto_pin_cfg;
-const char *hda_get_autocfg_input_label(struct hda_codec *codec,
- const struct auto_pin_cfg *cfg,
- int input);
-int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid,
- const struct auto_pin_cfg *cfg,
- char *label, int maxlen, int *indexp);
-
-enum {
- INPUT_PIN_ATTR_UNUSED, /* pin not connected */
- INPUT_PIN_ATTR_INT, /* internal mic/line-in */
- INPUT_PIN_ATTR_DOCK, /* docking mic/line-in */
- INPUT_PIN_ATTR_NORMAL, /* mic/line-in jack */
- INPUT_PIN_ATTR_REAR, /* mic/line-in jack in rear */
- INPUT_PIN_ATTR_FRONT, /* mic/line-in jack in front */
- INPUT_PIN_ATTR_LAST = INPUT_PIN_ATTR_FRONT,
-};
-
-int snd_hda_get_input_pin_attr(unsigned int def_conf);
-
-struct auto_pin_cfg {
- int line_outs;
- /* sorted in the order of Front/Surr/CLFE/Side */
- hda_nid_t line_out_pins[AUTO_CFG_MAX_OUTS];
- int speaker_outs;
- hda_nid_t speaker_pins[AUTO_CFG_MAX_OUTS];
- int hp_outs;
- int line_out_type; /* AUTO_PIN_XXX_OUT */
- hda_nid_t hp_pins[AUTO_CFG_MAX_OUTS];
- int num_inputs;
- struct auto_pin_cfg_item inputs[AUTO_CFG_MAX_INS];
- int dig_outs;
- hda_nid_t dig_out_pins[2];
- hda_nid_t dig_in_pin;
- hda_nid_t mono_out_pin;
- int dig_out_type[2]; /* HDA_PCM_TYPE_XXX */
- int dig_in_type; /* HDA_PCM_TYPE_XXX */
-};
-
-/* bit-flags for snd_hda_parse_pin_def_config() behavior */
-#define HDA_PINCFG_NO_HP_FIXUP (1 << 0) /* no HP-split */
-#define HDA_PINCFG_NO_LO_FIXUP (1 << 1) /* don't take other outs as LO */
-#define HDA_PINCFG_HEADSET_MIC (1 << 2) /* Try to find headset mic; mark seq number as 0xc to trigger */
-#define HDA_PINCFG_HEADPHONE_MIC (1 << 3) /* Try to find headphone mic; mark seq number as 0xd to trigger */
-
-int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
- struct auto_pin_cfg *cfg,
- const hda_nid_t *ignore_nids,
- unsigned int cond_flags);
-
-/* older function */
-#define snd_hda_parse_pin_def_config(codec, cfg, ignore) \
- snd_hda_parse_pin_defcfg(codec, cfg, ignore, 0)
-
-static inline int auto_cfg_hp_outs(const struct auto_pin_cfg *cfg)
-{
- return (cfg->line_out_type == AUTO_PIN_HP_OUT) ?
- cfg->line_outs : cfg->hp_outs;
-}
-static inline const hda_nid_t *auto_cfg_hp_pins(const struct auto_pin_cfg *cfg)
-{
- return (cfg->line_out_type == AUTO_PIN_HP_OUT) ?
- cfg->line_out_pins : cfg->hp_pins;
-}
-static inline int auto_cfg_speaker_outs(const struct auto_pin_cfg *cfg)
-{
- return (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) ?
- cfg->line_outs : cfg->speaker_outs;
-}
-static inline const hda_nid_t *auto_cfg_speaker_pins(const struct auto_pin_cfg *cfg)
-{
- return (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) ?
- cfg->line_out_pins : cfg->speaker_pins;
-}
-
-#endif /* __SOUND_HDA_AUTO_PARSER_H */
diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c
deleted file mode 100644
index 13a7d92e8d8d..000000000000
--- a/sound/pci/hda/hda_beep.c
+++ /dev/null
@@ -1,345 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Digital Beep Input Interface for HD-audio codec
- *
- * Author: Matt Ranostay <matt.ranostay@konsulko.com>
- * Copyright (c) 2008 Embedded Alley Solutions Inc
- */
-
-#include <linux/input.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
-#include <linux/export.h>
-#include <sound/core.h>
-#include "hda_beep.h"
-#include "hda_local.h"
-
-enum {
- DIGBEEP_HZ_STEP = 46875, /* 46.875 Hz */
- DIGBEEP_HZ_MIN = 93750, /* 93.750 Hz */
- DIGBEEP_HZ_MAX = 12000000, /* 12 KHz */
-};
-
-/* generate or stop tone */
-static void generate_tone(struct hda_beep *beep, int tone)
-{
- struct hda_codec *codec = beep->codec;
-
- if (tone && !beep->playing) {
- snd_hda_power_up(codec);
- if (beep->power_hook)
- beep->power_hook(beep, true);
- beep->playing = 1;
- }
- if (!codec->beep_just_power_on)
- snd_hda_codec_write(codec, beep->nid, 0,
- AC_VERB_SET_BEEP_CONTROL, tone);
- if (!tone && beep->playing) {
- beep->playing = 0;
- if (beep->power_hook)
- beep->power_hook(beep, false);
- snd_hda_power_down(codec);
- }
-}
-
-static void snd_hda_generate_beep(struct work_struct *work)
-{
- struct hda_beep *beep =
- container_of(work, struct hda_beep, beep_work);
-
- if (beep->enabled)
- generate_tone(beep, beep->tone);
-}
-
-/* (non-standard) Linear beep tone calculation for IDT/STAC codecs
- *
- * The tone frequency of beep generator on IDT/STAC codecs is
- * defined from the 8bit tone parameter, in Hz,
- * freq = 48000 * (257 - tone) / 1024
- * that is from 12kHz to 93.75Hz in steps of 46.875 Hz
- */
-static int beep_linear_tone(struct hda_beep *beep, int hz)
-{
- if (hz <= 0)
- return 0;
- hz *= 1000; /* fixed point */
- hz = hz - DIGBEEP_HZ_MIN
- + DIGBEEP_HZ_STEP / 2; /* round to nearest step */
- if (hz < 0)
- hz = 0; /* turn off PC beep*/
- else if (hz >= (DIGBEEP_HZ_MAX - DIGBEEP_HZ_MIN))
- hz = 1; /* max frequency */
- else {
- hz /= DIGBEEP_HZ_STEP;
- hz = 255 - hz;
- }
- return hz;
-}
-
-/* HD-audio standard beep tone parameter calculation
- *
- * The tone frequency in Hz is calculated as
- * freq = 48000 / (tone * 4)
- * from 47Hz to 12kHz
- */
-static int beep_standard_tone(struct hda_beep *beep, int hz)
-{
- if (hz <= 0)
- return 0; /* disabled */
- hz = 12000 / hz;
- if (hz > 0xff)
- return 0xff;
- if (hz <= 0)
- return 1;
- return hz;
-}
-
-static int snd_hda_beep_event(struct input_dev *dev, unsigned int type,
- unsigned int code, int hz)
-{
- struct hda_beep *beep = input_get_drvdata(dev);
-
- switch (code) {
- case SND_BELL:
- if (hz)
- hz = 1000;
- fallthrough;
- case SND_TONE:
- if (beep->linear_tone)
- beep->tone = beep_linear_tone(beep, hz);
- else
- beep->tone = beep_standard_tone(beep, hz);
- break;
- default:
- return -1;
- }
-
- /* schedule beep event */
- schedule_work(&beep->beep_work);
- return 0;
-}
-
-static void turn_on_beep(struct hda_beep *beep)
-{
- if (beep->keep_power_at_enable)
- snd_hda_power_up_pm(beep->codec);
-}
-
-static void turn_off_beep(struct hda_beep *beep)
-{
- cancel_work_sync(&beep->beep_work);
- if (beep->playing) {
- /* turn off beep */
- generate_tone(beep, 0);
- }
- if (beep->keep_power_at_enable)
- snd_hda_power_down_pm(beep->codec);
-}
-
-/**
- * snd_hda_enable_beep_device - Turn on/off beep sound
- * @codec: the HDA codec
- * @enable: flag to turn on/off
- */
-int snd_hda_enable_beep_device(struct hda_codec *codec, int enable)
-{
- struct hda_beep *beep = codec->beep;
- if (!beep)
- return 0;
- enable = !!enable;
- if (beep->enabled != enable) {
- beep->enabled = enable;
- if (enable)
- turn_on_beep(beep);
- else
- turn_off_beep(beep);
- return 1;
- }
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_enable_beep_device);
-
-static int beep_dev_register(struct snd_device *device)
-{
- struct hda_beep *beep = device->device_data;
- int err;
-
- err = input_register_device(beep->dev);
- if (!err)
- beep->registered = true;
- return err;
-}
-
-static int beep_dev_disconnect(struct snd_device *device)
-{
- struct hda_beep *beep = device->device_data;
-
- if (beep->registered)
- input_unregister_device(beep->dev);
- else
- input_free_device(beep->dev);
- if (beep->enabled)
- turn_off_beep(beep);
- return 0;
-}
-
-static int beep_dev_free(struct snd_device *device)
-{
- struct hda_beep *beep = device->device_data;
-
- beep->codec->beep = NULL;
- kfree(beep);
- return 0;
-}
-
-/**
- * snd_hda_attach_beep_device - Attach a beep input device
- * @codec: the HDA codec
- * @nid: beep NID
- *
- * Attach a beep object to the given widget. If beep hint is turned off
- * explicitly or beep_mode of the codec is turned off, this doesn't nothing.
- *
- * Currently, only one beep device is allowed to each codec.
- */
-int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
-{
- static const struct snd_device_ops ops = {
- .dev_register = beep_dev_register,
- .dev_disconnect = beep_dev_disconnect,
- .dev_free = beep_dev_free,
- };
- struct input_dev *input_dev;
- struct hda_beep *beep;
- int err;
-
- if (!codec->beep_just_power_on) {
- if (!snd_hda_get_bool_hint(codec, "beep"))
- return 0; /* disabled explicitly by hints */
- if (codec->beep_mode == HDA_BEEP_MODE_OFF)
- return 0; /* disabled by module option */
- }
-
- beep = kzalloc(sizeof(*beep), GFP_KERNEL);
- if (beep == NULL)
- return -ENOMEM;
- snprintf(beep->phys, sizeof(beep->phys),
- "card%d/codec#%d/beep0", codec->card->number, codec->addr);
- /* enable linear scale */
- snd_hda_codec_write_cache(codec, nid, 0,
- AC_VERB_SET_DIGI_CONVERT_2, 0x01);
-
- beep->nid = nid;
- beep->codec = codec;
- codec->beep = beep;
-
- INIT_WORK(&beep->beep_work, &snd_hda_generate_beep);
-
- input_dev = input_allocate_device();
- if (!input_dev) {
- err = -ENOMEM;
- goto err_free;
- }
-
- /* setup digital beep device */
- input_dev->name = "HDA Digital PCBeep";
- input_dev->phys = beep->phys;
- input_dev->id.bustype = BUS_PCI;
- input_dev->dev.parent = &codec->card->card_dev;
-
- input_dev->id.vendor = codec->core.vendor_id >> 16;
- input_dev->id.product = codec->core.vendor_id & 0xffff;
- input_dev->id.version = 0x01;
-
- input_dev->evbit[0] = BIT_MASK(EV_SND);
- input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE);
- input_dev->event = snd_hda_beep_event;
- input_set_drvdata(input_dev, beep);
-
- beep->dev = input_dev;
-
- err = snd_device_new(codec->card, SNDRV_DEV_JACK, beep, &ops);
- if (err < 0)
- goto err_input;
-
- return 0;
-
- err_input:
- input_free_device(beep->dev);
- err_free:
- kfree(beep);
- codec->beep = NULL;
- return err;
-}
-EXPORT_SYMBOL_GPL(snd_hda_attach_beep_device);
-
-/**
- * snd_hda_detach_beep_device - Detach the beep device
- * @codec: the HDA codec
- */
-void snd_hda_detach_beep_device(struct hda_codec *codec)
-{
- if (!codec->bus->shutdown && codec->beep)
- snd_device_free(codec->card, codec->beep);
-}
-EXPORT_SYMBOL_GPL(snd_hda_detach_beep_device);
-
-static bool ctl_has_mute(struct snd_kcontrol *kcontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- return query_amp_caps(codec, get_amp_nid(kcontrol),
- get_amp_direction(kcontrol)) & AC_AMPCAP_MUTE;
-}
-
-/* get/put callbacks for beep mute mixer switches */
-
-/**
- * snd_hda_mixer_amp_switch_get_beep - Get callback for beep controls
- * @kcontrol: ctl element
- * @ucontrol: pointer to get/store the data
- */
-int snd_hda_mixer_amp_switch_get_beep(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct hda_beep *beep = codec->beep;
- int chs = get_amp_channels(kcontrol);
-
- if (beep && (!beep->enabled || !ctl_has_mute(kcontrol))) {
- if (chs & 1)
- ucontrol->value.integer.value[0] = beep->enabled;
- if (chs & 2)
- ucontrol->value.integer.value[1] = beep->enabled;
- return 0;
- }
- return snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
-}
-EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_get_beep);
-
-/**
- * snd_hda_mixer_amp_switch_put_beep - Put callback for beep controls
- * @kcontrol: ctl element
- * @ucontrol: pointer to get/store the data
- */
-int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct hda_beep *beep = codec->beep;
- if (beep) {
- u8 chs = get_amp_channels(kcontrol);
- int enable = 0;
- long *valp = ucontrol->value.integer.value;
- if (chs & 1) {
- enable |= *valp;
- valp++;
- }
- if (chs & 2)
- enable |= *valp;
- snd_hda_enable_beep_device(codec, enable);
- }
- if (!ctl_has_mute(kcontrol))
- return 0;
- return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
-}
-EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_put_beep);
diff --git a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h
deleted file mode 100644
index 923ea862446a..000000000000
--- a/sound/pci/hda/hda_beep.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Digital Beep Input Interface for HD-audio codec
- *
- * Author: Matt Ranostay <matt.ranostay@konsulko.com>
- * Copyright (c) 2008 Embedded Alley Solutions Inc
- */
-
-#ifndef __SOUND_HDA_BEEP_H
-#define __SOUND_HDA_BEEP_H
-
-#include <sound/hda_codec.h>
-
-#define HDA_BEEP_MODE_OFF 0
-#define HDA_BEEP_MODE_ON 1
-
-/* beep information */
-struct hda_beep {
- struct input_dev *dev;
- struct hda_codec *codec;
- char phys[32];
- int tone;
- hda_nid_t nid;
- unsigned int registered:1;
- unsigned int enabled:1;
- unsigned int linear_tone:1; /* linear tone for IDT/STAC codec */
- unsigned int playing:1;
- unsigned int keep_power_at_enable:1; /* set by driver */
- struct work_struct beep_work; /* scheduled task for beep event */
- void (*power_hook)(struct hda_beep *beep, bool on);
-};
-
-#ifdef CONFIG_SND_HDA_INPUT_BEEP
-int snd_hda_enable_beep_device(struct hda_codec *codec, int enable);
-int snd_hda_attach_beep_device(struct hda_codec *codec, int nid);
-void snd_hda_detach_beep_device(struct hda_codec *codec);
-#else
-static inline int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
-{
- return 0;
-}
-static inline void snd_hda_detach_beep_device(struct hda_codec *codec)
-{
-}
-#endif
-#endif
diff --git a/sound/pci/hda/hda_bind.c b/sound/pci/hda/hda_bind.c
deleted file mode 100644
index df8f88beddd0..000000000000
--- a/sound/pci/hda/hda_bind.c
+++ /dev/null
@@ -1,343 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * HD-audio codec driver binding
- * Copyright (c) Takashi Iwai <tiwai@suse.de>
- */
-
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-#include <linux/module.h>
-#include <linux/export.h>
-#include <linux/pm.h>
-#include <sound/core.h>
-#include <sound/hda_codec.h>
-#include "hda_local.h"
-#include "hda_jack.h"
-
-/*
- * find a matching codec id
- */
-static int hda_codec_match(struct hdac_device *dev, const struct hdac_driver *drv)
-{
- struct hda_codec *codec = container_of(dev, struct hda_codec, core);
- const struct hda_codec_driver *driver =
- container_of(drv, struct hda_codec_driver, core);
- const struct hda_device_id *list;
- /* check probe_id instead of vendor_id if set */
- u32 id = codec->probe_id ? codec->probe_id : codec->core.vendor_id;
- u32 rev_id = codec->core.revision_id;
-
- for (list = driver->id; list->vendor_id; list++) {
- if (list->vendor_id == id &&
- (!list->rev_id || list->rev_id == rev_id)) {
- codec->preset = list;
- return 1;
- }
- }
- return 0;
-}
-
-/* process an unsolicited event */
-static void hda_codec_unsol_event(struct hdac_device *dev, unsigned int ev)
-{
- struct hda_codec *codec = container_of(dev, struct hda_codec, core);
-
- /* ignore unsol events during shutdown */
- if (codec->card->shutdown || codec->bus->shutdown)
- return;
-
- /* ignore unsol events during system suspend/resume */
- if (codec->core.dev.power.power_state.event != PM_EVENT_ON)
- return;
-
- if (codec->patch_ops.unsol_event)
- codec->patch_ops.unsol_event(codec, ev);
-}
-
-/**
- * snd_hda_codec_set_name - set the codec name
- * @codec: the HDA codec
- * @name: name string to set
- */
-int snd_hda_codec_set_name(struct hda_codec *codec, const char *name)
-{
- int err;
-
- if (!name)
- return 0;
- err = snd_hdac_device_set_chip_name(&codec->core, name);
- if (err < 0)
- return err;
-
- /* update the mixer name */
- if (!*codec->card->mixername ||
- codec->bus->mixer_assigned >= codec->core.addr) {
- snprintf(codec->card->mixername,
- sizeof(codec->card->mixername), "%s %s",
- codec->core.vendor_name, codec->core.chip_name);
- codec->bus->mixer_assigned = codec->core.addr;
- }
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_codec_set_name);
-
-static int hda_codec_driver_probe(struct device *dev)
-{
- struct hda_codec *codec = dev_to_hda_codec(dev);
- struct module *owner = dev->driver->owner;
- hda_codec_patch_t patch;
- int err;
-
- if (codec->bus->core.ext_ops) {
- if (WARN_ON(!codec->bus->core.ext_ops->hdev_attach))
- return -EINVAL;
- return codec->bus->core.ext_ops->hdev_attach(&codec->core);
- }
-
- if (WARN_ON(!codec->preset))
- return -EINVAL;
-
- err = snd_hda_codec_set_name(codec, codec->preset->name);
- if (err < 0)
- goto error;
- err = snd_hdac_regmap_init(&codec->core);
- if (err < 0)
- goto error;
-
- if (!try_module_get(owner)) {
- err = -EINVAL;
- goto error;
- }
-
- patch = (hda_codec_patch_t)codec->preset->driver_data;
- if (patch) {
- err = patch(codec);
- if (err < 0)
- goto error_module_put;
- }
-
- err = snd_hda_codec_build_pcms(codec);
- if (err < 0)
- goto error_module;
- err = snd_hda_codec_build_controls(codec);
- if (err < 0)
- goto error_module;
- /* only register after the bus probe finished; otherwise it's racy */
- if (!codec->bus->bus_probing && codec->card->registered) {
- err = snd_card_register(codec->card);
- if (err < 0)
- goto error_module;
- snd_hda_codec_register(codec);
- }
-
- codec->core.lazy_cache = true;
- return 0;
-
- error_module:
- if (codec->patch_ops.free)
- codec->patch_ops.free(codec);
- error_module_put:
- module_put(owner);
-
- error:
- snd_hda_codec_cleanup_for_unbind(codec);
- codec->preset = NULL;
- return err;
-}
-
-static int hda_codec_driver_remove(struct device *dev)
-{
- struct hda_codec *codec = dev_to_hda_codec(dev);
-
- if (codec->bus->core.ext_ops) {
- if (WARN_ON(!codec->bus->core.ext_ops->hdev_detach))
- return -EINVAL;
- return codec->bus->core.ext_ops->hdev_detach(&codec->core);
- }
-
- snd_hda_codec_disconnect_pcms(codec);
- snd_hda_jack_tbl_disconnect(codec);
- if (!refcount_dec_and_test(&codec->pcm_ref))
- wait_event(codec->remove_sleep, !refcount_read(&codec->pcm_ref));
- snd_power_sync_ref(codec->bus->card);
-
- if (codec->patch_ops.free)
- codec->patch_ops.free(codec);
- snd_hda_codec_cleanup_for_unbind(codec);
- codec->preset = NULL;
- module_put(dev->driver->owner);
- return 0;
-}
-
-static void hda_codec_driver_shutdown(struct device *dev)
-{
- snd_hda_codec_shutdown(dev_to_hda_codec(dev));
-}
-
-int __hda_codec_driver_register(struct hda_codec_driver *drv, const char *name,
- struct module *owner)
-{
- drv->core.driver.name = name;
- drv->core.driver.owner = owner;
- drv->core.driver.bus = &snd_hda_bus_type;
- drv->core.driver.probe = hda_codec_driver_probe;
- drv->core.driver.remove = hda_codec_driver_remove;
- drv->core.driver.shutdown = hda_codec_driver_shutdown;
- drv->core.driver.pm = pm_ptr(&hda_codec_driver_pm);
- drv->core.type = HDA_DEV_LEGACY;
- drv->core.match = hda_codec_match;
- drv->core.unsol_event = hda_codec_unsol_event;
- return driver_register(&drv->core.driver);
-}
-EXPORT_SYMBOL_GPL(__hda_codec_driver_register);
-
-void hda_codec_driver_unregister(struct hda_codec_driver *drv)
-{
- driver_unregister(&drv->core.driver);
-}
-EXPORT_SYMBOL_GPL(hda_codec_driver_unregister);
-
-static inline bool codec_probed(struct hda_codec *codec)
-{
- return device_attach(hda_codec_dev(codec)) > 0 && codec->preset;
-}
-
-/* try to auto-load codec module */
-static void request_codec_module(struct hda_codec *codec)
-{
-#ifdef MODULE
- char modalias[32];
- const char *mod = NULL;
-
- switch (codec->probe_id) {
- case HDA_CODEC_ID_GENERIC_HDMI:
-#if IS_MODULE(CONFIG_SND_HDA_CODEC_HDMI)
- mod = "snd-hda-codec-hdmi";
-#endif
- break;
- case HDA_CODEC_ID_GENERIC:
-#if IS_MODULE(CONFIG_SND_HDA_GENERIC)
- mod = "snd-hda-codec-generic";
-#endif
- break;
- default:
- snd_hdac_codec_modalias(&codec->core, modalias, sizeof(modalias));
- mod = modalias;
- break;
- }
-
- if (mod)
- request_module(mod);
-#endif /* MODULE */
-}
-
-/* try to auto-load and bind the codec module */
-static void codec_bind_module(struct hda_codec *codec)
-{
-#ifdef MODULE
- request_codec_module(codec);
- if (codec_probed(codec))
- return;
-#endif
-}
-
-#if IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI)
-/* if all audio out widgets are digital, let's assume the codec as a HDMI/DP */
-static bool is_likely_hdmi_codec(struct hda_codec *codec)
-{
- hda_nid_t nid;
-
- /*
- * For ASoC users, if snd_hda_hdmi_codec module is denylisted and any
- * event causes i915 enumeration to fail, ->wcaps remains uninitialized.
- */
- if (!codec->wcaps)
- return true;
-
- for_each_hda_codec_node(nid, codec) {
- unsigned int wcaps = get_wcaps(codec, nid);
- switch (get_wcaps_type(wcaps)) {
- case AC_WID_AUD_IN:
- return false; /* HDMI parser supports only HDMI out */
- case AC_WID_AUD_OUT:
- if (!(wcaps & AC_WCAP_DIGITAL))
- return false;
- break;
- }
- }
- return true;
-}
-#else
-/* no HDMI codec parser support */
-#define is_likely_hdmi_codec(codec) false
-#endif /* CONFIG_SND_HDA_CODEC_HDMI */
-
-static int codec_bind_generic(struct hda_codec *codec)
-{
- if (codec->probe_id)
- return -ENODEV;
-
- if (is_likely_hdmi_codec(codec)) {
- codec->probe_id = HDA_CODEC_ID_GENERIC_HDMI;
- request_codec_module(codec);
- if (codec_probed(codec))
- return 0;
- }
-
- codec->probe_id = HDA_CODEC_ID_GENERIC;
- request_codec_module(codec);
- if (codec_probed(codec))
- return 0;
- return -ENODEV;
-}
-
-#if IS_ENABLED(CONFIG_SND_HDA_GENERIC)
-#define is_generic_config(codec) \
- (codec->modelname && !strcmp(codec->modelname, "generic"))
-#else
-#define is_generic_config(codec) 0
-#endif
-
-/**
- * snd_hda_codec_configure - (Re-)configure the HD-audio codec
- * @codec: the HDA codec
- *
- * Start parsing of the given codec tree and (re-)initialize the whole
- * patch instance.
- *
- * Returns 0 if successful or a negative error code.
- */
-int snd_hda_codec_configure(struct hda_codec *codec)
-{
- int err;
-
- if (codec->configured)
- return 0;
-
- if (is_generic_config(codec))
- codec->probe_id = HDA_CODEC_ID_GENERIC;
- else
- codec->probe_id = 0;
-
- if (!device_is_registered(&codec->core.dev)) {
- err = snd_hdac_device_register(&codec->core);
- if (err < 0)
- return err;
- }
-
- if (!codec->preset)
- codec_bind_module(codec);
- if (!codec->preset) {
- err = codec_bind_generic(codec);
- if (err < 0) {
- codec_dbg(codec, "Unable to bind the codec\n");
- return err;
- }
- }
-
- codec->configured = 1;
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_codec_configure);
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
deleted file mode 100644
index c018beeecd3d..000000000000
--- a/sound/pci/hda/hda_codec.c
+++ /dev/null
@@ -1,4060 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Universal Interface for Intel High Definition Audio Codec
- *
- * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
- */
-
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-#include <linux/module.h>
-#include <linux/pm.h>
-#include <linux/pm_runtime.h>
-#include <sound/core.h>
-#include <sound/hda_codec.h>
-#include <sound/asoundef.h>
-#include <sound/tlv.h>
-#include <sound/initval.h>
-#include <sound/jack.h>
-#include "hda_local.h"
-#include "hda_beep.h"
-#include "hda_jack.h"
-#include <sound/hda_hwdep.h>
-#include <sound/hda_component.h>
-
-#define codec_in_pm(codec) snd_hdac_is_in_pm(&codec->core)
-#define hda_codec_is_power_on(codec) snd_hdac_is_power_on(&codec->core)
-#define codec_has_epss(codec) \
- ((codec)->core.power_caps & AC_PWRST_EPSS)
-#define codec_has_clkstop(codec) \
- ((codec)->core.power_caps & AC_PWRST_CLKSTOP)
-
-/*
- * Send and receive a verb - passed to exec_verb override for hdac_device
- */
-static int codec_exec_verb(struct hdac_device *dev, unsigned int cmd,
- unsigned int flags, unsigned int *res)
-{
- struct hda_codec *codec = container_of(dev, struct hda_codec, core);
- struct hda_bus *bus = codec->bus;
- int err;
-
- if (cmd == ~0)
- return -1;
-
- again:
- snd_hda_power_up_pm(codec);
- mutex_lock(&bus->core.cmd_mutex);
- if (flags & HDA_RW_NO_RESPONSE_FALLBACK)
- bus->no_response_fallback = 1;
- err = snd_hdac_bus_exec_verb_unlocked(&bus->core, codec->core.addr,
- cmd, res);
- bus->no_response_fallback = 0;
- mutex_unlock(&bus->core.cmd_mutex);
- snd_hda_power_down_pm(codec);
- if (!codec_in_pm(codec) && res && err == -EAGAIN) {
- if (bus->response_reset) {
- codec_dbg(codec,
- "resetting BUS due to fatal communication error\n");
- snd_hda_bus_reset(bus);
- }
- goto again;
- }
- /* clear reset-flag when the communication gets recovered */
- if (!err || codec_in_pm(codec))
- bus->response_reset = 0;
- return err;
-}
-
-/**
- * snd_hda_sequence_write - sequence writes
- * @codec: the HDA codec
- * @seq: VERB array to send
- *
- * Send the commands sequentially from the given array.
- * The array must be terminated with NID=0.
- */
-void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq)
-{
- for (; seq->nid; seq++)
- snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param);
-}
-EXPORT_SYMBOL_GPL(snd_hda_sequence_write);
-
-/* connection list element */
-struct hda_conn_list {
- struct list_head list;
- int len;
- hda_nid_t nid;
- hda_nid_t conns[] __counted_by(len);
-};
-
-/* look up the cached results */
-static struct hda_conn_list *
-lookup_conn_list(struct hda_codec *codec, hda_nid_t nid)
-{
- struct hda_conn_list *p;
- list_for_each_entry(p, &codec->conn_list, list) {
- if (p->nid == nid)
- return p;
- }
- return NULL;
-}
-
-static int add_conn_list(struct hda_codec *codec, hda_nid_t nid, int len,
- const hda_nid_t *list)
-{
- struct hda_conn_list *p;
-
- p = kmalloc(struct_size(p, conns, len), GFP_KERNEL);
- if (!p)
- return -ENOMEM;
- p->len = len;
- p->nid = nid;
- memcpy(p->conns, list, len * sizeof(hda_nid_t));
- list_add(&p->list, &codec->conn_list);
- return 0;
-}
-
-static void remove_conn_list(struct hda_codec *codec)
-{
- while (!list_empty(&codec->conn_list)) {
- struct hda_conn_list *p;
- p = list_first_entry(&codec->conn_list, typeof(*p), list);
- list_del(&p->list);
- kfree(p);
- }
-}
-
-/* read the connection and add to the cache */
-static int read_and_add_raw_conns(struct hda_codec *codec, hda_nid_t nid)
-{
- hda_nid_t list[32];
- hda_nid_t *result = list;
- int len;
-
- len = snd_hda_get_raw_connections(codec, nid, list, ARRAY_SIZE(list));
- if (len == -ENOSPC) {
- len = snd_hda_get_num_raw_conns(codec, nid);
- result = kmalloc_array(len, sizeof(hda_nid_t), GFP_KERNEL);
- if (!result)
- return -ENOMEM;
- len = snd_hda_get_raw_connections(codec, nid, result, len);
- }
- if (len >= 0)
- len = snd_hda_override_conn_list(codec, nid, len, result);
- if (result != list)
- kfree(result);
- return len;
-}
-
-/**
- * snd_hda_get_conn_list - get connection list
- * @codec: the HDA codec
- * @nid: NID to parse
- * @listp: the pointer to store NID list
- *
- * Parses the connection list of the given widget and stores the pointer
- * to the list of NIDs.
- *
- * Returns the number of connections, or a negative error code.
- *
- * Note that the returned pointer isn't protected against the list
- * modification. If snd_hda_override_conn_list() might be called
- * concurrently, protect with a mutex appropriately.
- */
-int snd_hda_get_conn_list(struct hda_codec *codec, hda_nid_t nid,
- const hda_nid_t **listp)
-{
- bool added = false;
-
- for (;;) {
- int err;
- const struct hda_conn_list *p;
-
- /* if the connection-list is already cached, read it */
- p = lookup_conn_list(codec, nid);
- if (p) {
- if (listp)
- *listp = p->conns;
- return p->len;
- }
- if (snd_BUG_ON(added))
- return -EINVAL;
-
- err = read_and_add_raw_conns(codec, nid);
- if (err < 0)
- return err;
- added = true;
- }
-}
-EXPORT_SYMBOL_GPL(snd_hda_get_conn_list);
-
-/**
- * snd_hda_get_connections - copy connection list
- * @codec: the HDA codec
- * @nid: NID to parse
- * @conn_list: connection list array; when NULL, checks only the size
- * @max_conns: max. number of connections to store
- *
- * Parses the connection list of the given widget and stores the list
- * of NIDs.
- *
- * Returns the number of connections, or a negative error code.
- */
-int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
- hda_nid_t *conn_list, int max_conns)
-{
- const hda_nid_t *list;
- int len = snd_hda_get_conn_list(codec, nid, &list);
-
- if (len > 0 && conn_list) {
- if (len > max_conns) {
- codec_err(codec, "Too many connections %d for NID 0x%x\n",
- len, nid);
- return -EINVAL;
- }
- memcpy(conn_list, list, len * sizeof(hda_nid_t));
- }
-
- return len;
-}
-EXPORT_SYMBOL_GPL(snd_hda_get_connections);
-
-/**
- * snd_hda_override_conn_list - add/modify the connection-list to cache
- * @codec: the HDA codec
- * @nid: NID to parse
- * @len: number of connection list entries
- * @list: the list of connection entries
- *
- * Add or modify the given connection-list to the cache. If the corresponding
- * cache already exists, invalidate it and append a new one.
- *
- * Returns zero or a negative error code.
- */
-int snd_hda_override_conn_list(struct hda_codec *codec, hda_nid_t nid, int len,
- const hda_nid_t *list)
-{
- struct hda_conn_list *p;
-
- p = lookup_conn_list(codec, nid);
- if (p) {
- list_del(&p->list);
- kfree(p);
- }
-
- return add_conn_list(codec, nid, len, list);
-}
-EXPORT_SYMBOL_GPL(snd_hda_override_conn_list);
-
-/**
- * snd_hda_get_conn_index - get the connection index of the given NID
- * @codec: the HDA codec
- * @mux: NID containing the list
- * @nid: NID to select
- * @recursive: 1 when searching NID recursively, otherwise 0
- *
- * Parses the connection list of the widget @mux and checks whether the
- * widget @nid is present. If it is, return the connection index.
- * Otherwise it returns -1.
- */
-int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux,
- hda_nid_t nid, int recursive)
-{
- const hda_nid_t *conn;
- int i, nums;
-
- nums = snd_hda_get_conn_list(codec, mux, &conn);
- for (i = 0; i < nums; i++)
- if (conn[i] == nid)
- return i;
- if (!recursive)
- return -1;
- if (recursive > 10) {
- codec_dbg(codec, "too deep connection for 0x%x\n", nid);
- return -1;
- }
- recursive++;
- for (i = 0; i < nums; i++) {
- unsigned int type = get_wcaps_type(get_wcaps(codec, conn[i]));
- if (type == AC_WID_PIN || type == AC_WID_AUD_OUT)
- continue;
- if (snd_hda_get_conn_index(codec, conn[i], nid, recursive) >= 0)
- return i;
- }
- return -1;
-}
-EXPORT_SYMBOL_GPL(snd_hda_get_conn_index);
-
-/**
- * snd_hda_get_num_devices - get DEVLIST_LEN parameter of the given widget
- * @codec: the HDA codec
- * @nid: NID of the pin to parse
- *
- * Get the device entry number on the given widget. This is a feature of
- * DP MST audio. Each pin can have several device entries in it.
- */
-unsigned int snd_hda_get_num_devices(struct hda_codec *codec, hda_nid_t nid)
-{
- unsigned int wcaps = get_wcaps(codec, nid);
- unsigned int parm;
-
- if (!codec->dp_mst || !(wcaps & AC_WCAP_DIGITAL) ||
- get_wcaps_type(wcaps) != AC_WID_PIN)
- return 0;
-
- parm = snd_hdac_read_parm_uncached(&codec->core, nid, AC_PAR_DEVLIST_LEN);
- if (parm == -1)
- parm = 0;
- return parm & AC_DEV_LIST_LEN_MASK;
-}
-EXPORT_SYMBOL_GPL(snd_hda_get_num_devices);
-
-/**
- * snd_hda_get_devices - copy device list without cache
- * @codec: the HDA codec
- * @nid: NID of the pin to parse
- * @dev_list: device list array
- * @max_devices: max. number of devices to store
- *
- * Copy the device list. This info is dynamic and so not cached.
- * Currently called only from hda_proc.c, so not exported.
- */
-int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid,
- u8 *dev_list, int max_devices)
-{
- unsigned int parm;
- int i, dev_len, devices;
-
- parm = snd_hda_get_num_devices(codec, nid);
- if (!parm) /* not multi-stream capable */
- return 0;
-
- dev_len = parm + 1;
- dev_len = dev_len < max_devices ? dev_len : max_devices;
-
- devices = 0;
- while (devices < dev_len) {
- if (snd_hdac_read(&codec->core, nid,
- AC_VERB_GET_DEVICE_LIST, devices, &parm))
- break; /* error */
-
- for (i = 0; i < 8; i++) {
- dev_list[devices] = (u8)parm;
- parm >>= 4;
- devices++;
- if (devices >= dev_len)
- break;
- }
- }
- return devices;
-}
-
-/**
- * snd_hda_get_dev_select - get device entry select on the pin
- * @codec: the HDA codec
- * @nid: NID of the pin to get device entry select
- *
- * Get the devcie entry select on the pin. Return the device entry
- * id selected on the pin. Return 0 means the first device entry
- * is selected or MST is not supported.
- */
-int snd_hda_get_dev_select(struct hda_codec *codec, hda_nid_t nid)
-{
- /* not support dp_mst will always return 0, using first dev_entry */
- if (!codec->dp_mst)
- return 0;
-
- return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DEVICE_SEL, 0);
-}
-EXPORT_SYMBOL_GPL(snd_hda_get_dev_select);
-
-/**
- * snd_hda_set_dev_select - set device entry select on the pin
- * @codec: the HDA codec
- * @nid: NID of the pin to set device entry select
- * @dev_id: device entry id to be set
- *
- * Set the device entry select on the pin nid.
- */
-int snd_hda_set_dev_select(struct hda_codec *codec, hda_nid_t nid, int dev_id)
-{
- int ret, num_devices;
-
- /* not support dp_mst will always return 0, using first dev_entry */
- if (!codec->dp_mst)
- return 0;
-
- /* AC_PAR_DEVLIST_LEN is 0 based. */
- num_devices = snd_hda_get_num_devices(codec, nid) + 1;
- /* If Device List Length is 0 (num_device = 1),
- * the pin is not multi stream capable.
- * Do nothing in this case.
- */
- if (num_devices == 1)
- return 0;
-
- /* Behavior of setting index being equal to or greater than
- * Device List Length is not predictable
- */
- if (num_devices <= dev_id)
- return -EINVAL;
-
- ret = snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_DEVICE_SEL, dev_id);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(snd_hda_set_dev_select);
-
-/*
- * read widget caps for each widget and store in cache
- */
-static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node)
-{
- int i;
- hda_nid_t nid;
-
- codec->wcaps = kmalloc_array(codec->core.num_nodes, 4, GFP_KERNEL);
- if (!codec->wcaps)
- return -ENOMEM;
- nid = codec->core.start_nid;
- for (i = 0; i < codec->core.num_nodes; i++, nid++)
- codec->wcaps[i] = snd_hdac_read_parm_uncached(&codec->core,
- nid, AC_PAR_AUDIO_WIDGET_CAP);
- return 0;
-}
-
-/* read all pin default configurations and save codec->init_pins */
-static int read_pin_defaults(struct hda_codec *codec)
-{
- hda_nid_t nid;
-
- for_each_hda_codec_node(nid, codec) {
- struct hda_pincfg *pin;
- unsigned int wcaps = get_wcaps(codec, nid);
- unsigned int wid_type = get_wcaps_type(wcaps);
- if (wid_type != AC_WID_PIN)
- continue;
- pin = snd_array_new(&codec->init_pins);
- if (!pin)
- return -ENOMEM;
- pin->nid = nid;
- pin->cfg = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_CONFIG_DEFAULT, 0);
- /*
- * all device entries are the same widget control so far
- * fixme: if any codec is different, need fix here
- */
- pin->ctrl = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_PIN_WIDGET_CONTROL,
- 0);
- }
- return 0;
-}
-
-/* look up the given pin config list and return the item matching with NID */
-static struct hda_pincfg *look_up_pincfg(struct hda_codec *codec,
- struct snd_array *array,
- hda_nid_t nid)
-{
- struct hda_pincfg *pin;
- int i;
-
- snd_array_for_each(array, i, pin) {
- if (pin->nid == nid)
- return pin;
- }
- return NULL;
-}
-
-/* set the current pin config value for the given NID.
- * the value is cached, and read via snd_hda_codec_get_pincfg()
- */
-int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
- hda_nid_t nid, unsigned int cfg)
-{
- struct hda_pincfg *pin;
-
- /* the check below may be invalid when pins are added by a fixup
- * dynamically (e.g. via snd_hda_codec_update_widgets()), so disabled
- * for now
- */
- /*
- if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
- return -EINVAL;
- */
-
- pin = look_up_pincfg(codec, list, nid);
- if (!pin) {
- pin = snd_array_new(list);
- if (!pin)
- return -ENOMEM;
- pin->nid = nid;
- }
- pin->cfg = cfg;
- return 0;
-}
-
-/**
- * snd_hda_codec_set_pincfg - Override a pin default configuration
- * @codec: the HDA codec
- * @nid: NID to set the pin config
- * @cfg: the pin default config value
- *
- * Override a pin default configuration value in the cache.
- * This value can be read by snd_hda_codec_get_pincfg() in a higher
- * priority than the real hardware value.
- */
-int snd_hda_codec_set_pincfg(struct hda_codec *codec,
- hda_nid_t nid, unsigned int cfg)
-{
- return snd_hda_add_pincfg(codec, &codec->driver_pins, nid, cfg);
-}
-EXPORT_SYMBOL_GPL(snd_hda_codec_set_pincfg);
-
-/**
- * snd_hda_codec_get_pincfg - Obtain a pin-default configuration
- * @codec: the HDA codec
- * @nid: NID to get the pin config
- *
- * Get the current pin config value of the given pin NID.
- * If the pincfg value is cached or overridden via sysfs or driver,
- * returns the cached value.
- */
-unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid)
-{
- struct hda_pincfg *pin;
-
-#ifdef CONFIG_SND_HDA_RECONFIG
- {
- unsigned int cfg = 0;
- mutex_lock(&codec->user_mutex);
- pin = look_up_pincfg(codec, &codec->user_pins, nid);
- if (pin)
- cfg = pin->cfg;
- mutex_unlock(&codec->user_mutex);
- if (cfg)
- return cfg;
- }
-#endif
- pin = look_up_pincfg(codec, &codec->driver_pins, nid);
- if (pin)
- return pin->cfg;
- pin = look_up_pincfg(codec, &codec->init_pins, nid);
- if (pin)
- return pin->cfg;
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_codec_get_pincfg);
-
-/**
- * snd_hda_codec_set_pin_target - remember the current pinctl target value
- * @codec: the HDA codec
- * @nid: pin NID
- * @val: assigned pinctl value
- *
- * This function stores the given value to a pinctl target value in the
- * pincfg table. This isn't always as same as the actually written value
- * but can be referred at any time via snd_hda_codec_get_pin_target().
- */
-int snd_hda_codec_set_pin_target(struct hda_codec *codec, hda_nid_t nid,
- unsigned int val)
-{
- struct hda_pincfg *pin;
-
- pin = look_up_pincfg(codec, &codec->init_pins, nid);
- if (!pin)
- return -EINVAL;
- pin->target = val;
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_codec_set_pin_target);
-
-/**
- * snd_hda_codec_get_pin_target - return the current pinctl target value
- * @codec: the HDA codec
- * @nid: pin NID
- */
-int snd_hda_codec_get_pin_target(struct hda_codec *codec, hda_nid_t nid)
-{
- struct hda_pincfg *pin;
-
- pin = look_up_pincfg(codec, &codec->init_pins, nid);
- if (!pin)
- return 0;
- return pin->target;
-}
-EXPORT_SYMBOL_GPL(snd_hda_codec_get_pin_target);
-
-/**
- * snd_hda_shutup_pins - Shut up all pins
- * @codec: the HDA codec
- *
- * Clear all pin controls to shup up before suspend for avoiding click noise.
- * The controls aren't cached so that they can be resumed properly.
- */
-void snd_hda_shutup_pins(struct hda_codec *codec)
-{
- const struct hda_pincfg *pin;
- int i;
-
- /* don't shut up pins when unloading the driver; otherwise it breaks
- * the default pin setup at the next load of the driver
- */
- if (codec->bus->shutdown)
- return;
- snd_array_for_each(&codec->init_pins, i, pin) {
- /* use read here for syncing after issuing each verb */
- snd_hda_codec_read(codec, pin->nid, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
- }
- codec->pins_shutup = 1;
-}
-EXPORT_SYMBOL_GPL(snd_hda_shutup_pins);
-
-/* Restore the pin controls cleared previously via snd_hda_shutup_pins() */
-static void restore_shutup_pins(struct hda_codec *codec)
-{
- const struct hda_pincfg *pin;
- int i;
-
- if (!codec->pins_shutup)
- return;
- if (codec->bus->shutdown)
- return;
- snd_array_for_each(&codec->init_pins, i, pin) {
- snd_hda_codec_write(codec, pin->nid, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- pin->ctrl);
- }
- codec->pins_shutup = 0;
-}
-
-static void hda_jackpoll_work(struct work_struct *work)
-{
- struct hda_codec *codec =
- container_of(work, struct hda_codec, jackpoll_work.work);
-
- /* for non-polling trigger: we need nothing if already powered on */
- if (!codec->jackpoll_interval && snd_hdac_is_power_on(&codec->core))
- return;
-
- /* the power-up/down sequence triggers the runtime resume */
- snd_hda_power_up_pm(codec);
- /* update jacks manually if polling is required, too */
- if (codec->jackpoll_interval) {
- snd_hda_jack_set_dirty_all(codec);
- snd_hda_jack_poll_all(codec);
- }
- snd_hda_power_down_pm(codec);
-
- if (!codec->jackpoll_interval)
- return;
-
- schedule_delayed_work(&codec->jackpoll_work,
- codec->jackpoll_interval);
-}
-
-/* release all pincfg lists */
-static void free_init_pincfgs(struct hda_codec *codec)
-{
- snd_array_free(&codec->driver_pins);
-#ifdef CONFIG_SND_HDA_RECONFIG
- snd_array_free(&codec->user_pins);
-#endif
- snd_array_free(&codec->init_pins);
-}
-
-/*
- * audio-converter setup caches
- */
-struct hda_cvt_setup {
- hda_nid_t nid;
- u8 stream_tag;
- u8 channel_id;
- u16 format_id;
- unsigned char active; /* cvt is currently used */
- unsigned char dirty; /* setups should be cleared */
-};
-
-/* get or create a cache entry for the given audio converter NID */
-static struct hda_cvt_setup *
-get_hda_cvt_setup(struct hda_codec *codec, hda_nid_t nid)
-{
- struct hda_cvt_setup *p;
- int i;
-
- snd_array_for_each(&codec->cvt_setups, i, p) {
- if (p->nid == nid)
- return p;
- }
- p = snd_array_new(&codec->cvt_setups);
- if (p)
- p->nid = nid;
- return p;
-}
-
-/*
- * PCM device
- */
-void snd_hda_codec_pcm_put(struct hda_pcm *pcm)
-{
- if (refcount_dec_and_test(&pcm->codec->pcm_ref))
- wake_up(&pcm->codec->remove_sleep);
-}
-EXPORT_SYMBOL_GPL(snd_hda_codec_pcm_put);
-
-struct hda_pcm *snd_hda_codec_pcm_new(struct hda_codec *codec,
- const char *fmt, ...)
-{
- struct hda_pcm *pcm;
- va_list args;
-
- pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
- if (!pcm)
- return NULL;
-
- pcm->codec = codec;
- va_start(args, fmt);
- pcm->name = kvasprintf(GFP_KERNEL, fmt, args);
- va_end(args);
- if (!pcm->name) {
- kfree(pcm);
- return NULL;
- }
-
- list_add_tail(&pcm->list, &codec->pcm_list_head);
- refcount_inc(&codec->pcm_ref);
- return pcm;
-}
-EXPORT_SYMBOL_GPL(snd_hda_codec_pcm_new);
-
-/*
- * codec destructor
- */
-void snd_hda_codec_disconnect_pcms(struct hda_codec *codec)
-{
- struct hda_pcm *pcm;
-
- list_for_each_entry(pcm, &codec->pcm_list_head, list) {
- if (pcm->disconnected)
- continue;
- if (pcm->pcm)
- snd_device_disconnect(codec->card, pcm->pcm);
- snd_hda_codec_pcm_put(pcm);
- pcm->disconnected = 1;
- }
-}
-
-static void codec_release_pcms(struct hda_codec *codec)
-{
- struct hda_pcm *pcm, *n;
-
- list_for_each_entry_safe(pcm, n, &codec->pcm_list_head, list) {
- list_del(&pcm->list);
- if (pcm->pcm)
- snd_device_free(pcm->codec->card, pcm->pcm);
- clear_bit(pcm->device, pcm->codec->bus->pcm_dev_bits);
- kfree(pcm->name);
- kfree(pcm);
- }
-}
-
-/**
- * snd_hda_codec_cleanup_for_unbind - Prepare codec for removal
- * @codec: codec device to cleanup
- */
-void snd_hda_codec_cleanup_for_unbind(struct hda_codec *codec)
-{
- if (codec->core.registered) {
- /* pm_runtime_put() is called in snd_hdac_device_exit() */
- pm_runtime_get_noresume(hda_codec_dev(codec));
- pm_runtime_disable(hda_codec_dev(codec));
- codec->core.registered = 0;
- }
-
- snd_hda_codec_disconnect_pcms(codec);
- cancel_delayed_work_sync(&codec->jackpoll_work);
- if (!codec->in_freeing)
- snd_hda_ctls_clear(codec);
- codec_release_pcms(codec);
- snd_hda_detach_beep_device(codec);
- memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
- snd_hda_jack_tbl_clear(codec);
- codec->proc_widget_hook = NULL;
- codec->spec = NULL;
-
- /* free only driver_pins so that init_pins + user_pins are restored */
- snd_array_free(&codec->driver_pins);
- snd_array_free(&codec->cvt_setups);
- snd_array_free(&codec->spdif_out);
- snd_array_free(&codec->verbs);
- codec->follower_dig_outs = NULL;
- codec->spdif_status_reset = 0;
- snd_array_free(&codec->mixers);
- snd_array_free(&codec->nids);
- remove_conn_list(codec);
- snd_hdac_regmap_exit(&codec->core);
- codec->configured = 0;
- refcount_set(&codec->pcm_ref, 1); /* reset refcount */
-}
-EXPORT_SYMBOL_GPL(snd_hda_codec_cleanup_for_unbind);
-
-static unsigned int hda_set_power_state(struct hda_codec *codec,
- unsigned int power_state);
-
-/* enable/disable display power per codec */
-void snd_hda_codec_display_power(struct hda_codec *codec, bool enable)
-{
- if (codec->display_power_control)
- snd_hdac_display_power(&codec->bus->core, codec->addr, enable);
-}
-
-/**
- * snd_hda_codec_register - Finalize codec initialization
- * @codec: codec device to register
- *
- * Also called from hda_bind.c
- */
-void snd_hda_codec_register(struct hda_codec *codec)
-{
- if (codec->core.registered)
- return;
- if (device_is_registered(hda_codec_dev(codec))) {
- snd_hda_codec_display_power(codec, true);
- pm_runtime_enable(hda_codec_dev(codec));
- /* it was powered up in snd_hda_codec_new(), now all done */
- snd_hda_power_down(codec);
- codec->core.registered = 1;
- }
-}
-EXPORT_SYMBOL_GPL(snd_hda_codec_register);
-
-static int snd_hda_codec_dev_register(struct snd_device *device)
-{
- snd_hda_codec_register(device->device_data);
- return 0;
-}
-
-/**
- * snd_hda_codec_unregister - Unregister specified codec device
- * @codec: codec device to unregister
- */
-void snd_hda_codec_unregister(struct hda_codec *codec)
-{
- codec->in_freeing = 1;
- /*
- * snd_hda_codec_device_new() is used by legacy HDA and ASoC driver.
- * We can't unregister ASoC device since it will be unregistered in
- * snd_hdac_ext_bus_device_remove().
- */
- if (codec->core.type == HDA_DEV_LEGACY)
- snd_hdac_device_unregister(&codec->core);
- snd_hda_codec_display_power(codec, false);
-
- /*
- * In the case of ASoC HD-audio bus, the device refcount is released in
- * snd_hdac_ext_bus_device_remove() explicitly.
- */
- if (codec->core.type == HDA_DEV_LEGACY)
- put_device(hda_codec_dev(codec));
-}
-EXPORT_SYMBOL_GPL(snd_hda_codec_unregister);
-
-static int snd_hda_codec_dev_free(struct snd_device *device)
-{
- snd_hda_codec_unregister(device->device_data);
- return 0;
-}
-
-static void snd_hda_codec_dev_release(struct device *dev)
-{
- struct hda_codec *codec = dev_to_hda_codec(dev);
-
- free_init_pincfgs(codec);
- snd_hdac_device_exit(&codec->core);
- snd_hda_sysfs_clear(codec);
- kfree(codec->modelname);
- kfree(codec->wcaps);
- kfree(codec);
-}
-
-#define DEV_NAME_LEN 31
-
-/**
- * snd_hda_codec_device_init - allocate HDA codec device
- * @bus: codec's parent bus
- * @codec_addr: the codec address on the parent bus
- * @fmt: format string for the device's name
- *
- * Returns newly allocated codec device or ERR_PTR() on failure.
- */
-struct hda_codec *
-snd_hda_codec_device_init(struct hda_bus *bus, unsigned int codec_addr,
- const char *fmt, ...)
-{
- va_list vargs;
- char name[DEV_NAME_LEN];
- struct hda_codec *codec;
- int err;
-
- if (snd_BUG_ON(!bus))
- return ERR_PTR(-EINVAL);
- if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS))
- return ERR_PTR(-EINVAL);
-
- codec = kzalloc(sizeof(*codec), GFP_KERNEL);
- if (!codec)
- return ERR_PTR(-ENOMEM);
-
- va_start(vargs, fmt);
- vsprintf(name, fmt, vargs);
- va_end(vargs);
-
- err = snd_hdac_device_init(&codec->core, &bus->core, name, codec_addr);
- if (err < 0) {
- kfree(codec);
- return ERR_PTR(err);
- }
-
- codec->bus = bus;
- codec->depop_delay = -1;
- codec->fixup_id = HDA_FIXUP_ID_NOT_SET;
- codec->core.dev.release = snd_hda_codec_dev_release;
- codec->core.type = HDA_DEV_LEGACY;
-
- mutex_init(&codec->spdif_mutex);
- mutex_init(&codec->control_mutex);
- snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 32);
- snd_array_init(&codec->nids, sizeof(struct hda_nid_item), 32);
- snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16);
- snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16);
- snd_array_init(&codec->cvt_setups, sizeof(struct hda_cvt_setup), 8);
- snd_array_init(&codec->spdif_out, sizeof(struct hda_spdif_out), 16);
- snd_array_init(&codec->jacktbl, sizeof(struct hda_jack_tbl), 16);
- snd_array_init(&codec->verbs, sizeof(struct hda_verb *), 8);
- INIT_LIST_HEAD(&codec->conn_list);
- INIT_LIST_HEAD(&codec->pcm_list_head);
- INIT_DELAYED_WORK(&codec->jackpoll_work, hda_jackpoll_work);
- refcount_set(&codec->pcm_ref, 1);
- init_waitqueue_head(&codec->remove_sleep);
-
- return codec;
-}
-EXPORT_SYMBOL_GPL(snd_hda_codec_device_init);
-
-/**
- * snd_hda_codec_new - create a HDA codec
- * @bus: the bus to assign
- * @card: card for this codec
- * @codec_addr: the codec address
- * @codecp: the pointer to store the generated codec
- *
- * Returns 0 if successful, or a negative error code.
- */
-int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card,
- unsigned int codec_addr, struct hda_codec **codecp)
-{
- struct hda_codec *codec;
- int ret;
-
- codec = snd_hda_codec_device_init(bus, codec_addr, "hdaudioC%dD%d",
- card->number, codec_addr);
- if (IS_ERR(codec))
- return PTR_ERR(codec);
- *codecp = codec;
-
- ret = snd_hda_codec_device_new(bus, card, codec_addr, *codecp, true);
- if (ret)
- put_device(hda_codec_dev(*codecp));
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(snd_hda_codec_new);
-
-int snd_hda_codec_device_new(struct hda_bus *bus, struct snd_card *card,
- unsigned int codec_addr, struct hda_codec *codec,
- bool snddev_managed)
-{
- char component[31];
- hda_nid_t fg;
- int err;
- static const struct snd_device_ops dev_ops = {
- .dev_register = snd_hda_codec_dev_register,
- .dev_free = snd_hda_codec_dev_free,
- };
-
- dev_dbg(card->dev, "%s: entry\n", __func__);
-
- if (snd_BUG_ON(!bus))
- return -EINVAL;
- if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS))
- return -EINVAL;
-
- codec->core.exec_verb = codec_exec_verb;
- codec->card = card;
- codec->addr = codec_addr;
-
- codec->power_jiffies = jiffies;
-
- snd_hda_sysfs_init(codec);
-
- if (codec->bus->modelname) {
- codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
- if (!codec->modelname)
- return -ENOMEM;
- }
-
- fg = codec->core.afg ? codec->core.afg : codec->core.mfg;
- err = read_widget_caps(codec, fg);
- if (err < 0)
- return err;
- err = read_pin_defaults(codec);
- if (err < 0)
- return err;
-
- /* power-up all before initialization */
- hda_set_power_state(codec, AC_PWRST_D0);
- codec->core.dev.power.power_state = PMSG_ON;
-
- snd_hda_codec_proc_new(codec);
-
- snd_hda_create_hwdep(codec);
-
- sprintf(component, "HDA:%08x,%08x,%08x", codec->core.vendor_id,
- codec->core.subsystem_id, codec->core.revision_id);
- snd_component_add(card, component);
-
- if (snddev_managed) {
- /* ASoC features component management instead */
- err = snd_device_new(card, SNDRV_DEV_CODEC, codec, &dev_ops);
- if (err < 0)
- return err;
- }
-
-#ifdef CONFIG_PM
- /* PM runtime needs to be enabled later after binding codec */
- if (codec->core.dev.power.runtime_auto)
- pm_runtime_forbid(&codec->core.dev);
- else
- /* Keep the usage_count consistent across subsequent probing */
- pm_runtime_get_noresume(&codec->core.dev);
-#endif
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_codec_device_new);
-
-/**
- * snd_hda_codec_update_widgets - Refresh widget caps and pin defaults
- * @codec: the HDA codec
- *
- * Forcibly refresh the all widget caps and the init pin configurations of
- * the given codec.
- */
-int snd_hda_codec_update_widgets(struct hda_codec *codec)
-{
- hda_nid_t fg;
- int err;
-
- err = snd_hdac_refresh_widgets(&codec->core);
- if (err < 0)
- return err;
-
- /* Assume the function group node does not change,
- * only the widget nodes may change.
- */
- kfree(codec->wcaps);
- fg = codec->core.afg ? codec->core.afg : codec->core.mfg;
- err = read_widget_caps(codec, fg);
- if (err < 0)
- return err;
-
- snd_array_free(&codec->init_pins);
- err = read_pin_defaults(codec);
-
- return err;
-}
-EXPORT_SYMBOL_GPL(snd_hda_codec_update_widgets);
-
-/* update the stream-id if changed */
-static void update_pcm_stream_id(struct hda_codec *codec,
- struct hda_cvt_setup *p, hda_nid_t nid,
- u32 stream_tag, int channel_id)
-{
- unsigned int oldval, newval;
-
- if (p->stream_tag != stream_tag || p->channel_id != channel_id) {
- oldval = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0);
- newval = (stream_tag << 4) | channel_id;
- if (oldval != newval)
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_CHANNEL_STREAMID,
- newval);
- p->stream_tag = stream_tag;
- p->channel_id = channel_id;
- }
-}
-
-/* update the format-id if changed */
-static void update_pcm_format(struct hda_codec *codec, struct hda_cvt_setup *p,
- hda_nid_t nid, int format)
-{
- unsigned int oldval;
-
- if (p->format_id != format) {
- oldval = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_STREAM_FORMAT, 0);
- if (oldval != format) {
- msleep(1);
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_STREAM_FORMAT,
- format);
- }
- p->format_id = format;
- }
-}
-
-/**
- * snd_hda_codec_setup_stream - set up the codec for streaming
- * @codec: the CODEC to set up
- * @nid: the NID to set up
- * @stream_tag: stream tag to pass, it's between 0x1 and 0xf.
- * @channel_id: channel id to pass, zero based.
- * @format: stream format.
- */
-void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
- u32 stream_tag,
- int channel_id, int format)
-{
- struct hda_codec *c;
- struct hda_cvt_setup *p;
- int type;
- int i;
-
- if (!nid)
- return;
-
- codec_dbg(codec,
- "hda_codec_setup_stream: NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
- nid, stream_tag, channel_id, format);
- p = get_hda_cvt_setup(codec, nid);
- if (!p)
- return;
-
- if (codec->patch_ops.stream_pm)
- codec->patch_ops.stream_pm(codec, nid, true);
- if (codec->pcm_format_first)
- update_pcm_format(codec, p, nid, format);
- update_pcm_stream_id(codec, p, nid, stream_tag, channel_id);
- if (!codec->pcm_format_first)
- update_pcm_format(codec, p, nid, format);
-
- p->active = 1;
- p->dirty = 0;
-
- /* make other inactive cvts with the same stream-tag dirty */
- type = get_wcaps_type(get_wcaps(codec, nid));
- list_for_each_codec(c, codec->bus) {
- snd_array_for_each(&c->cvt_setups, i, p) {
- if (!p->active && p->stream_tag == stream_tag &&
- get_wcaps_type(get_wcaps(c, p->nid)) == type)
- p->dirty = 1;
- }
- }
-}
-EXPORT_SYMBOL_GPL(snd_hda_codec_setup_stream);
-
-static void really_cleanup_stream(struct hda_codec *codec,
- struct hda_cvt_setup *q);
-
-/**
- * __snd_hda_codec_cleanup_stream - clean up the codec for closing
- * @codec: the CODEC to clean up
- * @nid: the NID to clean up
- * @do_now: really clean up the stream instead of clearing the active flag
- */
-void __snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid,
- int do_now)
-{
- struct hda_cvt_setup *p;
-
- if (!nid)
- return;
-
- if (codec->no_sticky_stream)
- do_now = 1;
-
- codec_dbg(codec, "hda_codec_cleanup_stream: NID=0x%x\n", nid);
- p = get_hda_cvt_setup(codec, nid);
- if (p) {
- /* here we just clear the active flag when do_now isn't set;
- * actual clean-ups will be done later in
- * purify_inactive_streams() called from snd_hda_codec_prpapre()
- */
- if (do_now)
- really_cleanup_stream(codec, p);
- else
- p->active = 0;
- }
-}
-EXPORT_SYMBOL_GPL(__snd_hda_codec_cleanup_stream);
-
-static void really_cleanup_stream(struct hda_codec *codec,
- struct hda_cvt_setup *q)
-{
- hda_nid_t nid = q->nid;
- if (q->stream_tag || q->channel_id)
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
- if (q->format_id)
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0
-);
- memset(q, 0, sizeof(*q));
- q->nid = nid;
- if (codec->patch_ops.stream_pm)
- codec->patch_ops.stream_pm(codec, nid, false);
-}
-
-/* clean up the all conflicting obsolete streams */
-static void purify_inactive_streams(struct hda_codec *codec)
-{
- struct hda_codec *c;
- struct hda_cvt_setup *p;
- int i;
-
- list_for_each_codec(c, codec->bus) {
- snd_array_for_each(&c->cvt_setups, i, p) {
- if (p->dirty)
- really_cleanup_stream(c, p);
- }
- }
-}
-
-/* clean up all streams; called from suspend */
-static void hda_cleanup_all_streams(struct hda_codec *codec)
-{
- struct hda_cvt_setup *p;
- int i;
-
- snd_array_for_each(&codec->cvt_setups, i, p) {
- if (p->stream_tag)
- really_cleanup_stream(codec, p);
- }
-}
-
-/*
- * amp access functions
- */
-
-/**
- * query_amp_caps - query AMP capabilities
- * @codec: the HD-auio codec
- * @nid: the NID to query
- * @direction: either #HDA_INPUT or #HDA_OUTPUT
- *
- * Query AMP capabilities for the given widget and direction.
- * Returns the obtained capability bits.
- *
- * When cap bits have been already read, this doesn't read again but
- * returns the cached value.
- */
-u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
-{
- if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD))
- nid = codec->core.afg;
- return snd_hda_param_read(codec, nid,
- direction == HDA_OUTPUT ?
- AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP);
-}
-EXPORT_SYMBOL_GPL(query_amp_caps);
-
-/**
- * snd_hda_check_amp_caps - query AMP capabilities
- * @codec: the HD-audio codec
- * @nid: the NID to query
- * @dir: either #HDA_INPUT or #HDA_OUTPUT
- * @bits: bit mask to check the result
- *
- * Check whether the widget has the given amp capability for the direction.
- */
-bool snd_hda_check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
- int dir, unsigned int bits)
-{
- if (!nid)
- return false;
- if (get_wcaps(codec, nid) & (1 << (dir + 1)))
- if (query_amp_caps(codec, nid, dir) & bits)
- return true;
- return false;
-}
-EXPORT_SYMBOL_GPL(snd_hda_check_amp_caps);
-
-/**
- * snd_hda_override_amp_caps - Override the AMP capabilities
- * @codec: the CODEC to clean up
- * @nid: the NID to clean up
- * @dir: either #HDA_INPUT or #HDA_OUTPUT
- * @caps: the capability bits to set
- *
- * Override the cached AMP caps bits value by the given one.
- * This function is useful if the driver needs to adjust the AMP ranges,
- * e.g. limit to 0dB, etc.
- *
- * Returns zero if successful or a negative error code.
- */
-int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
- unsigned int caps)
-{
- unsigned int parm;
-
- snd_hda_override_wcaps(codec, nid,
- get_wcaps(codec, nid) | AC_WCAP_AMP_OVRD);
- parm = dir == HDA_OUTPUT ? AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP;
- return snd_hdac_override_parm(&codec->core, nid, parm, caps);
-}
-EXPORT_SYMBOL_GPL(snd_hda_override_amp_caps);
-
-static unsigned int encode_amp(struct hda_codec *codec, hda_nid_t nid,
- int ch, int dir, int idx)
-{
- unsigned int cmd = snd_hdac_regmap_encode_amp(nid, ch, dir, idx);
-
- /* enable fake mute if no h/w mute but min=mute */
- if ((query_amp_caps(codec, nid, dir) &
- (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) == AC_AMPCAP_MIN_MUTE)
- cmd |= AC_AMP_FAKE_MUTE;
- return cmd;
-}
-
-/**
- * snd_hda_codec_amp_update - update the AMP mono value
- * @codec: HD-audio codec
- * @nid: NID to read the AMP value
- * @ch: channel to update (0 or 1)
- * @dir: #HDA_INPUT or #HDA_OUTPUT
- * @idx: the index value (only for input direction)
- * @mask: bit mask to set
- * @val: the bits value to set
- *
- * Update the AMP values for the given channel, direction and index.
- */
-int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid,
- int ch, int dir, int idx, int mask, int val)
-{
- unsigned int cmd = encode_amp(codec, nid, ch, dir, idx);
-
- return snd_hdac_regmap_update_raw(&codec->core, cmd, mask, val);
-}
-EXPORT_SYMBOL_GPL(snd_hda_codec_amp_update);
-
-/**
- * snd_hda_codec_amp_stereo - update the AMP stereo values
- * @codec: HD-audio codec
- * @nid: NID to read the AMP value
- * @direction: #HDA_INPUT or #HDA_OUTPUT
- * @idx: the index value (only for input direction)
- * @mask: bit mask to set
- * @val: the bits value to set
- *
- * Update the AMP values like snd_hda_codec_amp_update(), but for a
- * stereo widget with the same mask and value.
- */
-int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
- int direction, int idx, int mask, int val)
-{
- int ch, ret = 0;
-
- if (snd_BUG_ON(mask & ~0xff))
- mask &= 0xff;
- for (ch = 0; ch < 2; ch++)
- ret |= snd_hda_codec_amp_update(codec, nid, ch, direction,
- idx, mask, val);
- return ret;
-}
-EXPORT_SYMBOL_GPL(snd_hda_codec_amp_stereo);
-
-/**
- * snd_hda_codec_amp_init - initialize the AMP value
- * @codec: the HDA codec
- * @nid: NID to read the AMP value
- * @ch: channel (left=0 or right=1)
- * @dir: #HDA_INPUT or #HDA_OUTPUT
- * @idx: the index value (only for input direction)
- * @mask: bit mask to set
- * @val: the bits value to set
- *
- * Works like snd_hda_codec_amp_update() but it writes the value only at
- * the first access. If the amp was already initialized / updated beforehand,
- * this does nothing.
- */
-int snd_hda_codec_amp_init(struct hda_codec *codec, hda_nid_t nid, int ch,
- int dir, int idx, int mask, int val)
-{
- unsigned int cmd = encode_amp(codec, nid, ch, dir, idx);
-
- if (!codec->core.regmap)
- return -EINVAL;
- return snd_hdac_regmap_update_raw_once(&codec->core, cmd, mask, val);
-}
-EXPORT_SYMBOL_GPL(snd_hda_codec_amp_init);
-
-/**
- * snd_hda_codec_amp_init_stereo - initialize the stereo AMP value
- * @codec: the HDA codec
- * @nid: NID to read the AMP value
- * @dir: #HDA_INPUT or #HDA_OUTPUT
- * @idx: the index value (only for input direction)
- * @mask: bit mask to set
- * @val: the bits value to set
- *
- * Call snd_hda_codec_amp_init() for both stereo channels.
- */
-int snd_hda_codec_amp_init_stereo(struct hda_codec *codec, hda_nid_t nid,
- int dir, int idx, int mask, int val)
-{
- int ch, ret = 0;
-
- if (snd_BUG_ON(mask & ~0xff))
- mask &= 0xff;
- for (ch = 0; ch < 2; ch++)
- ret |= snd_hda_codec_amp_init(codec, nid, ch, dir,
- idx, mask, val);
- return ret;
-}
-EXPORT_SYMBOL_GPL(snd_hda_codec_amp_init_stereo);
-
-static u32 get_amp_max_value(struct hda_codec *codec, hda_nid_t nid, int dir,
- unsigned int ofs)
-{
- u32 caps = query_amp_caps(codec, nid, dir);
- /* get num steps */
- caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
- if (ofs < caps)
- caps -= ofs;
- return caps;
-}
-
-/**
- * snd_hda_mixer_amp_volume_info - Info callback for a standard AMP mixer
- * @kcontrol: referred ctl element
- * @uinfo: pointer to get/store the data
- *
- * The control element is supposed to have the private_value field
- * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
- */
-int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- u16 nid = get_amp_nid(kcontrol);
- u8 chs = get_amp_channels(kcontrol);
- int dir = get_amp_direction(kcontrol);
- unsigned int ofs = get_amp_offset(kcontrol);
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = chs == 3 ? 2 : 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = get_amp_max_value(codec, nid, dir, ofs);
- if (!uinfo->value.integer.max) {
- codec_warn(codec,
- "num_steps = 0 for NID=0x%x (ctl = %s)\n",
- nid, kcontrol->id.name);
- return -EINVAL;
- }
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_volume_info);
-
-
-static inline unsigned int
-read_amp_value(struct hda_codec *codec, hda_nid_t nid,
- int ch, int dir, int idx, unsigned int ofs)
-{
- unsigned int val;
- val = snd_hda_codec_amp_read(codec, nid, ch, dir, idx);
- val &= HDA_AMP_VOLMASK;
- if (val >= ofs)
- val -= ofs;
- else
- val = 0;
- return val;
-}
-
-static inline int
-update_amp_value(struct hda_codec *codec, hda_nid_t nid,
- int ch, int dir, int idx, unsigned int ofs,
- unsigned int val)
-{
- unsigned int maxval;
-
- if (val > 0)
- val += ofs;
- /* ofs = 0: raw max value */
- maxval = get_amp_max_value(codec, nid, dir, 0);
- if (val > maxval)
- return -EINVAL;
- return snd_hda_codec_amp_update(codec, nid, ch, dir, idx,
- HDA_AMP_VOLMASK, val);
-}
-
-/**
- * snd_hda_mixer_amp_volume_get - Get callback for a standard AMP mixer volume
- * @kcontrol: ctl element
- * @ucontrol: pointer to get/store the data
- *
- * The control element is supposed to have the private_value field
- * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
- */
-int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = get_amp_nid(kcontrol);
- int chs = get_amp_channels(kcontrol);
- int dir = get_amp_direction(kcontrol);
- int idx = get_amp_index(kcontrol);
- unsigned int ofs = get_amp_offset(kcontrol);
- long *valp = ucontrol->value.integer.value;
-
- if (chs & 1)
- *valp++ = read_amp_value(codec, nid, 0, dir, idx, ofs);
- if (chs & 2)
- *valp = read_amp_value(codec, nid, 1, dir, idx, ofs);
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_volume_get);
-
-/**
- * snd_hda_mixer_amp_volume_put - Put callback for a standard AMP mixer volume
- * @kcontrol: ctl element
- * @ucontrol: pointer to get/store the data
- *
- * The control element is supposed to have the private_value field
- * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
- */
-int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = get_amp_nid(kcontrol);
- int chs = get_amp_channels(kcontrol);
- int dir = get_amp_direction(kcontrol);
- int idx = get_amp_index(kcontrol);
- unsigned int ofs = get_amp_offset(kcontrol);
- long *valp = ucontrol->value.integer.value;
- int change = 0;
- int err;
-
- if (chs & 1) {
- err = update_amp_value(codec, nid, 0, dir, idx, ofs, *valp);
- if (err < 0)
- return err;
- change |= err;
- valp++;
- }
- if (chs & 2) {
- err = update_amp_value(codec, nid, 1, dir, idx, ofs, *valp);
- if (err < 0)
- return err;
- change |= err;
- }
- return change;
-}
-EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_volume_put);
-
-/* inquiry the amp caps and convert to TLV */
-static void get_ctl_amp_tlv(struct snd_kcontrol *kcontrol, unsigned int *tlv)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = get_amp_nid(kcontrol);
- int dir = get_amp_direction(kcontrol);
- unsigned int ofs = get_amp_offset(kcontrol);
- bool min_mute = get_amp_min_mute(kcontrol);
- u32 caps, val1, val2;
-
- caps = query_amp_caps(codec, nid, dir);
- val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
- val2 = (val2 + 1) * 25;
- val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
- val1 += ofs;
- val1 = ((int)val1) * ((int)val2);
- if (min_mute || (caps & AC_AMPCAP_MIN_MUTE))
- val2 |= TLV_DB_SCALE_MUTE;
- tlv[SNDRV_CTL_TLVO_TYPE] = SNDRV_CTL_TLVT_DB_SCALE;
- tlv[SNDRV_CTL_TLVO_LEN] = 2 * sizeof(unsigned int);
- tlv[SNDRV_CTL_TLVO_DB_SCALE_MIN] = val1;
- tlv[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP] = val2;
-}
-
-/**
- * snd_hda_mixer_amp_tlv - TLV callback for a standard AMP mixer volume
- * @kcontrol: ctl element
- * @op_flag: operation flag
- * @size: byte size of input TLV
- * @_tlv: TLV data
- *
- * The control element is supposed to have the private_value field
- * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
- */
-int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
- unsigned int size, unsigned int __user *_tlv)
-{
- unsigned int tlv[4];
-
- if (size < 4 * sizeof(unsigned int))
- return -ENOMEM;
- get_ctl_amp_tlv(kcontrol, tlv);
- if (copy_to_user(_tlv, tlv, sizeof(tlv)))
- return -EFAULT;
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_tlv);
-
-/**
- * snd_hda_set_vmaster_tlv - Set TLV for a virtual master control
- * @codec: HD-audio codec
- * @nid: NID of a reference widget
- * @dir: #HDA_INPUT or #HDA_OUTPUT
- * @tlv: TLV data to be stored, at least 4 elements
- *
- * Set (static) TLV data for a virtual master volume using the AMP caps
- * obtained from the reference NID.
- * The volume range is recalculated as if the max volume is 0dB.
- */
-void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
- unsigned int *tlv)
-{
- u32 caps;
- int nums, step;
-
- caps = query_amp_caps(codec, nid, dir);
- nums = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
- step = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
- step = (step + 1) * 25;
- tlv[SNDRV_CTL_TLVO_TYPE] = SNDRV_CTL_TLVT_DB_SCALE;
- tlv[SNDRV_CTL_TLVO_LEN] = 2 * sizeof(unsigned int);
- tlv[SNDRV_CTL_TLVO_DB_SCALE_MIN] = -nums * step;
- tlv[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP] = step;
-}
-EXPORT_SYMBOL_GPL(snd_hda_set_vmaster_tlv);
-
-/* find a mixer control element with the given name */
-static struct snd_kcontrol *
-find_mixer_ctl(struct hda_codec *codec, const char *name, int dev, int idx)
-{
- struct snd_ctl_elem_id id;
- memset(&id, 0, sizeof(id));
- id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
- id.device = dev;
- id.index = idx;
- if (snd_BUG_ON(strlen(name) >= sizeof(id.name)))
- return NULL;
- strcpy(id.name, name);
- return snd_ctl_find_id(codec->card, &id);
-}
-
-/**
- * snd_hda_find_mixer_ctl - Find a mixer control element with the given name
- * @codec: HD-audio codec
- * @name: ctl id name string
- *
- * Get the control element with the given id string and IFACE_MIXER.
- */
-struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
- const char *name)
-{
- return find_mixer_ctl(codec, name, 0, 0);
-}
-EXPORT_SYMBOL_GPL(snd_hda_find_mixer_ctl);
-
-static int find_empty_mixer_ctl_idx(struct hda_codec *codec, const char *name,
- int start_idx)
-{
- int i, idx;
- /* 16 ctlrs should be large enough */
- for (i = 0, idx = start_idx; i < 16; i++, idx++) {
- if (!find_mixer_ctl(codec, name, 0, idx))
- return idx;
- }
- return -EBUSY;
-}
-
-/**
- * snd_hda_ctl_add - Add a control element and assign to the codec
- * @codec: HD-audio codec
- * @nid: corresponding NID (optional)
- * @kctl: the control element to assign
- *
- * Add the given control element to an array inside the codec instance.
- * All control elements belonging to a codec are supposed to be added
- * by this function so that a proper clean-up works at the free or
- * reconfiguration time.
- *
- * If non-zero @nid is passed, the NID is assigned to the control element.
- * The assignment is shown in the codec proc file.
- *
- * snd_hda_ctl_add() checks the control subdev id field whether
- * #HDA_SUBDEV_NID_FLAG bit is set. If set (and @nid is zero), the lower
- * bits value is taken as the NID to assign. The #HDA_NID_ITEM_AMP bit
- * specifies if kctl->private_value is a HDA amplifier value.
- */
-int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid,
- struct snd_kcontrol *kctl)
-{
- int err;
- unsigned short flags = 0;
- struct hda_nid_item *item;
-
- if (kctl->id.subdevice & HDA_SUBDEV_AMP_FLAG) {
- flags |= HDA_NID_ITEM_AMP;
- if (nid == 0)
- nid = get_amp_nid_(kctl->private_value);
- }
- if ((kctl->id.subdevice & HDA_SUBDEV_NID_FLAG) != 0 && nid == 0)
- nid = kctl->id.subdevice & 0xffff;
- if (kctl->id.subdevice & (HDA_SUBDEV_NID_FLAG|HDA_SUBDEV_AMP_FLAG))
- kctl->id.subdevice = 0;
- err = snd_ctl_add(codec->card, kctl);
- if (err < 0)
- return err;
- item = snd_array_new(&codec->mixers);
- if (!item)
- return -ENOMEM;
- item->kctl = kctl;
- item->nid = nid;
- item->flags = flags;
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_ctl_add);
-
-/**
- * snd_hda_ctls_clear - Clear all controls assigned to the given codec
- * @codec: HD-audio codec
- */
-void snd_hda_ctls_clear(struct hda_codec *codec)
-{
- int i;
- struct hda_nid_item *items = codec->mixers.list;
-
- for (i = 0; i < codec->mixers.used; i++)
- snd_ctl_remove(codec->card, items[i].kctl);
- snd_array_free(&codec->mixers);
- snd_array_free(&codec->nids);
-}
-
-/**
- * snd_hda_lock_devices - pseudo device locking
- * @bus: the BUS
- *
- * toggle card->shutdown to allow/disallow the device access (as a hack)
- */
-int snd_hda_lock_devices(struct hda_bus *bus)
-{
- struct snd_card *card = bus->card;
- struct hda_codec *codec;
-
- spin_lock(&card->files_lock);
- if (card->shutdown)
- goto err_unlock;
- card->shutdown = 1;
- if (!list_empty(&card->ctl_files))
- goto err_clear;
-
- list_for_each_codec(codec, bus) {
- struct hda_pcm *cpcm;
- list_for_each_entry(cpcm, &codec->pcm_list_head, list) {
- if (!cpcm->pcm)
- continue;
- if (cpcm->pcm->streams[0].substream_opened ||
- cpcm->pcm->streams[1].substream_opened)
- goto err_clear;
- }
- }
- spin_unlock(&card->files_lock);
- return 0;
-
- err_clear:
- card->shutdown = 0;
- err_unlock:
- spin_unlock(&card->files_lock);
- return -EINVAL;
-}
-EXPORT_SYMBOL_GPL(snd_hda_lock_devices);
-
-/**
- * snd_hda_unlock_devices - pseudo device unlocking
- * @bus: the BUS
- */
-void snd_hda_unlock_devices(struct hda_bus *bus)
-{
- struct snd_card *card = bus->card;
-
- spin_lock(&card->files_lock);
- card->shutdown = 0;
- spin_unlock(&card->files_lock);
-}
-EXPORT_SYMBOL_GPL(snd_hda_unlock_devices);
-
-/**
- * snd_hda_codec_reset - Clear all objects assigned to the codec
- * @codec: HD-audio codec
- *
- * This frees the all PCM and control elements assigned to the codec, and
- * clears the caches and restores the pin default configurations.
- *
- * When a device is being used, it returns -EBSY. If successfully freed,
- * returns zero.
- */
-int snd_hda_codec_reset(struct hda_codec *codec)
-{
- struct hda_bus *bus = codec->bus;
-
- if (snd_hda_lock_devices(bus) < 0)
- return -EBUSY;
-
- /* OK, let it free */
- device_release_driver(hda_codec_dev(codec));
-
- /* allow device access again */
- snd_hda_unlock_devices(bus);
- return 0;
-}
-
-typedef int (*map_follower_func_t)(struct hda_codec *, void *, struct snd_kcontrol *);
-
-/* apply the function to all matching follower ctls in the mixer list */
-static int map_followers(struct hda_codec *codec, const char * const *followers,
- const char *suffix, map_follower_func_t func, void *data)
-{
- struct hda_nid_item *items;
- const char * const *s;
- int i, err;
-
- items = codec->mixers.list;
- for (i = 0; i < codec->mixers.used; i++) {
- struct snd_kcontrol *sctl = items[i].kctl;
- if (!sctl || sctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER)
- continue;
- for (s = followers; *s; s++) {
- char tmpname[sizeof(sctl->id.name)];
- const char *name = *s;
- if (suffix) {
- snprintf(tmpname, sizeof(tmpname), "%s %s",
- name, suffix);
- name = tmpname;
- }
- if (!strcmp(sctl->id.name, name)) {
- err = func(codec, data, sctl);
- if (err)
- return err;
- break;
- }
- }
- }
- return 0;
-}
-
-static int check_follower_present(struct hda_codec *codec,
- void *data, struct snd_kcontrol *sctl)
-{
- return 1;
-}
-
-/* call kctl->put with the given value(s) */
-static int put_kctl_with_value(struct snd_kcontrol *kctl, int val)
-{
- struct snd_ctl_elem_value *ucontrol;
- ucontrol = kzalloc(sizeof(*ucontrol), GFP_KERNEL);
- if (!ucontrol)
- return -ENOMEM;
- ucontrol->value.integer.value[0] = val;
- ucontrol->value.integer.value[1] = val;
- kctl->put(kctl, ucontrol);
- kfree(ucontrol);
- return 0;
-}
-
-struct follower_init_arg {
- struct hda_codec *codec;
- int step;
-};
-
-/* initialize the follower volume with 0dB via snd_ctl_apply_vmaster_followers() */
-static int init_follower_0dB(struct snd_kcontrol *follower,
- struct snd_kcontrol *kctl,
- void *_arg)
-{
- struct follower_init_arg *arg = _arg;
- int _tlv[4];
- const int *tlv = NULL;
- int step;
- int val;
-
- if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
- if (kctl->tlv.c != snd_hda_mixer_amp_tlv) {
- codec_err(arg->codec,
- "Unexpected TLV callback for follower %s:%d\n",
- kctl->id.name, kctl->id.index);
- return 0; /* ignore */
- }
- get_ctl_amp_tlv(kctl, _tlv);
- tlv = _tlv;
- } else if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_READ)
- tlv = kctl->tlv.p;
-
- if (!tlv || tlv[SNDRV_CTL_TLVO_TYPE] != SNDRV_CTL_TLVT_DB_SCALE)
- return 0;
-
- step = tlv[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP];
- step &= ~TLV_DB_SCALE_MUTE;
- if (!step)
- return 0;
- if (arg->step && arg->step != step) {
- codec_err(arg->codec,
- "Mismatching dB step for vmaster follower (%d!=%d)\n",
- arg->step, step);
- return 0;
- }
-
- arg->step = step;
- val = -tlv[SNDRV_CTL_TLVO_DB_SCALE_MIN] / step;
- if (val > 0) {
- put_kctl_with_value(follower, val);
- return val;
- }
-
- return 0;
-}
-
-/* unmute the follower via snd_ctl_apply_vmaster_followers() */
-static int init_follower_unmute(struct snd_kcontrol *follower,
- struct snd_kcontrol *kctl,
- void *_arg)
-{
- return put_kctl_with_value(follower, 1);
-}
-
-static int add_follower(struct hda_codec *codec,
- void *data, struct snd_kcontrol *follower)
-{
- return snd_ctl_add_follower(data, follower);
-}
-
-/**
- * __snd_hda_add_vmaster - create a virtual master control and add followers
- * @codec: HD-audio codec
- * @name: vmaster control name
- * @tlv: TLV data (optional)
- * @followers: follower control names (optional)
- * @suffix: suffix string to each follower name (optional)
- * @init_follower_vol: initialize followers to unmute/0dB
- * @access: kcontrol access rights
- * @ctl_ret: store the vmaster kcontrol in return
- *
- * Create a virtual master control with the given name. The TLV data
- * must be either NULL or a valid data.
- *
- * @followers is a NULL-terminated array of strings, each of which is a
- * follower control name. All controls with these names are assigned to
- * the new virtual master control.
- *
- * This function returns zero if successful or a negative error code.
- */
-int __snd_hda_add_vmaster(struct hda_codec *codec, char *name,
- unsigned int *tlv, const char * const *followers,
- const char *suffix, bool init_follower_vol,
- unsigned int access, struct snd_kcontrol **ctl_ret)
-{
- struct snd_kcontrol *kctl;
- int err;
-
- if (ctl_ret)
- *ctl_ret = NULL;
-
- err = map_followers(codec, followers, suffix, check_follower_present, NULL);
- if (err != 1) {
- codec_dbg(codec, "No follower found for %s\n", name);
- return 0;
- }
- kctl = snd_ctl_make_virtual_master(name, tlv);
- if (!kctl)
- return -ENOMEM;
- kctl->vd[0].access |= access;
- err = snd_hda_ctl_add(codec, 0, kctl);
- if (err < 0)
- return err;
-
- err = map_followers(codec, followers, suffix, add_follower, kctl);
- if (err < 0)
- return err;
-
- /* init with master mute & zero volume */
- put_kctl_with_value(kctl, 0);
- if (init_follower_vol) {
- struct follower_init_arg arg = {
- .codec = codec,
- .step = 0,
- };
- snd_ctl_apply_vmaster_followers(kctl,
- tlv ? init_follower_0dB : init_follower_unmute,
- &arg);
- }
-
- if (ctl_ret)
- *ctl_ret = kctl;
- return 0;
-}
-EXPORT_SYMBOL_GPL(__snd_hda_add_vmaster);
-
-/* meta hook to call each driver's vmaster hook */
-static void vmaster_hook(void *private_data, int enabled)
-{
- struct hda_vmaster_mute_hook *hook = private_data;
-
- hook->hook(hook->codec, enabled);
-}
-
-/**
- * snd_hda_add_vmaster_hook - Add a vmaster hw specific hook
- * @codec: the HDA codec
- * @hook: the vmaster hook object
- *
- * Add a hw specific hook (like EAPD) with the given vmaster switch kctl.
- */
-int snd_hda_add_vmaster_hook(struct hda_codec *codec,
- struct hda_vmaster_mute_hook *hook)
-{
- if (!hook->hook || !hook->sw_kctl)
- return 0;
- hook->codec = codec;
- snd_ctl_add_vmaster_hook(hook->sw_kctl, vmaster_hook, hook);
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_add_vmaster_hook);
-
-/**
- * snd_hda_sync_vmaster_hook - Sync vmaster hook
- * @hook: the vmaster hook
- *
- * Call the hook with the current value for synchronization.
- * Should be called in init callback.
- */
-void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook)
-{
- if (!hook->hook || !hook->codec)
- return;
- /* don't call vmaster hook in the destructor since it might have
- * been already destroyed
- */
- if (hook->codec->bus->shutdown)
- return;
- snd_ctl_sync_vmaster_hook(hook->sw_kctl);
-}
-EXPORT_SYMBOL_GPL(snd_hda_sync_vmaster_hook);
-
-
-/**
- * snd_hda_mixer_amp_switch_info - Info callback for a standard AMP mixer switch
- * @kcontrol: referred ctl element
- * @uinfo: pointer to get/store the data
- *
- * The control element is supposed to have the private_value field
- * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
- */
-int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- int chs = get_amp_channels(kcontrol);
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = chs == 3 ? 2 : 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_info);
-
-/**
- * snd_hda_mixer_amp_switch_get - Get callback for a standard AMP mixer switch
- * @kcontrol: ctl element
- * @ucontrol: pointer to get/store the data
- *
- * The control element is supposed to have the private_value field
- * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
- */
-int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = get_amp_nid(kcontrol);
- int chs = get_amp_channels(kcontrol);
- int dir = get_amp_direction(kcontrol);
- int idx = get_amp_index(kcontrol);
- long *valp = ucontrol->value.integer.value;
-
- if (chs & 1)
- *valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) &
- HDA_AMP_MUTE) ? 0 : 1;
- if (chs & 2)
- *valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) &
- HDA_AMP_MUTE) ? 0 : 1;
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_get);
-
-/**
- * snd_hda_mixer_amp_switch_put - Put callback for a standard AMP mixer switch
- * @kcontrol: ctl element
- * @ucontrol: pointer to get/store the data
- *
- * The control element is supposed to have the private_value field
- * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
- */
-int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = get_amp_nid(kcontrol);
- int chs = get_amp_channels(kcontrol);
- int dir = get_amp_direction(kcontrol);
- int idx = get_amp_index(kcontrol);
- long *valp = ucontrol->value.integer.value;
- int change = 0;
-
- if (chs & 1) {
- if (*valp < 0 || *valp > 1)
- return -EINVAL;
- change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
- HDA_AMP_MUTE,
- *valp ? 0 : HDA_AMP_MUTE);
- valp++;
- }
- if (chs & 2) {
- if (*valp < 0 || *valp > 1)
- return -EINVAL;
- change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
- HDA_AMP_MUTE,
- *valp ? 0 : HDA_AMP_MUTE);
- }
- hda_call_check_power_status(codec, nid);
- return change;
-}
-EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_put);
-
-/*
- * SPDIF out controls
- */
-
-static int snd_hda_spdif_mask_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
- uinfo->count = 1;
- return 0;
-}
-
-static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
- IEC958_AES0_NONAUDIO |
- IEC958_AES0_CON_EMPHASIS_5015 |
- IEC958_AES0_CON_NOT_COPYRIGHT;
- ucontrol->value.iec958.status[1] = IEC958_AES1_CON_CATEGORY |
- IEC958_AES1_CON_ORIGINAL;
- return 0;
-}
-
-static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
- IEC958_AES0_NONAUDIO |
- IEC958_AES0_PRO_EMPHASIS_5015;
- return 0;
-}
-
-static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- int idx = kcontrol->private_value;
- struct hda_spdif_out *spdif;
-
- if (WARN_ON(codec->spdif_out.used <= idx))
- return -EINVAL;
- mutex_lock(&codec->spdif_mutex);
- spdif = snd_array_elem(&codec->spdif_out, idx);
- ucontrol->value.iec958.status[0] = spdif->status & 0xff;
- ucontrol->value.iec958.status[1] = (spdif->status >> 8) & 0xff;
- ucontrol->value.iec958.status[2] = (spdif->status >> 16) & 0xff;
- ucontrol->value.iec958.status[3] = (spdif->status >> 24) & 0xff;
- mutex_unlock(&codec->spdif_mutex);
-
- return 0;
-}
-
-/* convert from SPDIF status bits to HDA SPDIF bits
- * bit 0 (DigEn) is always set zero (to be filled later)
- */
-static unsigned short convert_from_spdif_status(unsigned int sbits)
-{
- unsigned short val = 0;
-
- if (sbits & IEC958_AES0_PROFESSIONAL)
- val |= AC_DIG1_PROFESSIONAL;
- if (sbits & IEC958_AES0_NONAUDIO)
- val |= AC_DIG1_NONAUDIO;
- if (sbits & IEC958_AES0_PROFESSIONAL) {
- if ((sbits & IEC958_AES0_PRO_EMPHASIS) ==
- IEC958_AES0_PRO_EMPHASIS_5015)
- val |= AC_DIG1_EMPHASIS;
- } else {
- if ((sbits & IEC958_AES0_CON_EMPHASIS) ==
- IEC958_AES0_CON_EMPHASIS_5015)
- val |= AC_DIG1_EMPHASIS;
- if (!(sbits & IEC958_AES0_CON_NOT_COPYRIGHT))
- val |= AC_DIG1_COPYRIGHT;
- if (sbits & (IEC958_AES1_CON_ORIGINAL << 8))
- val |= AC_DIG1_LEVEL;
- val |= sbits & (IEC958_AES1_CON_CATEGORY << 8);
- }
- return val;
-}
-
-/* convert to SPDIF status bits from HDA SPDIF bits
- */
-static unsigned int convert_to_spdif_status(unsigned short val)
-{
- unsigned int sbits = 0;
-
- if (val & AC_DIG1_NONAUDIO)
- sbits |= IEC958_AES0_NONAUDIO;
- if (val & AC_DIG1_PROFESSIONAL)
- sbits |= IEC958_AES0_PROFESSIONAL;
- if (sbits & IEC958_AES0_PROFESSIONAL) {
- if (val & AC_DIG1_EMPHASIS)
- sbits |= IEC958_AES0_PRO_EMPHASIS_5015;
- } else {
- if (val & AC_DIG1_EMPHASIS)
- sbits |= IEC958_AES0_CON_EMPHASIS_5015;
- if (!(val & AC_DIG1_COPYRIGHT))
- sbits |= IEC958_AES0_CON_NOT_COPYRIGHT;
- if (val & AC_DIG1_LEVEL)
- sbits |= (IEC958_AES1_CON_ORIGINAL << 8);
- sbits |= val & (0x7f << 8);
- }
- return sbits;
-}
-
-/* set digital convert verbs both for the given NID and its followers */
-static void set_dig_out(struct hda_codec *codec, hda_nid_t nid,
- int mask, int val)
-{
- const hda_nid_t *d;
-
- snd_hdac_regmap_update(&codec->core, nid, AC_VERB_SET_DIGI_CONVERT_1,
- mask, val);
- d = codec->follower_dig_outs;
- if (!d)
- return;
- for (; *d; d++)
- snd_hdac_regmap_update(&codec->core, *d,
- AC_VERB_SET_DIGI_CONVERT_1, mask, val);
-}
-
-static inline void set_dig_out_convert(struct hda_codec *codec, hda_nid_t nid,
- int dig1, int dig2)
-{
- unsigned int mask = 0;
- unsigned int val = 0;
-
- if (dig1 != -1) {
- mask |= 0xff;
- val = dig1;
- }
- if (dig2 != -1) {
- mask |= 0xff00;
- val |= dig2 << 8;
- }
- set_dig_out(codec, nid, mask, val);
-}
-
-static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- int idx = kcontrol->private_value;
- struct hda_spdif_out *spdif;
- hda_nid_t nid;
- unsigned short val;
- int change;
-
- if (WARN_ON(codec->spdif_out.used <= idx))
- return -EINVAL;
- mutex_lock(&codec->spdif_mutex);
- spdif = snd_array_elem(&codec->spdif_out, idx);
- nid = spdif->nid;
- spdif->status = ucontrol->value.iec958.status[0] |
- ((unsigned int)ucontrol->value.iec958.status[1] << 8) |
- ((unsigned int)ucontrol->value.iec958.status[2] << 16) |
- ((unsigned int)ucontrol->value.iec958.status[3] << 24);
- val = convert_from_spdif_status(spdif->status);
- val |= spdif->ctls & 1;
- change = spdif->ctls != val;
- spdif->ctls = val;
- if (change && nid != (u16)-1)
- set_dig_out_convert(codec, nid, val & 0xff, (val >> 8) & 0xff);
- mutex_unlock(&codec->spdif_mutex);
- return change;
-}
-
-#define snd_hda_spdif_out_switch_info snd_ctl_boolean_mono_info
-
-static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- int idx = kcontrol->private_value;
- struct hda_spdif_out *spdif;
-
- if (WARN_ON(codec->spdif_out.used <= idx))
- return -EINVAL;
- mutex_lock(&codec->spdif_mutex);
- spdif = snd_array_elem(&codec->spdif_out, idx);
- ucontrol->value.integer.value[0] = spdif->ctls & AC_DIG1_ENABLE;
- mutex_unlock(&codec->spdif_mutex);
- return 0;
-}
-
-static inline void set_spdif_ctls(struct hda_codec *codec, hda_nid_t nid,
- int dig1, int dig2)
-{
- set_dig_out_convert(codec, nid, dig1, dig2);
- /* unmute amp switch (if any) */
- if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) &&
- (dig1 & AC_DIG1_ENABLE))
- snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, 0);
-}
-
-static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- int idx = kcontrol->private_value;
- struct hda_spdif_out *spdif;
- hda_nid_t nid;
- unsigned short val;
- int change;
-
- if (WARN_ON(codec->spdif_out.used <= idx))
- return -EINVAL;
- mutex_lock(&codec->spdif_mutex);
- spdif = snd_array_elem(&codec->spdif_out, idx);
- nid = spdif->nid;
- val = spdif->ctls & ~AC_DIG1_ENABLE;
- if (ucontrol->value.integer.value[0])
- val |= AC_DIG1_ENABLE;
- change = spdif->ctls != val;
- spdif->ctls = val;
- if (change && nid != (u16)-1)
- set_spdif_ctls(codec, nid, val & 0xff, -1);
- mutex_unlock(&codec->spdif_mutex);
- return change;
-}
-
-static const struct snd_kcontrol_new dig_mixes[] = {
- {
- .access = SNDRV_CTL_ELEM_ACCESS_READ,
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK),
- .info = snd_hda_spdif_mask_info,
- .get = snd_hda_spdif_cmask_get,
- },
- {
- .access = SNDRV_CTL_ELEM_ACCESS_READ,
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PRO_MASK),
- .info = snd_hda_spdif_mask_info,
- .get = snd_hda_spdif_pmask_get,
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
- .info = snd_hda_spdif_mask_info,
- .get = snd_hda_spdif_default_get,
- .put = snd_hda_spdif_default_put,
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH),
- .info = snd_hda_spdif_out_switch_info,
- .get = snd_hda_spdif_out_switch_get,
- .put = snd_hda_spdif_out_switch_put,
- },
- { } /* end */
-};
-
-/**
- * snd_hda_create_dig_out_ctls - create Output SPDIF-related controls
- * @codec: the HDA codec
- * @associated_nid: NID that new ctls associated with
- * @cvt_nid: converter NID
- * @type: HDA_PCM_TYPE_*
- * Creates controls related with the digital output.
- * Called from each patch supporting the digital out.
- *
- * Returns 0 if successful, or a negative error code.
- */
-int snd_hda_create_dig_out_ctls(struct hda_codec *codec,
- hda_nid_t associated_nid,
- hda_nid_t cvt_nid,
- int type)
-{
- int err;
- struct snd_kcontrol *kctl;
- const struct snd_kcontrol_new *dig_mix;
- int idx = 0;
- int val = 0;
- const int spdif_index = 16;
- struct hda_spdif_out *spdif;
- struct hda_bus *bus = codec->bus;
-
- if (bus->primary_dig_out_type == HDA_PCM_TYPE_HDMI &&
- type == HDA_PCM_TYPE_SPDIF) {
- idx = spdif_index;
- } else if (bus->primary_dig_out_type == HDA_PCM_TYPE_SPDIF &&
- type == HDA_PCM_TYPE_HDMI) {
- /* suppose a single SPDIF device */
- for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
- struct snd_ctl_elem_id id;
-
- kctl = find_mixer_ctl(codec, dig_mix->name, 0, 0);
- if (!kctl)
- break;
- id = kctl->id;
- id.index = spdif_index;
- err = snd_ctl_rename_id(codec->card, &kctl->id, &id);
- if (err < 0)
- return err;
- }
- bus->primary_dig_out_type = HDA_PCM_TYPE_HDMI;
- }
- if (!bus->primary_dig_out_type)
- bus->primary_dig_out_type = type;
-
- idx = find_empty_mixer_ctl_idx(codec, "IEC958 Playback Switch", idx);
- if (idx < 0) {
- codec_err(codec, "too many IEC958 outputs\n");
- return -EBUSY;
- }
- spdif = snd_array_new(&codec->spdif_out);
- if (!spdif)
- return -ENOMEM;
- for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
- kctl = snd_ctl_new1(dig_mix, codec);
- if (!kctl)
- return -ENOMEM;
- kctl->id.index = idx;
- kctl->private_value = codec->spdif_out.used - 1;
- err = snd_hda_ctl_add(codec, associated_nid, kctl);
- if (err < 0)
- return err;
- }
- spdif->nid = cvt_nid;
- snd_hdac_regmap_read(&codec->core, cvt_nid,
- AC_VERB_GET_DIGI_CONVERT_1, &val);
- spdif->ctls = val;
- spdif->status = convert_to_spdif_status(spdif->ctls);
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_create_dig_out_ctls);
-
-/**
- * snd_hda_spdif_out_of_nid - get the hda_spdif_out entry from the given NID
- * @codec: the HDA codec
- * @nid: widget NID
- *
- * call within spdif_mutex lock
- */
-struct hda_spdif_out *snd_hda_spdif_out_of_nid(struct hda_codec *codec,
- hda_nid_t nid)
-{
- struct hda_spdif_out *spdif;
- int i;
-
- snd_array_for_each(&codec->spdif_out, i, spdif) {
- if (spdif->nid == nid)
- return spdif;
- }
- return NULL;
-}
-EXPORT_SYMBOL_GPL(snd_hda_spdif_out_of_nid);
-
-/**
- * snd_hda_spdif_ctls_unassign - Unassign the given SPDIF ctl
- * @codec: the HDA codec
- * @idx: the SPDIF ctl index
- *
- * Unassign the widget from the given SPDIF control.
- */
-void snd_hda_spdif_ctls_unassign(struct hda_codec *codec, int idx)
-{
- struct hda_spdif_out *spdif;
-
- if (WARN_ON(codec->spdif_out.used <= idx))
- return;
- mutex_lock(&codec->spdif_mutex);
- spdif = snd_array_elem(&codec->spdif_out, idx);
- spdif->nid = (u16)-1;
- mutex_unlock(&codec->spdif_mutex);
-}
-EXPORT_SYMBOL_GPL(snd_hda_spdif_ctls_unassign);
-
-/**
- * snd_hda_spdif_ctls_assign - Assign the SPDIF controls to the given NID
- * @codec: the HDA codec
- * @idx: the SPDIF ctl idx
- * @nid: widget NID
- *
- * Assign the widget to the SPDIF control with the given index.
- */
-void snd_hda_spdif_ctls_assign(struct hda_codec *codec, int idx, hda_nid_t nid)
-{
- struct hda_spdif_out *spdif;
- unsigned short val;
-
- if (WARN_ON(codec->spdif_out.used <= idx))
- return;
- mutex_lock(&codec->spdif_mutex);
- spdif = snd_array_elem(&codec->spdif_out, idx);
- if (spdif->nid != nid) {
- spdif->nid = nid;
- val = spdif->ctls;
- set_spdif_ctls(codec, nid, val & 0xff, (val >> 8) & 0xff);
- }
- mutex_unlock(&codec->spdif_mutex);
-}
-EXPORT_SYMBOL_GPL(snd_hda_spdif_ctls_assign);
-
-/*
- * SPDIF sharing with analog output
- */
-static int spdif_share_sw_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
- ucontrol->value.integer.value[0] = mout->share_spdif;
- return 0;
-}
-
-static int spdif_share_sw_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
- mout->share_spdif = !!ucontrol->value.integer.value[0];
- return 0;
-}
-
-static const struct snd_kcontrol_new spdif_share_sw = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "IEC958 Default PCM Playback Switch",
- .info = snd_ctl_boolean_mono_info,
- .get = spdif_share_sw_get,
- .put = spdif_share_sw_put,
-};
-
-/**
- * snd_hda_create_spdif_share_sw - create Default PCM switch
- * @codec: the HDA codec
- * @mout: multi-out instance
- */
-int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
- struct hda_multi_out *mout)
-{
- struct snd_kcontrol *kctl;
-
- if (!mout->dig_out_nid)
- return 0;
-
- kctl = snd_ctl_new1(&spdif_share_sw, mout);
- if (!kctl)
- return -ENOMEM;
- /* ATTENTION: here mout is passed as private_data, instead of codec */
- return snd_hda_ctl_add(codec, mout->dig_out_nid, kctl);
-}
-EXPORT_SYMBOL_GPL(snd_hda_create_spdif_share_sw);
-
-/*
- * SPDIF input
- */
-
-#define snd_hda_spdif_in_switch_info snd_hda_spdif_out_switch_info
-
-static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-
- ucontrol->value.integer.value[0] = codec->spdif_in_enable;
- return 0;
-}
-
-static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = kcontrol->private_value;
- unsigned int val = !!ucontrol->value.integer.value[0];
- int change;
-
- mutex_lock(&codec->spdif_mutex);
- change = codec->spdif_in_enable != val;
- if (change) {
- codec->spdif_in_enable = val;
- snd_hdac_regmap_write(&codec->core, nid,
- AC_VERB_SET_DIGI_CONVERT_1, val);
- }
- mutex_unlock(&codec->spdif_mutex);
- return change;
-}
-
-static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = kcontrol->private_value;
- unsigned int val;
- unsigned int sbits;
-
- snd_hdac_regmap_read(&codec->core, nid,
- AC_VERB_GET_DIGI_CONVERT_1, &val);
- sbits = convert_to_spdif_status(val);
- ucontrol->value.iec958.status[0] = sbits;
- ucontrol->value.iec958.status[1] = sbits >> 8;
- ucontrol->value.iec958.status[2] = sbits >> 16;
- ucontrol->value.iec958.status[3] = sbits >> 24;
- return 0;
-}
-
-static const struct snd_kcontrol_new dig_in_ctls[] = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, SWITCH),
- .info = snd_hda_spdif_in_switch_info,
- .get = snd_hda_spdif_in_switch_get,
- .put = snd_hda_spdif_in_switch_put,
- },
- {
- .access = SNDRV_CTL_ELEM_ACCESS_READ,
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT),
- .info = snd_hda_spdif_mask_info,
- .get = snd_hda_spdif_in_status_get,
- },
- { } /* end */
-};
-
-/**
- * snd_hda_create_spdif_in_ctls - create Input SPDIF-related controls
- * @codec: the HDA codec
- * @nid: audio in widget NID
- *
- * Creates controls related with the SPDIF input.
- * Called from each patch supporting the SPDIF in.
- *
- * Returns 0 if successful, or a negative error code.
- */
-int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
-{
- int err;
- struct snd_kcontrol *kctl;
- const struct snd_kcontrol_new *dig_mix;
- int idx;
-
- idx = find_empty_mixer_ctl_idx(codec, "IEC958 Capture Switch", 0);
- if (idx < 0) {
- codec_err(codec, "too many IEC958 inputs\n");
- return -EBUSY;
- }
- for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
- kctl = snd_ctl_new1(dig_mix, codec);
- if (!kctl)
- return -ENOMEM;
- kctl->private_value = nid;
- err = snd_hda_ctl_add(codec, nid, kctl);
- if (err < 0)
- return err;
- }
- codec->spdif_in_enable =
- snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_DIGI_CONVERT_1, 0) &
- AC_DIG1_ENABLE;
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_create_spdif_in_ctls);
-
-/**
- * snd_hda_codec_set_power_to_all - Set the power state to all widgets
- * @codec: the HDA codec
- * @fg: function group (not used now)
- * @power_state: the power state to set (AC_PWRST_*)
- *
- * Set the given power state to all widgets that have the power control.
- * If the codec has power_filter set, it evaluates the power state and
- * filter out if it's unchanged as D3.
- */
-void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg,
- unsigned int power_state)
-{
- hda_nid_t nid;
-
- for_each_hda_codec_node(nid, codec) {
- unsigned int wcaps = get_wcaps(codec, nid);
- unsigned int state = power_state;
- if (!(wcaps & AC_WCAP_POWER))
- continue;
- if (codec->power_filter) {
- state = codec->power_filter(codec, nid, power_state);
- if (state != power_state && power_state == AC_PWRST_D3)
- continue;
- }
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE,
- state);
- }
-}
-EXPORT_SYMBOL_GPL(snd_hda_codec_set_power_to_all);
-
-/**
- * snd_hda_codec_eapd_power_filter - A power filter callback for EAPD
- * @codec: the HDA codec
- * @nid: widget NID
- * @power_state: power state to evalue
- *
- * Don't power down the widget if it controls eapd and EAPD_BTLENABLE is set.
- * This can be used a codec power_filter callback.
- */
-unsigned int snd_hda_codec_eapd_power_filter(struct hda_codec *codec,
- hda_nid_t nid,
- unsigned int power_state)
-{
- if (nid == codec->core.afg || nid == codec->core.mfg)
- return power_state;
- if (power_state == AC_PWRST_D3 &&
- get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_PIN &&
- (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)) {
- int eapd = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_EAPD_BTLENABLE, 0);
- if (eapd & 0x02)
- return AC_PWRST_D0;
- }
- return power_state;
-}
-EXPORT_SYMBOL_GPL(snd_hda_codec_eapd_power_filter);
-
-/*
- * set power state of the codec, and return the power state
- */
-static unsigned int hda_set_power_state(struct hda_codec *codec,
- unsigned int power_state)
-{
- hda_nid_t fg = codec->core.afg ? codec->core.afg : codec->core.mfg;
- int count;
- unsigned int state;
- int flags = 0;
-
- /* this delay seems necessary to avoid click noise at power-down */
- if (power_state == AC_PWRST_D3) {
- if (codec->depop_delay < 0)
- msleep(codec_has_epss(codec) ? 10 : 100);
- else if (codec->depop_delay > 0)
- msleep(codec->depop_delay);
- flags = HDA_RW_NO_RESPONSE_FALLBACK;
- }
-
- /* repeat power states setting at most 10 times*/
- for (count = 0; count < 10; count++) {
- if (codec->patch_ops.set_power_state)
- codec->patch_ops.set_power_state(codec, fg,
- power_state);
- else {
- state = power_state;
- if (codec->power_filter)
- state = codec->power_filter(codec, fg, state);
- if (state == power_state || power_state != AC_PWRST_D3)
- snd_hda_codec_read(codec, fg, flags,
- AC_VERB_SET_POWER_STATE,
- state);
- snd_hda_codec_set_power_to_all(codec, fg, power_state);
- }
- state = snd_hda_sync_power_state(codec, fg, power_state);
- if (!(state & AC_PWRST_ERROR))
- break;
- }
-
- return state;
-}
-
-/* sync power states of all widgets;
- * this is called at the end of codec parsing
- */
-static void sync_power_up_states(struct hda_codec *codec)
-{
- hda_nid_t nid;
-
- /* don't care if no filter is used */
- if (!codec->power_filter)
- return;
-
- for_each_hda_codec_node(nid, codec) {
- unsigned int wcaps = get_wcaps(codec, nid);
- unsigned int target;
- if (!(wcaps & AC_WCAP_POWER))
- continue;
- target = codec->power_filter(codec, nid, AC_PWRST_D0);
- if (target == AC_PWRST_D0)
- continue;
- if (!snd_hda_check_power_state(codec, nid, target))
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_POWER_STATE, target);
- }
-}
-
-#ifdef CONFIG_SND_HDA_RECONFIG
-/* execute additional init verbs */
-static void hda_exec_init_verbs(struct hda_codec *codec)
-{
- if (codec->init_verbs.list)
- snd_hda_sequence_write(codec, codec->init_verbs.list);
-}
-#else
-static inline void hda_exec_init_verbs(struct hda_codec *codec) {}
-#endif
-
-/* update the power on/off account with the current jiffies */
-static void update_power_acct(struct hda_codec *codec, bool on)
-{
- unsigned long delta = jiffies - codec->power_jiffies;
-
- if (on)
- codec->power_on_acct += delta;
- else
- codec->power_off_acct += delta;
- codec->power_jiffies += delta;
-}
-
-void snd_hda_update_power_acct(struct hda_codec *codec)
-{
- update_power_acct(codec, hda_codec_is_power_on(codec));
-}
-
-/*
- * call suspend and power-down; used both from PM and power-save
- * this function returns the power state in the end
- */
-static unsigned int hda_call_codec_suspend(struct hda_codec *codec)
-{
- unsigned int state;
-
- snd_hdac_enter_pm(&codec->core);
- if (codec->patch_ops.suspend)
- codec->patch_ops.suspend(codec);
- if (!codec->no_stream_clean_at_suspend)
- hda_cleanup_all_streams(codec);
- state = hda_set_power_state(codec, AC_PWRST_D3);
- update_power_acct(codec, true);
- snd_hdac_leave_pm(&codec->core);
- return state;
-}
-
-/*
- * kick up codec; used both from PM and power-save
- */
-static void hda_call_codec_resume(struct hda_codec *codec)
-{
- snd_hdac_enter_pm(&codec->core);
- if (codec->core.regmap)
- regcache_mark_dirty(codec->core.regmap);
-
- codec->power_jiffies = jiffies;
-
- hda_set_power_state(codec, AC_PWRST_D0);
- restore_shutup_pins(codec);
- hda_exec_init_verbs(codec);
- snd_hda_jack_set_dirty_all(codec);
- if (codec->patch_ops.resume)
- codec->patch_ops.resume(codec);
- else {
- if (codec->patch_ops.init)
- codec->patch_ops.init(codec);
- snd_hda_regmap_sync(codec);
- }
-
- if (codec->jackpoll_interval)
- hda_jackpoll_work(&codec->jackpoll_work.work);
- else
- snd_hda_jack_report_sync(codec);
- codec->core.dev.power.power_state = PMSG_ON;
- snd_hdac_leave_pm(&codec->core);
-}
-
-static int hda_codec_runtime_suspend(struct device *dev)
-{
- struct hda_codec *codec = dev_to_hda_codec(dev);
- unsigned int state;
-
- /* Nothing to do if card registration fails and the component driver never probes */
- if (!codec->card)
- return 0;
-
- cancel_delayed_work_sync(&codec->jackpoll_work);
-
- state = hda_call_codec_suspend(codec);
- if (codec->link_down_at_suspend ||
- (codec_has_clkstop(codec) && codec_has_epss(codec) &&
- (state & AC_PWRST_CLK_STOP_OK)))
- snd_hdac_codec_link_down(&codec->core);
- snd_hda_codec_display_power(codec, false);
-
- if (codec->bus->jackpoll_in_suspend &&
- (dev->power.power_state.event != PM_EVENT_SUSPEND))
- schedule_delayed_work(&codec->jackpoll_work,
- codec->jackpoll_interval);
- return 0;
-}
-
-static int hda_codec_runtime_resume(struct device *dev)
-{
- struct hda_codec *codec = dev_to_hda_codec(dev);
-
- /* Nothing to do if card registration fails and the component driver never probes */
- if (!codec->card)
- return 0;
-
- snd_hda_codec_display_power(codec, true);
- snd_hdac_codec_link_up(&codec->core);
- hda_call_codec_resume(codec);
- pm_runtime_mark_last_busy(dev);
- return 0;
-}
-
-static int hda_codec_pm_prepare(struct device *dev)
-{
- struct hda_codec *codec = dev_to_hda_codec(dev);
-
- cancel_delayed_work_sync(&codec->jackpoll_work);
- dev->power.power_state = PMSG_SUSPEND;
- return pm_runtime_suspended(dev);
-}
-
-static void hda_codec_pm_complete(struct device *dev)
-{
- struct hda_codec *codec = dev_to_hda_codec(dev);
-
- /* If no other pm-functions are called between prepare() and complete() */
- if (dev->power.power_state.event == PM_EVENT_SUSPEND)
- dev->power.power_state = PMSG_RESUME;
-
- if (pm_runtime_suspended(dev) && (codec->jackpoll_interval ||
- hda_codec_need_resume(codec) || codec->forced_resume))
- pm_request_resume(dev);
-}
-
-static int hda_codec_pm_suspend(struct device *dev)
-{
- dev->power.power_state = PMSG_SUSPEND;
- return pm_runtime_force_suspend(dev);
-}
-
-static int hda_codec_pm_resume(struct device *dev)
-{
- dev->power.power_state = PMSG_RESUME;
- return pm_runtime_force_resume(dev);
-}
-
-static int hda_codec_pm_freeze(struct device *dev)
-{
- struct hda_codec *codec = dev_to_hda_codec(dev);
-
- cancel_delayed_work_sync(&codec->jackpoll_work);
- dev->power.power_state = PMSG_FREEZE;
- return pm_runtime_force_suspend(dev);
-}
-
-static int hda_codec_pm_thaw(struct device *dev)
-{
- dev->power.power_state = PMSG_THAW;
- return pm_runtime_force_resume(dev);
-}
-
-static int hda_codec_pm_restore(struct device *dev)
-{
- dev->power.power_state = PMSG_RESTORE;
- return pm_runtime_force_resume(dev);
-}
-
-/* referred in hda_bind.c */
-const struct dev_pm_ops hda_codec_driver_pm = {
- .prepare = pm_sleep_ptr(hda_codec_pm_prepare),
- .complete = pm_sleep_ptr(hda_codec_pm_complete),
- .suspend = pm_sleep_ptr(hda_codec_pm_suspend),
- .resume = pm_sleep_ptr(hda_codec_pm_resume),
- .freeze = pm_sleep_ptr(hda_codec_pm_freeze),
- .thaw = pm_sleep_ptr(hda_codec_pm_thaw),
- .poweroff = pm_sleep_ptr(hda_codec_pm_suspend),
- .restore = pm_sleep_ptr(hda_codec_pm_restore),
- RUNTIME_PM_OPS(hda_codec_runtime_suspend, hda_codec_runtime_resume, NULL)
-};
-
-/* suspend the codec at shutdown; called from driver's shutdown callback */
-void snd_hda_codec_shutdown(struct hda_codec *codec)
-{
- struct hda_pcm *cpcm;
-
- /* Skip the shutdown if codec is not registered */
- if (!codec->core.registered)
- return;
-
- cancel_delayed_work_sync(&codec->jackpoll_work);
- list_for_each_entry(cpcm, &codec->pcm_list_head, list)
- snd_pcm_suspend_all(cpcm->pcm);
-
- pm_runtime_force_suspend(hda_codec_dev(codec));
- pm_runtime_disable(hda_codec_dev(codec));
-}
-
-/*
- * add standard channel maps if not specified
- */
-static int add_std_chmaps(struct hda_codec *codec)
-{
- struct hda_pcm *pcm;
- int str, err;
-
- list_for_each_entry(pcm, &codec->pcm_list_head, list) {
- for (str = 0; str < 2; str++) {
- struct hda_pcm_stream *hinfo = &pcm->stream[str];
- struct snd_pcm_chmap *chmap;
- const struct snd_pcm_chmap_elem *elem;
-
- if (!pcm->pcm || pcm->own_chmap || !hinfo->substreams)
- continue;
- elem = hinfo->chmap ? hinfo->chmap : snd_pcm_std_chmaps;
- err = snd_pcm_add_chmap_ctls(pcm->pcm, str, elem,
- hinfo->channels_max,
- 0, &chmap);
- if (err < 0)
- return err;
- chmap->channel_mask = SND_PCM_CHMAP_MASK_2468;
- }
- }
- return 0;
-}
-
-/* default channel maps for 2.1 speakers;
- * since HD-audio supports only stereo, odd number channels are omitted
- */
-const struct snd_pcm_chmap_elem snd_pcm_2_1_chmaps[] = {
- { .channels = 2,
- .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } },
- { .channels = 4,
- .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,
- SNDRV_CHMAP_LFE, SNDRV_CHMAP_LFE } },
- { }
-};
-EXPORT_SYMBOL_GPL(snd_pcm_2_1_chmaps);
-
-int snd_hda_codec_build_controls(struct hda_codec *codec)
-{
- int err = 0;
- hda_exec_init_verbs(codec);
- /* continue to initialize... */
- if (codec->patch_ops.init)
- err = codec->patch_ops.init(codec);
- if (!err && codec->patch_ops.build_controls)
- err = codec->patch_ops.build_controls(codec);
- if (err < 0)
- return err;
-
- /* we create chmaps here instead of build_pcms */
- err = add_std_chmaps(codec);
- if (err < 0)
- return err;
-
- if (codec->jackpoll_interval)
- hda_jackpoll_work(&codec->jackpoll_work.work);
- else
- snd_hda_jack_report_sync(codec); /* call at the last init point */
- sync_power_up_states(codec);
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_codec_build_controls);
-
-/*
- * PCM stuff
- */
-static int hda_pcm_default_open_close(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- return 0;
-}
-
-static int hda_pcm_default_prepare(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- unsigned int stream_tag,
- unsigned int format,
- struct snd_pcm_substream *substream)
-{
- snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
- return 0;
-}
-
-static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- snd_hda_codec_cleanup_stream(codec, hinfo->nid);
- return 0;
-}
-
-static int set_pcm_default_values(struct hda_codec *codec,
- struct hda_pcm_stream *info)
-{
- int err;
-
- /* query support PCM information from the given NID */
- if (info->nid && (!info->rates || !info->formats)) {
- err = snd_hda_query_supported_pcm(codec, info->nid,
- info->rates ? NULL : &info->rates,
- info->formats ? NULL : &info->formats,
- info->subformats ? NULL : &info->subformats,
- info->maxbps ? NULL : &info->maxbps);
- if (err < 0)
- return err;
- }
- if (info->ops.open == NULL)
- info->ops.open = hda_pcm_default_open_close;
- if (info->ops.close == NULL)
- info->ops.close = hda_pcm_default_open_close;
- if (info->ops.prepare == NULL) {
- if (snd_BUG_ON(!info->nid))
- return -EINVAL;
- info->ops.prepare = hda_pcm_default_prepare;
- }
- if (info->ops.cleanup == NULL) {
- if (snd_BUG_ON(!info->nid))
- return -EINVAL;
- info->ops.cleanup = hda_pcm_default_cleanup;
- }
- return 0;
-}
-
-/*
- * codec prepare/cleanup entries
- */
-/**
- * snd_hda_codec_prepare - Prepare a stream
- * @codec: the HDA codec
- * @hinfo: PCM information
- * @stream: stream tag to assign
- * @format: format id to assign
- * @substream: PCM substream to assign
- *
- * Calls the prepare callback set by the codec with the given arguments.
- * Clean up the inactive streams when successful.
- */
-int snd_hda_codec_prepare(struct hda_codec *codec,
- struct hda_pcm_stream *hinfo,
- unsigned int stream,
- unsigned int format,
- struct snd_pcm_substream *substream)
-{
- int ret;
- mutex_lock(&codec->bus->prepare_mutex);
- if (hinfo->ops.prepare)
- ret = hinfo->ops.prepare(hinfo, codec, stream, format,
- substream);
- else
- ret = -ENODEV;
- if (ret >= 0)
- purify_inactive_streams(codec);
- mutex_unlock(&codec->bus->prepare_mutex);
- return ret;
-}
-EXPORT_SYMBOL_GPL(snd_hda_codec_prepare);
-
-/**
- * snd_hda_codec_cleanup - Clean up stream resources
- * @codec: the HDA codec
- * @hinfo: PCM information
- * @substream: PCM substream
- *
- * Calls the cleanup callback set by the codec with the given arguments.
- */
-void snd_hda_codec_cleanup(struct hda_codec *codec,
- struct hda_pcm_stream *hinfo,
- struct snd_pcm_substream *substream)
-{
- mutex_lock(&codec->bus->prepare_mutex);
- if (hinfo->ops.cleanup)
- hinfo->ops.cleanup(hinfo, codec, substream);
- mutex_unlock(&codec->bus->prepare_mutex);
-}
-EXPORT_SYMBOL_GPL(snd_hda_codec_cleanup);
-
-/* global */
-const char *snd_hda_pcm_type_name[HDA_PCM_NTYPES] = {
- "Audio", "SPDIF", "HDMI", "Modem"
-};
-
-/*
- * get the empty PCM device number to assign
- */
-static int get_empty_pcm_device(struct hda_bus *bus, unsigned int type)
-{
- /* audio device indices; not linear to keep compatibility */
- /* assigned to static slots up to dev#10; if more needed, assign
- * the later slot dynamically (when CONFIG_SND_DYNAMIC_MINORS=y)
- */
- static const int audio_idx[HDA_PCM_NTYPES][5] = {
- [HDA_PCM_TYPE_AUDIO] = { 0, 2, 4, 5, -1 },
- [HDA_PCM_TYPE_SPDIF] = { 1, -1 },
- [HDA_PCM_TYPE_HDMI] = { 3, 7, 8, 9, -1 },
- [HDA_PCM_TYPE_MODEM] = { 6, -1 },
- };
- int i;
-
- if (type >= HDA_PCM_NTYPES) {
- dev_err(bus->card->dev, "Invalid PCM type %d\n", type);
- return -EINVAL;
- }
-
- for (i = 0; audio_idx[type][i] >= 0; i++) {
-#ifndef CONFIG_SND_DYNAMIC_MINORS
- if (audio_idx[type][i] >= 8)
- break;
-#endif
- if (!test_and_set_bit(audio_idx[type][i], bus->pcm_dev_bits))
- return audio_idx[type][i];
- }
-
-#ifdef CONFIG_SND_DYNAMIC_MINORS
- /* non-fixed slots starting from 10 */
- for (i = 10; i < 32; i++) {
- if (!test_and_set_bit(i, bus->pcm_dev_bits))
- return i;
- }
-#endif
-
- dev_warn(bus->card->dev, "Too many %s devices\n",
- snd_hda_pcm_type_name[type]);
-#ifndef CONFIG_SND_DYNAMIC_MINORS
- dev_warn(bus->card->dev,
- "Consider building the kernel with CONFIG_SND_DYNAMIC_MINORS=y\n");
-#endif
- return -EAGAIN;
-}
-
-/* call build_pcms ops of the given codec and set up the default parameters */
-int snd_hda_codec_parse_pcms(struct hda_codec *codec)
-{
- struct hda_pcm *cpcm;
- int err;
-
- if (!list_empty(&codec->pcm_list_head))
- return 0; /* already parsed */
-
- if (!codec->patch_ops.build_pcms)
- return 0;
-
- err = codec->patch_ops.build_pcms(codec);
- if (err < 0) {
- codec_err(codec, "cannot build PCMs for #%d (error %d)\n",
- codec->core.addr, err);
- return err;
- }
-
- list_for_each_entry(cpcm, &codec->pcm_list_head, list) {
- int stream;
-
- for_each_pcm_streams(stream) {
- struct hda_pcm_stream *info = &cpcm->stream[stream];
-
- if (!info->substreams)
- continue;
- err = set_pcm_default_values(codec, info);
- if (err < 0) {
- codec_warn(codec,
- "fail to setup default for PCM %s\n",
- cpcm->name);
- return err;
- }
- }
- }
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_codec_parse_pcms);
-
-/* assign all PCMs of the given codec */
-int snd_hda_codec_build_pcms(struct hda_codec *codec)
-{
- struct hda_bus *bus = codec->bus;
- struct hda_pcm *cpcm;
- int dev, err;
-
- err = snd_hda_codec_parse_pcms(codec);
- if (err < 0)
- return err;
-
- /* attach a new PCM streams */
- list_for_each_entry(cpcm, &codec->pcm_list_head, list) {
- if (cpcm->pcm)
- continue; /* already attached */
- if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
- continue; /* no substreams assigned */
-
- dev = get_empty_pcm_device(bus, cpcm->pcm_type);
- if (dev < 0) {
- cpcm->device = SNDRV_PCM_INVALID_DEVICE;
- continue; /* no fatal error */
- }
- cpcm->device = dev;
- err = snd_hda_attach_pcm_stream(bus, codec, cpcm);
- if (err < 0) {
- codec_err(codec,
- "cannot attach PCM stream %d for codec #%d\n",
- dev, codec->core.addr);
- continue; /* no fatal error */
- }
- }
-
- return 0;
-}
-
-/**
- * snd_hda_add_new_ctls - create controls from the array
- * @codec: the HDA codec
- * @knew: the array of struct snd_kcontrol_new
- *
- * This helper function creates and add new controls in the given array.
- * The array must be terminated with an empty entry as terminator.
- *
- * Returns 0 if successful, or a negative error code.
- */
-int snd_hda_add_new_ctls(struct hda_codec *codec,
- const struct snd_kcontrol_new *knew)
-{
- int err;
-
- for (; knew->name; knew++) {
- struct snd_kcontrol *kctl;
- int addr = 0, idx = 0;
- if (knew->iface == (__force snd_ctl_elem_iface_t)-1)
- continue; /* skip this codec private value */
- for (;;) {
- kctl = snd_ctl_new1(knew, codec);
- if (!kctl)
- return -ENOMEM;
- /* Do not use the id.device field for MIXER elements.
- * This field is for real device numbers (like PCM) but codecs
- * are hidden components from the user space view (unrelated
- * to the mixer element identification).
- */
- if (addr > 0 && codec->ctl_dev_id)
- kctl->id.device = addr;
- if (idx > 0)
- kctl->id.index = idx;
- err = snd_hda_ctl_add(codec, 0, kctl);
- if (!err)
- break;
- /* try first with another device index corresponding to
- * the codec addr; if it still fails (or it's the
- * primary codec), then try another control index
- */
- if (!addr && codec->core.addr) {
- addr = codec->core.addr;
- if (!codec->ctl_dev_id)
- idx += 10 * addr;
- } else if (!idx && !knew->index) {
- idx = find_empty_mixer_ctl_idx(codec,
- knew->name, 0);
- if (idx <= 0)
- return err;
- } else
- return err;
- }
- }
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_add_new_ctls);
-
-/**
- * snd_hda_codec_set_power_save - Configure codec's runtime PM
- * @codec: codec device to configure
- * @delay: autosuspend delay
- */
-void snd_hda_codec_set_power_save(struct hda_codec *codec, int delay)
-{
- struct device *dev = hda_codec_dev(codec);
-
- if (delay == 0 && codec->auto_runtime_pm)
- delay = 3000;
-
- if (delay > 0) {
- pm_runtime_set_autosuspend_delay(dev, delay);
- pm_runtime_use_autosuspend(dev);
- pm_runtime_allow(dev);
- if (!pm_runtime_suspended(dev))
- pm_runtime_mark_last_busy(dev);
- } else {
- pm_runtime_dont_use_autosuspend(dev);
- pm_runtime_forbid(dev);
- }
-}
-EXPORT_SYMBOL_GPL(snd_hda_codec_set_power_save);
-
-/**
- * snd_hda_set_power_save - reprogram autosuspend for the given delay
- * @bus: HD-audio bus
- * @delay: autosuspend delay in msec, 0 = off
- *
- * Synchronize the runtime PM autosuspend state from the power_save option.
- */
-void snd_hda_set_power_save(struct hda_bus *bus, int delay)
-{
- struct hda_codec *c;
-
- list_for_each_codec(c, bus)
- snd_hda_codec_set_power_save(c, delay);
-}
-EXPORT_SYMBOL_GPL(snd_hda_set_power_save);
-
-/**
- * snd_hda_check_amp_list_power - Check the amp list and update the power
- * @codec: HD-audio codec
- * @check: the object containing an AMP list and the status
- * @nid: NID to check / update
- *
- * Check whether the given NID is in the amp list. If it's in the list,
- * check the current AMP status, and update the power-status according
- * to the mute status.
- *
- * This function is supposed to be set or called from the check_power_status
- * patch ops.
- */
-int snd_hda_check_amp_list_power(struct hda_codec *codec,
- struct hda_loopback_check *check,
- hda_nid_t nid)
-{
- const struct hda_amp_list *p;
- int ch, v;
-
- if (!check->amplist)
- return 0;
- for (p = check->amplist; p->nid; p++) {
- if (p->nid == nid)
- break;
- }
- if (!p->nid)
- return 0; /* nothing changed */
-
- for (p = check->amplist; p->nid; p++) {
- for (ch = 0; ch < 2; ch++) {
- v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir,
- p->idx);
- if (!(v & HDA_AMP_MUTE) && v > 0) {
- if (!check->power_on) {
- check->power_on = 1;
- snd_hda_power_up_pm(codec);
- }
- return 1;
- }
- }
- }
- if (check->power_on) {
- check->power_on = 0;
- snd_hda_power_down_pm(codec);
- }
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_check_amp_list_power);
-
-/*
- * input MUX helper
- */
-
-/**
- * snd_hda_input_mux_info - Info callback helper for the input-mux enum
- * @imux: imux helper object
- * @uinfo: pointer to get/store the data
- */
-int snd_hda_input_mux_info(const struct hda_input_mux *imux,
- struct snd_ctl_elem_info *uinfo)
-{
- unsigned int index;
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = imux->num_items;
- if (!imux->num_items)
- return 0;
- index = uinfo->value.enumerated.item;
- if (index >= imux->num_items)
- index = imux->num_items - 1;
- strcpy(uinfo->value.enumerated.name, imux->items[index].label);
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_input_mux_info);
-
-/**
- * snd_hda_input_mux_put - Put callback helper for the input-mux enum
- * @codec: the HDA codec
- * @imux: imux helper object
- * @ucontrol: pointer to get/store the data
- * @nid: input mux NID
- * @cur_val: pointer to get/store the current imux value
- */
-int snd_hda_input_mux_put(struct hda_codec *codec,
- const struct hda_input_mux *imux,
- struct snd_ctl_elem_value *ucontrol,
- hda_nid_t nid,
- unsigned int *cur_val)
-{
- unsigned int idx;
-
- if (!imux->num_items)
- return 0;
- idx = ucontrol->value.enumerated.item[0];
- if (idx >= imux->num_items)
- idx = imux->num_items - 1;
- if (*cur_val == idx)
- return 0;
- snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
- imux->items[idx].index);
- *cur_val = idx;
- return 1;
-}
-EXPORT_SYMBOL_GPL(snd_hda_input_mux_put);
-
-
-/**
- * snd_hda_enum_helper_info - Helper for simple enum ctls
- * @kcontrol: ctl element
- * @uinfo: pointer to get/store the data
- * @num_items: number of enum items
- * @texts: enum item string array
- *
- * process kcontrol info callback of a simple string enum array
- * when @num_items is 0 or @texts is NULL, assume a boolean enum array
- */
-int snd_hda_enum_helper_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo,
- int num_items, const char * const *texts)
-{
- static const char * const texts_default[] = {
- "Disabled", "Enabled"
- };
-
- if (!texts || !num_items) {
- num_items = 2;
- texts = texts_default;
- }
-
- return snd_ctl_enum_info(uinfo, 1, num_items, texts);
-}
-EXPORT_SYMBOL_GPL(snd_hda_enum_helper_info);
-
-/*
- * Multi-channel / digital-out PCM helper functions
- */
-
-/* setup SPDIF output stream */
-static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
- unsigned int stream_tag, unsigned int format)
-{
- struct hda_spdif_out *spdif;
- unsigned int curr_fmt;
- bool reset;
-
- spdif = snd_hda_spdif_out_of_nid(codec, nid);
- /* Add sanity check to pass klockwork check.
- * This should never happen.
- */
- if (WARN_ON(spdif == NULL))
- return;
-
- curr_fmt = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_STREAM_FORMAT, 0);
- reset = codec->spdif_status_reset &&
- (spdif->ctls & AC_DIG1_ENABLE) &&
- curr_fmt != format;
-
- /* turn off SPDIF if needed; otherwise the IEC958 bits won't be
- updated */
- if (reset)
- set_dig_out_convert(codec, nid,
- spdif->ctls & ~AC_DIG1_ENABLE & 0xff,
- -1);
- snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
- if (codec->follower_dig_outs) {
- const hda_nid_t *d;
- for (d = codec->follower_dig_outs; *d; d++)
- snd_hda_codec_setup_stream(codec, *d, stream_tag, 0,
- format);
- }
- /* turn on again (if needed) */
- if (reset)
- set_dig_out_convert(codec, nid,
- spdif->ctls & 0xff, -1);
-}
-
-static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid)
-{
- snd_hda_codec_cleanup_stream(codec, nid);
- if (codec->follower_dig_outs) {
- const hda_nid_t *d;
- for (d = codec->follower_dig_outs; *d; d++)
- snd_hda_codec_cleanup_stream(codec, *d);
- }
-}
-
-/**
- * snd_hda_multi_out_dig_open - open the digital out in the exclusive mode
- * @codec: the HDA codec
- * @mout: hda_multi_out object
- */
-int snd_hda_multi_out_dig_open(struct hda_codec *codec,
- struct hda_multi_out *mout)
-{
- mutex_lock(&codec->spdif_mutex);
- if (mout->dig_out_used == HDA_DIG_ANALOG_DUP)
- /* already opened as analog dup; reset it once */
- cleanup_dig_out_stream(codec, mout->dig_out_nid);
- mout->dig_out_used = HDA_DIG_EXCLUSIVE;
- mutex_unlock(&codec->spdif_mutex);
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_multi_out_dig_open);
-
-/**
- * snd_hda_multi_out_dig_prepare - prepare the digital out stream
- * @codec: the HDA codec
- * @mout: hda_multi_out object
- * @stream_tag: stream tag to assign
- * @format: format id to assign
- * @substream: PCM substream to assign
- */
-int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
- struct hda_multi_out *mout,
- unsigned int stream_tag,
- unsigned int format,
- struct snd_pcm_substream *substream)
-{
- mutex_lock(&codec->spdif_mutex);
- setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format);
- mutex_unlock(&codec->spdif_mutex);
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_multi_out_dig_prepare);
-
-/**
- * snd_hda_multi_out_dig_cleanup - clean-up the digital out stream
- * @codec: the HDA codec
- * @mout: hda_multi_out object
- */
-int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec,
- struct hda_multi_out *mout)
-{
- mutex_lock(&codec->spdif_mutex);
- cleanup_dig_out_stream(codec, mout->dig_out_nid);
- mutex_unlock(&codec->spdif_mutex);
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_multi_out_dig_cleanup);
-
-/**
- * snd_hda_multi_out_dig_close - release the digital out stream
- * @codec: the HDA codec
- * @mout: hda_multi_out object
- */
-int snd_hda_multi_out_dig_close(struct hda_codec *codec,
- struct hda_multi_out *mout)
-{
- mutex_lock(&codec->spdif_mutex);
- mout->dig_out_used = 0;
- mutex_unlock(&codec->spdif_mutex);
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_multi_out_dig_close);
-
-/**
- * snd_hda_multi_out_analog_open - open analog outputs
- * @codec: the HDA codec
- * @mout: hda_multi_out object
- * @substream: PCM substream to assign
- * @hinfo: PCM information to assign
- *
- * Open analog outputs and set up the hw-constraints.
- * If the digital outputs can be opened as follower, open the digital
- * outputs, too.
- */
-int snd_hda_multi_out_analog_open(struct hda_codec *codec,
- struct hda_multi_out *mout,
- struct snd_pcm_substream *substream,
- struct hda_pcm_stream *hinfo)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- runtime->hw.channels_max = mout->max_channels;
- if (mout->dig_out_nid) {
- if (!mout->analog_rates) {
- mout->analog_rates = hinfo->rates;
- mout->analog_formats = hinfo->formats;
- mout->analog_maxbps = hinfo->maxbps;
- } else {
- runtime->hw.rates = mout->analog_rates;
- runtime->hw.formats = mout->analog_formats;
- hinfo->maxbps = mout->analog_maxbps;
- }
- if (!mout->spdif_rates) {
- snd_hda_query_supported_pcm(codec, mout->dig_out_nid,
- &mout->spdif_rates,
- &mout->spdif_formats,
- NULL,
- &mout->spdif_maxbps);
- }
- mutex_lock(&codec->spdif_mutex);
- if (mout->share_spdif) {
- if ((runtime->hw.rates & mout->spdif_rates) &&
- (runtime->hw.formats & mout->spdif_formats)) {
- runtime->hw.rates &= mout->spdif_rates;
- runtime->hw.formats &= mout->spdif_formats;
- if (mout->spdif_maxbps < hinfo->maxbps)
- hinfo->maxbps = mout->spdif_maxbps;
- } else {
- mout->share_spdif = 0;
- /* FIXME: need notify? */
- }
- }
- mutex_unlock(&codec->spdif_mutex);
- }
- return snd_pcm_hw_constraint_step(substream->runtime, 0,
- SNDRV_PCM_HW_PARAM_CHANNELS, 2);
-}
-EXPORT_SYMBOL_GPL(snd_hda_multi_out_analog_open);
-
-/**
- * snd_hda_multi_out_analog_prepare - Preapre the analog outputs.
- * @codec: the HDA codec
- * @mout: hda_multi_out object
- * @stream_tag: stream tag to assign
- * @format: format id to assign
- * @substream: PCM substream to assign
- *
- * Set up the i/o for analog out.
- * When the digital out is available, copy the front out to digital out, too.
- */
-int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
- struct hda_multi_out *mout,
- unsigned int stream_tag,
- unsigned int format,
- struct snd_pcm_substream *substream)
-{
- const hda_nid_t *nids = mout->dac_nids;
- int chs = substream->runtime->channels;
- struct hda_spdif_out *spdif;
- int i;
-
- mutex_lock(&codec->spdif_mutex);
- spdif = snd_hda_spdif_out_of_nid(codec, mout->dig_out_nid);
- if (mout->dig_out_nid && mout->share_spdif &&
- mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
- if (chs == 2 && spdif != NULL &&
- snd_hda_is_supported_format(codec, mout->dig_out_nid,
- format) &&
- !(spdif->status & IEC958_AES0_NONAUDIO)) {
- mout->dig_out_used = HDA_DIG_ANALOG_DUP;
- setup_dig_out_stream(codec, mout->dig_out_nid,
- stream_tag, format);
- } else {
- mout->dig_out_used = 0;
- cleanup_dig_out_stream(codec, mout->dig_out_nid);
- }
- }
- mutex_unlock(&codec->spdif_mutex);
-
- /* front */
- snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag,
- 0, format);
- if (!mout->no_share_stream &&
- mout->hp_nid && mout->hp_nid != nids[HDA_FRONT])
- /* headphone out will just decode front left/right (stereo) */
- snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag,
- 0, format);
- /* extra outputs copied from front */
- for (i = 0; i < ARRAY_SIZE(mout->hp_out_nid); i++)
- if (!mout->no_share_stream && mout->hp_out_nid[i])
- snd_hda_codec_setup_stream(codec,
- mout->hp_out_nid[i],
- stream_tag, 0, format);
-
- /* surrounds */
- for (i = 1; i < mout->num_dacs; i++) {
- if (chs >= (i + 1) * 2) /* independent out */
- snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
- i * 2, format);
- else if (!mout->no_share_stream) /* copy front */
- snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
- 0, format);
- }
-
- /* extra surrounds */
- for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++) {
- int ch = 0;
- if (!mout->extra_out_nid[i])
- break;
- if (chs >= (i + 1) * 2)
- ch = i * 2;
- else if (!mout->no_share_stream)
- break;
- snd_hda_codec_setup_stream(codec, mout->extra_out_nid[i],
- stream_tag, ch, format);
- }
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_multi_out_analog_prepare);
-
-/**
- * snd_hda_multi_out_analog_cleanup - clean up the setting for analog out
- * @codec: the HDA codec
- * @mout: hda_multi_out object
- */
-int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
- struct hda_multi_out *mout)
-{
- const hda_nid_t *nids = mout->dac_nids;
- int i;
-
- for (i = 0; i < mout->num_dacs; i++)
- snd_hda_codec_cleanup_stream(codec, nids[i]);
- if (mout->hp_nid)
- snd_hda_codec_cleanup_stream(codec, mout->hp_nid);
- for (i = 0; i < ARRAY_SIZE(mout->hp_out_nid); i++)
- if (mout->hp_out_nid[i])
- snd_hda_codec_cleanup_stream(codec,
- mout->hp_out_nid[i]);
- for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
- if (mout->extra_out_nid[i])
- snd_hda_codec_cleanup_stream(codec,
- mout->extra_out_nid[i]);
- mutex_lock(&codec->spdif_mutex);
- if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
- cleanup_dig_out_stream(codec, mout->dig_out_nid);
- mout->dig_out_used = 0;
- }
- mutex_unlock(&codec->spdif_mutex);
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_multi_out_analog_cleanup);
-
-/**
- * snd_hda_get_default_vref - Get the default (mic) VREF pin bits
- * @codec: the HDA codec
- * @pin: referred pin NID
- *
- * Guess the suitable VREF pin bits to be set as the pin-control value.
- * Note: the function doesn't set the AC_PINCTL_IN_EN bit.
- */
-unsigned int snd_hda_get_default_vref(struct hda_codec *codec, hda_nid_t pin)
-{
- unsigned int pincap;
- unsigned int oldval;
- oldval = snd_hda_codec_read(codec, pin, 0,
- AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
- pincap = snd_hda_query_pin_caps(codec, pin);
- pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
- /* Exception: if the default pin setup is vref50, we give it priority */
- if ((pincap & AC_PINCAP_VREF_80) && oldval != PIN_VREF50)
- return AC_PINCTL_VREF_80;
- else if (pincap & AC_PINCAP_VREF_50)
- return AC_PINCTL_VREF_50;
- else if (pincap & AC_PINCAP_VREF_100)
- return AC_PINCTL_VREF_100;
- else if (pincap & AC_PINCAP_VREF_GRD)
- return AC_PINCTL_VREF_GRD;
- return AC_PINCTL_VREF_HIZ;
-}
-EXPORT_SYMBOL_GPL(snd_hda_get_default_vref);
-
-/**
- * snd_hda_correct_pin_ctl - correct the pin ctl value for matching with the pin cap
- * @codec: the HDA codec
- * @pin: referred pin NID
- * @val: pin ctl value to audit
- */
-unsigned int snd_hda_correct_pin_ctl(struct hda_codec *codec,
- hda_nid_t pin, unsigned int val)
-{
- static const unsigned int cap_lists[][2] = {
- { AC_PINCTL_VREF_100, AC_PINCAP_VREF_100 },
- { AC_PINCTL_VREF_80, AC_PINCAP_VREF_80 },
- { AC_PINCTL_VREF_50, AC_PINCAP_VREF_50 },
- { AC_PINCTL_VREF_GRD, AC_PINCAP_VREF_GRD },
- };
- unsigned int cap;
-
- if (!val)
- return 0;
- cap = snd_hda_query_pin_caps(codec, pin);
- if (!cap)
- return val; /* don't know what to do... */
-
- if (val & AC_PINCTL_OUT_EN) {
- if (!(cap & AC_PINCAP_OUT))
- val &= ~(AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN);
- else if ((val & AC_PINCTL_HP_EN) && !(cap & AC_PINCAP_HP_DRV))
- val &= ~AC_PINCTL_HP_EN;
- }
-
- if (val & AC_PINCTL_IN_EN) {
- if (!(cap & AC_PINCAP_IN))
- val &= ~(AC_PINCTL_IN_EN | AC_PINCTL_VREFEN);
- else {
- unsigned int vcap, vref;
- int i;
- vcap = (cap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
- vref = val & AC_PINCTL_VREFEN;
- for (i = 0; i < ARRAY_SIZE(cap_lists); i++) {
- if (vref == cap_lists[i][0] &&
- !(vcap & cap_lists[i][1])) {
- if (i == ARRAY_SIZE(cap_lists) - 1)
- vref = AC_PINCTL_VREF_HIZ;
- else
- vref = cap_lists[i + 1][0];
- }
- }
- val &= ~AC_PINCTL_VREFEN;
- val |= vref;
- }
- }
-
- return val;
-}
-EXPORT_SYMBOL_GPL(snd_hda_correct_pin_ctl);
-
-/**
- * _snd_hda_set_pin_ctl - Helper to set pin ctl value
- * @codec: the HDA codec
- * @pin: referred pin NID
- * @val: pin control value to set
- * @cached: access over codec pinctl cache or direct write
- *
- * This function is a helper to set a pin ctl value more safely.
- * It corrects the pin ctl value via snd_hda_correct_pin_ctl(), stores the
- * value in pin target array via snd_hda_codec_set_pin_target(), then
- * actually writes the value via either snd_hda_codec_write_cache() or
- * snd_hda_codec_write() depending on @cached flag.
- */
-int _snd_hda_set_pin_ctl(struct hda_codec *codec, hda_nid_t pin,
- unsigned int val, bool cached)
-{
- val = snd_hda_correct_pin_ctl(codec, pin, val);
- snd_hda_codec_set_pin_target(codec, pin, val);
- if (cached)
- return snd_hda_codec_write_cache(codec, pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, val);
- else
- return snd_hda_codec_write(codec, pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, val);
-}
-EXPORT_SYMBOL_GPL(_snd_hda_set_pin_ctl);
-
-/**
- * snd_hda_add_imux_item - Add an item to input_mux
- * @codec: the HDA codec
- * @imux: imux helper object
- * @label: the name of imux item to assign
- * @index: index number of imux item to assign
- * @type_idx: pointer to store the resultant label index
- *
- * When the same label is used already in the existing items, the number
- * suffix is appended to the label. This label index number is stored
- * to type_idx when non-NULL pointer is given.
- */
-int snd_hda_add_imux_item(struct hda_codec *codec,
- struct hda_input_mux *imux, const char *label,
- int index, int *type_idx)
-{
- int i, label_idx = 0;
- if (imux->num_items >= HDA_MAX_NUM_INPUTS) {
- codec_err(codec, "hda_codec: Too many imux items!\n");
- return -EINVAL;
- }
- for (i = 0; i < imux->num_items; i++) {
- if (!strncmp(label, imux->items[i].label, strlen(label)))
- label_idx++;
- }
- if (type_idx)
- *type_idx = label_idx;
- if (label_idx > 0)
- snprintf(imux->items[imux->num_items].label,
- sizeof(imux->items[imux->num_items].label),
- "%s %d", label, label_idx);
- else
- strscpy(imux->items[imux->num_items].label, label,
- sizeof(imux->items[imux->num_items].label));
- imux->items[imux->num_items].index = index;
- imux->num_items++;
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_add_imux_item);
-
-/**
- * snd_hda_bus_reset_codecs - Reset the bus
- * @bus: HD-audio bus
- */
-void snd_hda_bus_reset_codecs(struct hda_bus *bus)
-{
- struct hda_codec *codec;
-
- list_for_each_codec(codec, bus) {
- /* FIXME: maybe a better way needed for forced reset */
- if (current_work() != &codec->jackpoll_work.work)
- cancel_delayed_work_sync(&codec->jackpoll_work);
- if (hda_codec_is_power_on(codec)) {
- hda_call_codec_suspend(codec);
- hda_call_codec_resume(codec);
- }
- }
-}
-
-/**
- * snd_print_pcm_bits - Print the supported PCM fmt bits to the string buffer
- * @pcm: PCM caps bits
- * @buf: the string buffer to write
- * @buflen: the max buffer length
- *
- * used by hda_proc.c and hda_eld.c
- */
-void snd_print_pcm_bits(int pcm, char *buf, int buflen)
-{
- static const unsigned int bits[] = { 8, 16, 20, 24, 32 };
- int i, j;
-
- for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++)
- if (pcm & (AC_SUPPCM_BITS_8 << i))
- j += scnprintf(buf + j, buflen - j, " %d", bits[i]);
-
- buf[j] = '\0'; /* necessary when j == 0 */
-}
-EXPORT_SYMBOL_GPL(snd_print_pcm_bits);
-
-MODULE_DESCRIPTION("HDA codec core");
-MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/hda_component.c b/sound/pci/hda/hda_component.c
deleted file mode 100644
index 71860e2d6377..000000000000
--- a/sound/pci/hda/hda_component.c
+++ /dev/null
@@ -1,212 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * HD audio Component Binding Interface
- *
- * Copyright (C) 2021, 2023 Cirrus Logic, Inc. and
- * Cirrus Logic International Semiconductor Ltd.
- */
-
-#include <linux/acpi.h>
-#include <linux/component.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <sound/hda_codec.h>
-#include "hda_component.h"
-#include "hda_local.h"
-
-#ifdef CONFIG_ACPI
-void hda_component_acpi_device_notify(struct hda_component_parent *parent,
- acpi_handle handle, u32 event, void *data)
-{
- struct hda_component *comp;
- int i;
-
- mutex_lock(&parent->mutex);
- for (i = 0; i < ARRAY_SIZE(parent->comps); i++) {
- comp = hda_component_from_index(parent, i);
- if (comp->dev && comp->acpi_notify)
- comp->acpi_notify(acpi_device_handle(comp->adev), event, comp->dev);
- }
- mutex_unlock(&parent->mutex);
-}
-EXPORT_SYMBOL_NS_GPL(hda_component_acpi_device_notify, "SND_HDA_SCODEC_COMPONENT");
-
-int hda_component_manager_bind_acpi_notifications(struct hda_codec *cdc,
- struct hda_component_parent *parent,
- acpi_notify_handler handler, void *data)
-{
- bool support_notifications = false;
- struct acpi_device *adev;
- struct hda_component *comp;
- int ret;
- int i;
-
- adev = parent->comps[0].adev;
- if (!acpi_device_handle(adev))
- return 0;
-
- for (i = 0; i < ARRAY_SIZE(parent->comps); i++) {
- comp = hda_component_from_index(parent, i);
- support_notifications = support_notifications ||
- comp->acpi_notifications_supported;
- }
-
- if (support_notifications) {
- ret = acpi_install_notify_handler(adev->handle, ACPI_DEVICE_NOTIFY,
- handler, data);
- if (ret < 0) {
- codec_warn(cdc, "Failed to install notify handler: %d\n", ret);
- return 0;
- }
-
- codec_dbg(cdc, "Notify handler installed\n");
- }
-
- return 0;
-}
-EXPORT_SYMBOL_NS_GPL(hda_component_manager_bind_acpi_notifications, "SND_HDA_SCODEC_COMPONENT");
-
-void hda_component_manager_unbind_acpi_notifications(struct hda_codec *cdc,
- struct hda_component_parent *parent,
- acpi_notify_handler handler)
-{
- struct acpi_device *adev;
- int ret;
-
- adev = parent->comps[0].adev;
- if (!acpi_device_handle(adev))
- return;
-
- ret = acpi_remove_notify_handler(adev->handle, ACPI_DEVICE_NOTIFY, handler);
- if (ret < 0)
- codec_warn(cdc, "Failed to uninstall notify handler: %d\n", ret);
-}
-EXPORT_SYMBOL_NS_GPL(hda_component_manager_unbind_acpi_notifications, "SND_HDA_SCODEC_COMPONENT");
-#endif /* ifdef CONFIG_ACPI */
-
-void hda_component_manager_playback_hook(struct hda_component_parent *parent, int action)
-{
- struct hda_component *comp;
- int i;
-
- mutex_lock(&parent->mutex);
- for (i = 0; i < ARRAY_SIZE(parent->comps); i++) {
- comp = hda_component_from_index(parent, i);
- if (comp->dev && comp->pre_playback_hook)
- comp->pre_playback_hook(comp->dev, action);
- }
- for (i = 0; i < ARRAY_SIZE(parent->comps); i++) {
- comp = hda_component_from_index(parent, i);
- if (comp->dev && comp->playback_hook)
- comp->playback_hook(comp->dev, action);
- }
- for (i = 0; i < ARRAY_SIZE(parent->comps); i++) {
- comp = hda_component_from_index(parent, i);
- if (comp->dev && comp->post_playback_hook)
- comp->post_playback_hook(comp->dev, action);
- }
- mutex_unlock(&parent->mutex);
-}
-EXPORT_SYMBOL_NS_GPL(hda_component_manager_playback_hook, "SND_HDA_SCODEC_COMPONENT");
-
-struct hda_scodec_match {
- const char *bus;
- const char *hid;
- const char *match_str;
- int index;
-};
-
-/* match the device name in a slightly relaxed manner */
-static int hda_comp_match_dev_name(struct device *dev, void *data)
-{
- struct hda_scodec_match *p = data;
- const char *d = dev_name(dev);
- int n = strlen(p->bus);
- char tmp[32];
-
- /* check the bus name */
- if (strncmp(d, p->bus, n))
- return 0;
- /* skip the bus number */
- if (isdigit(d[n]))
- n++;
- /* the rest must be exact matching */
- snprintf(tmp, sizeof(tmp), p->match_str, p->hid, p->index);
- return !strcmp(d + n, tmp);
-}
-
-int hda_component_manager_bind(struct hda_codec *cdc,
- struct hda_component_parent *parent)
-{
- int ret;
-
- /* Init shared and component specific data */
- memset(parent->comps, 0, sizeof(parent->comps));
-
- mutex_lock(&parent->mutex);
- ret = component_bind_all(hda_codec_dev(cdc), parent);
- mutex_unlock(&parent->mutex);
-
- return ret;
-}
-EXPORT_SYMBOL_NS_GPL(hda_component_manager_bind, "SND_HDA_SCODEC_COMPONENT");
-
-int hda_component_manager_init(struct hda_codec *cdc,
- struct hda_component_parent *parent, int count,
- const char *bus, const char *hid,
- const char *match_str,
- const struct component_master_ops *ops)
-{
- struct device *dev = hda_codec_dev(cdc);
- struct component_match *match = NULL;
- struct hda_scodec_match *sm;
- int ret, i;
-
- if (parent->codec) {
- codec_err(cdc, "Component binding already created (SSID: %x)\n",
- cdc->core.subsystem_id);
- return -EINVAL;
- }
- parent->codec = cdc;
-
- mutex_init(&parent->mutex);
-
- for (i = 0; i < count; i++) {
- sm = devm_kmalloc(dev, sizeof(*sm), GFP_KERNEL);
- if (!sm)
- return -ENOMEM;
-
- sm->bus = bus;
- sm->hid = hid;
- sm->match_str = match_str;
- sm->index = i;
- component_match_add(dev, &match, hda_comp_match_dev_name, sm);
- }
-
- ret = component_master_add_with_match(dev, ops, match);
- if (ret)
- codec_err(cdc, "Fail to register component aggregator %d\n", ret);
-
- return ret;
-}
-EXPORT_SYMBOL_NS_GPL(hda_component_manager_init, "SND_HDA_SCODEC_COMPONENT");
-
-void hda_component_manager_free(struct hda_component_parent *parent,
- const struct component_master_ops *ops)
-{
- struct device *dev;
-
- if (!parent->codec)
- return;
-
- dev = hda_codec_dev(parent->codec);
-
- component_master_del(dev, ops);
-
- parent->codec = NULL;
-}
-EXPORT_SYMBOL_NS_GPL(hda_component_manager_free, "SND_HDA_SCODEC_COMPONENT");
-
-MODULE_DESCRIPTION("HD Audio component binding library");
-MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
-MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/hda_component.h b/sound/pci/hda/hda_component.h
deleted file mode 100644
index 7ee37154749f..000000000000
--- a/sound/pci/hda/hda_component.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * HD audio Component Binding Interface
- *
- * Copyright (C) 2021 Cirrus Logic, Inc. and
- * Cirrus Logic International Semiconductor Ltd.
- */
-
-#ifndef __HDA_COMPONENT_H__
-#define __HDA_COMPONENT_H__
-
-#include <linux/acpi.h>
-#include <linux/component.h>
-#include <linux/mutex.h>
-#include <sound/hda_codec.h>
-
-#define HDA_MAX_COMPONENTS 4
-#define HDA_MAX_NAME_SIZE 50
-
-struct hda_component {
- struct device *dev;
- char name[HDA_MAX_NAME_SIZE];
- struct acpi_device *adev;
- bool acpi_notifications_supported;
- void (*acpi_notify)(acpi_handle handle, u32 event, struct device *dev);
- void (*pre_playback_hook)(struct device *dev, int action);
- void (*playback_hook)(struct device *dev, int action);
- void (*post_playback_hook)(struct device *dev, int action);
-};
-
-struct hda_component_parent {
- struct mutex mutex;
- struct hda_codec *codec;
- struct hda_component comps[HDA_MAX_COMPONENTS];
-};
-
-#ifdef CONFIG_ACPI
-void hda_component_acpi_device_notify(struct hda_component_parent *parent,
- acpi_handle handle, u32 event, void *data);
-int hda_component_manager_bind_acpi_notifications(struct hda_codec *cdc,
- struct hda_component_parent *parent,
- acpi_notify_handler handler, void *data);
-void hda_component_manager_unbind_acpi_notifications(struct hda_codec *cdc,
- struct hda_component_parent *parent,
- acpi_notify_handler handler);
-#else
-static inline void hda_component_acpi_device_notify(struct hda_component_parent *parent,
- acpi_handle handle,
- u32 event,
- void *data)
-{
-}
-
-static inline int hda_component_manager_bind_acpi_notifications(struct hda_codec *cdc,
- struct hda_component_parent *parent,
- acpi_notify_handler handler,
- void *data)
-
-{
- return 0;
-}
-
-static inline void hda_component_manager_unbind_acpi_notifications(struct hda_codec *cdc,
- struct hda_component_parent *parent,
- acpi_notify_handler handler)
-{
-}
-#endif /* ifdef CONFIG_ACPI */
-
-void hda_component_manager_playback_hook(struct hda_component_parent *parent, int action);
-
-int hda_component_manager_init(struct hda_codec *cdc,
- struct hda_component_parent *parent, int count,
- const char *bus, const char *hid,
- const char *match_str,
- const struct component_master_ops *ops);
-
-void hda_component_manager_free(struct hda_component_parent *parent,
- const struct component_master_ops *ops);
-
-int hda_component_manager_bind(struct hda_codec *cdc, struct hda_component_parent *parent);
-
-static inline struct hda_component *hda_component_from_index(struct hda_component_parent *parent,
- int index)
-{
- if (!parent)
- return NULL;
-
- if (index < 0 || index >= ARRAY_SIZE(parent->comps))
- return NULL;
-
- return &parent->comps[index];
-}
-
-static inline void hda_component_manager_unbind(struct hda_codec *cdc,
- struct hda_component_parent *parent)
-{
- mutex_lock(&parent->mutex);
- component_unbind_all(hda_codec_dev(cdc), parent);
- mutex_unlock(&parent->mutex);
-}
-
-#endif /* ifndef __HDA_COMPONENT_H__ */
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c
deleted file mode 100644
index f3330b7e0fcf..000000000000
--- a/sound/pci/hda/hda_controller.c
+++ /dev/null
@@ -1,1336 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- *
- * Implementation of primary alsa driver code base for Intel HD Audio.
- *
- * Copyright(c) 2004 Intel Corporation
- *
- * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
- * PeiSen Hou <pshou@realtek.com.tw>
- */
-
-#include <linux/clocksource.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pm_runtime.h>
-#include <linux/slab.h>
-
-#ifdef CONFIG_X86
-/* for art-tsc conversion */
-#include <asm/tsc.h>
-#endif
-
-#include <sound/core.h>
-#include <sound/initval.h>
-#include <sound/pcm_params.h>
-#include "hda_controller.h"
-#include "hda_local.h"
-
-#define CREATE_TRACE_POINTS
-#include "hda_controller_trace.h"
-
-/* DSP lock helpers */
-#define dsp_lock(dev) snd_hdac_dsp_lock(azx_stream(dev))
-#define dsp_unlock(dev) snd_hdac_dsp_unlock(azx_stream(dev))
-#define dsp_is_locked(dev) snd_hdac_stream_is_locked(azx_stream(dev))
-
-/* assign a stream for the PCM */
-static inline struct azx_dev *
-azx_assign_device(struct azx *chip, struct snd_pcm_substream *substream)
-{
- struct hdac_stream *s;
-
- s = snd_hdac_stream_assign(azx_bus(chip), substream);
- if (!s)
- return NULL;
- return stream_to_azx_dev(s);
-}
-
-/* release the assigned stream */
-static inline void azx_release_device(struct azx_dev *azx_dev)
-{
- snd_hdac_stream_release(azx_stream(azx_dev));
-}
-
-static inline struct hda_pcm_stream *
-to_hda_pcm_stream(struct snd_pcm_substream *substream)
-{
- struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
- return &apcm->info->stream[substream->stream];
-}
-
-static u64 azx_adjust_codec_delay(struct snd_pcm_substream *substream,
- u64 nsec)
-{
- struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
- struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream);
- u64 codec_frames, codec_nsecs;
-
- if (!hinfo->ops.get_delay)
- return nsec;
-
- codec_frames = hinfo->ops.get_delay(hinfo, apcm->codec, substream);
- codec_nsecs = div_u64(codec_frames * 1000000000LL,
- substream->runtime->rate);
-
- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
- return nsec + codec_nsecs;
-
- return (nsec > codec_nsecs) ? nsec - codec_nsecs : 0;
-}
-
-/*
- * PCM ops
- */
-
-static int azx_pcm_close(struct snd_pcm_substream *substream)
-{
- struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
- struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream);
- struct azx *chip = apcm->chip;
- struct azx_dev *azx_dev = get_azx_dev(substream);
-
- trace_azx_pcm_close(chip, azx_dev);
- mutex_lock(&chip->open_mutex);
- azx_release_device(azx_dev);
- if (hinfo->ops.close)
- hinfo->ops.close(hinfo, apcm->codec, substream);
- snd_hda_power_down(apcm->codec);
- mutex_unlock(&chip->open_mutex);
- snd_hda_codec_pcm_put(apcm->info);
- return 0;
-}
-
-static int azx_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *hw_params)
-{
- struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
- struct azx *chip = apcm->chip;
- struct azx_dev *azx_dev = get_azx_dev(substream);
- struct hdac_stream *hdas = azx_stream(azx_dev);
- int ret = 0;
-
- trace_azx_pcm_hw_params(chip, azx_dev);
- dsp_lock(azx_dev);
- if (dsp_is_locked(azx_dev)) {
- ret = -EBUSY;
- goto unlock;
- }
-
- /* Set up BDLEs here, return -ENOMEM if too many BDLEs are required */
- hdas->bufsize = params_buffer_bytes(hw_params);
- hdas->period_bytes = params_period_bytes(hw_params);
- hdas->format_val = 0;
- hdas->no_period_wakeup =
- (hw_params->info & SNDRV_PCM_INFO_NO_PERIOD_WAKEUP) &&
- (hw_params->flags & SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP);
- if (snd_hdac_stream_setup_periods(hdas) < 0)
- ret = -ENOMEM;
-
-unlock:
- dsp_unlock(azx_dev);
- return ret;
-}
-
-static int azx_pcm_hw_free(struct snd_pcm_substream *substream)
-{
- struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
- struct azx_dev *azx_dev = get_azx_dev(substream);
- struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream);
-
- /* reset BDL address */
- dsp_lock(azx_dev);
- if (!dsp_is_locked(azx_dev))
- snd_hdac_stream_cleanup(azx_stream(azx_dev));
-
- snd_hda_codec_cleanup(apcm->codec, hinfo, substream);
-
- azx_stream(azx_dev)->prepared = 0;
- dsp_unlock(azx_dev);
- return 0;
-}
-
-static int azx_pcm_prepare(struct snd_pcm_substream *substream)
-{
- struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
- struct azx *chip = apcm->chip;
- struct azx_dev *azx_dev = get_azx_dev(substream);
- struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream);
- struct snd_pcm_runtime *runtime = substream->runtime;
- unsigned int format_val, stream_tag, bits;
- int err;
- struct hda_spdif_out *spdif =
- snd_hda_spdif_out_of_nid(apcm->codec, hinfo->nid);
- unsigned short ctls = spdif ? spdif->ctls : 0;
-
- trace_azx_pcm_prepare(chip, azx_dev);
- dsp_lock(azx_dev);
- if (dsp_is_locked(azx_dev)) {
- err = -EBUSY;
- goto unlock;
- }
-
- snd_hdac_stream_reset(azx_stream(azx_dev));
- bits = snd_hdac_stream_format_bits(runtime->format, SNDRV_PCM_SUBFORMAT_STD, hinfo->maxbps);
-
- format_val = snd_hdac_spdif_stream_format(runtime->channels, bits, runtime->rate, ctls);
- if (!format_val) {
- dev_err(chip->card->dev,
- "invalid format_val, rate=%d, ch=%d, format=%d\n",
- runtime->rate, runtime->channels, runtime->format);
- err = -EINVAL;
- goto unlock;
- }
-
- err = snd_hdac_stream_set_params(azx_stream(azx_dev), format_val);
- if (err < 0)
- goto unlock;
-
- snd_hdac_stream_setup(azx_stream(azx_dev), false);
-
- stream_tag = azx_dev->core.stream_tag;
- /* CA-IBG chips need the playback stream starting from 1 */
- if ((chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) &&
- stream_tag > chip->capture_streams)
- stream_tag -= chip->capture_streams;
- err = snd_hda_codec_prepare(apcm->codec, hinfo, stream_tag,
- azx_dev->core.format_val, substream);
-
- unlock:
- if (!err)
- azx_stream(azx_dev)->prepared = 1;
- dsp_unlock(azx_dev);
- return err;
-}
-
-static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
-{
- struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
- struct azx *chip = apcm->chip;
- struct hdac_bus *bus = azx_bus(chip);
- struct azx_dev *azx_dev;
- struct snd_pcm_substream *s;
- struct hdac_stream *hstr;
- bool start;
- int sbits = 0;
- int sync_reg;
-
- azx_dev = get_azx_dev(substream);
- trace_azx_pcm_trigger(chip, azx_dev, cmd);
-
- hstr = azx_stream(azx_dev);
- if (chip->driver_caps & AZX_DCAPS_OLD_SSYNC)
- sync_reg = AZX_REG_OLD_SSYNC;
- else
- sync_reg = AZX_REG_SSYNC;
-
- if (dsp_is_locked(azx_dev) || !hstr->prepared)
- return -EPIPE;
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- case SNDRV_PCM_TRIGGER_RESUME:
- start = true;
- break;
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_STOP:
- start = false;
- break;
- default:
- return -EINVAL;
- }
-
- snd_pcm_group_for_each_entry(s, substream) {
- if (s->pcm->card != substream->pcm->card)
- continue;
- azx_dev = get_azx_dev(s);
- sbits |= 1 << azx_dev->core.index;
- snd_pcm_trigger_done(s, substream);
- }
-
- spin_lock(&bus->reg_lock);
-
- /* first, set SYNC bits of corresponding streams */
- snd_hdac_stream_sync_trigger(hstr, true, sbits, sync_reg);
-
- snd_pcm_group_for_each_entry(s, substream) {
- if (s->pcm->card != substream->pcm->card)
- continue;
- azx_dev = get_azx_dev(s);
- if (start) {
- azx_dev->insufficient = 1;
- snd_hdac_stream_start(azx_stream(azx_dev));
- } else {
- snd_hdac_stream_stop(azx_stream(azx_dev));
- }
- }
- spin_unlock(&bus->reg_lock);
-
- snd_hdac_stream_sync(hstr, start, sbits);
-
- spin_lock(&bus->reg_lock);
- /* reset SYNC bits */
- snd_hdac_stream_sync_trigger(hstr, false, sbits, sync_reg);
- snd_hdac_stream_timecounter_init(hstr, sbits, start);
- spin_unlock(&bus->reg_lock);
- return 0;
-}
-
-unsigned int azx_get_pos_lpib(struct azx *chip, struct azx_dev *azx_dev)
-{
- return snd_hdac_stream_get_pos_lpib(azx_stream(azx_dev));
-}
-EXPORT_SYMBOL_GPL(azx_get_pos_lpib);
-
-unsigned int azx_get_pos_posbuf(struct azx *chip, struct azx_dev *azx_dev)
-{
- return snd_hdac_stream_get_pos_posbuf(azx_stream(azx_dev));
-}
-EXPORT_SYMBOL_GPL(azx_get_pos_posbuf);
-
-unsigned int azx_get_position(struct azx *chip,
- struct azx_dev *azx_dev)
-{
- struct snd_pcm_substream *substream = azx_dev->core.substream;
- unsigned int pos;
- int stream = substream->stream;
- int delay = 0;
-
- if (chip->get_position[stream])
- pos = chip->get_position[stream](chip, azx_dev);
- else /* use the position buffer as default */
- pos = azx_get_pos_posbuf(chip, azx_dev);
-
- if (pos >= azx_dev->core.bufsize)
- pos = 0;
-
- if (substream->runtime) {
- struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
- struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream);
-
- if (chip->get_delay[stream])
- delay += chip->get_delay[stream](chip, azx_dev, pos);
- if (hinfo->ops.get_delay)
- delay += hinfo->ops.get_delay(hinfo, apcm->codec,
- substream);
- substream->runtime->delay = delay;
- }
-
- trace_azx_get_position(chip, azx_dev, pos, delay);
- return pos;
-}
-EXPORT_SYMBOL_GPL(azx_get_position);
-
-static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream)
-{
- struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
- struct azx *chip = apcm->chip;
- struct azx_dev *azx_dev = get_azx_dev(substream);
- return bytes_to_frames(substream->runtime,
- azx_get_position(chip, azx_dev));
-}
-
-/*
- * azx_scale64: Scale base by mult/div while not overflowing sanely
- *
- * Derived from scale64_check_overflow in kernel/time/timekeeping.c
- *
- * The tmestamps for a 48Khz stream can overflow after (2^64/10^9)/48K which
- * is about 384307 ie ~4.5 days.
- *
- * This scales the calculation so that overflow will happen but after 2^64 /
- * 48000 secs, which is pretty large!
- *
- * In caln below:
- * base may overflow, but since there isn’t any additional division
- * performed on base it’s OK
- * rem can’t overflow because both are 32-bit values
- */
-
-#ifdef CONFIG_X86
-static u64 azx_scale64(u64 base, u32 num, u32 den)
-{
- u64 rem;
-
- rem = do_div(base, den);
-
- base *= num;
- rem *= num;
-
- do_div(rem, den);
-
- return base + rem;
-}
-
-static int azx_get_sync_time(ktime_t *device,
- struct system_counterval_t *system, void *ctx)
-{
- struct snd_pcm_substream *substream = ctx;
- struct azx_dev *azx_dev = get_azx_dev(substream);
- struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
- struct azx *chip = apcm->chip;
- struct snd_pcm_runtime *runtime;
- u64 ll_counter, ll_counter_l, ll_counter_h;
- u64 tsc_counter, tsc_counter_l, tsc_counter_h;
- u32 wallclk_ctr, wallclk_cycles;
- bool direction;
- u32 dma_select;
- u32 timeout;
- u32 retry_count = 0;
-
- runtime = substream->runtime;
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- direction = 1;
- else
- direction = 0;
-
- /* 0th stream tag is not used, so DMA ch 0 is for 1st stream tag */
- do {
- timeout = 100;
- dma_select = (direction << GTSCC_CDMAS_DMA_DIR_SHIFT) |
- (azx_dev->core.stream_tag - 1);
- snd_hdac_chip_writel(azx_bus(chip), GTSCC, dma_select);
-
- /* Enable the capture */
- snd_hdac_chip_updatel(azx_bus(chip), GTSCC, 0, GTSCC_TSCCI_MASK);
-
- while (timeout) {
- if (snd_hdac_chip_readl(azx_bus(chip), GTSCC) &
- GTSCC_TSCCD_MASK)
- break;
-
- timeout--;
- }
-
- if (!timeout) {
- dev_err(chip->card->dev, "GTSCC capture Timedout!\n");
- return -EIO;
- }
-
- /* Read wall clock counter */
- wallclk_ctr = snd_hdac_chip_readl(azx_bus(chip), WALFCC);
-
- /* Read TSC counter */
- tsc_counter_l = snd_hdac_chip_readl(azx_bus(chip), TSCCL);
- tsc_counter_h = snd_hdac_chip_readl(azx_bus(chip), TSCCU);
-
- /* Read Link counter */
- ll_counter_l = snd_hdac_chip_readl(azx_bus(chip), LLPCL);
- ll_counter_h = snd_hdac_chip_readl(azx_bus(chip), LLPCU);
-
- /* Ack: registers read done */
- snd_hdac_chip_writel(azx_bus(chip), GTSCC, GTSCC_TSCCD_SHIFT);
-
- tsc_counter = (tsc_counter_h << TSCCU_CCU_SHIFT) |
- tsc_counter_l;
-
- ll_counter = (ll_counter_h << LLPC_CCU_SHIFT) | ll_counter_l;
- wallclk_cycles = wallclk_ctr & WALFCC_CIF_MASK;
-
- /*
- * An error occurs near frame "rollover". The clocks in
- * frame value indicates whether this error may have
- * occurred. Here we use the value of 10 i.e.,
- * HDA_MAX_CYCLE_OFFSET
- */
- if (wallclk_cycles < HDA_MAX_CYCLE_VALUE - HDA_MAX_CYCLE_OFFSET
- && wallclk_cycles > HDA_MAX_CYCLE_OFFSET)
- break;
-
- /*
- * Sleep before we read again, else we may again get
- * value near to MAX_CYCLE. Try to sleep for different
- * amount of time so we dont hit the same number again
- */
- udelay(retry_count++);
-
- } while (retry_count != HDA_MAX_CYCLE_READ_RETRY);
-
- if (retry_count == HDA_MAX_CYCLE_READ_RETRY) {
- dev_err_ratelimited(chip->card->dev,
- "Error in WALFCC cycle count\n");
- return -EIO;
- }
-
- *device = ns_to_ktime(azx_scale64(ll_counter,
- NSEC_PER_SEC, runtime->rate));
- *device = ktime_add_ns(*device, (wallclk_cycles * NSEC_PER_SEC) /
- ((HDA_MAX_CYCLE_VALUE + 1) * runtime->rate));
-
- system->cycles = tsc_counter;
- system->cs_id = CSID_X86_ART;
-
- return 0;
-}
-
-#else
-static int azx_get_sync_time(ktime_t *device,
- struct system_counterval_t *system, void *ctx)
-{
- return -ENXIO;
-}
-#endif
-
-static int azx_get_crosststamp(struct snd_pcm_substream *substream,
- struct system_device_crosststamp *xtstamp)
-{
- return get_device_system_crosststamp(azx_get_sync_time,
- substream, NULL, xtstamp);
-}
-
-static inline bool is_link_time_supported(struct snd_pcm_runtime *runtime,
- struct snd_pcm_audio_tstamp_config *ts)
-{
- if (runtime->hw.info & SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME)
- if (ts->type_requested == SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED)
- return true;
-
- return false;
-}
-
-static int azx_get_time_info(struct snd_pcm_substream *substream,
- struct timespec64 *system_ts, struct timespec64 *audio_ts,
- struct snd_pcm_audio_tstamp_config *audio_tstamp_config,
- struct snd_pcm_audio_tstamp_report *audio_tstamp_report)
-{
- struct azx_dev *azx_dev = get_azx_dev(substream);
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct system_device_crosststamp xtstamp;
- int ret;
- u64 nsec;
-
- if ((substream->runtime->hw.info & SNDRV_PCM_INFO_HAS_LINK_ATIME) &&
- (audio_tstamp_config->type_requested == SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK)) {
-
- snd_pcm_gettime(substream->runtime, system_ts);
-
- nsec = timecounter_read(&azx_dev->core.tc);
- if (audio_tstamp_config->report_delay)
- nsec = azx_adjust_codec_delay(substream, nsec);
-
- *audio_ts = ns_to_timespec64(nsec);
-
- audio_tstamp_report->actual_type = SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK;
- audio_tstamp_report->accuracy_report = 1; /* rest of structure is valid */
- audio_tstamp_report->accuracy = 42; /* 24 MHz WallClock == 42ns resolution */
-
- } else if (is_link_time_supported(runtime, audio_tstamp_config)) {
-
- ret = azx_get_crosststamp(substream, &xtstamp);
- if (ret)
- return ret;
-
- switch (runtime->tstamp_type) {
- case SNDRV_PCM_TSTAMP_TYPE_MONOTONIC:
- return -EINVAL;
-
- case SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW:
- *system_ts = ktime_to_timespec64(xtstamp.sys_monoraw);
- break;
-
- default:
- *system_ts = ktime_to_timespec64(xtstamp.sys_realtime);
- break;
-
- }
-
- *audio_ts = ktime_to_timespec64(xtstamp.device);
-
- audio_tstamp_report->actual_type =
- SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED;
- audio_tstamp_report->accuracy_report = 1;
- /* 24 MHz WallClock == 42ns resolution */
- audio_tstamp_report->accuracy = 42;
-
- } else {
- audio_tstamp_report->actual_type = SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT;
- }
-
- return 0;
-}
-
-static const struct snd_pcm_hardware azx_pcm_hw = {
- .info = (SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_MMAP_VALID |
- /* No full-resume yet implemented */
- /* SNDRV_PCM_INFO_RESUME |*/
- SNDRV_PCM_INFO_PAUSE |
- SNDRV_PCM_INFO_SYNC_START |
- SNDRV_PCM_INFO_HAS_WALL_CLOCK | /* legacy */
- SNDRV_PCM_INFO_HAS_LINK_ATIME |
- SNDRV_PCM_INFO_NO_PERIOD_WAKEUP),
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- .rates = SNDRV_PCM_RATE_48000,
- .rate_min = 48000,
- .rate_max = 48000,
- .channels_min = 2,
- .channels_max = 2,
- .buffer_bytes_max = AZX_MAX_BUF_SIZE,
- .period_bytes_min = 128,
- .period_bytes_max = AZX_MAX_BUF_SIZE / 2,
- .periods_min = 2,
- .periods_max = AZX_MAX_FRAG,
- .fifo_size = 0,
-};
-
-static int azx_pcm_open(struct snd_pcm_substream *substream)
-{
- struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
- struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream);
- struct azx *chip = apcm->chip;
- struct azx_dev *azx_dev;
- struct snd_pcm_runtime *runtime = substream->runtime;
- int err;
- int buff_step;
-
- snd_hda_codec_pcm_get(apcm->info);
- mutex_lock(&chip->open_mutex);
- azx_dev = azx_assign_device(chip, substream);
- trace_azx_pcm_open(chip, azx_dev);
- if (azx_dev == NULL) {
- err = -EBUSY;
- goto unlock;
- }
- runtime->private_data = azx_dev;
-
- runtime->hw = azx_pcm_hw;
- if (chip->gts_present)
- runtime->hw.info |= SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME;
- runtime->hw.channels_min = hinfo->channels_min;
- runtime->hw.channels_max = hinfo->channels_max;
- runtime->hw.formats = hinfo->formats;
- runtime->hw.rates = hinfo->rates;
- snd_pcm_limit_hw_rates(runtime);
- snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
-
- /* avoid wrap-around with wall-clock */
- snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_TIME,
- 20,
- 178000000);
-
- if (chip->align_buffer_size)
- /* constrain buffer sizes to be multiple of 128
- bytes. This is more efficient in terms of memory
- access but isn't required by the HDA spec and
- prevents users from specifying exact period/buffer
- sizes. For example for 44.1kHz, a period size set
- to 20ms will be rounded to 19.59ms. */
- buff_step = 128;
- else
- /* Don't enforce steps on buffer sizes, still need to
- be multiple of 4 bytes (HDA spec). Tested on Intel
- HDA controllers, may not work on all devices where
- option needs to be disabled */
- buff_step = 4;
-
- snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
- buff_step);
- snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
- buff_step);
- snd_hda_power_up(apcm->codec);
- if (hinfo->ops.open)
- err = hinfo->ops.open(hinfo, apcm->codec, substream);
- else
- err = -ENODEV;
- if (err < 0) {
- azx_release_device(azx_dev);
- goto powerdown;
- }
- snd_pcm_limit_hw_rates(runtime);
- /* sanity check */
- if (snd_BUG_ON(!runtime->hw.channels_min) ||
- snd_BUG_ON(!runtime->hw.channels_max) ||
- snd_BUG_ON(!runtime->hw.formats) ||
- snd_BUG_ON(!runtime->hw.rates)) {
- azx_release_device(azx_dev);
- if (hinfo->ops.close)
- hinfo->ops.close(hinfo, apcm->codec, substream);
- err = -EINVAL;
- goto powerdown;
- }
-
- /* disable LINK_ATIME timestamps for capture streams
- until we figure out how to handle digital inputs */
- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
- runtime->hw.info &= ~SNDRV_PCM_INFO_HAS_WALL_CLOCK; /* legacy */
- runtime->hw.info &= ~SNDRV_PCM_INFO_HAS_LINK_ATIME;
- }
-
- snd_pcm_set_sync(substream);
- mutex_unlock(&chip->open_mutex);
- return 0;
-
- powerdown:
- snd_hda_power_down(apcm->codec);
- unlock:
- mutex_unlock(&chip->open_mutex);
- snd_hda_codec_pcm_put(apcm->info);
- return err;
-}
-
-static const struct snd_pcm_ops azx_pcm_ops = {
- .open = azx_pcm_open,
- .close = azx_pcm_close,
- .hw_params = azx_pcm_hw_params,
- .hw_free = azx_pcm_hw_free,
- .prepare = azx_pcm_prepare,
- .trigger = azx_pcm_trigger,
- .pointer = azx_pcm_pointer,
- .get_time_info = azx_get_time_info,
-};
-
-static void azx_pcm_free(struct snd_pcm *pcm)
-{
- struct azx_pcm *apcm = pcm->private_data;
- if (apcm) {
- list_del(&apcm->list);
- apcm->info->pcm = NULL;
- kfree(apcm);
- }
-}
-
-#define MAX_PREALLOC_SIZE (32 * 1024 * 1024)
-
-int snd_hda_attach_pcm_stream(struct hda_bus *_bus, struct hda_codec *codec,
- struct hda_pcm *cpcm)
-{
- struct hdac_bus *bus = &_bus->core;
- struct azx *chip = bus_to_azx(bus);
- struct snd_pcm *pcm;
- struct azx_pcm *apcm;
- int pcm_dev = cpcm->device;
- unsigned int size;
- int s, err;
- int type = SNDRV_DMA_TYPE_DEV_SG;
-
- list_for_each_entry(apcm, &chip->pcm_list, list) {
- if (apcm->pcm->device == pcm_dev) {
- dev_err(chip->card->dev, "PCM %d already exists\n",
- pcm_dev);
- return -EBUSY;
- }
- }
- err = snd_pcm_new(chip->card, cpcm->name, pcm_dev,
- cpcm->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams,
- cpcm->stream[SNDRV_PCM_STREAM_CAPTURE].substreams,
- &pcm);
- if (err < 0)
- return err;
- strscpy(pcm->name, cpcm->name, sizeof(pcm->name));
- apcm = kzalloc(sizeof(*apcm), GFP_KERNEL);
- if (apcm == NULL) {
- snd_device_free(chip->card, pcm);
- return -ENOMEM;
- }
- apcm->chip = chip;
- apcm->pcm = pcm;
- apcm->codec = codec;
- apcm->info = cpcm;
- pcm->private_data = apcm;
- pcm->private_free = azx_pcm_free;
- if (cpcm->pcm_type == HDA_PCM_TYPE_MODEM)
- pcm->dev_class = SNDRV_PCM_CLASS_MODEM;
- list_add_tail(&apcm->list, &chip->pcm_list);
- cpcm->pcm = pcm;
- for (s = 0; s < 2; s++) {
- if (cpcm->stream[s].substreams)
- snd_pcm_set_ops(pcm, s, &azx_pcm_ops);
- }
- /* buffer pre-allocation */
- size = CONFIG_SND_HDA_PREALLOC_SIZE * 1024;
- if (size > MAX_PREALLOC_SIZE)
- size = MAX_PREALLOC_SIZE;
- if (chip->uc_buffer)
- type = SNDRV_DMA_TYPE_DEV_WC_SG;
- snd_pcm_set_managed_buffer_all(pcm, type, chip->card->dev,
- size, MAX_PREALLOC_SIZE);
- return 0;
-}
-
-static unsigned int azx_command_addr(u32 cmd)
-{
- unsigned int addr = cmd >> 28;
-
- if (addr >= AZX_MAX_CODECS) {
- snd_BUG();
- addr = 0;
- }
-
- return addr;
-}
-
-/* receive a response */
-static int azx_rirb_get_response(struct hdac_bus *bus, unsigned int addr,
- unsigned int *res)
-{
- struct azx *chip = bus_to_azx(bus);
- struct hda_bus *hbus = &chip->bus;
- int err;
-
- again:
- err = snd_hdac_bus_get_response(bus, addr, res);
- if (!err)
- return 0;
-
- if (hbus->no_response_fallback)
- return -EIO;
-
- if (!bus->polling_mode) {
- dev_warn(chip->card->dev,
- "azx_get_response timeout, switching to polling mode: last cmd=0x%08x\n",
- bus->last_cmd[addr]);
- bus->polling_mode = 1;
- goto again;
- }
-
- if (chip->msi) {
- dev_warn(chip->card->dev,
- "No response from codec, disabling MSI: last cmd=0x%08x\n",
- bus->last_cmd[addr]);
- if (chip->ops->disable_msi_reset_irq &&
- chip->ops->disable_msi_reset_irq(chip) < 0)
- return -EIO;
- goto again;
- }
-
- if (chip->probing) {
- /* If this critical timeout happens during the codec probing
- * phase, this is likely an access to a non-existing codec
- * slot. Better to return an error and reset the system.
- */
- return -EIO;
- }
-
- /* no fallback mechanism? */
- if (!chip->fallback_to_single_cmd)
- return -EIO;
-
- /* a fatal communication error; need either to reset or to fallback
- * to the single_cmd mode
- */
- if (hbus->allow_bus_reset && !hbus->response_reset && !hbus->in_reset) {
- hbus->response_reset = 1;
- dev_err(chip->card->dev,
- "No response from codec, resetting bus: last cmd=0x%08x\n",
- bus->last_cmd[addr]);
- return -EAGAIN; /* give a chance to retry */
- }
-
- dev_err(chip->card->dev,
- "azx_get_response timeout, switching to single_cmd mode: last cmd=0x%08x\n",
- bus->last_cmd[addr]);
- chip->single_cmd = 1;
- hbus->response_reset = 0;
- snd_hdac_bus_stop_cmd_io(bus);
- return -EIO;
-}
-
-/*
- * Use the single immediate command instead of CORB/RIRB for simplicity
- *
- * Note: according to Intel, this is not preferred use. The command was
- * intended for the BIOS only, and may get confused with unsolicited
- * responses. So, we shouldn't use it for normal operation from the
- * driver.
- * I left the codes, however, for debugging/testing purposes.
- */
-
-/* receive a response */
-static int azx_single_wait_for_response(struct azx *chip, unsigned int addr)
-{
- int timeout = 50;
-
- while (timeout--) {
- /* check IRV busy bit */
- if (azx_readw(chip, IRS) & AZX_IRS_VALID) {
- /* reuse rirb.res as the response return value */
- azx_bus(chip)->rirb.res[addr] = azx_readl(chip, IR);
- return 0;
- }
- udelay(1);
- }
- if (printk_ratelimit())
- dev_dbg(chip->card->dev, "get_response timeout: IRS=0x%x\n",
- azx_readw(chip, IRS));
- azx_bus(chip)->rirb.res[addr] = -1;
- return -EIO;
-}
-
-/* send a command */
-static int azx_single_send_cmd(struct hdac_bus *bus, u32 val)
-{
- struct azx *chip = bus_to_azx(bus);
- unsigned int addr = azx_command_addr(val);
- int timeout = 50;
-
- bus->last_cmd[azx_command_addr(val)] = val;
- while (timeout--) {
- /* check ICB busy bit */
- if (!((azx_readw(chip, IRS) & AZX_IRS_BUSY))) {
- /* Clear IRV valid bit */
- azx_writew(chip, IRS, azx_readw(chip, IRS) |
- AZX_IRS_VALID);
- azx_writel(chip, IC, val);
- azx_writew(chip, IRS, azx_readw(chip, IRS) |
- AZX_IRS_BUSY);
- return azx_single_wait_for_response(chip, addr);
- }
- udelay(1);
- }
- if (printk_ratelimit())
- dev_dbg(chip->card->dev,
- "send_cmd timeout: IRS=0x%x, val=0x%x\n",
- azx_readw(chip, IRS), val);
- return -EIO;
-}
-
-/* receive a response */
-static int azx_single_get_response(struct hdac_bus *bus, unsigned int addr,
- unsigned int *res)
-{
- if (res)
- *res = bus->rirb.res[addr];
- return 0;
-}
-
-/*
- * The below are the main callbacks from hda_codec.
- *
- * They are just the skeleton to call sub-callbacks according to the
- * current setting of chip->single_cmd.
- */
-
-/* send a command */
-static int azx_send_cmd(struct hdac_bus *bus, unsigned int val)
-{
- struct azx *chip = bus_to_azx(bus);
-
- if (chip->disabled)
- return 0;
- if (chip->single_cmd || bus->use_pio_for_commands)
- return azx_single_send_cmd(bus, val);
- else
- return snd_hdac_bus_send_cmd(bus, val);
-}
-
-/* get a response */
-static int azx_get_response(struct hdac_bus *bus, unsigned int addr,
- unsigned int *res)
-{
- struct azx *chip = bus_to_azx(bus);
-
- if (chip->disabled)
- return 0;
- if (chip->single_cmd || bus->use_pio_for_commands)
- return azx_single_get_response(bus, addr, res);
- else
- return azx_rirb_get_response(bus, addr, res);
-}
-
-static const struct hdac_bus_ops bus_core_ops = {
- .command = azx_send_cmd,
- .get_response = azx_get_response,
-};
-
-#ifdef CONFIG_SND_HDA_DSP_LOADER
-/*
- * DSP loading code (e.g. for CA0132)
- */
-
-/* use the first stream for loading DSP */
-static struct azx_dev *
-azx_get_dsp_loader_dev(struct azx *chip)
-{
- struct hdac_bus *bus = azx_bus(chip);
- struct hdac_stream *s;
-
- list_for_each_entry(s, &bus->stream_list, list)
- if (s->index == chip->playback_index_offset)
- return stream_to_azx_dev(s);
-
- return NULL;
-}
-
-int snd_hda_codec_load_dsp_prepare(struct hda_codec *codec, unsigned int format,
- unsigned int byte_size,
- struct snd_dma_buffer *bufp)
-{
- struct hdac_bus *bus = &codec->bus->core;
- struct azx *chip = bus_to_azx(bus);
- struct azx_dev *azx_dev;
- struct hdac_stream *hstr;
- bool saved = false;
- int err;
-
- azx_dev = azx_get_dsp_loader_dev(chip);
- hstr = azx_stream(azx_dev);
- spin_lock_irq(&bus->reg_lock);
- if (hstr->opened) {
- chip->saved_azx_dev = *azx_dev;
- saved = true;
- }
- spin_unlock_irq(&bus->reg_lock);
-
- err = snd_hdac_dsp_prepare(hstr, format, byte_size, bufp);
- if (err < 0) {
- spin_lock_irq(&bus->reg_lock);
- if (saved)
- *azx_dev = chip->saved_azx_dev;
- spin_unlock_irq(&bus->reg_lock);
- return err;
- }
-
- hstr->prepared = 0;
- return err;
-}
-EXPORT_SYMBOL_GPL(snd_hda_codec_load_dsp_prepare);
-
-void snd_hda_codec_load_dsp_trigger(struct hda_codec *codec, bool start)
-{
- struct hdac_bus *bus = &codec->bus->core;
- struct azx *chip = bus_to_azx(bus);
- struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip);
-
- snd_hdac_dsp_trigger(azx_stream(azx_dev), start);
-}
-EXPORT_SYMBOL_GPL(snd_hda_codec_load_dsp_trigger);
-
-void snd_hda_codec_load_dsp_cleanup(struct hda_codec *codec,
- struct snd_dma_buffer *dmab)
-{
- struct hdac_bus *bus = &codec->bus->core;
- struct azx *chip = bus_to_azx(bus);
- struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip);
- struct hdac_stream *hstr = azx_stream(azx_dev);
-
- if (!dmab->area || !hstr->locked)
- return;
-
- snd_hdac_dsp_cleanup(hstr, dmab);
- spin_lock_irq(&bus->reg_lock);
- if (hstr->opened)
- *azx_dev = chip->saved_azx_dev;
- hstr->locked = false;
- spin_unlock_irq(&bus->reg_lock);
-}
-EXPORT_SYMBOL_GPL(snd_hda_codec_load_dsp_cleanup);
-#endif /* CONFIG_SND_HDA_DSP_LOADER */
-
-/*
- * reset and start the controller registers
- */
-void azx_init_chip(struct azx *chip, bool full_reset)
-{
- if (snd_hdac_bus_init_chip(azx_bus(chip), full_reset)) {
- /* correct RINTCNT for CXT */
- if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND)
- azx_writew(chip, RINTCNT, 0xc0);
- }
-}
-EXPORT_SYMBOL_GPL(azx_init_chip);
-
-void azx_stop_all_streams(struct azx *chip)
-{
- struct hdac_bus *bus = azx_bus(chip);
-
- snd_hdac_stop_streams(bus);
-}
-EXPORT_SYMBOL_GPL(azx_stop_all_streams);
-
-void azx_stop_chip(struct azx *chip)
-{
- snd_hdac_bus_stop_chip(azx_bus(chip));
-}
-EXPORT_SYMBOL_GPL(azx_stop_chip);
-
-/*
- * interrupt handler
- */
-static void stream_update(struct hdac_bus *bus, struct hdac_stream *s)
-{
- struct azx *chip = bus_to_azx(bus);
- struct azx_dev *azx_dev = stream_to_azx_dev(s);
-
- /* check whether this IRQ is really acceptable */
- if (!chip->ops->position_check ||
- chip->ops->position_check(chip, azx_dev)) {
- spin_unlock(&bus->reg_lock);
- snd_pcm_period_elapsed(azx_stream(azx_dev)->substream);
- spin_lock(&bus->reg_lock);
- }
-}
-
-irqreturn_t azx_interrupt(int irq, void *dev_id)
-{
- struct azx *chip = dev_id;
- struct hdac_bus *bus = azx_bus(chip);
- u32 status;
- bool active, handled = false;
- int repeat = 0; /* count for avoiding endless loop */
-
- if (azx_has_pm_runtime(chip))
- if (!pm_runtime_active(chip->card->dev))
- return IRQ_NONE;
-
- spin_lock(&bus->reg_lock);
-
- if (chip->disabled)
- goto unlock;
-
- do {
- status = azx_readl(chip, INTSTS);
- if (status == 0 || status == 0xffffffff)
- break;
-
- handled = true;
- active = false;
- if (snd_hdac_bus_handle_stream_irq(bus, status, stream_update))
- active = true;
-
- status = azx_readb(chip, RIRBSTS);
- if (status & RIRB_INT_MASK) {
- /*
- * Clearing the interrupt status here ensures that no
- * interrupt gets masked after the RIRB wp is read in
- * snd_hdac_bus_update_rirb. This avoids a possible
- * race condition where codec response in RIRB may
- * remain unserviced by IRQ, eventually falling back
- * to polling mode in azx_rirb_get_response.
- */
- azx_writeb(chip, RIRBSTS, RIRB_INT_MASK);
- active = true;
- if (status & RIRB_INT_RESPONSE) {
- if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND)
- udelay(80);
- snd_hdac_bus_update_rirb(bus);
- }
- }
- } while (active && ++repeat < 10);
-
- unlock:
- spin_unlock(&bus->reg_lock);
-
- return IRQ_RETVAL(handled);
-}
-EXPORT_SYMBOL_GPL(azx_interrupt);
-
-/*
- * Codec initerface
- */
-
-/*
- * Probe the given codec address
- */
-static int probe_codec(struct azx *chip, int addr)
-{
- unsigned int cmd = (addr << 28) | (AC_NODE_ROOT << 20) |
- (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID;
- struct hdac_bus *bus = azx_bus(chip);
- int err;
- unsigned int res = -1;
-
- mutex_lock(&bus->cmd_mutex);
- chip->probing = 1;
- azx_send_cmd(bus, cmd);
- err = azx_get_response(bus, addr, &res);
- chip->probing = 0;
- mutex_unlock(&bus->cmd_mutex);
- if (err < 0 || res == -1)
- return -EIO;
- dev_dbg(chip->card->dev, "codec #%d probed OK\n", addr);
- return 0;
-}
-
-void snd_hda_bus_reset(struct hda_bus *bus)
-{
- struct azx *chip = bus_to_azx(&bus->core);
-
- bus->in_reset = 1;
- azx_stop_chip(chip);
- azx_init_chip(chip, true);
- if (bus->core.chip_init)
- snd_hda_bus_reset_codecs(bus);
- bus->in_reset = 0;
-}
-
-/* HD-audio bus initialization */
-int azx_bus_init(struct azx *chip, const char *model)
-{
- struct hda_bus *bus = &chip->bus;
- int err;
-
- err = snd_hdac_bus_init(&bus->core, chip->card->dev, &bus_core_ops);
- if (err < 0)
- return err;
-
- bus->card = chip->card;
- mutex_init(&bus->prepare_mutex);
- bus->pci = chip->pci;
- bus->modelname = model;
- bus->mixer_assigned = -1;
- bus->core.snoop = azx_snoop(chip);
- if (chip->get_position[0] != azx_get_pos_lpib ||
- chip->get_position[1] != azx_get_pos_lpib)
- bus->core.use_posbuf = true;
- bus->core.bdl_pos_adj = chip->bdl_pos_adj;
- if (chip->driver_caps & AZX_DCAPS_CORBRP_SELF_CLEAR)
- bus->core.corbrp_self_clear = true;
-
- if (chip->driver_caps & AZX_DCAPS_4K_BDLE_BOUNDARY)
- bus->core.align_bdle_4k = true;
-
- if (chip->driver_caps & AZX_DCAPS_PIO_COMMANDS)
- bus->core.use_pio_for_commands = true;
-
- /* enable sync_write flag for stable communication as default */
- bus->core.sync_write = 1;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(azx_bus_init);
-
-/* Probe codecs */
-int azx_probe_codecs(struct azx *chip, unsigned int max_slots)
-{
- struct hdac_bus *bus = azx_bus(chip);
- int c, codecs, err;
-
- codecs = 0;
- if (!max_slots)
- max_slots = AZX_DEFAULT_CODECS;
-
- /* First try to probe all given codec slots */
- for (c = 0; c < max_slots; c++) {
- if ((bus->codec_mask & (1 << c)) & chip->codec_probe_mask) {
- if (probe_codec(chip, c) < 0) {
- /* Some BIOSen give you wrong codec addresses
- * that don't exist
- */
- dev_warn(chip->card->dev,
- "Codec #%d probe error; disabling it...\n", c);
- bus->codec_mask &= ~(1 << c);
- /* no codecs */
- if (bus->codec_mask == 0)
- break;
- /* More badly, accessing to a non-existing
- * codec often screws up the controller chip,
- * and disturbs the further communications.
- * Thus if an error occurs during probing,
- * better to reset the controller chip to
- * get back to the sanity state.
- */
- azx_stop_chip(chip);
- azx_init_chip(chip, true);
- }
- }
- }
-
- /* Then create codec instances */
- for (c = 0; c < max_slots; c++) {
- if ((bus->codec_mask & (1 << c)) & chip->codec_probe_mask) {
- struct hda_codec *codec;
- err = snd_hda_codec_new(&chip->bus, chip->card, c, &codec);
- if (err < 0)
- continue;
- codec->jackpoll_interval = chip->jackpoll_interval;
- codec->beep_mode = chip->beep_mode;
- codec->ctl_dev_id = chip->ctl_dev_id;
- codecs++;
- }
- }
- if (!codecs) {
- dev_err(chip->card->dev, "no codecs initialized\n");
- return -ENXIO;
- }
- return 0;
-}
-EXPORT_SYMBOL_GPL(azx_probe_codecs);
-
-/* configure each codec instance */
-int azx_codec_configure(struct azx *chip)
-{
- struct hda_codec *codec, *next;
- int success = 0;
-
- list_for_each_codec(codec, &chip->bus) {
- if (!snd_hda_codec_configure(codec))
- success++;
- }
-
- if (success) {
- /* unregister failed codecs if any codec has been probed */
- list_for_each_codec_safe(codec, next, &chip->bus) {
- if (!codec->configured) {
- codec_err(codec, "Unable to configure, disabling\n");
- snd_hdac_device_unregister(&codec->core);
- }
- }
- }
-
- return success ? 0 : -ENODEV;
-}
-EXPORT_SYMBOL_GPL(azx_codec_configure);
-
-static int stream_direction(struct azx *chip, unsigned char index)
-{
- if (index >= chip->capture_index_offset &&
- index < chip->capture_index_offset + chip->capture_streams)
- return SNDRV_PCM_STREAM_CAPTURE;
- return SNDRV_PCM_STREAM_PLAYBACK;
-}
-
-/* initialize SD streams */
-int azx_init_streams(struct azx *chip)
-{
- int i;
- int stream_tags[2] = { 0, 0 };
-
- /* initialize each stream (aka device)
- * assign the starting bdl address to each stream (device)
- * and initialize
- */
- for (i = 0; i < chip->num_streams; i++) {
- struct azx_dev *azx_dev = kzalloc(sizeof(*azx_dev), GFP_KERNEL);
- int dir, tag;
-
- if (!azx_dev)
- return -ENOMEM;
-
- dir = stream_direction(chip, i);
- /* stream tag must be unique throughout
- * the stream direction group,
- * valid values 1...15
- * use separate stream tag if the flag
- * AZX_DCAPS_SEPARATE_STREAM_TAG is used
- */
- if (chip->driver_caps & AZX_DCAPS_SEPARATE_STREAM_TAG)
- tag = ++stream_tags[dir];
- else
- tag = i + 1;
- snd_hdac_stream_init(azx_bus(chip), azx_stream(azx_dev),
- i, dir, tag);
- }
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(azx_init_streams);
-
-void azx_free_streams(struct azx *chip)
-{
- struct hdac_bus *bus = azx_bus(chip);
- struct hdac_stream *s;
-
- while (!list_empty(&bus->stream_list)) {
- s = list_first_entry(&bus->stream_list, struct hdac_stream, list);
- list_del(&s->list);
- kfree(stream_to_azx_dev(s));
- }
-}
-EXPORT_SYMBOL_GPL(azx_free_streams);
diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h
deleted file mode 100644
index c2d0109866e6..000000000000
--- a/sound/pci/hda/hda_controller.h
+++ /dev/null
@@ -1,215 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Common functionality for the alsa driver code base for HD Audio.
- */
-
-#ifndef __SOUND_HDA_CONTROLLER_H
-#define __SOUND_HDA_CONTROLLER_H
-
-#include <linux/timecounter.h>
-#include <linux/interrupt.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/initval.h>
-#include <sound/hda_codec.h>
-#include <sound/hda_register.h>
-
-#define AZX_MAX_CODECS HDA_MAX_CODECS
-#define AZX_DEFAULT_CODECS 4
-
-/* driver quirks (capabilities) */
-/* bits 0-7 are used for indicating driver type */
-#define AZX_DCAPS_NO_TCSEL (1 << 8) /* No Intel TCSEL bit */
-#define AZX_DCAPS_NO_MSI (1 << 9) /* No MSI support */
-#define AZX_DCAPS_SNOOP_MASK (3 << 10) /* snoop type mask */
-#define AZX_DCAPS_SNOOP_OFF (1 << 12) /* snoop default off */
-#ifdef CONFIG_SND_HDA_I915
-#define AZX_DCAPS_I915_COMPONENT (1 << 13) /* bind with i915 gfx */
-#else
-#define AZX_DCAPS_I915_COMPONENT 0 /* NOP */
-#endif
-/* 14 unused */
-#define AZX_DCAPS_CTX_WORKAROUND (1 << 15) /* X-Fi workaround */
-#define AZX_DCAPS_POSFIX_LPIB (1 << 16) /* Use LPIB as default */
-#define AZX_DCAPS_AMD_WORKAROUND (1 << 17) /* AMD-specific workaround */
-#define AZX_DCAPS_NO_64BIT (1 << 18) /* No 64bit address */
-/* 19 unused */
-#define AZX_DCAPS_OLD_SSYNC (1 << 20) /* Old SSYNC reg for ICH */
-#define AZX_DCAPS_NO_ALIGN_BUFSIZE (1 << 21) /* no buffer size alignment */
-/* 22 unused */
-#define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23) /* BDLE in 4k boundary */
-/* 24 unused */
-#define AZX_DCAPS_COUNT_LPIB_DELAY (1 << 25) /* Take LPIB as delay */
-#define AZX_DCAPS_PM_RUNTIME (1 << 26) /* runtime PM support */
-#define AZX_DCAPS_RETRY_PROBE (1 << 27) /* retry probe if no codec is configured */
-#define AZX_DCAPS_CORBRP_SELF_CLEAR (1 << 28) /* CORBRP clears itself after reset */
-#define AZX_DCAPS_NO_MSI64 (1 << 29) /* Stick to 32-bit MSIs */
-#define AZX_DCAPS_SEPARATE_STREAM_TAG (1 << 30) /* capture and playback use separate stream tag */
-#define AZX_DCAPS_PIO_COMMANDS (1 << 31) /* Use PIO instead of CORB for commands */
-
-enum {
- AZX_SNOOP_TYPE_NONE,
- AZX_SNOOP_TYPE_SCH,
- AZX_SNOOP_TYPE_ATI,
- AZX_SNOOP_TYPE_NVIDIA,
-};
-
-struct azx_dev {
- struct hdac_stream core;
-
- unsigned int irq_pending:1;
- /*
- * For VIA:
- * A flag to ensure DMA position is 0
- * when link position is not greater than FIFO size
- */
- unsigned int insufficient:1;
-};
-
-#define azx_stream(dev) (&(dev)->core)
-#define stream_to_azx_dev(s) container_of(s, struct azx_dev, core)
-
-struct azx;
-
-/* Functions to read/write to hda registers. */
-struct hda_controller_ops {
- /* Disable msi if supported, PCI only */
- int (*disable_msi_reset_irq)(struct azx *);
- /* Check if current position is acceptable */
- int (*position_check)(struct azx *chip, struct azx_dev *azx_dev);
- /* enable/disable the link power */
- int (*link_power)(struct azx *chip, bool enable);
-};
-
-struct azx_pcm {
- struct azx *chip;
- struct snd_pcm *pcm;
- struct hda_codec *codec;
- struct hda_pcm *info;
- struct list_head list;
-};
-
-typedef unsigned int (*azx_get_pos_callback_t)(struct azx *, struct azx_dev *);
-typedef int (*azx_get_delay_callback_t)(struct azx *, struct azx_dev *, unsigned int pos);
-
-struct azx {
- struct hda_bus bus;
-
- struct snd_card *card;
- struct pci_dev *pci;
- int dev_index;
-
- /* chip type specific */
- int driver_type;
- unsigned int driver_caps;
- int playback_streams;
- int playback_index_offset;
- int capture_streams;
- int capture_index_offset;
- int num_streams;
- int jackpoll_interval; /* jack poll interval in jiffies */
-
- /* Register interaction. */
- const struct hda_controller_ops *ops;
-
- /* position adjustment callbacks */
- azx_get_pos_callback_t get_position[2];
- azx_get_delay_callback_t get_delay[2];
-
- /* locks */
- struct mutex open_mutex; /* Prevents concurrent open/close operations */
-
- /* PCM */
- struct list_head pcm_list; /* azx_pcm list */
-
- /* HD codec */
- int codec_probe_mask; /* copied from probe_mask option */
- unsigned int beep_mode;
- bool ctl_dev_id;
-
-#ifdef CONFIG_SND_HDA_PATCH_LOADER
- const struct firmware *fw;
-#endif
-
- /* flags */
- int bdl_pos_adj;
- unsigned int running:1;
- unsigned int fallback_to_single_cmd:1;
- unsigned int single_cmd:1;
- unsigned int msi:1;
- unsigned int probing:1; /* codec probing phase */
- unsigned int snoop:1;
- unsigned int uc_buffer:1; /* non-cached pages for stream buffers */
- unsigned int align_buffer_size:1;
- unsigned int disabled:1; /* disabled by vga_switcheroo */
- unsigned int pm_prepared:1;
-
- /* GTS present */
- unsigned int gts_present:1;
-
-#ifdef CONFIG_SND_HDA_DSP_LOADER
- struct azx_dev saved_azx_dev;
-#endif
-};
-
-#define azx_bus(chip) (&(chip)->bus.core)
-#define bus_to_azx(_bus) container_of(_bus, struct azx, bus.core)
-
-static inline bool azx_snoop(struct azx *chip)
-{
- return !IS_ENABLED(CONFIG_X86) || chip->snoop;
-}
-
-/*
- * macros for easy use
- */
-
-#define azx_writel(chip, reg, value) \
- snd_hdac_chip_writel(azx_bus(chip), reg, value)
-#define azx_readl(chip, reg) \
- snd_hdac_chip_readl(azx_bus(chip), reg)
-#define azx_writew(chip, reg, value) \
- snd_hdac_chip_writew(azx_bus(chip), reg, value)
-#define azx_readw(chip, reg) \
- snd_hdac_chip_readw(azx_bus(chip), reg)
-#define azx_writeb(chip, reg, value) \
- snd_hdac_chip_writeb(azx_bus(chip), reg, value)
-#define azx_readb(chip, reg) \
- snd_hdac_chip_readb(azx_bus(chip), reg)
-
-#define azx_has_pm_runtime(chip) \
- ((chip)->driver_caps & AZX_DCAPS_PM_RUNTIME)
-
-/* PCM setup */
-static inline struct azx_dev *get_azx_dev(struct snd_pcm_substream *substream)
-{
- return substream->runtime->private_data;
-}
-unsigned int azx_get_position(struct azx *chip, struct azx_dev *azx_dev);
-unsigned int azx_get_pos_lpib(struct azx *chip, struct azx_dev *azx_dev);
-unsigned int azx_get_pos_posbuf(struct azx *chip, struct azx_dev *azx_dev);
-
-/* Stream control. */
-void azx_stop_all_streams(struct azx *chip);
-
-/* Allocation functions. */
-#define azx_alloc_stream_pages(chip) \
- snd_hdac_bus_alloc_stream_pages(azx_bus(chip))
-#define azx_free_stream_pages(chip) \
- snd_hdac_bus_free_stream_pages(azx_bus(chip))
-
-/* Low level azx interface */
-void azx_init_chip(struct azx *chip, bool full_reset);
-void azx_stop_chip(struct azx *chip);
-#define azx_enter_link_reset(chip) \
- snd_hdac_bus_enter_link_reset(azx_bus(chip))
-irqreturn_t azx_interrupt(int irq, void *dev_id);
-
-/* Codec interface */
-int azx_bus_init(struct azx *chip, const char *model);
-int azx_probe_codecs(struct azx *chip, unsigned int max_slots);
-int azx_codec_configure(struct azx *chip);
-int azx_init_streams(struct azx *chip);
-void azx_free_streams(struct azx *chip);
-
-#endif /* __SOUND_HDA_CONTROLLER_H */
diff --git a/sound/pci/hda/hda_controller_trace.h b/sound/pci/hda/hda_controller_trace.h
deleted file mode 100644
index bf48304e230a..000000000000
--- a/sound/pci/hda/hda_controller_trace.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM hda_controller
-#define TRACE_INCLUDE_FILE hda_controller_trace
-
-#if !defined(_TRACE_HDA_CONTROLLER_H) || defined(TRACE_HEADER_MULTI_READ)
-#define _TRACE_HDA_CONTROLLER_H
-
-#include <linux/tracepoint.h>
-
-struct azx;
-struct azx_dev;
-
-TRACE_EVENT(azx_pcm_trigger,
-
- TP_PROTO(struct azx *chip, struct azx_dev *dev, int cmd),
-
- TP_ARGS(chip, dev, cmd),
-
- TP_STRUCT__entry(
- __field( int, card )
- __field( int, idx )
- __field( int, cmd )
- ),
-
- TP_fast_assign(
- __entry->card = (chip)->card->number;
- __entry->idx = (dev)->core.index;
- __entry->cmd = cmd;
- ),
-
- TP_printk("[%d:%d] cmd=%d", __entry->card, __entry->idx, __entry->cmd)
-);
-
-TRACE_EVENT(azx_get_position,
-
- TP_PROTO(struct azx *chip, struct azx_dev *dev, unsigned int pos, unsigned int delay),
-
- TP_ARGS(chip, dev, pos, delay),
-
- TP_STRUCT__entry(
- __field( int, card )
- __field( int, idx )
- __field( unsigned int, pos )
- __field( unsigned int, delay )
- ),
-
- TP_fast_assign(
- __entry->card = (chip)->card->number;
- __entry->idx = (dev)->core.index;
- __entry->pos = pos;
- __entry->delay = delay;
- ),
-
- TP_printk("[%d:%d] pos=%u, delay=%u", __entry->card, __entry->idx, __entry->pos, __entry->delay)
-);
-
-DECLARE_EVENT_CLASS(azx_pcm,
- TP_PROTO(struct azx *chip, struct azx_dev *azx_dev),
-
- TP_ARGS(chip, azx_dev),
-
- TP_STRUCT__entry(
- __field( unsigned char, stream_tag )
- ),
-
- TP_fast_assign(
- __entry->stream_tag = (azx_dev)->core.stream_tag;
- ),
-
- TP_printk("stream_tag: %d", __entry->stream_tag)
-);
-
-DEFINE_EVENT(azx_pcm, azx_pcm_open,
- TP_PROTO(struct azx *chip, struct azx_dev *azx_dev),
- TP_ARGS(chip, azx_dev)
-);
-
-DEFINE_EVENT(azx_pcm, azx_pcm_close,
- TP_PROTO(struct azx *chip, struct azx_dev *azx_dev),
- TP_ARGS(chip, azx_dev)
-);
-
-DEFINE_EVENT(azx_pcm, azx_pcm_hw_params,
- TP_PROTO(struct azx *chip, struct azx_dev *azx_dev),
- TP_ARGS(chip, azx_dev)
-);
-
-DEFINE_EVENT(azx_pcm, azx_pcm_prepare,
- TP_PROTO(struct azx *chip, struct azx_dev *azx_dev),
- TP_ARGS(chip, azx_dev)
-);
-
-#endif /* _TRACE_HDA_CONTROLLER_H */
-
-/* This part must be outside protection */
-#undef TRACE_INCLUDE_PATH
-#define TRACE_INCLUDE_PATH .
-#include <trace/define_trace.h>
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c
deleted file mode 100644
index d3e87b9c1a4f..000000000000
--- a/sound/pci/hda/hda_eld.c
+++ /dev/null
@@ -1,402 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Generic routines and proc interface for ELD(EDID Like Data) information
- *
- * Copyright(c) 2008 Intel Corporation.
- * Copyright (c) 2013 Anssi Hannula <anssi.hannula@iki.fi>
- *
- * Authors:
- * Wu Fengguang <wfg@linux.intel.com>
- */
-
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <sound/core.h>
-#include <linux/unaligned.h>
-#include <sound/hda_chmap.h>
-#include <sound/hda_codec.h>
-#include "hda_local.h"
-
-enum cea_edid_versions {
- CEA_EDID_VER_NONE = 0,
- CEA_EDID_VER_CEA861 = 1,
- CEA_EDID_VER_CEA861A = 2,
- CEA_EDID_VER_CEA861BCD = 3,
- CEA_EDID_VER_RESERVED = 4,
-};
-
-/*
- * The following two lists are shared between
- * - HDMI audio InfoFrame (source to sink)
- * - CEA E-EDID Extension (sink to source)
- */
-
-static unsigned int hdmi_get_eld_data(struct hda_codec *codec, hda_nid_t nid,
- int byte_index)
-{
- unsigned int val;
-
- val = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_HDMI_ELDD, byte_index);
-#ifdef BE_PARANOID
- codec_info(codec, "HDMI: ELD data byte %d: 0x%x\n", byte_index, val);
-#endif
- return val;
-}
-
-int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid)
-{
- return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE,
- AC_DIPSIZE_ELD_BUF);
-}
-
-int snd_hdmi_get_eld(struct hda_codec *codec, hda_nid_t nid,
- unsigned char *buf, int *eld_size)
-{
- int i;
- int ret = 0;
- int size;
-
- /*
- * ELD size is initialized to zero in caller function. If no errors and
- * ELD is valid, actual eld_size is assigned.
- */
-
- size = snd_hdmi_get_eld_size(codec, nid);
- if (size == 0) {
- /* wfg: workaround for ASUS P5E-VM HDMI board */
- codec_info(codec, "HDMI: ELD buf size is 0, force 128\n");
- size = 128;
- }
- if (size < ELD_FIXED_BYTES || size > ELD_MAX_SIZE) {
- codec_info(codec, "HDMI: invalid ELD buf size %d\n", size);
- return -ERANGE;
- }
-
- /* set ELD buffer */
- for (i = 0; i < size; i++) {
- unsigned int val = hdmi_get_eld_data(codec, nid, i);
- /*
- * Graphics driver might be writing to ELD buffer right now.
- * Just abort. The caller will repoll after a while.
- */
- if (!(val & AC_ELDD_ELD_VALID)) {
- codec_info(codec, "HDMI: invalid ELD data byte %d\n", i);
- ret = -EINVAL;
- goto error;
- }
- val &= AC_ELDD_ELD_DATA;
- /*
- * The first byte cannot be zero. This can happen on some DVI
- * connections. Some Intel chips may also need some 250ms delay
- * to return non-zero ELD data, even when the graphics driver
- * correctly writes ELD content before setting ELD_valid bit.
- */
- if (!val && !i) {
- codec_dbg(codec, "HDMI: 0 ELD data\n");
- ret = -EINVAL;
- goto error;
- }
- buf[i] = val;
- }
-
- *eld_size = size;
-error:
- return ret;
-}
-
-#ifdef CONFIG_SND_PROC_FS
-void snd_hdmi_print_eld_info(struct hdmi_eld *eld,
- struct snd_info_buffer *buffer,
- hda_nid_t pin_nid, int dev_id, hda_nid_t cvt_nid)
-{
- snd_iprintf(buffer, "monitor_present\t\t%d\n", eld->monitor_present);
- snd_iprintf(buffer, "eld_valid\t\t%d\n", eld->eld_valid);
- snd_iprintf(buffer, "codec_pin_nid\t\t0x%x\n", pin_nid);
- snd_iprintf(buffer, "codec_dev_id\t\t0x%x\n", dev_id);
- snd_iprintf(buffer, "codec_cvt_nid\t\t0x%x\n", cvt_nid);
-
- if (!eld->eld_valid)
- return;
-
- snd_print_eld_info(&eld->info, buffer);
-}
-
-void snd_hdmi_write_eld_info(struct hdmi_eld *eld,
- struct snd_info_buffer *buffer)
-{
- struct snd_parsed_hdmi_eld *e = &eld->info;
- char line[64];
- char name[64];
- char *sname;
- long long val;
- unsigned int n;
-
- while (!snd_info_get_line(buffer, line, sizeof(line))) {
- if (sscanf(line, "%s %llx", name, &val) != 2)
- continue;
- /*
- * We don't allow modification to these fields:
- * monitor_name manufacture_id product_id
- * eld_version edid_version
- */
- if (!strcmp(name, "monitor_present"))
- eld->monitor_present = val;
- else if (!strcmp(name, "eld_valid"))
- eld->eld_valid = val;
- else if (!strcmp(name, "connection_type"))
- e->conn_type = val;
- else if (!strcmp(name, "port_id"))
- e->port_id = val;
- else if (!strcmp(name, "support_hdcp"))
- e->support_hdcp = val;
- else if (!strcmp(name, "support_ai"))
- e->support_ai = val;
- else if (!strcmp(name, "audio_sync_delay"))
- e->aud_synch_delay = val;
- else if (!strcmp(name, "speakers"))
- e->spk_alloc = val;
- else if (!strcmp(name, "sad_count"))
- e->sad_count = val;
- else if (!strncmp(name, "sad", 3)) {
- sname = name + 4;
- n = name[3] - '0';
- if (name[4] >= '0' && name[4] <= '9') {
- sname++;
- n = 10 * n + name[4] - '0';
- }
- if (n >= ELD_MAX_SAD)
- continue;
- if (!strcmp(sname, "_coding_type"))
- e->sad[n].format = val;
- else if (!strcmp(sname, "_channels"))
- e->sad[n].channels = val;
- else if (!strcmp(sname, "_rates"))
- e->sad[n].rates = val;
- else if (!strcmp(sname, "_bits"))
- e->sad[n].sample_bits = val;
- else if (!strcmp(sname, "_max_bitrate"))
- e->sad[n].max_bitrate = val;
- else if (!strcmp(sname, "_profile"))
- e->sad[n].profile = val;
- if (n >= e->sad_count)
- e->sad_count = n + 1;
- }
- }
-}
-#endif /* CONFIG_SND_PROC_FS */
-
-/* update PCM info based on ELD */
-void snd_hdmi_eld_update_pcm_info(struct snd_parsed_hdmi_eld *e,
- struct hda_pcm_stream *hinfo)
-{
- u32 rates;
- u64 formats;
- unsigned int maxbps;
- unsigned int channels_max;
- int i;
-
- /* assume basic audio support (the basic audio flag is not in ELD;
- * however, all audio capable sinks are required to support basic
- * audio) */
- rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
- SNDRV_PCM_RATE_48000;
- formats = SNDRV_PCM_FMTBIT_S16_LE;
- maxbps = 16;
- channels_max = 2;
- for (i = 0; i < e->sad_count; i++) {
- struct snd_cea_sad *a = &e->sad[i];
- rates |= a->rates;
- if (a->channels > channels_max)
- channels_max = a->channels;
- if (a->format == AUDIO_CODING_TYPE_LPCM) {
- if (a->sample_bits & ELD_PCM_BITS_20) {
- formats |= SNDRV_PCM_FMTBIT_S32_LE;
- if (maxbps < 20)
- maxbps = 20;
- }
- if (a->sample_bits & ELD_PCM_BITS_24) {
- formats |= SNDRV_PCM_FMTBIT_S32_LE;
- if (maxbps < 24)
- maxbps = 24;
- }
- }
- }
-
- /* restrict the parameters by the values the codec provides */
- hinfo->rates &= rates;
- hinfo->formats &= formats;
- hinfo->maxbps = min(hinfo->maxbps, maxbps);
- hinfo->channels_max = min(hinfo->channels_max, channels_max);
-}
-
-
-/* ATI/AMD specific stuff (ELD emulation) */
-
-#define ATI_VERB_SET_AUDIO_DESCRIPTOR 0x776
-#define ATI_VERB_SET_SINK_INFO_INDEX 0x780
-#define ATI_VERB_GET_SPEAKER_ALLOCATION 0xf70
-#define ATI_VERB_GET_AUDIO_DESCRIPTOR 0xf76
-#define ATI_VERB_GET_AUDIO_VIDEO_DELAY 0xf7b
-#define ATI_VERB_GET_SINK_INFO_INDEX 0xf80
-#define ATI_VERB_GET_SINK_INFO_DATA 0xf81
-
-#define ATI_SPKALLOC_SPKALLOC 0x007f
-#define ATI_SPKALLOC_TYPE_HDMI 0x0100
-#define ATI_SPKALLOC_TYPE_DISPLAYPORT 0x0200
-
-/* first three bytes are just standard SAD */
-#define ATI_AUDIODESC_CHANNELS 0x00000007
-#define ATI_AUDIODESC_RATES 0x0000ff00
-#define ATI_AUDIODESC_LPCM_STEREO_RATES 0xff000000
-
-/* in standard HDMI VSDB format */
-#define ATI_DELAY_VIDEO_LATENCY 0x000000ff
-#define ATI_DELAY_AUDIO_LATENCY 0x0000ff00
-
-enum ati_sink_info_idx {
- ATI_INFO_IDX_MANUFACTURER_ID = 0,
- ATI_INFO_IDX_PRODUCT_ID = 1,
- ATI_INFO_IDX_SINK_DESC_LEN = 2,
- ATI_INFO_IDX_PORT_ID_LOW = 3,
- ATI_INFO_IDX_PORT_ID_HIGH = 4,
- ATI_INFO_IDX_SINK_DESC_FIRST = 5,
- ATI_INFO_IDX_SINK_DESC_LAST = 22, /* max len 18 bytes */
-};
-
-int snd_hdmi_get_eld_ati(struct hda_codec *codec, hda_nid_t nid,
- unsigned char *buf, int *eld_size, bool rev3_or_later)
-{
- int spkalloc, ati_sad, aud_synch;
- int sink_desc_len = 0;
- int pos, i;
-
- /* ATI/AMD does not have ELD, emulate it */
-
- spkalloc = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_SPEAKER_ALLOCATION, 0);
-
- if (spkalloc <= 0) {
- codec_info(codec, "HDMI ATI/AMD: no speaker allocation for ELD\n");
- return -EINVAL;
- }
-
- memset(buf, 0, ELD_FIXED_BYTES + ELD_MAX_MNL + ELD_MAX_SAD * 3);
-
- /* version */
- buf[0] = ELD_VER_CEA_861D << 3;
-
- /* speaker allocation from EDID */
- buf[7] = spkalloc & ATI_SPKALLOC_SPKALLOC;
-
- /* is DisplayPort? */
- if (spkalloc & ATI_SPKALLOC_TYPE_DISPLAYPORT)
- buf[5] |= 0x04;
-
- pos = ELD_FIXED_BYTES;
-
- if (rev3_or_later) {
- int sink_info;
-
- snd_hda_codec_write(codec, nid, 0, ATI_VERB_SET_SINK_INFO_INDEX, ATI_INFO_IDX_PORT_ID_LOW);
- sink_info = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_SINK_INFO_DATA, 0);
- put_unaligned_le32(sink_info, buf + 8);
-
- snd_hda_codec_write(codec, nid, 0, ATI_VERB_SET_SINK_INFO_INDEX, ATI_INFO_IDX_PORT_ID_HIGH);
- sink_info = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_SINK_INFO_DATA, 0);
- put_unaligned_le32(sink_info, buf + 12);
-
- snd_hda_codec_write(codec, nid, 0, ATI_VERB_SET_SINK_INFO_INDEX, ATI_INFO_IDX_MANUFACTURER_ID);
- sink_info = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_SINK_INFO_DATA, 0);
- put_unaligned_le16(sink_info, buf + 16);
-
- snd_hda_codec_write(codec, nid, 0, ATI_VERB_SET_SINK_INFO_INDEX, ATI_INFO_IDX_PRODUCT_ID);
- sink_info = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_SINK_INFO_DATA, 0);
- put_unaligned_le16(sink_info, buf + 18);
-
- snd_hda_codec_write(codec, nid, 0, ATI_VERB_SET_SINK_INFO_INDEX, ATI_INFO_IDX_SINK_DESC_LEN);
- sink_desc_len = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_SINK_INFO_DATA, 0);
-
- if (sink_desc_len > ELD_MAX_MNL) {
- codec_info(codec, "HDMI ATI/AMD: Truncating HDMI sink description with length %d\n",
- sink_desc_len);
- sink_desc_len = ELD_MAX_MNL;
- }
-
- buf[4] |= sink_desc_len;
-
- for (i = 0; i < sink_desc_len; i++) {
- snd_hda_codec_write(codec, nid, 0, ATI_VERB_SET_SINK_INFO_INDEX, ATI_INFO_IDX_SINK_DESC_FIRST + i);
- buf[pos++] = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_SINK_INFO_DATA, 0);
- }
- }
-
- for (i = AUDIO_CODING_TYPE_LPCM; i <= AUDIO_CODING_TYPE_WMAPRO; i++) {
- if (i == AUDIO_CODING_TYPE_SACD || i == AUDIO_CODING_TYPE_DST)
- continue; /* not handled by ATI/AMD */
-
- snd_hda_codec_write(codec, nid, 0, ATI_VERB_SET_AUDIO_DESCRIPTOR, i << 3);
- ati_sad = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_AUDIO_DESCRIPTOR, 0);
-
- if (ati_sad <= 0)
- continue;
-
- if (ati_sad & ATI_AUDIODESC_RATES) {
- /* format is supported, copy SAD as-is */
- buf[pos++] = (ati_sad & 0x0000ff) >> 0;
- buf[pos++] = (ati_sad & 0x00ff00) >> 8;
- buf[pos++] = (ati_sad & 0xff0000) >> 16;
- }
-
- if (i == AUDIO_CODING_TYPE_LPCM
- && (ati_sad & ATI_AUDIODESC_LPCM_STEREO_RATES)
- && (ati_sad & ATI_AUDIODESC_LPCM_STEREO_RATES) >> 16 != (ati_sad & ATI_AUDIODESC_RATES)) {
- /* for PCM there is a separate stereo rate mask */
- buf[pos++] = ((ati_sad & 0x000000ff) & ~ATI_AUDIODESC_CHANNELS) | 0x1;
- /* rates from the extra byte */
- buf[pos++] = (ati_sad & 0xff000000) >> 24;
- buf[pos++] = (ati_sad & 0x00ff0000) >> 16;
- }
- }
-
- if (pos == ELD_FIXED_BYTES + sink_desc_len) {
- codec_info(codec, "HDMI ATI/AMD: no audio descriptors for ELD\n");
- return -EINVAL;
- }
-
- /*
- * HDMI VSDB latency format:
- * separately for both audio and video:
- * 0 field not valid or unknown latency
- * [1..251] msecs = (x-1)*2 (max 500ms with x = 251 = 0xfb)
- * 255 audio/video not supported
- *
- * HDA latency format:
- * single value indicating video latency relative to audio:
- * 0 unknown or 0ms
- * [1..250] msecs = x*2 (max 500ms with x = 250 = 0xfa)
- * [251..255] reserved
- */
- aud_synch = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_AUDIO_VIDEO_DELAY, 0);
- if ((aud_synch & ATI_DELAY_VIDEO_LATENCY) && (aud_synch & ATI_DELAY_AUDIO_LATENCY)) {
- int video_latency_hdmi = (aud_synch & ATI_DELAY_VIDEO_LATENCY);
- int audio_latency_hdmi = (aud_synch & ATI_DELAY_AUDIO_LATENCY) >> 8;
-
- if (video_latency_hdmi <= 0xfb && audio_latency_hdmi <= 0xfb &&
- video_latency_hdmi > audio_latency_hdmi)
- buf[6] = video_latency_hdmi - audio_latency_hdmi;
- /* else unknown/invalid or 0ms or video ahead of audio, so use zero */
- }
-
- /* SAD count */
- buf[5] |= ((pos - ELD_FIXED_BYTES - sink_desc_len) / 3) << 4;
-
- /* Baseline ELD block length is 4-byte aligned */
- pos = round_up(pos, 4);
-
- /* Baseline ELD length (4-byte header is not counted in) */
- buf[2] = (pos - 4) / 4;
-
- *eld_size = pos;
-
- return 0;
-}
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
deleted file mode 100644
index b34d84fedcc8..000000000000
--- a/sound/pci/hda/hda_generic.c
+++ /dev/null
@@ -1,6159 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Universal Interface for Intel High Definition Audio Codec
- *
- * Generic widget tree parser
- *
- * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
- */
-
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/export.h>
-#include <linux/sort.h>
-#include <linux/delay.h>
-#include <linux/ctype.h>
-#include <linux/string.h>
-#include <linux/bitops.h>
-#include <linux/module.h>
-#include <linux/leds.h>
-#include <sound/core.h>
-#include <sound/jack.h>
-#include <sound/tlv.h>
-#include <sound/hda_codec.h>
-#include "hda_local.h"
-#include "hda_auto_parser.h"
-#include "hda_jack.h"
-#include "hda_beep.h"
-#include "hda_generic.h"
-
-
-/**
- * snd_hda_gen_spec_init - initialize hda_gen_spec struct
- * @spec: hda_gen_spec object to initialize
- *
- * Initialize the given hda_gen_spec object.
- */
-int snd_hda_gen_spec_init(struct hda_gen_spec *spec)
-{
- snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
- snd_array_init(&spec->paths, sizeof(struct nid_path), 8);
- snd_array_init(&spec->loopback_list, sizeof(struct hda_amp_list), 8);
- mutex_init(&spec->pcm_mutex);
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_gen_spec_init);
-
-/**
- * snd_hda_gen_add_kctl - Add a new kctl_new struct from the template
- * @spec: hda_gen_spec object
- * @name: name string to override the template, NULL if unchanged
- * @temp: template for the new kctl
- *
- * Add a new kctl (actually snd_kcontrol_new to be instantiated later)
- * element based on the given snd_kcontrol_new template @temp and the
- * name string @name to the list in @spec.
- * Returns the newly created object or NULL as error.
- */
-struct snd_kcontrol_new *
-snd_hda_gen_add_kctl(struct hda_gen_spec *spec, const char *name,
- const struct snd_kcontrol_new *temp)
-{
- struct snd_kcontrol_new *knew = snd_array_new(&spec->kctls);
- if (!knew)
- return NULL;
- *knew = *temp;
- if (name)
- knew->name = kstrdup(name, GFP_KERNEL);
- else if (knew->name)
- knew->name = kstrdup(knew->name, GFP_KERNEL);
- if (!knew->name)
- return NULL;
- return knew;
-}
-EXPORT_SYMBOL_GPL(snd_hda_gen_add_kctl);
-
-static void free_kctls(struct hda_gen_spec *spec)
-{
- if (spec->kctls.list) {
- struct snd_kcontrol_new *kctl = spec->kctls.list;
- int i;
- for (i = 0; i < spec->kctls.used; i++)
- kfree(kctl[i].name);
- }
- snd_array_free(&spec->kctls);
-}
-
-static void snd_hda_gen_spec_free(struct hda_gen_spec *spec)
-{
- if (!spec)
- return;
- free_kctls(spec);
- snd_array_free(&spec->paths);
- snd_array_free(&spec->loopback_list);
-#ifdef CONFIG_SND_HDA_GENERIC_LEDS
- if (spec->led_cdevs[LED_AUDIO_MUTE])
- led_classdev_unregister(spec->led_cdevs[LED_AUDIO_MUTE]);
- if (spec->led_cdevs[LED_AUDIO_MICMUTE])
- led_classdev_unregister(spec->led_cdevs[LED_AUDIO_MICMUTE]);
-#endif
-}
-
-/*
- * store user hints
- */
-static void parse_user_hints(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
- int val;
-
- val = snd_hda_get_bool_hint(codec, "jack_detect");
- if (val >= 0)
- codec->no_jack_detect = !val;
- val = snd_hda_get_bool_hint(codec, "inv_jack_detect");
- if (val >= 0)
- codec->inv_jack_detect = !!val;
- val = snd_hda_get_bool_hint(codec, "trigger_sense");
- if (val >= 0)
- codec->no_trigger_sense = !val;
- val = snd_hda_get_bool_hint(codec, "inv_eapd");
- if (val >= 0)
- codec->inv_eapd = !!val;
- val = snd_hda_get_bool_hint(codec, "pcm_format_first");
- if (val >= 0)
- codec->pcm_format_first = !!val;
- val = snd_hda_get_bool_hint(codec, "sticky_stream");
- if (val >= 0)
- codec->no_sticky_stream = !val;
- val = snd_hda_get_bool_hint(codec, "spdif_status_reset");
- if (val >= 0)
- codec->spdif_status_reset = !!val;
- val = snd_hda_get_bool_hint(codec, "pin_amp_workaround");
- if (val >= 0)
- codec->pin_amp_workaround = !!val;
- val = snd_hda_get_bool_hint(codec, "single_adc_amp");
- if (val >= 0)
- codec->single_adc_amp = !!val;
- val = snd_hda_get_bool_hint(codec, "power_save_node");
- if (val >= 0)
- codec->power_save_node = !!val;
-
- val = snd_hda_get_bool_hint(codec, "auto_mute");
- if (val >= 0)
- spec->suppress_auto_mute = !val;
- val = snd_hda_get_bool_hint(codec, "auto_mic");
- if (val >= 0)
- spec->suppress_auto_mic = !val;
- val = snd_hda_get_bool_hint(codec, "line_in_auto_switch");
- if (val >= 0)
- spec->line_in_auto_switch = !!val;
- val = snd_hda_get_bool_hint(codec, "auto_mute_via_amp");
- if (val >= 0)
- spec->auto_mute_via_amp = !!val;
- val = snd_hda_get_bool_hint(codec, "need_dac_fix");
- if (val >= 0)
- spec->need_dac_fix = !!val;
- val = snd_hda_get_bool_hint(codec, "primary_hp");
- if (val >= 0)
- spec->no_primary_hp = !val;
- val = snd_hda_get_bool_hint(codec, "multi_io");
- if (val >= 0)
- spec->no_multi_io = !val;
- val = snd_hda_get_bool_hint(codec, "multi_cap_vol");
- if (val >= 0)
- spec->multi_cap_vol = !!val;
- val = snd_hda_get_bool_hint(codec, "inv_dmic_split");
- if (val >= 0)
- spec->inv_dmic_split = !!val;
- val = snd_hda_get_bool_hint(codec, "indep_hp");
- if (val >= 0)
- spec->indep_hp = !!val;
- val = snd_hda_get_bool_hint(codec, "add_stereo_mix_input");
- if (val >= 0)
- spec->add_stereo_mix_input = !!val;
- /* the following two are just for compatibility */
- val = snd_hda_get_bool_hint(codec, "add_out_jack_modes");
- if (val >= 0)
- spec->add_jack_modes = !!val;
- val = snd_hda_get_bool_hint(codec, "add_in_jack_modes");
- if (val >= 0)
- spec->add_jack_modes = !!val;
- val = snd_hda_get_bool_hint(codec, "add_jack_modes");
- if (val >= 0)
- spec->add_jack_modes = !!val;
- val = snd_hda_get_bool_hint(codec, "power_down_unused");
- if (val >= 0)
- spec->power_down_unused = !!val;
- val = snd_hda_get_bool_hint(codec, "add_hp_mic");
- if (val >= 0)
- spec->hp_mic = !!val;
- val = snd_hda_get_bool_hint(codec, "hp_mic_detect");
- if (val >= 0)
- spec->suppress_hp_mic_detect = !val;
- val = snd_hda_get_bool_hint(codec, "vmaster");
- if (val >= 0)
- spec->suppress_vmaster = !val;
-
- if (!snd_hda_get_int_hint(codec, "mixer_nid", &val))
- spec->mixer_nid = val;
-}
-
-/*
- * pin control value accesses
- */
-
-#define update_pin_ctl(codec, pin, val) \
- snd_hda_codec_write_cache(codec, pin, 0, \
- AC_VERB_SET_PIN_WIDGET_CONTROL, val)
-
-/* restore the pinctl based on the cached value */
-static inline void restore_pin_ctl(struct hda_codec *codec, hda_nid_t pin)
-{
- update_pin_ctl(codec, pin, snd_hda_codec_get_pin_target(codec, pin));
-}
-
-/* set the pinctl target value and write it if requested */
-static void set_pin_target(struct hda_codec *codec, hda_nid_t pin,
- unsigned int val, bool do_write)
-{
- if (!pin)
- return;
- val = snd_hda_correct_pin_ctl(codec, pin, val);
- snd_hda_codec_set_pin_target(codec, pin, val);
- if (do_write)
- update_pin_ctl(codec, pin, val);
-}
-
-/* set pinctl target values for all given pins */
-static void set_pin_targets(struct hda_codec *codec, int num_pins,
- hda_nid_t *pins, unsigned int val)
-{
- int i;
- for (i = 0; i < num_pins; i++)
- set_pin_target(codec, pins[i], val, false);
-}
-
-/*
- * parsing paths
- */
-
-/* return the position of NID in the list, or -1 if not found */
-static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
-{
- int i;
- for (i = 0; i < nums; i++)
- if (list[i] == nid)
- return i;
- return -1;
-}
-
-/* return true if the given NID is contained in the path */
-static bool is_nid_contained(struct nid_path *path, hda_nid_t nid)
-{
- return find_idx_in_nid_list(nid, path->path, path->depth) >= 0;
-}
-
-static struct nid_path *get_nid_path(struct hda_codec *codec,
- hda_nid_t from_nid, hda_nid_t to_nid,
- int anchor_nid)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct nid_path *path;
- int i;
-
- snd_array_for_each(&spec->paths, i, path) {
- if (path->depth <= 0)
- continue;
- if ((!from_nid || path->path[0] == from_nid) &&
- (!to_nid || path->path[path->depth - 1] == to_nid)) {
- if (!anchor_nid ||
- (anchor_nid > 0 && is_nid_contained(path, anchor_nid)) ||
- (anchor_nid < 0 && !is_nid_contained(path, anchor_nid)))
- return path;
- }
- }
- return NULL;
-}
-
-/**
- * snd_hda_get_path_idx - get the index number corresponding to the path
- * instance
- * @codec: the HDA codec
- * @path: nid_path object
- *
- * The returned index starts from 1, i.e. the actual array index with offset 1,
- * and zero is handled as an invalid path
- */
-int snd_hda_get_path_idx(struct hda_codec *codec, struct nid_path *path)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct nid_path *array = spec->paths.list;
- ssize_t idx;
-
- if (!spec->paths.used)
- return 0;
- idx = path - array;
- if (idx < 0 || idx >= spec->paths.used)
- return 0;
- return idx + 1;
-}
-EXPORT_SYMBOL_GPL(snd_hda_get_path_idx);
-
-/**
- * snd_hda_get_path_from_idx - get the path instance corresponding to the
- * given index number
- * @codec: the HDA codec
- * @idx: the path index
- */
-struct nid_path *snd_hda_get_path_from_idx(struct hda_codec *codec, int idx)
-{
- struct hda_gen_spec *spec = codec->spec;
-
- if (idx <= 0 || idx > spec->paths.used)
- return NULL;
- return snd_array_elem(&spec->paths, idx - 1);
-}
-EXPORT_SYMBOL_GPL(snd_hda_get_path_from_idx);
-
-/* check whether the given DAC is already found in any existing paths */
-static bool is_dac_already_used(struct hda_codec *codec, hda_nid_t nid)
-{
- struct hda_gen_spec *spec = codec->spec;
- const struct nid_path *path;
- int i;
-
- snd_array_for_each(&spec->paths, i, path) {
- if (path->path[0] == nid)
- return true;
- }
- return false;
-}
-
-/* check whether the given two widgets can be connected */
-static bool is_reachable_path(struct hda_codec *codec,
- hda_nid_t from_nid, hda_nid_t to_nid)
-{
- if (!from_nid || !to_nid)
- return false;
- return snd_hda_get_conn_index(codec, to_nid, from_nid, true) >= 0;
-}
-
-/* nid, dir and idx */
-#define AMP_VAL_COMPARE_MASK (0xffff | (1U << 18) | (0x0f << 19))
-
-/* check whether the given ctl is already assigned in any path elements */
-static bool is_ctl_used(struct hda_codec *codec, unsigned int val, int type)
-{
- struct hda_gen_spec *spec = codec->spec;
- const struct nid_path *path;
- int i;
-
- val &= AMP_VAL_COMPARE_MASK;
- snd_array_for_each(&spec->paths, i, path) {
- if ((path->ctls[type] & AMP_VAL_COMPARE_MASK) == val)
- return true;
- }
- return false;
-}
-
-/* check whether a control with the given (nid, dir, idx) was assigned */
-static bool is_ctl_associated(struct hda_codec *codec, hda_nid_t nid,
- int dir, int idx, int type)
-{
- unsigned int val = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir);
- return is_ctl_used(codec, val, type);
-}
-
-static void print_nid_path(struct hda_codec *codec,
- const char *pfx, struct nid_path *path)
-{
- char buf[40];
- char *pos = buf;
- int i;
-
- *pos = 0;
- for (i = 0; i < path->depth; i++)
- pos += scnprintf(pos, sizeof(buf) - (pos - buf), "%s%02x",
- pos != buf ? ":" : "",
- path->path[i]);
-
- codec_dbg(codec, "%s path: depth=%d '%s'\n", pfx, path->depth, buf);
-}
-
-/* called recursively */
-static bool __parse_nid_path(struct hda_codec *codec,
- hda_nid_t from_nid, hda_nid_t to_nid,
- int anchor_nid, struct nid_path *path,
- int depth)
-{
- const hda_nid_t *conn;
- int i, nums;
-
- if (to_nid == anchor_nid)
- anchor_nid = 0; /* anchor passed */
- else if (to_nid == (hda_nid_t)(-anchor_nid))
- return false; /* hit the exclusive nid */
-
- nums = snd_hda_get_conn_list(codec, to_nid, &conn);
- for (i = 0; i < nums; i++) {
- if (conn[i] != from_nid) {
- /* special case: when from_nid is 0,
- * try to find an empty DAC
- */
- if (from_nid ||
- get_wcaps_type(get_wcaps(codec, conn[i])) != AC_WID_AUD_OUT ||
- is_dac_already_used(codec, conn[i]))
- continue;
- }
- /* anchor is not requested or already passed? */
- if (anchor_nid <= 0)
- goto found;
- }
- if (depth >= MAX_NID_PATH_DEPTH)
- return false;
- for (i = 0; i < nums; i++) {
- unsigned int type;
- type = get_wcaps_type(get_wcaps(codec, conn[i]));
- if (type == AC_WID_AUD_OUT || type == AC_WID_AUD_IN ||
- type == AC_WID_PIN)
- continue;
- if (__parse_nid_path(codec, from_nid, conn[i],
- anchor_nid, path, depth + 1))
- goto found;
- }
- return false;
-
- found:
- path->path[path->depth] = conn[i];
- path->idx[path->depth + 1] = i;
- if (nums > 1 && get_wcaps_type(get_wcaps(codec, to_nid)) != AC_WID_AUD_MIX)
- path->multi[path->depth + 1] = 1;
- path->depth++;
- return true;
-}
-
-/*
- * snd_hda_parse_nid_path - parse the widget path from the given nid to
- * the target nid
- * @codec: the HDA codec
- * @from_nid: the NID where the path start from
- * @to_nid: the NID where the path ends at
- * @anchor_nid: the anchor indication
- * @path: the path object to store the result
- *
- * Returns true if a matching path is found.
- *
- * The parsing behavior depends on parameters:
- * when @from_nid is 0, try to find an empty DAC;
- * when @anchor_nid is set to a positive value, only paths through the widget
- * with the given value are evaluated.
- * when @anchor_nid is set to a negative value, paths through the widget
- * with the negative of given value are excluded, only other paths are chosen.
- * when @anchor_nid is zero, no special handling about path selection.
- */
-static bool snd_hda_parse_nid_path(struct hda_codec *codec, hda_nid_t from_nid,
- hda_nid_t to_nid, int anchor_nid,
- struct nid_path *path)
-{
- if (__parse_nid_path(codec, from_nid, to_nid, anchor_nid, path, 1)) {
- path->path[path->depth] = to_nid;
- path->depth++;
- return true;
- }
- return false;
-}
-
-/**
- * snd_hda_add_new_path - parse the path between the given NIDs and
- * add to the path list
- * @codec: the HDA codec
- * @from_nid: the NID where the path start from
- * @to_nid: the NID where the path ends at
- * @anchor_nid: the anchor indication, see snd_hda_parse_nid_path()
- *
- * If no valid path is found, returns NULL.
- */
-struct nid_path *
-snd_hda_add_new_path(struct hda_codec *codec, hda_nid_t from_nid,
- hda_nid_t to_nid, int anchor_nid)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct nid_path *path;
-
- if (from_nid && to_nid && !is_reachable_path(codec, from_nid, to_nid))
- return NULL;
-
- /* check whether the path has been already added */
- path = get_nid_path(codec, from_nid, to_nid, anchor_nid);
- if (path)
- return path;
-
- path = snd_array_new(&spec->paths);
- if (!path)
- return NULL;
- memset(path, 0, sizeof(*path));
- if (snd_hda_parse_nid_path(codec, from_nid, to_nid, anchor_nid, path))
- return path;
- /* push back */
- spec->paths.used--;
- return NULL;
-}
-EXPORT_SYMBOL_GPL(snd_hda_add_new_path);
-
-/* clear the given path as invalid so that it won't be picked up later */
-static void invalidate_nid_path(struct hda_codec *codec, int idx)
-{
- struct nid_path *path = snd_hda_get_path_from_idx(codec, idx);
- if (!path)
- return;
- memset(path, 0, sizeof(*path));
-}
-
-/* return a DAC if paired to the given pin by codec driver */
-static hda_nid_t get_preferred_dac(struct hda_codec *codec, hda_nid_t pin)
-{
- struct hda_gen_spec *spec = codec->spec;
- const hda_nid_t *list = spec->preferred_dacs;
-
- if (!list)
- return 0;
- for (; *list; list += 2)
- if (*list == pin)
- return list[1];
- return 0;
-}
-
-/* look for an empty DAC slot */
-static hda_nid_t look_for_dac(struct hda_codec *codec, hda_nid_t pin,
- bool is_digital)
-{
- struct hda_gen_spec *spec = codec->spec;
- bool cap_digital;
- int i;
-
- for (i = 0; i < spec->num_all_dacs; i++) {
- hda_nid_t nid = spec->all_dacs[i];
- if (!nid || is_dac_already_used(codec, nid))
- continue;
- cap_digital = !!(get_wcaps(codec, nid) & AC_WCAP_DIGITAL);
- if (is_digital != cap_digital)
- continue;
- if (is_reachable_path(codec, nid, pin))
- return nid;
- }
- return 0;
-}
-
-/* replace the channels in the composed amp value with the given number */
-static unsigned int amp_val_replace_channels(unsigned int val, unsigned int chs)
-{
- val &= ~(0x3U << 16);
- val |= chs << 16;
- return val;
-}
-
-static bool same_amp_caps(struct hda_codec *codec, hda_nid_t nid1,
- hda_nid_t nid2, int dir)
-{
- if (!(get_wcaps(codec, nid1) & (1 << (dir + 1))))
- return !(get_wcaps(codec, nid2) & (1 << (dir + 1)));
- return (query_amp_caps(codec, nid1, dir) ==
- query_amp_caps(codec, nid2, dir));
-}
-
-/* look for a widget suitable for assigning a mute switch in the path */
-static hda_nid_t look_for_out_mute_nid(struct hda_codec *codec,
- struct nid_path *path)
-{
- int i;
-
- for (i = path->depth - 1; i >= 0; i--) {
- if (nid_has_mute(codec, path->path[i], HDA_OUTPUT))
- return path->path[i];
- if (i != path->depth - 1 && i != 0 &&
- nid_has_mute(codec, path->path[i], HDA_INPUT))
- return path->path[i];
- }
- return 0;
-}
-
-/* look for a widget suitable for assigning a volume ctl in the path */
-static hda_nid_t look_for_out_vol_nid(struct hda_codec *codec,
- struct nid_path *path)
-{
- struct hda_gen_spec *spec = codec->spec;
- int i;
-
- for (i = path->depth - 1; i >= 0; i--) {
- hda_nid_t nid = path->path[i];
- if ((spec->out_vol_mask >> nid) & 1)
- continue;
- if (nid_has_volume(codec, nid, HDA_OUTPUT))
- return nid;
- }
- return 0;
-}
-
-/*
- * path activation / deactivation
- */
-
-/* can have the amp-in capability? */
-static bool has_amp_in(struct hda_codec *codec, struct nid_path *path, int idx)
-{
- hda_nid_t nid = path->path[idx];
- unsigned int caps = get_wcaps(codec, nid);
- unsigned int type = get_wcaps_type(caps);
-
- if (!(caps & AC_WCAP_IN_AMP))
- return false;
- if (type == AC_WID_PIN && idx > 0) /* only for input pins */
- return false;
- return true;
-}
-
-/* can have the amp-out capability? */
-static bool has_amp_out(struct hda_codec *codec, struct nid_path *path, int idx)
-{
- hda_nid_t nid = path->path[idx];
- unsigned int caps = get_wcaps(codec, nid);
- unsigned int type = get_wcaps_type(caps);
-
- if (!(caps & AC_WCAP_OUT_AMP))
- return false;
- if (type == AC_WID_PIN && !idx) /* only for output pins */
- return false;
- return true;
-}
-
-/* check whether the given (nid,dir,idx) is active */
-static bool is_active_nid(struct hda_codec *codec, hda_nid_t nid,
- unsigned int dir, unsigned int idx)
-{
- struct hda_gen_spec *spec = codec->spec;
- int type = get_wcaps_type(get_wcaps(codec, nid));
- const struct nid_path *path;
- int i, n;
-
- if (nid == codec->core.afg)
- return true;
-
- snd_array_for_each(&spec->paths, n, path) {
- if (!path->active)
- continue;
- if (codec->power_save_node) {
- if (!path->stream_enabled)
- continue;
- /* ignore unplugged paths except for DAC/ADC */
- if (!(path->pin_enabled || path->pin_fixed) &&
- type != AC_WID_AUD_OUT && type != AC_WID_AUD_IN)
- continue;
- }
- for (i = 0; i < path->depth; i++) {
- if (path->path[i] == nid) {
- if (dir == HDA_OUTPUT || idx == -1 ||
- path->idx[i] == idx)
- return true;
- break;
- }
- }
- }
- return false;
-}
-
-/* check whether the NID is referred by any active paths */
-#define is_active_nid_for_any(codec, nid) \
- is_active_nid(codec, nid, HDA_OUTPUT, -1)
-
-/* get the default amp value for the target state */
-static int get_amp_val_to_activate(struct hda_codec *codec, hda_nid_t nid,
- int dir, unsigned int caps, bool enable)
-{
- unsigned int val = 0;
-
- if (caps & AC_AMPCAP_NUM_STEPS) {
- /* set to 0dB */
- if (enable)
- val = (caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT;
- }
- if (caps & (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) {
- if (!enable)
- val |= HDA_AMP_MUTE;
- }
- return val;
-}
-
-/* is this a stereo widget or a stereo-to-mono mix? */
-static bool is_stereo_amps(struct hda_codec *codec, hda_nid_t nid, int dir)
-{
- unsigned int wcaps = get_wcaps(codec, nid);
- hda_nid_t conn;
-
- if (wcaps & AC_WCAP_STEREO)
- return true;
- if (dir != HDA_INPUT || get_wcaps_type(wcaps) != AC_WID_AUD_MIX)
- return false;
- if (snd_hda_get_num_conns(codec, nid) != 1)
- return false;
- if (snd_hda_get_connections(codec, nid, &conn, 1) < 0)
- return false;
- return !!(get_wcaps(codec, conn) & AC_WCAP_STEREO);
-}
-
-/* initialize the amp value (only at the first time) */
-static void init_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx)
-{
- unsigned int caps = query_amp_caps(codec, nid, dir);
- int val = get_amp_val_to_activate(codec, nid, dir, caps, false);
-
- if (is_stereo_amps(codec, nid, dir))
- snd_hda_codec_amp_init_stereo(codec, nid, dir, idx, 0xff, val);
- else
- snd_hda_codec_amp_init(codec, nid, 0, dir, idx, 0xff, val);
-}
-
-/* update the amp, doing in stereo or mono depending on NID */
-static int update_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx,
- unsigned int mask, unsigned int val)
-{
- if (is_stereo_amps(codec, nid, dir))
- return snd_hda_codec_amp_stereo(codec, nid, dir, idx,
- mask, val);
- else
- return snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
- mask, val);
-}
-
-/* calculate amp value mask we can modify;
- * if the given amp is controlled by mixers, don't touch it
- */
-static unsigned int get_amp_mask_to_modify(struct hda_codec *codec,
- hda_nid_t nid, int dir, int idx,
- unsigned int caps)
-{
- unsigned int mask = 0xff;
-
- if (caps & (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) {
- if (is_ctl_associated(codec, nid, dir, idx, NID_PATH_MUTE_CTL))
- mask &= ~0x80;
- }
- if (caps & AC_AMPCAP_NUM_STEPS) {
- if (is_ctl_associated(codec, nid, dir, idx, NID_PATH_VOL_CTL) ||
- is_ctl_associated(codec, nid, dir, idx, NID_PATH_BOOST_CTL))
- mask &= ~0x7f;
- }
- return mask;
-}
-
-static void activate_amp(struct hda_codec *codec, hda_nid_t nid, int dir,
- int idx, int idx_to_check, bool enable)
-{
- unsigned int caps;
- unsigned int mask, val;
-
- caps = query_amp_caps(codec, nid, dir);
- val = get_amp_val_to_activate(codec, nid, dir, caps, enable);
- mask = get_amp_mask_to_modify(codec, nid, dir, idx_to_check, caps);
- if (!mask)
- return;
-
- val &= mask;
- update_amp(codec, nid, dir, idx, mask, val);
-}
-
-static void check_and_activate_amp(struct hda_codec *codec, hda_nid_t nid,
- int dir, int idx, int idx_to_check,
- bool enable)
-{
- /* check whether the given amp is still used by others */
- if (!enable && is_active_nid(codec, nid, dir, idx_to_check))
- return;
- activate_amp(codec, nid, dir, idx, idx_to_check, enable);
-}
-
-static void activate_amp_out(struct hda_codec *codec, struct nid_path *path,
- int i, bool enable)
-{
- hda_nid_t nid = path->path[i];
- init_amp(codec, nid, HDA_OUTPUT, 0);
- check_and_activate_amp(codec, nid, HDA_OUTPUT, 0, 0, enable);
-}
-
-static void activate_amp_in(struct hda_codec *codec, struct nid_path *path,
- int i, bool enable, bool add_aamix)
-{
- struct hda_gen_spec *spec = codec->spec;
- const hda_nid_t *conn;
- int n, nums, idx;
- int type;
- hda_nid_t nid = path->path[i];
-
- nums = snd_hda_get_conn_list(codec, nid, &conn);
- if (nums < 0)
- return;
- type = get_wcaps_type(get_wcaps(codec, nid));
- if (type == AC_WID_PIN ||
- (type == AC_WID_AUD_IN && codec->single_adc_amp)) {
- nums = 1;
- idx = 0;
- } else
- idx = path->idx[i];
-
- for (n = 0; n < nums; n++)
- init_amp(codec, nid, HDA_INPUT, n);
-
- /* here is a little bit tricky in comparison with activate_amp_out();
- * when aa-mixer is available, we need to enable the path as well
- */
- for (n = 0; n < nums; n++) {
- if (n != idx) {
- if (conn[n] != spec->mixer_merge_nid)
- continue;
- /* when aamix is disabled, force to off */
- if (!add_aamix) {
- activate_amp(codec, nid, HDA_INPUT, n, n, false);
- continue;
- }
- }
- check_and_activate_amp(codec, nid, HDA_INPUT, n, idx, enable);
- }
-}
-
-/* sync power of each widget in the given path */
-static hda_nid_t path_power_update(struct hda_codec *codec,
- struct nid_path *path,
- bool allow_powerdown)
-{
- hda_nid_t nid, changed = 0;
- int i, state, power;
-
- for (i = 0; i < path->depth; i++) {
- nid = path->path[i];
- if (!(get_wcaps(codec, nid) & AC_WCAP_POWER))
- continue;
- if (nid == codec->core.afg)
- continue;
- if (!allow_powerdown || is_active_nid_for_any(codec, nid))
- state = AC_PWRST_D0;
- else
- state = AC_PWRST_D3;
- power = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_POWER_STATE, 0);
- if (power != (state | (state << 4))) {
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_POWER_STATE, state);
- changed = nid;
- /* all known codecs seem to be capable to handl
- * widgets state even in D3, so far.
- * if any new codecs need to restore the widget
- * states after D0 transition, call the function
- * below.
- */
-#if 0 /* disabled */
- if (state == AC_PWRST_D0)
- snd_hdac_regmap_sync_node(&codec->core, nid);
-#endif
- }
- }
- return changed;
-}
-
-/* do sync with the last power state change */
-static void sync_power_state_change(struct hda_codec *codec, hda_nid_t nid)
-{
- if (nid) {
- msleep(10);
- snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_POWER_STATE, 0);
- }
-}
-
-/**
- * snd_hda_activate_path - activate or deactivate the given path
- * @codec: the HDA codec
- * @path: the path to activate/deactivate
- * @enable: flag to activate or not
- * @add_aamix: enable the input from aamix NID
- *
- * If @add_aamix is set, enable the input from aa-mix NID as well (if any).
- */
-void snd_hda_activate_path(struct hda_codec *codec, struct nid_path *path,
- bool enable, bool add_aamix)
-{
- struct hda_gen_spec *spec = codec->spec;
- int i;
-
- path->active = enable;
-
- /* make sure the widget is powered up */
- if (enable && (spec->power_down_unused || codec->power_save_node))
- path_power_update(codec, path, codec->power_save_node);
-
- for (i = path->depth - 1; i >= 0; i--) {
- hda_nid_t nid = path->path[i];
-
- if (enable && path->multi[i])
- snd_hda_codec_write_cache(codec, nid, 0,
- AC_VERB_SET_CONNECT_SEL,
- path->idx[i]);
- if (has_amp_in(codec, path, i))
- activate_amp_in(codec, path, i, enable, add_aamix);
- if (has_amp_out(codec, path, i))
- activate_amp_out(codec, path, i, enable);
- }
-}
-EXPORT_SYMBOL_GPL(snd_hda_activate_path);
-
-/* if the given path is inactive, put widgets into D3 (only if suitable) */
-static void path_power_down_sync(struct hda_codec *codec, struct nid_path *path)
-{
- struct hda_gen_spec *spec = codec->spec;
-
- if (!(spec->power_down_unused || codec->power_save_node) || path->active)
- return;
- sync_power_state_change(codec, path_power_update(codec, path, true));
-}
-
-/* turn on/off EAPD on the given pin */
-static void set_pin_eapd(struct hda_codec *codec, hda_nid_t pin, bool enable)
-{
- struct hda_gen_spec *spec = codec->spec;
- if (spec->own_eapd_ctl ||
- !(snd_hda_query_pin_caps(codec, pin) & AC_PINCAP_EAPD))
- return;
- if (spec->keep_eapd_on && !enable)
- return;
- if (codec->inv_eapd)
- enable = !enable;
- snd_hda_codec_write_cache(codec, pin, 0,
- AC_VERB_SET_EAPD_BTLENABLE,
- enable ? 0x02 : 0x00);
-}
-
-/* re-initialize the path specified by the given path index */
-static void resume_path_from_idx(struct hda_codec *codec, int path_idx)
-{
- struct nid_path *path = snd_hda_get_path_from_idx(codec, path_idx);
- if (path)
- snd_hda_activate_path(codec, path, path->active, false);
-}
-
-
-/*
- * Helper functions for creating mixer ctl elements
- */
-
-static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol);
-static int hda_gen_bind_mute_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol);
-static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol);
-
-enum {
- HDA_CTL_WIDGET_VOL,
- HDA_CTL_WIDGET_MUTE,
- HDA_CTL_BIND_MUTE,
-};
-static const struct snd_kcontrol_new control_templates[] = {
- HDA_CODEC_VOLUME(NULL, 0, 0, 0),
- /* only the put callback is replaced for handling the special mute */
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .subdevice = HDA_SUBDEV_AMP_FLAG,
- .info = snd_hda_mixer_amp_switch_info,
- .get = snd_hda_mixer_amp_switch_get,
- .put = hda_gen_mixer_mute_put, /* replaced */
- .private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0),
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .info = snd_hda_mixer_amp_switch_info,
- .get = hda_gen_bind_mute_get,
- .put = hda_gen_bind_mute_put, /* replaced */
- .private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0),
- },
-};
-
-/* add dynamic controls from template */
-static struct snd_kcontrol_new *
-add_control(struct hda_gen_spec *spec, int type, const char *name,
- int cidx, unsigned long val)
-{
- struct snd_kcontrol_new *knew;
-
- knew = snd_hda_gen_add_kctl(spec, name, &control_templates[type]);
- if (!knew)
- return NULL;
- knew->index = cidx;
- if (get_amp_nid_(val))
- knew->subdevice = HDA_SUBDEV_AMP_FLAG;
- if (knew->access == 0)
- knew->access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
- knew->private_value = val;
- return knew;
-}
-
-static int add_control_with_pfx(struct hda_gen_spec *spec, int type,
- const char *pfx, const char *dir,
- const char *sfx, int cidx, unsigned long val)
-{
- char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
- int len;
-
- len = snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
- if (snd_BUG_ON(len >= sizeof(name)))
- return -EINVAL;
- if (!add_control(spec, type, name, cidx, val))
- return -ENOMEM;
- return 0;
-}
-
-#define add_pb_vol_ctrl(spec, type, pfx, val) \
- add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
-#define add_pb_sw_ctrl(spec, type, pfx, val) \
- add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
-#define __add_pb_vol_ctrl(spec, type, pfx, cidx, val) \
- add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
-#define __add_pb_sw_ctrl(spec, type, pfx, cidx, val) \
- add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
-
-static int add_vol_ctl(struct hda_codec *codec, const char *pfx, int cidx,
- unsigned int chs, struct nid_path *path)
-{
- unsigned int val;
- if (!path)
- return 0;
- val = path->ctls[NID_PATH_VOL_CTL];
- if (!val)
- return 0;
- val = amp_val_replace_channels(val, chs);
- return __add_pb_vol_ctrl(codec->spec, HDA_CTL_WIDGET_VOL, pfx, cidx, val);
-}
-
-/* return the channel bits suitable for the given path->ctls[] */
-static int get_default_ch_nums(struct hda_codec *codec, struct nid_path *path,
- int type)
-{
- int chs = 1; /* mono (left only) */
- if (path) {
- hda_nid_t nid = get_amp_nid_(path->ctls[type]);
- if (nid && (get_wcaps(codec, nid) & AC_WCAP_STEREO))
- chs = 3; /* stereo */
- }
- return chs;
-}
-
-static int add_stereo_vol(struct hda_codec *codec, const char *pfx, int cidx,
- struct nid_path *path)
-{
- int chs = get_default_ch_nums(codec, path, NID_PATH_VOL_CTL);
- return add_vol_ctl(codec, pfx, cidx, chs, path);
-}
-
-/* create a mute-switch for the given mixer widget;
- * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
- */
-static int add_sw_ctl(struct hda_codec *codec, const char *pfx, int cidx,
- unsigned int chs, struct nid_path *path)
-{
- unsigned int val;
- int type = HDA_CTL_WIDGET_MUTE;
-
- if (!path)
- return 0;
- val = path->ctls[NID_PATH_MUTE_CTL];
- if (!val)
- return 0;
- val = amp_val_replace_channels(val, chs);
- if (get_amp_direction_(val) == HDA_INPUT) {
- hda_nid_t nid = get_amp_nid_(val);
- int nums = snd_hda_get_num_conns(codec, nid);
- if (nums > 1) {
- type = HDA_CTL_BIND_MUTE;
- val |= nums << 19;
- }
- }
- return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
-}
-
-static int add_stereo_sw(struct hda_codec *codec, const char *pfx,
- int cidx, struct nid_path *path)
-{
- int chs = get_default_ch_nums(codec, path, NID_PATH_MUTE_CTL);
- return add_sw_ctl(codec, pfx, cidx, chs, path);
-}
-
-/* playback mute control with the software mute bit check */
-static void sync_auto_mute_bits(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct hda_gen_spec *spec = codec->spec;
-
- if (spec->auto_mute_via_amp) {
- hda_nid_t nid = get_amp_nid(kcontrol);
- bool enabled = !((spec->mute_bits >> nid) & 1);
- ucontrol->value.integer.value[0] &= enabled;
- ucontrol->value.integer.value[1] &= enabled;
- }
-}
-
-static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- sync_auto_mute_bits(kcontrol, ucontrol);
- return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
-}
-
-/*
- * Bound mute controls
- */
-#define AMP_VAL_IDX_SHIFT 19
-#define AMP_VAL_IDX_MASK (0x0f<<19)
-
-static int hda_gen_bind_mute_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- unsigned long pval;
- int err;
-
- mutex_lock(&codec->control_mutex);
- pval = kcontrol->private_value;
- kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
- err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
- kcontrol->private_value = pval;
- mutex_unlock(&codec->control_mutex);
- return err;
-}
-
-static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- unsigned long pval;
- int i, indices, err = 0, change = 0;
-
- sync_auto_mute_bits(kcontrol, ucontrol);
-
- mutex_lock(&codec->control_mutex);
- pval = kcontrol->private_value;
- indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
- for (i = 0; i < indices; i++) {
- kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) |
- (i << AMP_VAL_IDX_SHIFT);
- err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
- if (err < 0)
- break;
- change |= err;
- }
- kcontrol->private_value = pval;
- mutex_unlock(&codec->control_mutex);
- return err < 0 ? err : change;
-}
-
-/* any ctl assigned to the path with the given index? */
-static bool path_has_mixer(struct hda_codec *codec, int path_idx, int ctl_type)
-{
- struct nid_path *path = snd_hda_get_path_from_idx(codec, path_idx);
- return path && path->ctls[ctl_type];
-}
-
-static const char * const channel_name[] = {
- "Front", "Surround", "CLFE", "Side", "Back",
-};
-
-/* give some appropriate ctl name prefix for the given line out channel */
-static const char *get_line_out_pfx(struct hda_codec *codec, int ch,
- int *index, int ctl_type)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->autocfg;
-
- *index = 0;
- if (cfg->line_outs == 1 && !spec->multi_ios &&
- !codec->force_pin_prefix &&
- !cfg->hp_outs && !cfg->speaker_outs)
- return spec->vmaster_mute.hook ? "PCM" : "Master";
-
- /* if there is really a single DAC used in the whole output paths,
- * use it master (or "PCM" if a vmaster hook is present)
- */
- if (spec->multiout.num_dacs == 1 && !spec->mixer_nid &&
- !codec->force_pin_prefix &&
- !spec->multiout.hp_out_nid[0] && !spec->multiout.extra_out_nid[0])
- return spec->vmaster_mute.hook ? "PCM" : "Master";
-
- /* multi-io channels */
- if (ch >= cfg->line_outs)
- goto fixed_name;
-
- switch (cfg->line_out_type) {
- case AUTO_PIN_SPEAKER_OUT:
- /* if the primary channel vol/mute is shared with HP volume,
- * don't name it as Speaker
- */
- if (!ch && cfg->hp_outs &&
- !path_has_mixer(codec, spec->hp_paths[0], ctl_type))
- break;
- if (cfg->line_outs == 1)
- return "Speaker";
- if (cfg->line_outs == 2)
- return ch ? "Bass Speaker" : "Speaker";
- break;
- case AUTO_PIN_HP_OUT:
- /* if the primary channel vol/mute is shared with spk volume,
- * don't name it as Headphone
- */
- if (!ch && cfg->speaker_outs &&
- !path_has_mixer(codec, spec->speaker_paths[0], ctl_type))
- break;
- /* for multi-io case, only the primary out */
- if (ch && spec->multi_ios)
- break;
- *index = ch;
- return "Headphone";
- case AUTO_PIN_LINE_OUT:
- /* This deals with the case where one HP or one Speaker or
- * one HP + one Speaker need to share the DAC with LO
- */
- if (!ch) {
- bool hp_lo_shared = false, spk_lo_shared = false;
-
- if (cfg->speaker_outs)
- spk_lo_shared = !path_has_mixer(codec,
- spec->speaker_paths[0], ctl_type);
- if (cfg->hp_outs)
- hp_lo_shared = !path_has_mixer(codec, spec->hp_paths[0], ctl_type);
- if (hp_lo_shared && spk_lo_shared)
- return spec->vmaster_mute.hook ? "PCM" : "Master";
- if (hp_lo_shared)
- return "Headphone+LO";
- if (spk_lo_shared)
- return "Speaker+LO";
- }
- }
-
- /* for a single channel output, we don't have to name the channel */
- if (cfg->line_outs == 1 && !spec->multi_ios)
- return "Line Out";
-
- fixed_name:
- if (ch >= ARRAY_SIZE(channel_name)) {
- snd_BUG();
- return "PCM";
- }
-
- return channel_name[ch];
-}
-
-/*
- * Parse output paths
- */
-
-/* badness definition */
-enum {
- /* No primary DAC is found for the main output */
- BAD_NO_PRIMARY_DAC = 0x10000,
- /* No DAC is found for the extra output */
- BAD_NO_DAC = 0x4000,
- /* No possible multi-ios */
- BAD_MULTI_IO = 0x120,
- /* No individual DAC for extra output */
- BAD_NO_EXTRA_DAC = 0x102,
- /* No individual DAC for extra surrounds */
- BAD_NO_EXTRA_SURR_DAC = 0x101,
- /* Primary DAC shared with main surrounds */
- BAD_SHARED_SURROUND = 0x100,
- /* No independent HP possible */
- BAD_NO_INDEP_HP = 0x10,
- /* Primary DAC shared with main CLFE */
- BAD_SHARED_CLFE = 0x10,
- /* Primary DAC shared with extra surrounds */
- BAD_SHARED_EXTRA_SURROUND = 0x10,
- /* Volume widget is shared */
- BAD_SHARED_VOL = 0x10,
-};
-
-/* look for widgets in the given path which are appropriate for
- * volume and mute controls, and assign the values to ctls[].
- *
- * When no appropriate widget is found in the path, the badness value
- * is incremented depending on the situation. The function returns the
- * total badness for both volume and mute controls.
- */
-static int assign_out_path_ctls(struct hda_codec *codec, struct nid_path *path)
-{
- struct hda_gen_spec *spec = codec->spec;
- hda_nid_t nid;
- unsigned int val;
- int badness = 0;
-
- if (!path)
- return BAD_SHARED_VOL * 2;
-
- if (path->ctls[NID_PATH_VOL_CTL] ||
- path->ctls[NID_PATH_MUTE_CTL])
- return 0; /* already evaluated */
-
- nid = look_for_out_vol_nid(codec, path);
- if (nid) {
- val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
- if (spec->dac_min_mute)
- val |= HDA_AMP_VAL_MIN_MUTE;
- if (is_ctl_used(codec, val, NID_PATH_VOL_CTL))
- badness += BAD_SHARED_VOL;
- else
- path->ctls[NID_PATH_VOL_CTL] = val;
- } else
- badness += BAD_SHARED_VOL;
- nid = look_for_out_mute_nid(codec, path);
- if (nid) {
- unsigned int wid_type = get_wcaps_type(get_wcaps(codec, nid));
- if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT ||
- nid_has_mute(codec, nid, HDA_OUTPUT))
- val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
- else
- val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT);
- if (is_ctl_used(codec, val, NID_PATH_MUTE_CTL))
- badness += BAD_SHARED_VOL;
- else
- path->ctls[NID_PATH_MUTE_CTL] = val;
- } else
- badness += BAD_SHARED_VOL;
- return badness;
-}
-
-const struct badness_table hda_main_out_badness = {
- .no_primary_dac = BAD_NO_PRIMARY_DAC,
- .no_dac = BAD_NO_DAC,
- .shared_primary = BAD_NO_PRIMARY_DAC,
- .shared_surr = BAD_SHARED_SURROUND,
- .shared_clfe = BAD_SHARED_CLFE,
- .shared_surr_main = BAD_SHARED_SURROUND,
-};
-EXPORT_SYMBOL_GPL(hda_main_out_badness);
-
-const struct badness_table hda_extra_out_badness = {
- .no_primary_dac = BAD_NO_DAC,
- .no_dac = BAD_NO_DAC,
- .shared_primary = BAD_NO_EXTRA_DAC,
- .shared_surr = BAD_SHARED_EXTRA_SURROUND,
- .shared_clfe = BAD_SHARED_EXTRA_SURROUND,
- .shared_surr_main = BAD_NO_EXTRA_SURR_DAC,
-};
-EXPORT_SYMBOL_GPL(hda_extra_out_badness);
-
-/* get the DAC of the primary output corresponding to the given array index */
-static hda_nid_t get_primary_out(struct hda_codec *codec, int idx)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->autocfg;
-
- if (cfg->line_outs > idx)
- return spec->private_dac_nids[idx];
- idx -= cfg->line_outs;
- if (spec->multi_ios > idx)
- return spec->multi_io[idx].dac;
- return 0;
-}
-
-/* return the DAC if it's reachable, otherwise zero */
-static inline hda_nid_t try_dac(struct hda_codec *codec,
- hda_nid_t dac, hda_nid_t pin)
-{
- return is_reachable_path(codec, dac, pin) ? dac : 0;
-}
-
-/* try to assign DACs to pins and return the resultant badness */
-static int try_assign_dacs(struct hda_codec *codec, int num_outs,
- const hda_nid_t *pins, hda_nid_t *dacs,
- int *path_idx,
- const struct badness_table *bad)
-{
- struct hda_gen_spec *spec = codec->spec;
- int i, j;
- int badness = 0;
- hda_nid_t dac;
-
- if (!num_outs)
- return 0;
-
- for (i = 0; i < num_outs; i++) {
- struct nid_path *path;
- hda_nid_t pin = pins[i];
-
- if (!spec->preferred_dacs) {
- path = snd_hda_get_path_from_idx(codec, path_idx[i]);
- if (path) {
- badness += assign_out_path_ctls(codec, path);
- continue;
- }
- }
-
- dacs[i] = get_preferred_dac(codec, pin);
- if (dacs[i]) {
- if (is_dac_already_used(codec, dacs[i]))
- badness += bad->shared_primary;
- } else if (spec->preferred_dacs) {
- badness += BAD_NO_PRIMARY_DAC;
- }
-
- if (!dacs[i])
- dacs[i] = look_for_dac(codec, pin, false);
- if (!dacs[i] && !i) {
- /* try to steal the DAC of surrounds for the front */
- for (j = 1; j < num_outs; j++) {
- if (is_reachable_path(codec, dacs[j], pin)) {
- dacs[0] = dacs[j];
- dacs[j] = 0;
- invalidate_nid_path(codec, path_idx[j]);
- path_idx[j] = 0;
- break;
- }
- }
- }
- dac = dacs[i];
- if (!dac) {
- if (num_outs > 2)
- dac = try_dac(codec, get_primary_out(codec, i), pin);
- if (!dac)
- dac = try_dac(codec, dacs[0], pin);
- if (!dac)
- dac = try_dac(codec, get_primary_out(codec, i), pin);
- if (dac) {
- if (!i)
- badness += bad->shared_primary;
- else if (i == 1)
- badness += bad->shared_surr;
- else
- badness += bad->shared_clfe;
- } else if (is_reachable_path(codec, spec->private_dac_nids[0], pin)) {
- dac = spec->private_dac_nids[0];
- badness += bad->shared_surr_main;
- } else if (!i)
- badness += bad->no_primary_dac;
- else
- badness += bad->no_dac;
- }
- if (!dac)
- continue;
- path = snd_hda_add_new_path(codec, dac, pin, -spec->mixer_nid);
- if (!path && !i && spec->mixer_nid) {
- /* try with aamix */
- path = snd_hda_add_new_path(codec, dac, pin, 0);
- }
- if (!path) {
- dacs[i] = 0;
- badness += bad->no_dac;
- } else {
- /* print_nid_path(codec, "output", path); */
- path->active = true;
- path_idx[i] = snd_hda_get_path_idx(codec, path);
- badness += assign_out_path_ctls(codec, path);
- }
- }
-
- return badness;
-}
-
-/* return NID if the given pin has only a single connection to a certain DAC */
-static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
-{
- struct hda_gen_spec *spec = codec->spec;
- int i;
- hda_nid_t nid_found = 0;
-
- for (i = 0; i < spec->num_all_dacs; i++) {
- hda_nid_t nid = spec->all_dacs[i];
- if (!nid || is_dac_already_used(codec, nid))
- continue;
- if (is_reachable_path(codec, nid, pin)) {
- if (nid_found)
- return 0;
- nid_found = nid;
- }
- }
- return nid_found;
-}
-
-/* check whether the given pin can be a multi-io pin */
-static bool can_be_multiio_pin(struct hda_codec *codec,
- unsigned int location, hda_nid_t nid)
-{
- unsigned int defcfg, caps;
-
- defcfg = snd_hda_codec_get_pincfg(codec, nid);
- if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
- return false;
- if (location && get_defcfg_location(defcfg) != location)
- return false;
- caps = snd_hda_query_pin_caps(codec, nid);
- if (!(caps & AC_PINCAP_OUT))
- return false;
- return true;
-}
-
-/* count the number of input pins that are capable to be multi-io */
-static int count_multiio_pins(struct hda_codec *codec, hda_nid_t reference_pin)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->autocfg;
- unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
- unsigned int location = get_defcfg_location(defcfg);
- int type, i;
- int num_pins = 0;
-
- for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
- for (i = 0; i < cfg->num_inputs; i++) {
- if (cfg->inputs[i].type != type)
- continue;
- if (can_be_multiio_pin(codec, location,
- cfg->inputs[i].pin))
- num_pins++;
- }
- }
- return num_pins;
-}
-
-/*
- * multi-io helper
- *
- * When hardwired is set, try to fill ony hardwired pins, and returns
- * zero if any pins are filled, non-zero if nothing found.
- * When hardwired is off, try to fill possible input pins, and returns
- * the badness value.
- */
-static int fill_multi_ios(struct hda_codec *codec,
- hda_nid_t reference_pin,
- bool hardwired)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->autocfg;
- int type, i, j, num_pins, old_pins;
- unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
- unsigned int location = get_defcfg_location(defcfg);
- int badness = 0;
- struct nid_path *path;
-
- old_pins = spec->multi_ios;
- if (old_pins >= 2)
- goto end_fill;
-
- num_pins = count_multiio_pins(codec, reference_pin);
- if (num_pins < 2)
- goto end_fill;
-
- for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
- for (i = 0; i < cfg->num_inputs; i++) {
- hda_nid_t nid = cfg->inputs[i].pin;
- hda_nid_t dac = 0;
-
- if (cfg->inputs[i].type != type)
- continue;
- if (!can_be_multiio_pin(codec, location, nid))
- continue;
- for (j = 0; j < spec->multi_ios; j++) {
- if (nid == spec->multi_io[j].pin)
- break;
- }
- if (j < spec->multi_ios)
- continue;
-
- if (hardwired)
- dac = get_dac_if_single(codec, nid);
- else if (!dac)
- dac = look_for_dac(codec, nid, false);
- if (!dac) {
- badness++;
- continue;
- }
- path = snd_hda_add_new_path(codec, dac, nid,
- -spec->mixer_nid);
- if (!path) {
- badness++;
- continue;
- }
- /* print_nid_path(codec, "multiio", path); */
- spec->multi_io[spec->multi_ios].pin = nid;
- spec->multi_io[spec->multi_ios].dac = dac;
- spec->out_paths[cfg->line_outs + spec->multi_ios] =
- snd_hda_get_path_idx(codec, path);
- spec->multi_ios++;
- if (spec->multi_ios >= 2)
- break;
- }
- }
- end_fill:
- if (badness)
- badness = BAD_MULTI_IO;
- if (old_pins == spec->multi_ios) {
- if (hardwired)
- return 1; /* nothing found */
- else
- return badness; /* no badness if nothing found */
- }
- if (!hardwired && spec->multi_ios < 2) {
- /* cancel newly assigned paths */
- spec->paths.used -= spec->multi_ios - old_pins;
- spec->multi_ios = old_pins;
- return badness;
- }
-
- /* assign volume and mute controls */
- for (i = old_pins; i < spec->multi_ios; i++) {
- path = snd_hda_get_path_from_idx(codec, spec->out_paths[cfg->line_outs + i]);
- badness += assign_out_path_ctls(codec, path);
- }
-
- return badness;
-}
-
-/* map DACs for all pins in the list if they are single connections */
-static bool map_singles(struct hda_codec *codec, int outs,
- const hda_nid_t *pins, hda_nid_t *dacs, int *path_idx)
-{
- struct hda_gen_spec *spec = codec->spec;
- int i;
- bool found = false;
- for (i = 0; i < outs; i++) {
- struct nid_path *path;
- hda_nid_t dac;
- if (dacs[i])
- continue;
- dac = get_dac_if_single(codec, pins[i]);
- if (!dac)
- continue;
- path = snd_hda_add_new_path(codec, dac, pins[i],
- -spec->mixer_nid);
- if (!path && !i && spec->mixer_nid)
- path = snd_hda_add_new_path(codec, dac, pins[i], 0);
- if (path) {
- dacs[i] = dac;
- found = true;
- /* print_nid_path(codec, "output", path); */
- path->active = true;
- path_idx[i] = snd_hda_get_path_idx(codec, path);
- }
- }
- return found;
-}
-
-static inline bool has_aamix_out_paths(struct hda_gen_spec *spec)
-{
- return spec->aamix_out_paths[0] || spec->aamix_out_paths[1] ||
- spec->aamix_out_paths[2];
-}
-
-/* create a new path including aamix if available, and return its index */
-static int check_aamix_out_path(struct hda_codec *codec, int path_idx)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct nid_path *path;
- hda_nid_t path_dac, dac, pin;
-
- path = snd_hda_get_path_from_idx(codec, path_idx);
- if (!path || !path->depth ||
- is_nid_contained(path, spec->mixer_nid))
- return 0;
- path_dac = path->path[0];
- dac = spec->private_dac_nids[0];
- pin = path->path[path->depth - 1];
- path = snd_hda_add_new_path(codec, dac, pin, spec->mixer_nid);
- if (!path) {
- if (dac != path_dac)
- dac = path_dac;
- else if (spec->multiout.hp_out_nid[0])
- dac = spec->multiout.hp_out_nid[0];
- else if (spec->multiout.extra_out_nid[0])
- dac = spec->multiout.extra_out_nid[0];
- else
- dac = 0;
- if (dac)
- path = snd_hda_add_new_path(codec, dac, pin,
- spec->mixer_nid);
- }
- if (!path)
- return 0;
- /* print_nid_path(codec, "output-aamix", path); */
- path->active = false; /* unused as default */
- path->pin_fixed = true; /* static route */
- return snd_hda_get_path_idx(codec, path);
-}
-
-/* check whether the independent HP is available with the current config */
-static bool indep_hp_possible(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->autocfg;
- struct nid_path *path;
- int i, idx;
-
- if (cfg->line_out_type == AUTO_PIN_HP_OUT)
- idx = spec->out_paths[0];
- else
- idx = spec->hp_paths[0];
- path = snd_hda_get_path_from_idx(codec, idx);
- if (!path)
- return false;
-
- /* assume no path conflicts unless aamix is involved */
- if (!spec->mixer_nid || !is_nid_contained(path, spec->mixer_nid))
- return true;
-
- /* check whether output paths contain aamix */
- for (i = 0; i < cfg->line_outs; i++) {
- if (spec->out_paths[i] == idx)
- break;
- path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]);
- if (path && is_nid_contained(path, spec->mixer_nid))
- return false;
- }
- for (i = 0; i < cfg->speaker_outs; i++) {
- path = snd_hda_get_path_from_idx(codec, spec->speaker_paths[i]);
- if (path && is_nid_contained(path, spec->mixer_nid))
- return false;
- }
-
- return true;
-}
-
-/* fill the empty entries in the dac array for speaker/hp with the
- * shared dac pointed by the paths
- */
-static void refill_shared_dacs(struct hda_codec *codec, int num_outs,
- hda_nid_t *dacs, int *path_idx)
-{
- struct nid_path *path;
- int i;
-
- for (i = 0; i < num_outs; i++) {
- if (dacs[i])
- continue;
- path = snd_hda_get_path_from_idx(codec, path_idx[i]);
- if (!path)
- continue;
- dacs[i] = path->path[0];
- }
-}
-
-/* fill in the dac_nids table from the parsed pin configuration */
-static int fill_and_eval_dacs(struct hda_codec *codec,
- bool fill_hardwired,
- bool fill_mio_first)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->autocfg;
- int i, err, badness;
-
- /* set num_dacs once to full for look_for_dac() */
- spec->multiout.num_dacs = cfg->line_outs;
- spec->multiout.dac_nids = spec->private_dac_nids;
- memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
- memset(spec->multiout.hp_out_nid, 0, sizeof(spec->multiout.hp_out_nid));
- memset(spec->multiout.extra_out_nid, 0, sizeof(spec->multiout.extra_out_nid));
- spec->multi_ios = 0;
- snd_array_free(&spec->paths);
-
- /* clear path indices */
- memset(spec->out_paths, 0, sizeof(spec->out_paths));
- memset(spec->hp_paths, 0, sizeof(spec->hp_paths));
- memset(spec->speaker_paths, 0, sizeof(spec->speaker_paths));
- memset(spec->aamix_out_paths, 0, sizeof(spec->aamix_out_paths));
- memset(spec->digout_paths, 0, sizeof(spec->digout_paths));
- memset(spec->input_paths, 0, sizeof(spec->input_paths));
- memset(spec->loopback_paths, 0, sizeof(spec->loopback_paths));
- memset(&spec->digin_path, 0, sizeof(spec->digin_path));
-
- badness = 0;
-
- /* fill hard-wired DACs first */
- if (fill_hardwired) {
- bool mapped;
- do {
- mapped = map_singles(codec, cfg->line_outs,
- cfg->line_out_pins,
- spec->private_dac_nids,
- spec->out_paths);
- mapped |= map_singles(codec, cfg->hp_outs,
- cfg->hp_pins,
- spec->multiout.hp_out_nid,
- spec->hp_paths);
- mapped |= map_singles(codec, cfg->speaker_outs,
- cfg->speaker_pins,
- spec->multiout.extra_out_nid,
- spec->speaker_paths);
- if (!spec->no_multi_io &&
- fill_mio_first && cfg->line_outs == 1 &&
- cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
- err = fill_multi_ios(codec, cfg->line_out_pins[0], true);
- if (!err)
- mapped = true;
- }
- } while (mapped);
- }
-
- badness += try_assign_dacs(codec, cfg->line_outs, cfg->line_out_pins,
- spec->private_dac_nids, spec->out_paths,
- spec->main_out_badness);
-
- if (!spec->no_multi_io && fill_mio_first &&
- cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
- /* try to fill multi-io first */
- err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
- if (err < 0)
- return err;
- /* we don't count badness at this stage yet */
- }
-
- if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
- err = try_assign_dacs(codec, cfg->hp_outs, cfg->hp_pins,
- spec->multiout.hp_out_nid,
- spec->hp_paths,
- spec->extra_out_badness);
- if (err < 0)
- return err;
- badness += err;
- }
- if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
- err = try_assign_dacs(codec, cfg->speaker_outs,
- cfg->speaker_pins,
- spec->multiout.extra_out_nid,
- spec->speaker_paths,
- spec->extra_out_badness);
- if (err < 0)
- return err;
- badness += err;
- }
- if (!spec->no_multi_io &&
- cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
- err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
- if (err < 0)
- return err;
- badness += err;
- }
-
- if (spec->mixer_nid) {
- spec->aamix_out_paths[0] =
- check_aamix_out_path(codec, spec->out_paths[0]);
- if (cfg->line_out_type != AUTO_PIN_HP_OUT)
- spec->aamix_out_paths[1] =
- check_aamix_out_path(codec, spec->hp_paths[0]);
- if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
- spec->aamix_out_paths[2] =
- check_aamix_out_path(codec, spec->speaker_paths[0]);
- }
-
- if (!spec->no_multi_io &&
- cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
- if (count_multiio_pins(codec, cfg->hp_pins[0]) >= 2)
- spec->multi_ios = 1; /* give badness */
-
- /* re-count num_dacs and squash invalid entries */
- spec->multiout.num_dacs = 0;
- for (i = 0; i < cfg->line_outs; i++) {
- if (spec->private_dac_nids[i])
- spec->multiout.num_dacs++;
- else {
- memmove(spec->private_dac_nids + i,
- spec->private_dac_nids + i + 1,
- sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
- spec->private_dac_nids[cfg->line_outs - 1] = 0;
- }
- }
-
- spec->ext_channel_count = spec->min_channel_count =
- spec->multiout.num_dacs * 2;
-
- if (spec->multi_ios == 2) {
- for (i = 0; i < 2; i++)
- spec->private_dac_nids[spec->multiout.num_dacs++] =
- spec->multi_io[i].dac;
- } else if (spec->multi_ios) {
- spec->multi_ios = 0;
- badness += BAD_MULTI_IO;
- }
-
- if (spec->indep_hp && !indep_hp_possible(codec))
- badness += BAD_NO_INDEP_HP;
-
- /* re-fill the shared DAC for speaker / headphone */
- if (cfg->line_out_type != AUTO_PIN_HP_OUT)
- refill_shared_dacs(codec, cfg->hp_outs,
- spec->multiout.hp_out_nid,
- spec->hp_paths);
- if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
- refill_shared_dacs(codec, cfg->speaker_outs,
- spec->multiout.extra_out_nid,
- spec->speaker_paths);
-
- return badness;
-}
-
-#define DEBUG_BADNESS
-
-#ifdef DEBUG_BADNESS
-#define debug_badness(fmt, ...) \
- codec_dbg(codec, fmt, ##__VA_ARGS__)
-#else
-#define debug_badness(fmt, ...) \
- do { if (0) codec_dbg(codec, fmt, ##__VA_ARGS__); } while (0)
-#endif
-
-#ifdef DEBUG_BADNESS
-static inline void print_nid_path_idx(struct hda_codec *codec,
- const char *pfx, int idx)
-{
- struct nid_path *path;
-
- path = snd_hda_get_path_from_idx(codec, idx);
- if (path)
- print_nid_path(codec, pfx, path);
-}
-
-static void debug_show_configs(struct hda_codec *codec,
- struct auto_pin_cfg *cfg)
-{
- struct hda_gen_spec *spec = codec->spec;
- static const char * const lo_type[3] = { "LO", "SP", "HP" };
- int i;
-
- debug_badness("multi_outs = %x/%x/%x/%x : %x/%x/%x/%x (type %s)\n",
- cfg->line_out_pins[0], cfg->line_out_pins[1],
- cfg->line_out_pins[2], cfg->line_out_pins[3],
- spec->multiout.dac_nids[0],
- spec->multiout.dac_nids[1],
- spec->multiout.dac_nids[2],
- spec->multiout.dac_nids[3],
- lo_type[cfg->line_out_type]);
- for (i = 0; i < cfg->line_outs; i++)
- print_nid_path_idx(codec, " out", spec->out_paths[i]);
- if (spec->multi_ios > 0)
- debug_badness("multi_ios(%d) = %x/%x : %x/%x\n",
- spec->multi_ios,
- spec->multi_io[0].pin, spec->multi_io[1].pin,
- spec->multi_io[0].dac, spec->multi_io[1].dac);
- for (i = 0; i < spec->multi_ios; i++)
- print_nid_path_idx(codec, " mio",
- spec->out_paths[cfg->line_outs + i]);
- if (cfg->hp_outs)
- debug_badness("hp_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
- cfg->hp_pins[0], cfg->hp_pins[1],
- cfg->hp_pins[2], cfg->hp_pins[3],
- spec->multiout.hp_out_nid[0],
- spec->multiout.hp_out_nid[1],
- spec->multiout.hp_out_nid[2],
- spec->multiout.hp_out_nid[3]);
- for (i = 0; i < cfg->hp_outs; i++)
- print_nid_path_idx(codec, " hp ", spec->hp_paths[i]);
- if (cfg->speaker_outs)
- debug_badness("spk_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
- cfg->speaker_pins[0], cfg->speaker_pins[1],
- cfg->speaker_pins[2], cfg->speaker_pins[3],
- spec->multiout.extra_out_nid[0],
- spec->multiout.extra_out_nid[1],
- spec->multiout.extra_out_nid[2],
- spec->multiout.extra_out_nid[3]);
- for (i = 0; i < cfg->speaker_outs; i++)
- print_nid_path_idx(codec, " spk", spec->speaker_paths[i]);
- for (i = 0; i < 3; i++)
- print_nid_path_idx(codec, " mix", spec->aamix_out_paths[i]);
-}
-#else
-#define debug_show_configs(codec, cfg) /* NOP */
-#endif
-
-/* find all available DACs of the codec */
-static void fill_all_dac_nids(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
- hda_nid_t nid;
-
- spec->num_all_dacs = 0;
- memset(spec->all_dacs, 0, sizeof(spec->all_dacs));
- for_each_hda_codec_node(nid, codec) {
- if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_AUD_OUT)
- continue;
- if (spec->num_all_dacs >= ARRAY_SIZE(spec->all_dacs)) {
- codec_err(codec, "Too many DACs!\n");
- break;
- }
- spec->all_dacs[spec->num_all_dacs++] = nid;
- }
-}
-
-static int parse_output_paths(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->autocfg;
- struct auto_pin_cfg *best_cfg;
- unsigned int val;
- int best_badness = INT_MAX;
- int badness;
- bool fill_hardwired = true, fill_mio_first = true;
- bool best_wired = true, best_mio = true;
- bool hp_spk_swapped = false;
-
- best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL);
- if (!best_cfg)
- return -ENOMEM;
- *best_cfg = *cfg;
-
- for (;;) {
- badness = fill_and_eval_dacs(codec, fill_hardwired,
- fill_mio_first);
- if (badness < 0) {
- kfree(best_cfg);
- return badness;
- }
- debug_badness("==> lo_type=%d, wired=%d, mio=%d, badness=0x%x\n",
- cfg->line_out_type, fill_hardwired, fill_mio_first,
- badness);
- debug_show_configs(codec, cfg);
- if (badness < best_badness) {
- best_badness = badness;
- *best_cfg = *cfg;
- best_wired = fill_hardwired;
- best_mio = fill_mio_first;
- }
- if (!badness)
- break;
- fill_mio_first = !fill_mio_first;
- if (!fill_mio_first)
- continue;
- fill_hardwired = !fill_hardwired;
- if (!fill_hardwired)
- continue;
- if (hp_spk_swapped)
- break;
- hp_spk_swapped = true;
- if (cfg->speaker_outs > 0 &&
- cfg->line_out_type == AUTO_PIN_HP_OUT) {
- cfg->hp_outs = cfg->line_outs;
- memcpy(cfg->hp_pins, cfg->line_out_pins,
- sizeof(cfg->hp_pins));
- cfg->line_outs = cfg->speaker_outs;
- memcpy(cfg->line_out_pins, cfg->speaker_pins,
- sizeof(cfg->speaker_pins));
- cfg->speaker_outs = 0;
- memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
- cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
- fill_hardwired = true;
- continue;
- }
- if (cfg->hp_outs > 0 &&
- cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
- cfg->speaker_outs = cfg->line_outs;
- memcpy(cfg->speaker_pins, cfg->line_out_pins,
- sizeof(cfg->speaker_pins));
- cfg->line_outs = cfg->hp_outs;
- memcpy(cfg->line_out_pins, cfg->hp_pins,
- sizeof(cfg->hp_pins));
- cfg->hp_outs = 0;
- memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
- cfg->line_out_type = AUTO_PIN_HP_OUT;
- fill_hardwired = true;
- continue;
- }
- break;
- }
-
- if (badness) {
- debug_badness("==> restoring best_cfg\n");
- *cfg = *best_cfg;
- fill_and_eval_dacs(codec, best_wired, best_mio);
- }
- debug_badness("==> Best config: lo_type=%d, wired=%d, mio=%d\n",
- cfg->line_out_type, best_wired, best_mio);
- debug_show_configs(codec, cfg);
-
- if (cfg->line_out_pins[0]) {
- struct nid_path *path;
- path = snd_hda_get_path_from_idx(codec, spec->out_paths[0]);
- if (path)
- spec->vmaster_nid = look_for_out_vol_nid(codec, path);
- if (spec->vmaster_nid) {
- snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
- HDA_OUTPUT, spec->vmaster_tlv);
- if (spec->dac_min_mute)
- spec->vmaster_tlv[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP] |= TLV_DB_SCALE_MUTE;
- }
- }
-
- /* set initial pinctl targets */
- if (spec->prefer_hp_amp || cfg->line_out_type == AUTO_PIN_HP_OUT)
- val = PIN_HP;
- else
- val = PIN_OUT;
- set_pin_targets(codec, cfg->line_outs, cfg->line_out_pins, val);
- if (cfg->line_out_type != AUTO_PIN_HP_OUT)
- set_pin_targets(codec, cfg->hp_outs, cfg->hp_pins, PIN_HP);
- if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
- val = spec->prefer_hp_amp ? PIN_HP : PIN_OUT;
- set_pin_targets(codec, cfg->speaker_outs,
- cfg->speaker_pins, val);
- }
-
- /* clear indep_hp flag if not available */
- if (spec->indep_hp && !indep_hp_possible(codec))
- spec->indep_hp = 0;
-
- kfree(best_cfg);
- return 0;
-}
-
-/* add playback controls from the parsed DAC table */
-static int create_multi_out_ctls(struct hda_codec *codec,
- const struct auto_pin_cfg *cfg)
-{
- struct hda_gen_spec *spec = codec->spec;
- int i, err, noutputs;
-
- noutputs = cfg->line_outs;
- if (spec->multi_ios > 0 && cfg->line_outs < 3)
- noutputs += spec->multi_ios;
-
- for (i = 0; i < noutputs; i++) {
- const char *name;
- int index;
- struct nid_path *path;
-
- path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]);
- if (!path)
- continue;
-
- name = get_line_out_pfx(codec, i, &index, NID_PATH_VOL_CTL);
- if (!name || !strcmp(name, "CLFE")) {
- /* Center/LFE */
- err = add_vol_ctl(codec, "Center", 0, 1, path);
- if (err < 0)
- return err;
- err = add_vol_ctl(codec, "LFE", 0, 2, path);
- if (err < 0)
- return err;
- } else {
- err = add_stereo_vol(codec, name, index, path);
- if (err < 0)
- return err;
- }
-
- name = get_line_out_pfx(codec, i, &index, NID_PATH_MUTE_CTL);
- if (!name || !strcmp(name, "CLFE")) {
- err = add_sw_ctl(codec, "Center", 0, 1, path);
- if (err < 0)
- return err;
- err = add_sw_ctl(codec, "LFE", 0, 2, path);
- if (err < 0)
- return err;
- } else {
- err = add_stereo_sw(codec, name, index, path);
- if (err < 0)
- return err;
- }
- }
- return 0;
-}
-
-static int create_extra_out(struct hda_codec *codec, int path_idx,
- const char *pfx, int cidx)
-{
- struct nid_path *path;
- int err;
-
- path = snd_hda_get_path_from_idx(codec, path_idx);
- if (!path)
- return 0;
- err = add_stereo_vol(codec, pfx, cidx, path);
- if (err < 0)
- return err;
- err = add_stereo_sw(codec, pfx, cidx, path);
- if (err < 0)
- return err;
- return 0;
-}
-
-/* add playback controls for speaker and HP outputs */
-static int create_extra_outs(struct hda_codec *codec, int num_pins,
- const int *paths, const char *pfx)
-{
- int i;
-
- for (i = 0; i < num_pins; i++) {
- const char *name;
- char tmp[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
- int err, idx = 0;
-
- if (num_pins == 2 && i == 1 && !strcmp(pfx, "Speaker"))
- name = "Bass Speaker";
- else if (num_pins >= 3) {
- snprintf(tmp, sizeof(tmp), "%s %s",
- pfx, channel_name[i]);
- name = tmp;
- } else {
- name = pfx;
- idx = i;
- }
- err = create_extra_out(codec, paths[i], name, idx);
- if (err < 0)
- return err;
- }
- return 0;
-}
-
-static int create_hp_out_ctls(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
- return create_extra_outs(codec, spec->autocfg.hp_outs,
- spec->hp_paths,
- "Headphone");
-}
-
-static int create_speaker_out_ctls(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
- return create_extra_outs(codec, spec->autocfg.speaker_outs,
- spec->speaker_paths,
- "Speaker");
-}
-
-/*
- * independent HP controls
- */
-
-static void call_hp_automute(struct hda_codec *codec,
- struct hda_jack_callback *jack);
-static int indep_hp_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
-}
-
-static int indep_hp_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct hda_gen_spec *spec = codec->spec;
- ucontrol->value.enumerated.item[0] = spec->indep_hp_enabled;
- return 0;
-}
-
-static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
- int nomix_path_idx, int mix_path_idx,
- int out_type);
-
-static int indep_hp_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct hda_gen_spec *spec = codec->spec;
- unsigned int select = ucontrol->value.enumerated.item[0];
- int ret = 0;
-
- mutex_lock(&spec->pcm_mutex);
- if (spec->active_streams) {
- ret = -EBUSY;
- goto unlock;
- }
-
- if (spec->indep_hp_enabled != select) {
- hda_nid_t *dacp;
- if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
- dacp = &spec->private_dac_nids[0];
- else
- dacp = &spec->multiout.hp_out_nid[0];
-
- /* update HP aamix paths in case it conflicts with indep HP */
- if (spec->have_aamix_ctl) {
- if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
- update_aamix_paths(codec, spec->aamix_mode,
- spec->out_paths[0],
- spec->aamix_out_paths[0],
- spec->autocfg.line_out_type);
- else
- update_aamix_paths(codec, spec->aamix_mode,
- spec->hp_paths[0],
- spec->aamix_out_paths[1],
- AUTO_PIN_HP_OUT);
- }
-
- spec->indep_hp_enabled = select;
- if (spec->indep_hp_enabled)
- *dacp = 0;
- else
- *dacp = spec->alt_dac_nid;
-
- call_hp_automute(codec, NULL);
- ret = 1;
- }
- unlock:
- mutex_unlock(&spec->pcm_mutex);
- return ret;
-}
-
-static const struct snd_kcontrol_new indep_hp_ctl = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Independent HP",
- .info = indep_hp_info,
- .get = indep_hp_get,
- .put = indep_hp_put,
-};
-
-
-static int create_indep_hp_ctls(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
- hda_nid_t dac;
-
- if (!spec->indep_hp)
- return 0;
- if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
- dac = spec->multiout.dac_nids[0];
- else
- dac = spec->multiout.hp_out_nid[0];
- if (!dac) {
- spec->indep_hp = 0;
- return 0;
- }
-
- spec->indep_hp_enabled = false;
- spec->alt_dac_nid = dac;
- if (!snd_hda_gen_add_kctl(spec, NULL, &indep_hp_ctl))
- return -ENOMEM;
- return 0;
-}
-
-/*
- * channel mode enum control
- */
-
-static int ch_mode_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct hda_gen_spec *spec = codec->spec;
- int chs;
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = spec->multi_ios + 1;
- if (uinfo->value.enumerated.item > spec->multi_ios)
- uinfo->value.enumerated.item = spec->multi_ios;
- chs = uinfo->value.enumerated.item * 2 + spec->min_channel_count;
- sprintf(uinfo->value.enumerated.name, "%dch", chs);
- return 0;
-}
-
-static int ch_mode_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct hda_gen_spec *spec = codec->spec;
- ucontrol->value.enumerated.item[0] =
- (spec->ext_channel_count - spec->min_channel_count) / 2;
- return 0;
-}
-
-static inline struct nid_path *
-get_multiio_path(struct hda_codec *codec, int idx)
-{
- struct hda_gen_spec *spec = codec->spec;
- return snd_hda_get_path_from_idx(codec,
- spec->out_paths[spec->autocfg.line_outs + idx]);
-}
-
-static void update_automute_all(struct hda_codec *codec);
-
-/* Default value to be passed as aamix argument for snd_hda_activate_path();
- * used for output paths
- */
-static bool aamix_default(struct hda_gen_spec *spec)
-{
- return !spec->have_aamix_ctl || spec->aamix_mode;
-}
-
-static int set_multi_io(struct hda_codec *codec, int idx, bool output)
-{
- struct hda_gen_spec *spec = codec->spec;
- hda_nid_t nid = spec->multi_io[idx].pin;
- struct nid_path *path;
-
- path = get_multiio_path(codec, idx);
- if (!path)
- return -EINVAL;
-
- if (path->active == output)
- return 0;
-
- if (output) {
- set_pin_target(codec, nid, PIN_OUT, true);
- snd_hda_activate_path(codec, path, true, aamix_default(spec));
- set_pin_eapd(codec, nid, true);
- } else {
- set_pin_eapd(codec, nid, false);
- snd_hda_activate_path(codec, path, false, aamix_default(spec));
- set_pin_target(codec, nid, spec->multi_io[idx].ctl_in, true);
- path_power_down_sync(codec, path);
- }
-
- /* update jack retasking in case it modifies any of them */
- update_automute_all(codec);
-
- return 0;
-}
-
-static int ch_mode_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct hda_gen_spec *spec = codec->spec;
- int i, ch;
-
- ch = ucontrol->value.enumerated.item[0];
- if (ch < 0 || ch > spec->multi_ios)
- return -EINVAL;
- if (ch == (spec->ext_channel_count - spec->min_channel_count) / 2)
- return 0;
- spec->ext_channel_count = ch * 2 + spec->min_channel_count;
- for (i = 0; i < spec->multi_ios; i++)
- set_multi_io(codec, i, i < ch);
- spec->multiout.max_channels = max(spec->ext_channel_count,
- spec->const_channel_count);
- if (spec->need_dac_fix)
- spec->multiout.num_dacs = spec->multiout.max_channels / 2;
- return 1;
-}
-
-static const struct snd_kcontrol_new channel_mode_enum = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Channel Mode",
- .info = ch_mode_info,
- .get = ch_mode_get,
- .put = ch_mode_put,
-};
-
-static int create_multi_channel_mode(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
-
- if (spec->multi_ios > 0) {
- if (!snd_hda_gen_add_kctl(spec, NULL, &channel_mode_enum))
- return -ENOMEM;
- }
- return 0;
-}
-
-/*
- * aamix loopback enable/disable switch
- */
-
-#define loopback_mixing_info indep_hp_info
-
-static int loopback_mixing_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct hda_gen_spec *spec = codec->spec;
- ucontrol->value.enumerated.item[0] = spec->aamix_mode;
- return 0;
-}
-
-static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
- int nomix_path_idx, int mix_path_idx,
- int out_type)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct nid_path *nomix_path, *mix_path;
-
- nomix_path = snd_hda_get_path_from_idx(codec, nomix_path_idx);
- mix_path = snd_hda_get_path_from_idx(codec, mix_path_idx);
- if (!nomix_path || !mix_path)
- return;
-
- /* if HP aamix path is driven from a different DAC and the
- * independent HP mode is ON, can't turn on aamix path
- */
- if (out_type == AUTO_PIN_HP_OUT && spec->indep_hp_enabled &&
- mix_path->path[0] != spec->alt_dac_nid)
- do_mix = false;
-
- if (do_mix) {
- snd_hda_activate_path(codec, nomix_path, false, true);
- snd_hda_activate_path(codec, mix_path, true, true);
- path_power_down_sync(codec, nomix_path);
- } else {
- snd_hda_activate_path(codec, mix_path, false, false);
- snd_hda_activate_path(codec, nomix_path, true, false);
- path_power_down_sync(codec, mix_path);
- }
-}
-
-/* re-initialize the output paths; only called from loopback_mixing_put() */
-static void update_output_paths(struct hda_codec *codec, int num_outs,
- const int *paths)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct nid_path *path;
- int i;
-
- for (i = 0; i < num_outs; i++) {
- path = snd_hda_get_path_from_idx(codec, paths[i]);
- if (path)
- snd_hda_activate_path(codec, path, path->active,
- spec->aamix_mode);
- }
-}
-
-static int loopback_mixing_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct hda_gen_spec *spec = codec->spec;
- const struct auto_pin_cfg *cfg = &spec->autocfg;
- unsigned int val = ucontrol->value.enumerated.item[0];
-
- if (val == spec->aamix_mode)
- return 0;
- spec->aamix_mode = val;
- if (has_aamix_out_paths(spec)) {
- update_aamix_paths(codec, val, spec->out_paths[0],
- spec->aamix_out_paths[0],
- cfg->line_out_type);
- update_aamix_paths(codec, val, spec->hp_paths[0],
- spec->aamix_out_paths[1],
- AUTO_PIN_HP_OUT);
- update_aamix_paths(codec, val, spec->speaker_paths[0],
- spec->aamix_out_paths[2],
- AUTO_PIN_SPEAKER_OUT);
- } else {
- update_output_paths(codec, cfg->line_outs, spec->out_paths);
- if (cfg->line_out_type != AUTO_PIN_HP_OUT)
- update_output_paths(codec, cfg->hp_outs, spec->hp_paths);
- if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
- update_output_paths(codec, cfg->speaker_outs,
- spec->speaker_paths);
- }
- return 1;
-}
-
-static const struct snd_kcontrol_new loopback_mixing_enum = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Loopback Mixing",
- .info = loopback_mixing_info,
- .get = loopback_mixing_get,
- .put = loopback_mixing_put,
-};
-
-static int create_loopback_mixing_ctl(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
-
- if (!spec->mixer_nid)
- return 0;
- if (!snd_hda_gen_add_kctl(spec, NULL, &loopback_mixing_enum))
- return -ENOMEM;
- spec->have_aamix_ctl = 1;
- return 0;
-}
-
-/*
- * shared headphone/mic handling
- */
-
-static void call_update_outputs(struct hda_codec *codec);
-
-/* for shared I/O, change the pin-control accordingly */
-static void update_hp_mic(struct hda_codec *codec, int adc_mux, bool force)
-{
- struct hda_gen_spec *spec = codec->spec;
- bool as_mic;
- unsigned int val;
- hda_nid_t pin;
-
- pin = spec->hp_mic_pin;
- as_mic = spec->cur_mux[adc_mux] == spec->hp_mic_mux_idx;
-
- if (!force) {
- val = snd_hda_codec_get_pin_target(codec, pin);
- if (as_mic) {
- if (val & PIN_IN)
- return;
- } else {
- if (val & PIN_OUT)
- return;
- }
- }
-
- val = snd_hda_get_default_vref(codec, pin);
- /* if the HP pin doesn't support VREF and the codec driver gives an
- * alternative pin, set up the VREF on that pin instead
- */
- if (val == AC_PINCTL_VREF_HIZ && spec->shared_mic_vref_pin) {
- const hda_nid_t vref_pin = spec->shared_mic_vref_pin;
- unsigned int vref_val = snd_hda_get_default_vref(codec, vref_pin);
- if (vref_val != AC_PINCTL_VREF_HIZ)
- snd_hda_set_pin_ctl_cache(codec, vref_pin,
- PIN_IN | (as_mic ? vref_val : 0));
- }
-
- if (!spec->hp_mic_jack_modes) {
- if (as_mic)
- val |= PIN_IN;
- else
- val = PIN_HP;
- set_pin_target(codec, pin, val, true);
- call_hp_automute(codec, NULL);
- }
-}
-
-/* create a shared input with the headphone out */
-static int create_hp_mic(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->autocfg;
- unsigned int defcfg;
- hda_nid_t nid;
-
- if (!spec->hp_mic) {
- if (spec->suppress_hp_mic_detect)
- return 0;
- /* automatic detection: only if no input or a single internal
- * input pin is found, try to detect the shared hp/mic
- */
- if (cfg->num_inputs > 1)
- return 0;
- else if (cfg->num_inputs == 1) {
- defcfg = snd_hda_codec_get_pincfg(codec, cfg->inputs[0].pin);
- if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
- return 0;
- }
- }
-
- spec->hp_mic = 0; /* clear once */
- if (cfg->num_inputs >= AUTO_CFG_MAX_INS)
- return 0;
-
- nid = 0;
- if (cfg->line_out_type == AUTO_PIN_HP_OUT && cfg->line_outs > 0)
- nid = cfg->line_out_pins[0];
- else if (cfg->hp_outs > 0)
- nid = cfg->hp_pins[0];
- if (!nid)
- return 0;
-
- if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_IN))
- return 0; /* no input */
-
- cfg->inputs[cfg->num_inputs].pin = nid;
- cfg->inputs[cfg->num_inputs].type = AUTO_PIN_MIC;
- cfg->inputs[cfg->num_inputs].is_headphone_mic = 1;
- cfg->num_inputs++;
- spec->hp_mic = 1;
- spec->hp_mic_pin = nid;
- /* we can't handle auto-mic together with HP-mic */
- spec->suppress_auto_mic = 1;
- codec_dbg(codec, "Enable shared I/O jack on NID 0x%x\n", nid);
- return 0;
-}
-
-/*
- * output jack mode
- */
-
-static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin);
-
-static const char * const out_jack_texts[] = {
- "Line Out", "Headphone Out",
-};
-
-static int out_jack_mode_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- return snd_hda_enum_helper_info(kcontrol, uinfo, 2, out_jack_texts);
-}
-
-static int out_jack_mode_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = kcontrol->private_value;
- if (snd_hda_codec_get_pin_target(codec, nid) == PIN_HP)
- ucontrol->value.enumerated.item[0] = 1;
- else
- ucontrol->value.enumerated.item[0] = 0;
- return 0;
-}
-
-static int out_jack_mode_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = kcontrol->private_value;
- unsigned int val;
-
- val = ucontrol->value.enumerated.item[0] ? PIN_HP : PIN_OUT;
- if (snd_hda_codec_get_pin_target(codec, nid) == val)
- return 0;
- snd_hda_set_pin_ctl_cache(codec, nid, val);
- return 1;
-}
-
-static const struct snd_kcontrol_new out_jack_mode_enum = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .info = out_jack_mode_info,
- .get = out_jack_mode_get,
- .put = out_jack_mode_put,
-};
-
-static bool find_kctl_name(struct hda_codec *codec, const char *name, int idx)
-{
- struct hda_gen_spec *spec = codec->spec;
- const struct snd_kcontrol_new *kctl;
- int i;
-
- snd_array_for_each(&spec->kctls, i, kctl) {
- if (!strcmp(kctl->name, name) && kctl->index == idx)
- return true;
- }
- return false;
-}
-
-static void get_jack_mode_name(struct hda_codec *codec, hda_nid_t pin,
- char *name, size_t name_len)
-{
- struct hda_gen_spec *spec = codec->spec;
- int idx = 0;
-
- snd_hda_get_pin_label(codec, pin, &spec->autocfg, name, name_len, &idx);
- strlcat(name, " Jack Mode", name_len);
-
- for (; find_kctl_name(codec, name, idx); idx++)
- ;
-}
-
-static int get_out_jack_num_items(struct hda_codec *codec, hda_nid_t pin)
-{
- struct hda_gen_spec *spec = codec->spec;
- if (spec->add_jack_modes) {
- unsigned int pincap = snd_hda_query_pin_caps(codec, pin);
- if ((pincap & AC_PINCAP_OUT) && (pincap & AC_PINCAP_HP_DRV))
- return 2;
- }
- return 1;
-}
-
-static int create_out_jack_modes(struct hda_codec *codec, int num_pins,
- hda_nid_t *pins)
-{
- struct hda_gen_spec *spec = codec->spec;
- int i;
-
- for (i = 0; i < num_pins; i++) {
- hda_nid_t pin = pins[i];
- if (pin == spec->hp_mic_pin)
- continue;
- if (get_out_jack_num_items(codec, pin) > 1) {
- struct snd_kcontrol_new *knew;
- char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
- get_jack_mode_name(codec, pin, name, sizeof(name));
- knew = snd_hda_gen_add_kctl(spec, name,
- &out_jack_mode_enum);
- if (!knew)
- return -ENOMEM;
- knew->private_value = pin;
- }
- }
-
- return 0;
-}
-
-/*
- * input jack mode
- */
-
-/* from AC_PINCTL_VREF_HIZ to AC_PINCTL_VREF_100 */
-#define NUM_VREFS 6
-
-static const char * const vref_texts[NUM_VREFS] = {
- "Line In", "Mic 50pc Bias", "Mic 0V Bias",
- "", "Mic 80pc Bias", "Mic 100pc Bias"
-};
-
-static unsigned int get_vref_caps(struct hda_codec *codec, hda_nid_t pin)
-{
- unsigned int pincap;
-
- pincap = snd_hda_query_pin_caps(codec, pin);
- pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
- /* filter out unusual vrefs */
- pincap &= ~(AC_PINCAP_VREF_GRD | AC_PINCAP_VREF_100);
- return pincap;
-}
-
-/* convert from the enum item index to the vref ctl index (0=HIZ, 1=50%...) */
-static int get_vref_idx(unsigned int vref_caps, unsigned int item_idx)
-{
- unsigned int i, n = 0;
-
- for (i = 0; i < NUM_VREFS; i++) {
- if (vref_caps & (1 << i)) {
- if (n == item_idx)
- return i;
- n++;
- }
- }
- return 0;
-}
-
-/* convert back from the vref ctl index to the enum item index */
-static int cvt_from_vref_idx(unsigned int vref_caps, unsigned int idx)
-{
- unsigned int i, n = 0;
-
- for (i = 0; i < NUM_VREFS; i++) {
- if (i == idx)
- return n;
- if (vref_caps & (1 << i))
- n++;
- }
- return 0;
-}
-
-static int in_jack_mode_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = kcontrol->private_value;
- unsigned int vref_caps = get_vref_caps(codec, nid);
-
- snd_hda_enum_helper_info(kcontrol, uinfo, hweight32(vref_caps),
- vref_texts);
- /* set the right text */
- strcpy(uinfo->value.enumerated.name,
- vref_texts[get_vref_idx(vref_caps, uinfo->value.enumerated.item)]);
- return 0;
-}
-
-static int in_jack_mode_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = kcontrol->private_value;
- unsigned int vref_caps = get_vref_caps(codec, nid);
- unsigned int idx;
-
- idx = snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_VREFEN;
- ucontrol->value.enumerated.item[0] = cvt_from_vref_idx(vref_caps, idx);
- return 0;
-}
-
-static int in_jack_mode_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = kcontrol->private_value;
- unsigned int vref_caps = get_vref_caps(codec, nid);
- unsigned int val, idx;
-
- val = snd_hda_codec_get_pin_target(codec, nid);
- idx = cvt_from_vref_idx(vref_caps, val & AC_PINCTL_VREFEN);
- if (idx == ucontrol->value.enumerated.item[0])
- return 0;
-
- val &= ~AC_PINCTL_VREFEN;
- val |= get_vref_idx(vref_caps, ucontrol->value.enumerated.item[0]);
- snd_hda_set_pin_ctl_cache(codec, nid, val);
- return 1;
-}
-
-static const struct snd_kcontrol_new in_jack_mode_enum = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .info = in_jack_mode_info,
- .get = in_jack_mode_get,
- .put = in_jack_mode_put,
-};
-
-static int get_in_jack_num_items(struct hda_codec *codec, hda_nid_t pin)
-{
- struct hda_gen_spec *spec = codec->spec;
- int nitems = 0;
- if (spec->add_jack_modes)
- nitems = hweight32(get_vref_caps(codec, pin));
- return nitems ? nitems : 1;
-}
-
-static int create_in_jack_mode(struct hda_codec *codec, hda_nid_t pin)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct snd_kcontrol_new *knew;
- char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
- unsigned int defcfg;
-
- if (pin == spec->hp_mic_pin)
- return 0; /* already done in create_out_jack_mode() */
-
- /* no jack mode for fixed pins */
- defcfg = snd_hda_codec_get_pincfg(codec, pin);
- if (snd_hda_get_input_pin_attr(defcfg) == INPUT_PIN_ATTR_INT)
- return 0;
-
- /* no multiple vref caps? */
- if (get_in_jack_num_items(codec, pin) <= 1)
- return 0;
-
- get_jack_mode_name(codec, pin, name, sizeof(name));
- knew = snd_hda_gen_add_kctl(spec, name, &in_jack_mode_enum);
- if (!knew)
- return -ENOMEM;
- knew->private_value = pin;
- return 0;
-}
-
-/*
- * HP/mic shared jack mode
- */
-static int hp_mic_jack_mode_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = kcontrol->private_value;
- int out_jacks = get_out_jack_num_items(codec, nid);
- int in_jacks = get_in_jack_num_items(codec, nid);
- const char *text = NULL;
- int idx;
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = out_jacks + in_jacks;
- if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
- uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
- idx = uinfo->value.enumerated.item;
- if (idx < out_jacks) {
- if (out_jacks > 1)
- text = out_jack_texts[idx];
- else
- text = "Headphone Out";
- } else {
- idx -= out_jacks;
- if (in_jacks > 1) {
- unsigned int vref_caps = get_vref_caps(codec, nid);
- text = vref_texts[get_vref_idx(vref_caps, idx)];
- } else
- text = "Mic In";
- }
-
- strcpy(uinfo->value.enumerated.name, text);
- return 0;
-}
-
-static int get_cur_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t nid)
-{
- int out_jacks = get_out_jack_num_items(codec, nid);
- int in_jacks = get_in_jack_num_items(codec, nid);
- unsigned int val = snd_hda_codec_get_pin_target(codec, nid);
- int idx = 0;
-
- if (val & PIN_OUT) {
- if (out_jacks > 1 && val == PIN_HP)
- idx = 1;
- } else if (val & PIN_IN) {
- idx = out_jacks;
- if (in_jacks > 1) {
- unsigned int vref_caps = get_vref_caps(codec, nid);
- val &= AC_PINCTL_VREFEN;
- idx += cvt_from_vref_idx(vref_caps, val);
- }
- }
- return idx;
-}
-
-static int hp_mic_jack_mode_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = kcontrol->private_value;
- ucontrol->value.enumerated.item[0] =
- get_cur_hp_mic_jack_mode(codec, nid);
- return 0;
-}
-
-static int hp_mic_jack_mode_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = kcontrol->private_value;
- int out_jacks = get_out_jack_num_items(codec, nid);
- int in_jacks = get_in_jack_num_items(codec, nid);
- unsigned int val, oldval, idx;
-
- oldval = get_cur_hp_mic_jack_mode(codec, nid);
- idx = ucontrol->value.enumerated.item[0];
- if (oldval == idx)
- return 0;
-
- if (idx < out_jacks) {
- if (out_jacks > 1)
- val = idx ? PIN_HP : PIN_OUT;
- else
- val = PIN_HP;
- } else {
- idx -= out_jacks;
- if (in_jacks > 1) {
- unsigned int vref_caps = get_vref_caps(codec, nid);
- val = snd_hda_codec_get_pin_target(codec, nid);
- val &= ~(AC_PINCTL_VREFEN | PIN_HP);
- val |= get_vref_idx(vref_caps, idx) | PIN_IN;
- } else
- val = snd_hda_get_default_vref(codec, nid) | PIN_IN;
- }
- snd_hda_set_pin_ctl_cache(codec, nid, val);
- call_hp_automute(codec, NULL);
-
- return 1;
-}
-
-static const struct snd_kcontrol_new hp_mic_jack_mode_enum = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .info = hp_mic_jack_mode_info,
- .get = hp_mic_jack_mode_get,
- .put = hp_mic_jack_mode_put,
-};
-
-static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct snd_kcontrol_new *knew;
-
- knew = snd_hda_gen_add_kctl(spec, "Headphone Mic Jack Mode",
- &hp_mic_jack_mode_enum);
- if (!knew)
- return -ENOMEM;
- knew->private_value = pin;
- spec->hp_mic_jack_modes = 1;
- return 0;
-}
-
-/*
- * Parse input paths
- */
-
-/* add the powersave loopback-list entry */
-static int add_loopback_list(struct hda_gen_spec *spec, hda_nid_t mix, int idx)
-{
- struct hda_amp_list *list;
-
- list = snd_array_new(&spec->loopback_list);
- if (!list)
- return -ENOMEM;
- list->nid = mix;
- list->dir = HDA_INPUT;
- list->idx = idx;
- spec->loopback.amplist = spec->loopback_list.list;
- return 0;
-}
-
-/* return true if either a volume or a mute amp is found for the given
- * aamix path; the amp has to be either in the mixer node or its direct leaf
- */
-static bool look_for_mix_leaf_ctls(struct hda_codec *codec, hda_nid_t mix_nid,
- hda_nid_t pin, unsigned int *mix_val,
- unsigned int *mute_val)
-{
- int idx, num_conns;
- const hda_nid_t *list;
- hda_nid_t nid;
-
- idx = snd_hda_get_conn_index(codec, mix_nid, pin, true);
- if (idx < 0)
- return false;
-
- *mix_val = *mute_val = 0;
- if (nid_has_volume(codec, mix_nid, HDA_INPUT))
- *mix_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
- if (nid_has_mute(codec, mix_nid, HDA_INPUT))
- *mute_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
- if (*mix_val && *mute_val)
- return true;
-
- /* check leaf node */
- num_conns = snd_hda_get_conn_list(codec, mix_nid, &list);
- if (num_conns < idx)
- return false;
- nid = list[idx];
- if (!*mix_val && nid_has_volume(codec, nid, HDA_OUTPUT) &&
- !is_ctl_associated(codec, nid, HDA_OUTPUT, 0, NID_PATH_VOL_CTL))
- *mix_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
- if (!*mute_val && nid_has_mute(codec, nid, HDA_OUTPUT) &&
- !is_ctl_associated(codec, nid, HDA_OUTPUT, 0, NID_PATH_MUTE_CTL))
- *mute_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
-
- return *mix_val || *mute_val;
-}
-
-/* create input playback/capture controls for the given pin */
-static int new_analog_input(struct hda_codec *codec, int input_idx,
- hda_nid_t pin, const char *ctlname, int ctlidx,
- hda_nid_t mix_nid)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct nid_path *path;
- unsigned int mix_val, mute_val;
- int err, idx;
-
- if (!look_for_mix_leaf_ctls(codec, mix_nid, pin, &mix_val, &mute_val))
- return 0;
-
- path = snd_hda_add_new_path(codec, pin, mix_nid, 0);
- if (!path)
- return -EINVAL;
- print_nid_path(codec, "loopback", path);
- spec->loopback_paths[input_idx] = snd_hda_get_path_idx(codec, path);
-
- idx = path->idx[path->depth - 1];
- if (mix_val) {
- err = __add_pb_vol_ctrl(spec, HDA_CTL_WIDGET_VOL, ctlname, ctlidx, mix_val);
- if (err < 0)
- return err;
- path->ctls[NID_PATH_VOL_CTL] = mix_val;
- }
-
- if (mute_val) {
- err = __add_pb_sw_ctrl(spec, HDA_CTL_WIDGET_MUTE, ctlname, ctlidx, mute_val);
- if (err < 0)
- return err;
- path->ctls[NID_PATH_MUTE_CTL] = mute_val;
- }
-
- path->active = true;
- path->stream_enabled = true; /* no DAC/ADC involved */
- err = add_loopback_list(spec, mix_nid, idx);
- if (err < 0)
- return err;
-
- if (spec->mixer_nid != spec->mixer_merge_nid &&
- !spec->loopback_merge_path) {
- path = snd_hda_add_new_path(codec, spec->mixer_nid,
- spec->mixer_merge_nid, 0);
- if (path) {
- print_nid_path(codec, "loopback-merge", path);
- path->active = true;
- path->pin_fixed = true; /* static route */
- path->stream_enabled = true; /* no DAC/ADC involved */
- spec->loopback_merge_path =
- snd_hda_get_path_idx(codec, path);
- }
- }
-
- return 0;
-}
-
-static int is_input_pin(struct hda_codec *codec, hda_nid_t nid)
-{
- unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
- return (pincap & AC_PINCAP_IN) != 0;
-}
-
-/* Parse the codec tree and retrieve ADCs */
-static int fill_adc_nids(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
- hda_nid_t nid;
- hda_nid_t *adc_nids = spec->adc_nids;
- int max_nums = ARRAY_SIZE(spec->adc_nids);
- int nums = 0;
-
- for_each_hda_codec_node(nid, codec) {
- unsigned int caps = get_wcaps(codec, nid);
- int type = get_wcaps_type(caps);
-
- if (type != AC_WID_AUD_IN || (caps & AC_WCAP_DIGITAL))
- continue;
- adc_nids[nums] = nid;
- if (++nums >= max_nums)
- break;
- }
- spec->num_adc_nids = nums;
-
- /* copy the detected ADCs to all_adcs[] */
- spec->num_all_adcs = nums;
- memcpy(spec->all_adcs, spec->adc_nids, nums * sizeof(hda_nid_t));
-
- return nums;
-}
-
-/* filter out invalid adc_nids that don't give all active input pins;
- * if needed, check whether dynamic ADC-switching is available
- */
-static int check_dyn_adc_switch(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct hda_input_mux *imux = &spec->input_mux;
- unsigned int ok_bits;
- int i, n, nums;
-
- nums = 0;
- ok_bits = 0;
- for (n = 0; n < spec->num_adc_nids; n++) {
- for (i = 0; i < imux->num_items; i++) {
- if (!spec->input_paths[i][n])
- break;
- }
- if (i >= imux->num_items) {
- ok_bits |= (1 << n);
- nums++;
- }
- }
-
- if (!ok_bits) {
- /* check whether ADC-switch is possible */
- for (i = 0; i < imux->num_items; i++) {
- for (n = 0; n < spec->num_adc_nids; n++) {
- if (spec->input_paths[i][n]) {
- spec->dyn_adc_idx[i] = n;
- break;
- }
- }
- }
-
- codec_dbg(codec, "enabling ADC switching\n");
- spec->dyn_adc_switch = 1;
- } else if (nums != spec->num_adc_nids) {
- /* shrink the invalid adcs and input paths */
- nums = 0;
- for (n = 0; n < spec->num_adc_nids; n++) {
- if (!(ok_bits & (1 << n)))
- continue;
- if (n != nums) {
- spec->adc_nids[nums] = spec->adc_nids[n];
- for (i = 0; i < imux->num_items; i++) {
- invalidate_nid_path(codec,
- spec->input_paths[i][nums]);
- spec->input_paths[i][nums] =
- spec->input_paths[i][n];
- spec->input_paths[i][n] = 0;
- }
- }
- nums++;
- }
- spec->num_adc_nids = nums;
- }
-
- if (imux->num_items == 1 ||
- (imux->num_items == 2 && spec->hp_mic)) {
- codec_dbg(codec, "reducing to a single ADC\n");
- spec->num_adc_nids = 1; /* reduce to a single ADC */
- }
-
- /* single index for individual volumes ctls */
- if (!spec->dyn_adc_switch && spec->multi_cap_vol)
- spec->num_adc_nids = 1;
-
- return 0;
-}
-
-/* parse capture source paths from the given pin and create imux items */
-static int parse_capture_source(struct hda_codec *codec, hda_nid_t pin,
- int cfg_idx, int num_adcs,
- const char *label, int anchor)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct hda_input_mux *imux = &spec->input_mux;
- int imux_idx = imux->num_items;
- bool imux_added = false;
- int c;
-
- for (c = 0; c < num_adcs; c++) {
- struct nid_path *path;
- hda_nid_t adc = spec->adc_nids[c];
-
- if (!is_reachable_path(codec, pin, adc))
- continue;
- path = snd_hda_add_new_path(codec, pin, adc, anchor);
- if (!path)
- continue;
- print_nid_path(codec, "input", path);
- spec->input_paths[imux_idx][c] =
- snd_hda_get_path_idx(codec, path);
-
- if (!imux_added) {
- if (spec->hp_mic_pin == pin)
- spec->hp_mic_mux_idx = imux->num_items;
- spec->imux_pins[imux->num_items] = pin;
- snd_hda_add_imux_item(codec, imux, label, cfg_idx, NULL);
- imux_added = true;
- if (spec->dyn_adc_switch)
- spec->dyn_adc_idx[imux_idx] = c;
- }
- }
-
- return 0;
-}
-
-/*
- * create playback/capture controls for input pins
- */
-
-/* fill the label for each input at first */
-static int fill_input_pin_labels(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
- const struct auto_pin_cfg *cfg = &spec->autocfg;
- int i;
-
- for (i = 0; i < cfg->num_inputs; i++) {
- hda_nid_t pin = cfg->inputs[i].pin;
- const char *label;
- int j, idx;
-
- if (!is_input_pin(codec, pin))
- continue;
-
- label = hda_get_autocfg_input_label(codec, cfg, i);
- idx = 0;
- for (j = i - 1; j >= 0; j--) {
- if (spec->input_labels[j] &&
- !strcmp(spec->input_labels[j], label)) {
- idx = spec->input_label_idxs[j] + 1;
- break;
- }
- }
-
- spec->input_labels[i] = label;
- spec->input_label_idxs[i] = idx;
- }
-
- return 0;
-}
-
-#define CFG_IDX_MIX 99 /* a dummy cfg->input idx for stereo mix */
-
-static int create_input_ctls(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
- const struct auto_pin_cfg *cfg = &spec->autocfg;
- hda_nid_t mixer = spec->mixer_nid;
- int num_adcs;
- int i, err;
- unsigned int val;
-
- num_adcs = fill_adc_nids(codec);
- if (num_adcs < 0)
- return 0;
-
- err = fill_input_pin_labels(codec);
- if (err < 0)
- return err;
-
- for (i = 0; i < cfg->num_inputs; i++) {
- hda_nid_t pin;
-
- pin = cfg->inputs[i].pin;
- if (!is_input_pin(codec, pin))
- continue;
-
- val = PIN_IN;
- if (cfg->inputs[i].type == AUTO_PIN_MIC)
- val |= snd_hda_get_default_vref(codec, pin);
- if (pin != spec->hp_mic_pin &&
- !snd_hda_codec_get_pin_target(codec, pin))
- set_pin_target(codec, pin, val, false);
-
- if (mixer) {
- if (is_reachable_path(codec, pin, mixer)) {
- err = new_analog_input(codec, i, pin,
- spec->input_labels[i],
- spec->input_label_idxs[i],
- mixer);
- if (err < 0)
- return err;
- }
- }
-
- err = parse_capture_source(codec, pin, i, num_adcs,
- spec->input_labels[i], -mixer);
- if (err < 0)
- return err;
-
- if (spec->add_jack_modes) {
- err = create_in_jack_mode(codec, pin);
- if (err < 0)
- return err;
- }
- }
-
- /* add stereo mix when explicitly enabled via hint */
- if (mixer && spec->add_stereo_mix_input == HDA_HINT_STEREO_MIX_ENABLE) {
- err = parse_capture_source(codec, mixer, CFG_IDX_MIX, num_adcs,
- "Stereo Mix", 0);
- if (err < 0)
- return err;
- else
- spec->suppress_auto_mic = 1;
- }
-
- return 0;
-}
-
-
-/*
- * input source mux
- */
-
-/* get the input path specified by the given adc and imux indices */
-static struct nid_path *get_input_path(struct hda_codec *codec, int adc_idx, int imux_idx)
-{
- struct hda_gen_spec *spec = codec->spec;
- if (imux_idx < 0 || imux_idx >= HDA_MAX_NUM_INPUTS) {
- snd_BUG();
- return NULL;
- }
- if (spec->dyn_adc_switch)
- adc_idx = spec->dyn_adc_idx[imux_idx];
- if (adc_idx < 0 || adc_idx >= AUTO_CFG_MAX_INS) {
- snd_BUG();
- return NULL;
- }
- return snd_hda_get_path_from_idx(codec, spec->input_paths[imux_idx][adc_idx]);
-}
-
-static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
- unsigned int idx);
-
-static int mux_enum_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct hda_gen_spec *spec = codec->spec;
- return snd_hda_input_mux_info(&spec->input_mux, uinfo);
-}
-
-static int mux_enum_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct hda_gen_spec *spec = codec->spec;
- /* the ctls are created at once with multiple counts */
- unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
-
- ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
- return 0;
-}
-
-static int mux_enum_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
- return mux_select(codec, adc_idx,
- ucontrol->value.enumerated.item[0]);
-}
-
-static const struct snd_kcontrol_new cap_src_temp = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Input Source",
- .info = mux_enum_info,
- .get = mux_enum_get,
- .put = mux_enum_put,
-};
-
-/*
- * capture volume and capture switch ctls
- */
-
-typedef int (*put_call_t)(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol);
-
-/* call the given amp update function for all amps in the imux list at once */
-static int cap_put_caller(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol,
- put_call_t func, int type)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct hda_gen_spec *spec = codec->spec;
- const struct hda_input_mux *imux;
- struct nid_path *path;
- int i, adc_idx, ret, err = 0;
-
- imux = &spec->input_mux;
- adc_idx = kcontrol->id.index;
- mutex_lock(&codec->control_mutex);
- for (i = 0; i < imux->num_items; i++) {
- path = get_input_path(codec, adc_idx, i);
- if (!path || !path->ctls[type])
- continue;
- kcontrol->private_value = path->ctls[type];
- ret = func(kcontrol, ucontrol);
- if (ret < 0) {
- err = ret;
- break;
- }
- if (ret > 0)
- err = 1;
- }
- mutex_unlock(&codec->control_mutex);
- if (err >= 0 && spec->cap_sync_hook)
- spec->cap_sync_hook(codec, kcontrol, ucontrol);
- return err;
-}
-
-/* capture volume ctl callbacks */
-#define cap_vol_info snd_hda_mixer_amp_volume_info
-#define cap_vol_get snd_hda_mixer_amp_volume_get
-#define cap_vol_tlv snd_hda_mixer_amp_tlv
-
-static int cap_vol_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- return cap_put_caller(kcontrol, ucontrol,
- snd_hda_mixer_amp_volume_put,
- NID_PATH_VOL_CTL);
-}
-
-static const struct snd_kcontrol_new cap_vol_temp = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Capture Volume",
- .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
- SNDRV_CTL_ELEM_ACCESS_TLV_READ |
- SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK),
- .info = cap_vol_info,
- .get = cap_vol_get,
- .put = cap_vol_put,
- .tlv = { .c = cap_vol_tlv },
-};
-
-/* capture switch ctl callbacks */
-#define cap_sw_info snd_ctl_boolean_stereo_info
-#define cap_sw_get snd_hda_mixer_amp_switch_get
-
-static int cap_sw_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- return cap_put_caller(kcontrol, ucontrol,
- snd_hda_mixer_amp_switch_put,
- NID_PATH_MUTE_CTL);
-}
-
-static const struct snd_kcontrol_new cap_sw_temp = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Capture Switch",
- .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
- .info = cap_sw_info,
- .get = cap_sw_get,
- .put = cap_sw_put,
-};
-
-static int parse_capvol_in_path(struct hda_codec *codec, struct nid_path *path)
-{
- hda_nid_t nid;
- int i, depth;
-
- path->ctls[NID_PATH_VOL_CTL] = path->ctls[NID_PATH_MUTE_CTL] = 0;
- for (depth = 0; depth < 3; depth++) {
- if (depth >= path->depth)
- return -EINVAL;
- i = path->depth - depth - 1;
- nid = path->path[i];
- if (!path->ctls[NID_PATH_VOL_CTL]) {
- if (nid_has_volume(codec, nid, HDA_OUTPUT))
- path->ctls[NID_PATH_VOL_CTL] =
- HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
- else if (nid_has_volume(codec, nid, HDA_INPUT)) {
- int idx = path->idx[i];
- if (!depth && codec->single_adc_amp)
- idx = 0;
- path->ctls[NID_PATH_VOL_CTL] =
- HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
- }
- }
- if (!path->ctls[NID_PATH_MUTE_CTL]) {
- if (nid_has_mute(codec, nid, HDA_OUTPUT))
- path->ctls[NID_PATH_MUTE_CTL] =
- HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
- else if (nid_has_mute(codec, nid, HDA_INPUT)) {
- int idx = path->idx[i];
- if (!depth && codec->single_adc_amp)
- idx = 0;
- path->ctls[NID_PATH_MUTE_CTL] =
- HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
- }
- }
- }
- return 0;
-}
-
-static bool is_inv_dmic_pin(struct hda_codec *codec, hda_nid_t nid)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->autocfg;
- unsigned int val;
- int i;
-
- if (!spec->inv_dmic_split)
- return false;
- for (i = 0; i < cfg->num_inputs; i++) {
- if (cfg->inputs[i].pin != nid)
- continue;
- if (cfg->inputs[i].type != AUTO_PIN_MIC)
- return false;
- val = snd_hda_codec_get_pincfg(codec, nid);
- return snd_hda_get_input_pin_attr(val) == INPUT_PIN_ATTR_INT;
- }
- return false;
-}
-
-/* capture switch put callback for a single control with hook call */
-static int cap_single_sw_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct hda_gen_spec *spec = codec->spec;
- int ret;
-
- ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
- if (ret < 0)
- return ret;
-
- if (spec->cap_sync_hook)
- spec->cap_sync_hook(codec, kcontrol, ucontrol);
-
- return ret;
-}
-
-static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
- int idx, bool is_switch, unsigned int ctl,
- bool inv_dmic)
-{
- struct hda_gen_spec *spec = codec->spec;
- char tmpname[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
- int type = is_switch ? HDA_CTL_WIDGET_MUTE : HDA_CTL_WIDGET_VOL;
- const char *sfx = is_switch ? "Switch" : "Volume";
- unsigned int chs = inv_dmic ? 1 : 3;
- struct snd_kcontrol_new *knew;
-
- if (!ctl)
- return 0;
-
- if (label)
- snprintf(tmpname, sizeof(tmpname),
- "%s Capture %s", label, sfx);
- else
- snprintf(tmpname, sizeof(tmpname),
- "Capture %s", sfx);
- knew = add_control(spec, type, tmpname, idx,
- amp_val_replace_channels(ctl, chs));
- if (!knew)
- return -ENOMEM;
- if (is_switch) {
- knew->put = cap_single_sw_put;
- if (spec->mic_mute_led)
- knew->access |= SNDRV_CTL_ELEM_ACCESS_MIC_LED;
- }
- if (!inv_dmic)
- return 0;
-
- /* Make independent right kcontrol */
- if (label)
- snprintf(tmpname, sizeof(tmpname),
- "Inverted %s Capture %s", label, sfx);
- else
- snprintf(tmpname, sizeof(tmpname),
- "Inverted Capture %s", sfx);
- knew = add_control(spec, type, tmpname, idx,
- amp_val_replace_channels(ctl, 2));
- if (!knew)
- return -ENOMEM;
- if (is_switch) {
- knew->put = cap_single_sw_put;
- if (spec->mic_mute_led)
- knew->access |= SNDRV_CTL_ELEM_ACCESS_MIC_LED;
- }
- return 0;
-}
-
-/* create single (and simple) capture volume and switch controls */
-static int create_single_cap_vol_ctl(struct hda_codec *codec, int idx,
- unsigned int vol_ctl, unsigned int sw_ctl,
- bool inv_dmic)
-{
- int err;
- err = add_single_cap_ctl(codec, NULL, idx, false, vol_ctl, inv_dmic);
- if (err < 0)
- return err;
- err = add_single_cap_ctl(codec, NULL, idx, true, sw_ctl, inv_dmic);
- if (err < 0)
- return err;
- return 0;
-}
-
-/* create bound capture volume and switch controls */
-static int create_bind_cap_vol_ctl(struct hda_codec *codec, int idx,
- unsigned int vol_ctl, unsigned int sw_ctl)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct snd_kcontrol_new *knew;
-
- if (vol_ctl) {
- knew = snd_hda_gen_add_kctl(spec, NULL, &cap_vol_temp);
- if (!knew)
- return -ENOMEM;
- knew->index = idx;
- knew->private_value = vol_ctl;
- knew->subdevice = HDA_SUBDEV_AMP_FLAG;
- }
- if (sw_ctl) {
- knew = snd_hda_gen_add_kctl(spec, NULL, &cap_sw_temp);
- if (!knew)
- return -ENOMEM;
- knew->index = idx;
- knew->private_value = sw_ctl;
- knew->subdevice = HDA_SUBDEV_AMP_FLAG;
- if (spec->mic_mute_led)
- knew->access |= SNDRV_CTL_ELEM_ACCESS_MIC_LED;
- }
- return 0;
-}
-
-/* return the vol ctl when used first in the imux list */
-static unsigned int get_first_cap_ctl(struct hda_codec *codec, int idx, int type)
-{
- struct nid_path *path;
- unsigned int ctl;
- int i;
-
- path = get_input_path(codec, 0, idx);
- if (!path)
- return 0;
- ctl = path->ctls[type];
- if (!ctl)
- return 0;
- for (i = 0; i < idx - 1; i++) {
- path = get_input_path(codec, 0, i);
- if (path && path->ctls[type] == ctl)
- return 0;
- }
- return ctl;
-}
-
-/* create individual capture volume and switch controls per input */
-static int create_multi_cap_vol_ctl(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct hda_input_mux *imux = &spec->input_mux;
- int i, err, type;
-
- for (i = 0; i < imux->num_items; i++) {
- bool inv_dmic;
- int idx;
-
- idx = imux->items[i].index;
- if (idx >= spec->autocfg.num_inputs)
- continue;
- inv_dmic = is_inv_dmic_pin(codec, spec->imux_pins[i]);
-
- for (type = 0; type < 2; type++) {
- err = add_single_cap_ctl(codec,
- spec->input_labels[idx],
- spec->input_label_idxs[idx],
- type,
- get_first_cap_ctl(codec, i, type),
- inv_dmic);
- if (err < 0)
- return err;
- }
- }
- return 0;
-}
-
-static int create_capture_mixers(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct hda_input_mux *imux = &spec->input_mux;
- int i, n, nums, err;
-
- if (spec->dyn_adc_switch)
- nums = 1;
- else
- nums = spec->num_adc_nids;
-
- if (!spec->auto_mic && imux->num_items > 1) {
- struct snd_kcontrol_new *knew;
- const char *name;
- name = nums > 1 ? "Input Source" : "Capture Source";
- knew = snd_hda_gen_add_kctl(spec, name, &cap_src_temp);
- if (!knew)
- return -ENOMEM;
- knew->count = nums;
- }
-
- for (n = 0; n < nums; n++) {
- bool multi = false;
- bool multi_cap_vol = spec->multi_cap_vol;
- bool inv_dmic = false;
- int vol, sw;
-
- vol = sw = 0;
- for (i = 0; i < imux->num_items; i++) {
- struct nid_path *path;
- path = get_input_path(codec, n, i);
- if (!path)
- continue;
- parse_capvol_in_path(codec, path);
- if (!vol)
- vol = path->ctls[NID_PATH_VOL_CTL];
- else if (vol != path->ctls[NID_PATH_VOL_CTL]) {
- multi = true;
- if (!same_amp_caps(codec, vol,
- path->ctls[NID_PATH_VOL_CTL], HDA_INPUT))
- multi_cap_vol = true;
- }
- if (!sw)
- sw = path->ctls[NID_PATH_MUTE_CTL];
- else if (sw != path->ctls[NID_PATH_MUTE_CTL]) {
- multi = true;
- if (!same_amp_caps(codec, sw,
- path->ctls[NID_PATH_MUTE_CTL], HDA_INPUT))
- multi_cap_vol = true;
- }
- if (is_inv_dmic_pin(codec, spec->imux_pins[i]))
- inv_dmic = true;
- }
-
- if (!multi)
- err = create_single_cap_vol_ctl(codec, n, vol, sw,
- inv_dmic);
- else if (!multi_cap_vol && !inv_dmic)
- err = create_bind_cap_vol_ctl(codec, n, vol, sw);
- else
- err = create_multi_cap_vol_ctl(codec);
- if (err < 0)
- return err;
- }
-
- return 0;
-}
-
-/*
- * add mic boosts if needed
- */
-
-/* check whether the given amp is feasible as a boost volume */
-static bool check_boost_vol(struct hda_codec *codec, hda_nid_t nid,
- int dir, int idx)
-{
- unsigned int step;
-
- if (!nid_has_volume(codec, nid, dir) ||
- is_ctl_associated(codec, nid, dir, idx, NID_PATH_VOL_CTL) ||
- is_ctl_associated(codec, nid, dir, idx, NID_PATH_BOOST_CTL))
- return false;
-
- step = (query_amp_caps(codec, nid, dir) & AC_AMPCAP_STEP_SIZE)
- >> AC_AMPCAP_STEP_SIZE_SHIFT;
- if (step < 0x20)
- return false;
- return true;
-}
-
-/* look for a boost amp in a widget close to the pin */
-static unsigned int look_for_boost_amp(struct hda_codec *codec,
- struct nid_path *path)
-{
- unsigned int val = 0;
- hda_nid_t nid;
- int depth;
-
- for (depth = 0; depth < 3; depth++) {
- if (depth >= path->depth - 1)
- break;
- nid = path->path[depth];
- if (depth && check_boost_vol(codec, nid, HDA_OUTPUT, 0)) {
- val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
- break;
- } else if (check_boost_vol(codec, nid, HDA_INPUT,
- path->idx[depth])) {
- val = HDA_COMPOSE_AMP_VAL(nid, 3, path->idx[depth],
- HDA_INPUT);
- break;
- }
- }
-
- return val;
-}
-
-static int parse_mic_boost(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->autocfg;
- struct hda_input_mux *imux = &spec->input_mux;
- int i;
-
- if (!spec->num_adc_nids)
- return 0;
-
- for (i = 0; i < imux->num_items; i++) {
- struct nid_path *path;
- unsigned int val;
- int idx;
- char boost_label[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
-
- idx = imux->items[i].index;
- if (idx >= imux->num_items)
- continue;
-
- /* check only line-in and mic pins */
- if (cfg->inputs[idx].type > AUTO_PIN_LINE_IN)
- continue;
-
- path = get_input_path(codec, 0, i);
- if (!path)
- continue;
-
- val = look_for_boost_amp(codec, path);
- if (!val)
- continue;
-
- /* create a boost control */
- snprintf(boost_label, sizeof(boost_label),
- "%s Boost Volume", spec->input_labels[idx]);
- if (!add_control(spec, HDA_CTL_WIDGET_VOL, boost_label,
- spec->input_label_idxs[idx], val))
- return -ENOMEM;
-
- path->ctls[NID_PATH_BOOST_CTL] = val;
- }
- return 0;
-}
-
-#ifdef CONFIG_SND_HDA_GENERIC_LEDS
-/*
- * vmaster mute LED hook helpers
- */
-
-static int create_mute_led_cdev(struct hda_codec *codec,
- int (*callback)(struct led_classdev *,
- enum led_brightness),
- bool micmute)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct led_classdev *cdev;
- int idx = micmute ? LED_AUDIO_MICMUTE : LED_AUDIO_MUTE;
- int err;
-
- cdev = devm_kzalloc(&codec->core.dev, sizeof(*cdev), GFP_KERNEL);
- if (!cdev)
- return -ENOMEM;
-
- cdev->name = micmute ? "hda::micmute" : "hda::mute";
- cdev->max_brightness = 1;
- cdev->default_trigger = micmute ? "audio-micmute" : "audio-mute";
- cdev->brightness_set_blocking = callback;
- cdev->flags = LED_CORE_SUSPENDRESUME;
-
- err = led_classdev_register(&codec->core.dev, cdev);
- if (err < 0)
- return err;
- spec->led_cdevs[idx] = cdev;
- return 0;
-}
-
-/**
- * snd_hda_gen_add_mute_led_cdev - Create a LED classdev and enable as vmaster mute LED
- * @codec: the HDA codec
- * @callback: the callback for LED classdev brightness_set_blocking
- */
-int snd_hda_gen_add_mute_led_cdev(struct hda_codec *codec,
- int (*callback)(struct led_classdev *,
- enum led_brightness))
-{
- struct hda_gen_spec *spec = codec->spec;
- int err;
-
- if (callback) {
- err = create_mute_led_cdev(codec, callback, false);
- if (err) {
- codec_warn(codec, "failed to create a mute LED cdev\n");
- return err;
- }
- }
-
- if (spec->vmaster_mute.hook)
- codec_err(codec, "vmaster hook already present before cdev!\n");
-
- spec->vmaster_mute_led = 1;
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_gen_add_mute_led_cdev);
-
-/**
- * snd_hda_gen_add_micmute_led_cdev - Create a LED classdev and enable as mic-mute LED
- * @codec: the HDA codec
- * @callback: the callback for LED classdev brightness_set_blocking
- *
- * Called from the codec drivers for offering the mic mute LED controls.
- * This creates a LED classdev and sets up the cap_sync_hook that is called at
- * each time when the capture mixer switch changes.
- *
- * When NULL is passed to @callback, no classdev is created but only the
- * LED-trigger is set up.
- *
- * Returns 0 or a negative error.
- */
-int snd_hda_gen_add_micmute_led_cdev(struct hda_codec *codec,
- int (*callback)(struct led_classdev *,
- enum led_brightness))
-{
- struct hda_gen_spec *spec = codec->spec;
- int err;
-
- if (callback) {
- err = create_mute_led_cdev(codec, callback, true);
- if (err) {
- codec_warn(codec, "failed to create a mic-mute LED cdev\n");
- return err;
- }
- }
-
- spec->mic_mute_led = 1;
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_gen_add_micmute_led_cdev);
-#endif /* CONFIG_SND_HDA_GENERIC_LEDS */
-
-/*
- * parse digital I/Os and set up NIDs in BIOS auto-parse mode
- */
-static void parse_digital(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct nid_path *path;
- int i, nums;
- hda_nid_t dig_nid, pin;
-
- /* support multiple SPDIFs; the secondary is set up as a follower */
- nums = 0;
- for (i = 0; i < spec->autocfg.dig_outs; i++) {
- pin = spec->autocfg.dig_out_pins[i];
- dig_nid = look_for_dac(codec, pin, true);
- if (!dig_nid)
- continue;
- path = snd_hda_add_new_path(codec, dig_nid, pin, 0);
- if (!path)
- continue;
- print_nid_path(codec, "digout", path);
- path->active = true;
- path->pin_fixed = true; /* no jack detection */
- spec->digout_paths[i] = snd_hda_get_path_idx(codec, path);
- set_pin_target(codec, pin, PIN_OUT, false);
- if (!nums) {
- spec->multiout.dig_out_nid = dig_nid;
- spec->dig_out_type = spec->autocfg.dig_out_type[0];
- } else {
- spec->multiout.follower_dig_outs = spec->follower_dig_outs;
- if (nums >= ARRAY_SIZE(spec->follower_dig_outs) - 1)
- break;
- spec->follower_dig_outs[nums - 1] = dig_nid;
- }
- nums++;
- }
-
- if (spec->autocfg.dig_in_pin) {
- pin = spec->autocfg.dig_in_pin;
- for_each_hda_codec_node(dig_nid, codec) {
- unsigned int wcaps = get_wcaps(codec, dig_nid);
- if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
- continue;
- if (!(wcaps & AC_WCAP_DIGITAL))
- continue;
- path = snd_hda_add_new_path(codec, pin, dig_nid, 0);
- if (path) {
- print_nid_path(codec, "digin", path);
- path->active = true;
- path->pin_fixed = true; /* no jack */
- spec->dig_in_nid = dig_nid;
- spec->digin_path = snd_hda_get_path_idx(codec, path);
- set_pin_target(codec, pin, PIN_IN, false);
- break;
- }
- }
- }
-}
-
-
-/*
- * input MUX handling
- */
-
-static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur);
-
-/* select the given imux item; either unmute exclusively or select the route */
-static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
- unsigned int idx)
-{
- struct hda_gen_spec *spec = codec->spec;
- const struct hda_input_mux *imux;
- struct nid_path *old_path, *path;
-
- imux = &spec->input_mux;
- if (!imux->num_items)
- return 0;
-
- if (idx >= imux->num_items)
- idx = imux->num_items - 1;
- if (spec->cur_mux[adc_idx] == idx)
- return 0;
-
- old_path = get_input_path(codec, adc_idx, spec->cur_mux[adc_idx]);
- if (!old_path)
- return 0;
- if (old_path->active)
- snd_hda_activate_path(codec, old_path, false, false);
-
- spec->cur_mux[adc_idx] = idx;
-
- if (spec->hp_mic)
- update_hp_mic(codec, adc_idx, false);
-
- if (spec->dyn_adc_switch)
- dyn_adc_pcm_resetup(codec, idx);
-
- path = get_input_path(codec, adc_idx, idx);
- if (!path)
- return 0;
- if (path->active)
- return 0;
- snd_hda_activate_path(codec, path, true, false);
- if (spec->cap_sync_hook)
- spec->cap_sync_hook(codec, NULL, NULL);
- path_power_down_sync(codec, old_path);
- return 1;
-}
-
-/* power up/down widgets in the all paths that match with the given NID
- * as terminals (either start- or endpoint)
- *
- * returns the last changed NID, or zero if unchanged.
- */
-static hda_nid_t set_path_power(struct hda_codec *codec, hda_nid_t nid,
- int pin_state, int stream_state)
-{
- struct hda_gen_spec *spec = codec->spec;
- hda_nid_t last, changed = 0;
- struct nid_path *path;
- int n;
-
- snd_array_for_each(&spec->paths, n, path) {
- if (!path->depth)
- continue;
- if (path->path[0] == nid ||
- path->path[path->depth - 1] == nid) {
- bool pin_old = path->pin_enabled;
- bool stream_old = path->stream_enabled;
-
- if (pin_state >= 0)
- path->pin_enabled = pin_state;
- if (stream_state >= 0)
- path->stream_enabled = stream_state;
- if ((!path->pin_fixed && path->pin_enabled != pin_old)
- || path->stream_enabled != stream_old) {
- last = path_power_update(codec, path, true);
- if (last)
- changed = last;
- }
- }
- }
- return changed;
-}
-
-/* check the jack status for power control */
-static bool detect_pin_state(struct hda_codec *codec, hda_nid_t pin)
-{
- if (!is_jack_detectable(codec, pin))
- return true;
- return snd_hda_jack_detect_state(codec, pin) != HDA_JACK_NOT_PRESENT;
-}
-
-/* power up/down the paths of the given pin according to the jack state;
- * power = 0/1 : only power up/down if it matches with the jack state,
- * < 0 : force power up/down to follow the jack sate
- *
- * returns the last changed NID, or zero if unchanged.
- */
-static hda_nid_t set_pin_power_jack(struct hda_codec *codec, hda_nid_t pin,
- int power)
-{
- bool on;
-
- if (!codec->power_save_node)
- return 0;
-
- on = detect_pin_state(codec, pin);
-
- if (power >= 0 && on != power)
- return 0;
- return set_path_power(codec, pin, on, -1);
-}
-
-static void pin_power_callback(struct hda_codec *codec,
- struct hda_jack_callback *jack,
- bool on)
-{
- if (jack && jack->nid)
- sync_power_state_change(codec,
- set_pin_power_jack(codec, jack->nid, on));
-}
-
-/* callback only doing power up -- called at first */
-static void pin_power_up_callback(struct hda_codec *codec,
- struct hda_jack_callback *jack)
-{
- pin_power_callback(codec, jack, true);
-}
-
-/* callback only doing power down -- called at last */
-static void pin_power_down_callback(struct hda_codec *codec,
- struct hda_jack_callback *jack)
-{
- pin_power_callback(codec, jack, false);
-}
-
-/* set up the power up/down callbacks */
-static void add_pin_power_ctls(struct hda_codec *codec, int num_pins,
- const hda_nid_t *pins, bool on)
-{
- int i;
- hda_jack_callback_fn cb =
- on ? pin_power_up_callback : pin_power_down_callback;
-
- for (i = 0; i < num_pins && pins[i]; i++) {
- if (is_jack_detectable(codec, pins[i]))
- snd_hda_jack_detect_enable_callback(codec, pins[i], cb);
- else
- set_path_power(codec, pins[i], true, -1);
- }
-}
-
-/* enabled power callback to each available I/O pin with jack detections;
- * the digital I/O pins are excluded because of the unreliable detectsion
- */
-static void add_all_pin_power_ctls(struct hda_codec *codec, bool on)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->autocfg;
- int i;
-
- if (!codec->power_save_node)
- return;
- add_pin_power_ctls(codec, cfg->line_outs, cfg->line_out_pins, on);
- if (cfg->line_out_type != AUTO_PIN_HP_OUT)
- add_pin_power_ctls(codec, cfg->hp_outs, cfg->hp_pins, on);
- if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
- add_pin_power_ctls(codec, cfg->speaker_outs, cfg->speaker_pins, on);
- for (i = 0; i < cfg->num_inputs; i++)
- add_pin_power_ctls(codec, 1, &cfg->inputs[i].pin, on);
-}
-
-/* sync path power up/down with the jack states of given pins */
-static void sync_pin_power_ctls(struct hda_codec *codec, int num_pins,
- const hda_nid_t *pins)
-{
- int i;
-
- for (i = 0; i < num_pins && pins[i]; i++)
- if (is_jack_detectable(codec, pins[i]))
- set_pin_power_jack(codec, pins[i], -1);
-}
-
-/* sync path power up/down with pins; called at init and resume */
-static void sync_all_pin_power_ctls(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->autocfg;
- int i;
-
- if (!codec->power_save_node)
- return;
- sync_pin_power_ctls(codec, cfg->line_outs, cfg->line_out_pins);
- if (cfg->line_out_type != AUTO_PIN_HP_OUT)
- sync_pin_power_ctls(codec, cfg->hp_outs, cfg->hp_pins);
- if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
- sync_pin_power_ctls(codec, cfg->speaker_outs, cfg->speaker_pins);
- for (i = 0; i < cfg->num_inputs; i++)
- sync_pin_power_ctls(codec, 1, &cfg->inputs[i].pin);
-}
-
-/* add fake paths if not present yet */
-static int add_fake_paths(struct hda_codec *codec, hda_nid_t nid,
- int num_pins, const hda_nid_t *pins)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct nid_path *path;
- int i;
-
- for (i = 0; i < num_pins; i++) {
- if (!pins[i])
- break;
- if (get_nid_path(codec, nid, pins[i], 0))
- continue;
- path = snd_array_new(&spec->paths);
- if (!path)
- return -ENOMEM;
- memset(path, 0, sizeof(*path));
- path->depth = 2;
- path->path[0] = nid;
- path->path[1] = pins[i];
- path->active = true;
- }
- return 0;
-}
-
-/* create fake paths to all outputs from beep */
-static int add_fake_beep_paths(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->autocfg;
- hda_nid_t nid = spec->beep_nid;
- int err;
-
- if (!codec->power_save_node || !nid)
- return 0;
- err = add_fake_paths(codec, nid, cfg->line_outs, cfg->line_out_pins);
- if (err < 0)
- return err;
- if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
- err = add_fake_paths(codec, nid, cfg->hp_outs, cfg->hp_pins);
- if (err < 0)
- return err;
- }
- if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
- err = add_fake_paths(codec, nid, cfg->speaker_outs,
- cfg->speaker_pins);
- if (err < 0)
- return err;
- }
- return 0;
-}
-
-/* power up/down beep widget and its output paths */
-static void beep_power_hook(struct hda_beep *beep, bool on)
-{
- set_path_power(beep->codec, beep->nid, -1, on);
-}
-
-/**
- * snd_hda_gen_fix_pin_power - Fix the power of the given pin widget to D0
- * @codec: the HDA codec
- * @pin: NID of pin to fix
- */
-int snd_hda_gen_fix_pin_power(struct hda_codec *codec, hda_nid_t pin)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct nid_path *path;
-
- path = snd_array_new(&spec->paths);
- if (!path)
- return -ENOMEM;
- memset(path, 0, sizeof(*path));
- path->depth = 1;
- path->path[0] = pin;
- path->active = true;
- path->pin_fixed = true;
- path->stream_enabled = true;
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_gen_fix_pin_power);
-
-/*
- * Jack detections for HP auto-mute and mic-switch
- */
-
-/* check each pin in the given array; returns true if any of them is plugged */
-static bool detect_jacks(struct hda_codec *codec, int num_pins, const hda_nid_t *pins)
-{
- int i;
- bool present = false;
-
- for (i = 0; i < num_pins; i++) {
- hda_nid_t nid = pins[i];
- if (!nid)
- break;
- /* don't detect pins retasked as inputs */
- if (snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_IN_EN)
- continue;
- if (snd_hda_jack_detect_state(codec, nid) == HDA_JACK_PRESENT)
- present = true;
- }
- return present;
-}
-
-/* standard HP/line-out auto-mute helper */
-static void do_automute(struct hda_codec *codec, int num_pins, const hda_nid_t *pins,
- int *paths, bool mute)
-{
- struct hda_gen_spec *spec = codec->spec;
- int i;
-
- for (i = 0; i < num_pins; i++) {
- hda_nid_t nid = pins[i];
- unsigned int val, oldval;
- if (!nid)
- break;
-
- oldval = snd_hda_codec_get_pin_target(codec, nid);
- if (oldval & PIN_IN)
- continue; /* no mute for inputs */
-
- if (spec->auto_mute_via_amp) {
- struct nid_path *path;
- hda_nid_t mute_nid;
-
- path = snd_hda_get_path_from_idx(codec, paths[i]);
- if (!path)
- continue;
- mute_nid = get_amp_nid_(path->ctls[NID_PATH_MUTE_CTL]);
- if (!mute_nid)
- continue;
- if (mute)
- spec->mute_bits |= (1ULL << mute_nid);
- else
- spec->mute_bits &= ~(1ULL << mute_nid);
- continue;
- } else {
- /* don't reset VREF value in case it's controlling
- * the amp (see alc861_fixup_asus_amp_vref_0f())
- */
- if (spec->keep_vref_in_automute)
- val = oldval & ~PIN_HP;
- else
- val = 0;
- if (!mute)
- val |= oldval;
- /* here we call update_pin_ctl() so that the pinctl is
- * changed without changing the pinctl target value;
- * the original target value will be still referred at
- * the init / resume again
- */
- update_pin_ctl(codec, nid, val);
- }
-
- set_pin_eapd(codec, nid, !mute);
- if (codec->power_save_node) {
- bool on = !mute;
- if (on)
- on = detect_pin_state(codec, nid);
- set_path_power(codec, nid, on, -1);
- }
- }
-}
-
-/**
- * snd_hda_gen_update_outputs - Toggle outputs muting
- * @codec: the HDA codec
- *
- * Update the mute status of all outputs based on the current jack states.
- */
-void snd_hda_gen_update_outputs(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
- int *paths;
- int on;
-
- /* Control HP pins/amps depending on master_mute state;
- * in general, HP pins/amps control should be enabled in all cases,
- * but currently set only for master_mute, just to be safe
- */
- if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
- paths = spec->out_paths;
- else
- paths = spec->hp_paths;
- do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
- spec->autocfg.hp_pins, paths, spec->master_mute);
-
- if (!spec->automute_speaker)
- on = 0;
- else
- on = spec->hp_jack_present | spec->line_jack_present;
- on |= spec->master_mute;
- spec->speaker_muted = on;
- if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
- paths = spec->out_paths;
- else
- paths = spec->speaker_paths;
- do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
- spec->autocfg.speaker_pins, paths, on);
-
- /* toggle line-out mutes if needed, too */
- /* if LO is a copy of either HP or Speaker, don't need to handle it */
- if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
- spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
- return;
- if (!spec->automute_lo)
- on = 0;
- else
- on = spec->hp_jack_present;
- on |= spec->master_mute;
- spec->line_out_muted = on;
- paths = spec->out_paths;
- do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
- spec->autocfg.line_out_pins, paths, on);
-}
-EXPORT_SYMBOL_GPL(snd_hda_gen_update_outputs);
-
-static void call_update_outputs(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
- if (spec->automute_hook)
- spec->automute_hook(codec);
- else
- snd_hda_gen_update_outputs(codec);
-
- /* sync the whole vmaster followers to reflect the new auto-mute status */
- if (spec->auto_mute_via_amp && !codec->bus->shutdown)
- snd_ctl_sync_vmaster(spec->vmaster_mute.sw_kctl, false);
-}
-
-/**
- * snd_hda_gen_hp_automute - standard HP-automute helper
- * @codec: the HDA codec
- * @jack: jack object, NULL for the whole
- */
-void snd_hda_gen_hp_automute(struct hda_codec *codec,
- struct hda_jack_callback *jack)
-{
- struct hda_gen_spec *spec = codec->spec;
- hda_nid_t *pins = spec->autocfg.hp_pins;
- int num_pins = ARRAY_SIZE(spec->autocfg.hp_pins);
-
- /* No detection for the first HP jack during indep-HP mode */
- if (spec->indep_hp_enabled) {
- pins++;
- num_pins--;
- }
-
- spec->hp_jack_present = detect_jacks(codec, num_pins, pins);
- if (!spec->detect_hp || (!spec->automute_speaker && !spec->automute_lo))
- return;
- call_update_outputs(codec);
-}
-EXPORT_SYMBOL_GPL(snd_hda_gen_hp_automute);
-
-/**
- * snd_hda_gen_line_automute - standard line-out-automute helper
- * @codec: the HDA codec
- * @jack: jack object, NULL for the whole
- */
-void snd_hda_gen_line_automute(struct hda_codec *codec,
- struct hda_jack_callback *jack)
-{
- struct hda_gen_spec *spec = codec->spec;
-
- if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
- return;
- /* check LO jack only when it's different from HP */
- if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0])
- return;
-
- spec->line_jack_present =
- detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
- spec->autocfg.line_out_pins);
- if (!spec->automute_speaker || !spec->detect_lo)
- return;
- call_update_outputs(codec);
-}
-EXPORT_SYMBOL_GPL(snd_hda_gen_line_automute);
-
-/**
- * snd_hda_gen_mic_autoswitch - standard mic auto-switch helper
- * @codec: the HDA codec
- * @jack: jack object, NULL for the whole
- */
-void snd_hda_gen_mic_autoswitch(struct hda_codec *codec,
- struct hda_jack_callback *jack)
-{
- struct hda_gen_spec *spec = codec->spec;
- int i;
-
- if (!spec->auto_mic)
- return;
-
- for (i = spec->am_num_entries - 1; i > 0; i--) {
- hda_nid_t pin = spec->am_entry[i].pin;
- /* don't detect pins retasked as outputs */
- if (snd_hda_codec_get_pin_target(codec, pin) & AC_PINCTL_OUT_EN)
- continue;
- if (snd_hda_jack_detect_state(codec, pin) == HDA_JACK_PRESENT) {
- mux_select(codec, 0, spec->am_entry[i].idx);
- return;
- }
- }
- mux_select(codec, 0, spec->am_entry[0].idx);
-}
-EXPORT_SYMBOL_GPL(snd_hda_gen_mic_autoswitch);
-
-/* call appropriate hooks */
-static void call_hp_automute(struct hda_codec *codec,
- struct hda_jack_callback *jack)
-{
- struct hda_gen_spec *spec = codec->spec;
- if (spec->hp_automute_hook)
- spec->hp_automute_hook(codec, jack);
- else
- snd_hda_gen_hp_automute(codec, jack);
-}
-
-static void call_line_automute(struct hda_codec *codec,
- struct hda_jack_callback *jack)
-{
- struct hda_gen_spec *spec = codec->spec;
- if (spec->line_automute_hook)
- spec->line_automute_hook(codec, jack);
- else
- snd_hda_gen_line_automute(codec, jack);
-}
-
-static void call_mic_autoswitch(struct hda_codec *codec,
- struct hda_jack_callback *jack)
-{
- struct hda_gen_spec *spec = codec->spec;
- if (spec->mic_autoswitch_hook)
- spec->mic_autoswitch_hook(codec, jack);
- else
- snd_hda_gen_mic_autoswitch(codec, jack);
-}
-
-/* update jack retasking */
-static void update_automute_all(struct hda_codec *codec)
-{
- call_hp_automute(codec, NULL);
- call_line_automute(codec, NULL);
- call_mic_autoswitch(codec, NULL);
-}
-
-/*
- * Auto-Mute mode mixer enum support
- */
-static int automute_mode_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct hda_gen_spec *spec = codec->spec;
- static const char * const texts3[] = {
- "Disabled", "Speaker Only", "Line Out+Speaker"
- };
-
- if (spec->automute_speaker_possible && spec->automute_lo_possible)
- return snd_hda_enum_helper_info(kcontrol, uinfo, 3, texts3);
- return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
-}
-
-static int automute_mode_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct hda_gen_spec *spec = codec->spec;
- unsigned int val = 0;
- if (spec->automute_speaker)
- val++;
- if (spec->automute_lo)
- val++;
-
- ucontrol->value.enumerated.item[0] = val;
- return 0;
-}
-
-static int automute_mode_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct hda_gen_spec *spec = codec->spec;
-
- switch (ucontrol->value.enumerated.item[0]) {
- case 0:
- if (!spec->automute_speaker && !spec->automute_lo)
- return 0;
- spec->automute_speaker = 0;
- spec->automute_lo = 0;
- break;
- case 1:
- if (spec->automute_speaker_possible) {
- if (!spec->automute_lo && spec->automute_speaker)
- return 0;
- spec->automute_speaker = 1;
- spec->automute_lo = 0;
- } else if (spec->automute_lo_possible) {
- if (spec->automute_lo)
- return 0;
- spec->automute_lo = 1;
- } else
- return -EINVAL;
- break;
- case 2:
- if (!spec->automute_lo_possible || !spec->automute_speaker_possible)
- return -EINVAL;
- if (spec->automute_speaker && spec->automute_lo)
- return 0;
- spec->automute_speaker = 1;
- spec->automute_lo = 1;
- break;
- default:
- return -EINVAL;
- }
- call_update_outputs(codec);
- return 1;
-}
-
-static const struct snd_kcontrol_new automute_mode_enum = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Auto-Mute Mode",
- .info = automute_mode_info,
- .get = automute_mode_get,
- .put = automute_mode_put,
-};
-
-static int add_automute_mode_enum(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
-
- if (!snd_hda_gen_add_kctl(spec, NULL, &automute_mode_enum))
- return -ENOMEM;
- return 0;
-}
-
-/*
- * Check the availability of HP/line-out auto-mute;
- * Set up appropriately if really supported
- */
-static int check_auto_mute_availability(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->autocfg;
- int present = 0;
- int i, err;
-
- if (spec->suppress_auto_mute)
- return 0;
-
- if (cfg->hp_pins[0])
- present++;
- if (cfg->line_out_pins[0])
- present++;
- if (cfg->speaker_pins[0])
- present++;
- if (present < 2) /* need two different output types */
- return 0;
-
- if (!cfg->speaker_pins[0] &&
- cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
- memcpy(cfg->speaker_pins, cfg->line_out_pins,
- sizeof(cfg->speaker_pins));
- cfg->speaker_outs = cfg->line_outs;
- }
-
- if (!cfg->hp_pins[0] &&
- cfg->line_out_type == AUTO_PIN_HP_OUT) {
- memcpy(cfg->hp_pins, cfg->line_out_pins,
- sizeof(cfg->hp_pins));
- cfg->hp_outs = cfg->line_outs;
- }
-
- for (i = 0; i < cfg->hp_outs; i++) {
- hda_nid_t nid = cfg->hp_pins[i];
- if (!is_jack_detectable(codec, nid))
- continue;
- codec_dbg(codec, "Enable HP auto-muting on NID 0x%x\n", nid);
- snd_hda_jack_detect_enable_callback(codec, nid,
- call_hp_automute);
- spec->detect_hp = 1;
- }
-
- if (cfg->line_out_type == AUTO_PIN_LINE_OUT && cfg->line_outs) {
- if (cfg->speaker_outs)
- for (i = 0; i < cfg->line_outs; i++) {
- hda_nid_t nid = cfg->line_out_pins[i];
- if (!is_jack_detectable(codec, nid))
- continue;
- codec_dbg(codec, "Enable Line-Out auto-muting on NID 0x%x\n", nid);
- snd_hda_jack_detect_enable_callback(codec, nid,
- call_line_automute);
- spec->detect_lo = 1;
- }
- spec->automute_lo_possible = spec->detect_hp;
- }
-
- spec->automute_speaker_possible = cfg->speaker_outs &&
- (spec->detect_hp || spec->detect_lo);
-
- spec->automute_lo = spec->automute_lo_possible;
- spec->automute_speaker = spec->automute_speaker_possible;
-
- if (spec->automute_speaker_possible || spec->automute_lo_possible) {
- /* create a control for automute mode */
- err = add_automute_mode_enum(codec);
- if (err < 0)
- return err;
- }
- return 0;
-}
-
-/* check whether all auto-mic pins are valid; setup indices if OK */
-static bool auto_mic_check_imux(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
- const struct hda_input_mux *imux;
- int i;
-
- imux = &spec->input_mux;
- for (i = 0; i < spec->am_num_entries; i++) {
- spec->am_entry[i].idx =
- find_idx_in_nid_list(spec->am_entry[i].pin,
- spec->imux_pins, imux->num_items);
- if (spec->am_entry[i].idx < 0)
- return false; /* no corresponding imux */
- }
-
- /* we don't need the jack detection for the first pin */
- for (i = 1; i < spec->am_num_entries; i++)
- snd_hda_jack_detect_enable_callback(codec,
- spec->am_entry[i].pin,
- call_mic_autoswitch);
- return true;
-}
-
-static int compare_attr(const void *ap, const void *bp)
-{
- const struct automic_entry *a = ap;
- const struct automic_entry *b = bp;
- return (int)(a->attr - b->attr);
-}
-
-/*
- * Check the availability of auto-mic switch;
- * Set up if really supported
- */
-static int check_auto_mic_availability(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->autocfg;
- unsigned int types;
- int i, num_pins;
-
- if (spec->suppress_auto_mic)
- return 0;
-
- types = 0;
- num_pins = 0;
- for (i = 0; i < cfg->num_inputs; i++) {
- hda_nid_t nid = cfg->inputs[i].pin;
- unsigned int attr;
- attr = snd_hda_codec_get_pincfg(codec, nid);
- attr = snd_hda_get_input_pin_attr(attr);
- if (types & (1 << attr))
- return 0; /* already occupied */
- switch (attr) {
- case INPUT_PIN_ATTR_INT:
- if (cfg->inputs[i].type != AUTO_PIN_MIC)
- return 0; /* invalid type */
- break;
- case INPUT_PIN_ATTR_UNUSED:
- return 0; /* invalid entry */
- default:
- if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
- return 0; /* invalid type */
- if (!spec->line_in_auto_switch &&
- cfg->inputs[i].type != AUTO_PIN_MIC)
- return 0; /* only mic is allowed */
- if (!is_jack_detectable(codec, nid))
- return 0; /* no unsol support */
- break;
- }
- if (num_pins >= MAX_AUTO_MIC_PINS)
- return 0;
- types |= (1 << attr);
- spec->am_entry[num_pins].pin = nid;
- spec->am_entry[num_pins].attr = attr;
- num_pins++;
- }
-
- if (num_pins < 2)
- return 0;
-
- spec->am_num_entries = num_pins;
- /* sort the am_entry in the order of attr so that the pin with a
- * higher attr will be selected when the jack is plugged.
- */
- sort(spec->am_entry, num_pins, sizeof(spec->am_entry[0]),
- compare_attr, NULL);
-
- if (!auto_mic_check_imux(codec))
- return 0;
-
- spec->auto_mic = 1;
- spec->num_adc_nids = 1;
- spec->cur_mux[0] = spec->am_entry[0].idx;
- codec_dbg(codec, "Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
- spec->am_entry[0].pin,
- spec->am_entry[1].pin,
- spec->am_entry[2].pin);
-
- return 0;
-}
-
-/**
- * snd_hda_gen_path_power_filter - power_filter hook to make inactive widgets
- * into power down
- * @codec: the HDA codec
- * @nid: NID to evalute
- * @power_state: target power state
- */
-unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
- hda_nid_t nid,
- unsigned int power_state)
-{
- struct hda_gen_spec *spec = codec->spec;
-
- if (!spec->power_down_unused && !codec->power_save_node)
- return power_state;
- if (power_state != AC_PWRST_D0 || nid == codec->core.afg)
- return power_state;
- if (get_wcaps_type(get_wcaps(codec, nid)) >= AC_WID_POWER)
- return power_state;
- if (is_active_nid_for_any(codec, nid))
- return power_state;
- return AC_PWRST_D3;
-}
-EXPORT_SYMBOL_GPL(snd_hda_gen_path_power_filter);
-
-/* mute all aamix inputs initially; parse up to the first leaves */
-static void mute_all_mixer_nid(struct hda_codec *codec, hda_nid_t mix)
-{
- int i, nums;
- const hda_nid_t *conn;
- bool has_amp;
-
- nums = snd_hda_get_conn_list(codec, mix, &conn);
- has_amp = nid_has_mute(codec, mix, HDA_INPUT);
- for (i = 0; i < nums; i++) {
- if (has_amp)
- update_amp(codec, mix, HDA_INPUT, i,
- 0xff, HDA_AMP_MUTE);
- else if (nid_has_volume(codec, conn[i], HDA_OUTPUT))
- update_amp(codec, conn[i], HDA_OUTPUT, 0,
- 0xff, HDA_AMP_MUTE);
- }
-}
-
-/**
- * snd_hda_gen_stream_pm - Stream power management callback
- * @codec: the HDA codec
- * @nid: audio widget
- * @on: power on/off flag
- *
- * Set this in patch_ops.stream_pm. Only valid with power_save_node flag.
- */
-void snd_hda_gen_stream_pm(struct hda_codec *codec, hda_nid_t nid, bool on)
-{
- if (codec->power_save_node)
- set_path_power(codec, nid, -1, on);
-}
-EXPORT_SYMBOL_GPL(snd_hda_gen_stream_pm);
-
-/* forcibly mute the speaker output without caching; return true if updated */
-static bool force_mute_output_path(struct hda_codec *codec, hda_nid_t nid)
-{
- if (!nid)
- return false;
- if (!nid_has_mute(codec, nid, HDA_OUTPUT))
- return false; /* no mute, skip */
- if (snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) &
- snd_hda_codec_amp_read(codec, nid, 1, HDA_OUTPUT, 0) &
- HDA_AMP_MUTE)
- return false; /* both channels already muted, skip */
-
- /* direct amp update without caching */
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
- AC_AMP_SET_OUTPUT | AC_AMP_SET_LEFT |
- AC_AMP_SET_RIGHT | HDA_AMP_MUTE);
- return true;
-}
-
-/**
- * snd_hda_gen_shutup_speakers - Forcibly mute the speaker outputs
- * @codec: the HDA codec
- *
- * Forcibly mute the speaker outputs, to be called at suspend or shutdown.
- *
- * The mute state done by this function isn't cached, hence the original state
- * will be restored at resume.
- *
- * Return true if the mute state has been changed.
- */
-bool snd_hda_gen_shutup_speakers(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
- const int *paths;
- const struct nid_path *path;
- int i, p, num_paths;
- bool updated = false;
-
- /* if already powered off, do nothing */
- if (!snd_hdac_is_power_on(&codec->core))
- return false;
-
- if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT) {
- paths = spec->out_paths;
- num_paths = spec->autocfg.line_outs;
- } else {
- paths = spec->speaker_paths;
- num_paths = spec->autocfg.speaker_outs;
- }
-
- for (i = 0; i < num_paths; i++) {
- path = snd_hda_get_path_from_idx(codec, paths[i]);
- if (!path)
- continue;
- for (p = 0; p < path->depth; p++)
- if (force_mute_output_path(codec, path->path[p]))
- updated = true;
- }
-
- return updated;
-}
-EXPORT_SYMBOL_GPL(snd_hda_gen_shutup_speakers);
-
-/**
- * snd_hda_gen_parse_auto_config - Parse the given BIOS configuration and
- * set up the hda_gen_spec
- * @codec: the HDA codec
- * @cfg: Parsed pin configuration
- *
- * return 1 if successful, 0 if the proper config is not found,
- * or a negative error code
- */
-int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
- struct auto_pin_cfg *cfg)
-{
- struct hda_gen_spec *spec = codec->spec;
- int err;
-
- parse_user_hints(codec);
-
- if (spec->vmaster_mute_led || spec->mic_mute_led)
- snd_ctl_led_request();
-
- if (spec->mixer_nid && !spec->mixer_merge_nid)
- spec->mixer_merge_nid = spec->mixer_nid;
-
- if (cfg != &spec->autocfg) {
- spec->autocfg = *cfg;
- cfg = &spec->autocfg;
- }
-
- if (!spec->main_out_badness)
- spec->main_out_badness = &hda_main_out_badness;
- if (!spec->extra_out_badness)
- spec->extra_out_badness = &hda_extra_out_badness;
-
- fill_all_dac_nids(codec);
-
- if (!cfg->line_outs) {
- if (cfg->dig_outs || cfg->dig_in_pin) {
- spec->multiout.max_channels = 2;
- spec->no_analog = 1;
- goto dig_only;
- }
- if (!cfg->num_inputs && !cfg->dig_in_pin)
- return 0; /* can't find valid BIOS pin config */
- }
-
- if (!spec->no_primary_hp &&
- cfg->line_out_type == AUTO_PIN_SPEAKER_OUT &&
- cfg->line_outs <= cfg->hp_outs) {
- /* use HP as primary out */
- cfg->speaker_outs = cfg->line_outs;
- memcpy(cfg->speaker_pins, cfg->line_out_pins,
- sizeof(cfg->speaker_pins));
- cfg->line_outs = cfg->hp_outs;
- memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
- cfg->hp_outs = 0;
- memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
- cfg->line_out_type = AUTO_PIN_HP_OUT;
- }
-
- err = parse_output_paths(codec);
- if (err < 0)
- return err;
- err = create_multi_channel_mode(codec);
- if (err < 0)
- return err;
- err = create_multi_out_ctls(codec, cfg);
- if (err < 0)
- return err;
- err = create_hp_out_ctls(codec);
- if (err < 0)
- return err;
- err = create_speaker_out_ctls(codec);
- if (err < 0)
- return err;
- err = create_indep_hp_ctls(codec);
- if (err < 0)
- return err;
- err = create_loopback_mixing_ctl(codec);
- if (err < 0)
- return err;
- err = create_hp_mic(codec);
- if (err < 0)
- return err;
- err = create_input_ctls(codec);
- if (err < 0)
- return err;
-
- /* add power-down pin callbacks at first */
- add_all_pin_power_ctls(codec, false);
-
- spec->const_channel_count = spec->ext_channel_count;
- /* check the multiple speaker and headphone pins */
- if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
- spec->const_channel_count = max(spec->const_channel_count,
- cfg->speaker_outs * 2);
- if (cfg->line_out_type != AUTO_PIN_HP_OUT)
- spec->const_channel_count = max(spec->const_channel_count,
- cfg->hp_outs * 2);
- spec->multiout.max_channels = max(spec->ext_channel_count,
- spec->const_channel_count);
-
- err = check_auto_mute_availability(codec);
- if (err < 0)
- return err;
-
- err = check_dyn_adc_switch(codec);
- if (err < 0)
- return err;
-
- err = check_auto_mic_availability(codec);
- if (err < 0)
- return err;
-
- /* add stereo mix if available and not enabled yet */
- if (!spec->auto_mic && spec->mixer_nid &&
- spec->add_stereo_mix_input == HDA_HINT_STEREO_MIX_AUTO &&
- spec->input_mux.num_items > 1) {
- err = parse_capture_source(codec, spec->mixer_nid,
- CFG_IDX_MIX, spec->num_all_adcs,
- "Stereo Mix", 0);
- if (err < 0)
- return err;
- }
-
-
- err = create_capture_mixers(codec);
- if (err < 0)
- return err;
-
- err = parse_mic_boost(codec);
- if (err < 0)
- return err;
-
- /* create "Headphone Mic Jack Mode" if no input selection is
- * available (or user specifies add_jack_modes hint)
- */
- if (spec->hp_mic_pin &&
- (spec->auto_mic || spec->input_mux.num_items == 1 ||
- spec->add_jack_modes)) {
- err = create_hp_mic_jack_mode(codec, spec->hp_mic_pin);
- if (err < 0)
- return err;
- }
-
- if (spec->add_jack_modes) {
- if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
- err = create_out_jack_modes(codec, cfg->line_outs,
- cfg->line_out_pins);
- if (err < 0)
- return err;
- }
- if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
- err = create_out_jack_modes(codec, cfg->hp_outs,
- cfg->hp_pins);
- if (err < 0)
- return err;
- }
- }
-
- /* add power-up pin callbacks at last */
- add_all_pin_power_ctls(codec, true);
-
- /* mute all aamix input initially */
- if (spec->mixer_nid)
- mute_all_mixer_nid(codec, spec->mixer_nid);
-
- dig_only:
- parse_digital(codec);
-
- if (spec->power_down_unused || codec->power_save_node) {
- if (!codec->power_filter)
- codec->power_filter = snd_hda_gen_path_power_filter;
- if (!codec->patch_ops.stream_pm)
- codec->patch_ops.stream_pm = snd_hda_gen_stream_pm;
- }
-
- if (!spec->no_analog && spec->beep_nid) {
- err = snd_hda_attach_beep_device(codec, spec->beep_nid);
- if (err < 0)
- return err;
- if (codec->beep && codec->power_save_node) {
- err = add_fake_beep_paths(codec);
- if (err < 0)
- return err;
- codec->beep->power_hook = beep_power_hook;
- }
- }
-
- return 1;
-}
-EXPORT_SYMBOL_GPL(snd_hda_gen_parse_auto_config);
-
-
-/*
- * Build control elements
- */
-
-/* follower controls for virtual master */
-static const char * const follower_pfxs[] = {
- "Front", "Surround", "Center", "LFE", "Side",
- "Headphone", "Speaker", "Mono", "Line Out",
- "CLFE", "Bass Speaker", "PCM",
- "Speaker Front", "Speaker Surround", "Speaker CLFE", "Speaker Side",
- "Headphone Front", "Headphone Surround", "Headphone CLFE",
- "Headphone Side", "Headphone+LO", "Speaker+LO",
- NULL,
-};
-
-/**
- * snd_hda_gen_build_controls - Build controls from the parsed results
- * @codec: the HDA codec
- *
- * Pass this to build_controls patch_ops.
- */
-int snd_hda_gen_build_controls(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
- int err;
-
- if (spec->kctls.used) {
- err = snd_hda_add_new_ctls(codec, spec->kctls.list);
- if (err < 0)
- return err;
- }
-
- if (spec->multiout.dig_out_nid) {
- err = snd_hda_create_dig_out_ctls(codec,
- spec->multiout.dig_out_nid,
- spec->multiout.dig_out_nid,
- spec->pcm_rec[1]->pcm_type);
- if (err < 0)
- return err;
- if (!spec->no_analog) {
- err = snd_hda_create_spdif_share_sw(codec,
- &spec->multiout);
- if (err < 0)
- return err;
- spec->multiout.share_spdif = 1;
- }
- }
- if (spec->dig_in_nid) {
- err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
- if (err < 0)
- return err;
- }
-
- /* if we have no master control, let's create it */
- if (!spec->no_analog && !spec->suppress_vmaster &&
- !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
- err = snd_hda_add_vmaster(codec, "Master Playback Volume",
- spec->vmaster_tlv, follower_pfxs,
- "Playback Volume", 0);
- if (err < 0)
- return err;
- }
- if (!spec->no_analog && !spec->suppress_vmaster &&
- !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
- err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
- NULL, follower_pfxs,
- "Playback Switch", true,
- spec->vmaster_mute_led ?
- SNDRV_CTL_ELEM_ACCESS_SPK_LED : 0,
- &spec->vmaster_mute.sw_kctl);
- if (err < 0)
- return err;
- if (spec->vmaster_mute.hook) {
- snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute);
- snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
- }
- }
-
- free_kctls(spec); /* no longer needed */
-
- err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
- if (err < 0)
- return err;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_gen_build_controls);
-
-
-/*
- * PCM definitions
- */
-
-static void call_pcm_playback_hook(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream,
- int action)
-{
- struct hda_gen_spec *spec = codec->spec;
- if (spec->pcm_playback_hook)
- spec->pcm_playback_hook(hinfo, codec, substream, action);
-}
-
-static void call_pcm_capture_hook(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream,
- int action)
-{
- struct hda_gen_spec *spec = codec->spec;
- if (spec->pcm_capture_hook)
- spec->pcm_capture_hook(hinfo, codec, substream, action);
-}
-
-/*
- * Analog playback callbacks
- */
-static int playback_pcm_open(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- struct hda_gen_spec *spec = codec->spec;
- int err;
-
- mutex_lock(&spec->pcm_mutex);
- err = snd_hda_multi_out_analog_open(codec,
- &spec->multiout, substream,
- hinfo);
- if (!err) {
- spec->active_streams |= 1 << STREAM_MULTI_OUT;
- call_pcm_playback_hook(hinfo, codec, substream,
- HDA_GEN_PCM_ACT_OPEN);
- }
- mutex_unlock(&spec->pcm_mutex);
- return err;
-}
-
-static int playback_pcm_prepare(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- unsigned int stream_tag,
- unsigned int format,
- struct snd_pcm_substream *substream)
-{
- struct hda_gen_spec *spec = codec->spec;
- int err;
-
- err = snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
- stream_tag, format, substream);
- if (!err)
- call_pcm_playback_hook(hinfo, codec, substream,
- HDA_GEN_PCM_ACT_PREPARE);
- return err;
-}
-
-static int playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- struct hda_gen_spec *spec = codec->spec;
- int err;
-
- err = snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
- if (!err)
- call_pcm_playback_hook(hinfo, codec, substream,
- HDA_GEN_PCM_ACT_CLEANUP);
- return err;
-}
-
-static int playback_pcm_close(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- struct hda_gen_spec *spec = codec->spec;
- mutex_lock(&spec->pcm_mutex);
- spec->active_streams &= ~(1 << STREAM_MULTI_OUT);
- call_pcm_playback_hook(hinfo, codec, substream,
- HDA_GEN_PCM_ACT_CLOSE);
- mutex_unlock(&spec->pcm_mutex);
- return 0;
-}
-
-static int capture_pcm_open(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_OPEN);
- return 0;
-}
-
-static int capture_pcm_prepare(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- unsigned int stream_tag,
- unsigned int format,
- struct snd_pcm_substream *substream)
-{
- snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
- call_pcm_capture_hook(hinfo, codec, substream,
- HDA_GEN_PCM_ACT_PREPARE);
- return 0;
-}
-
-static int capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- snd_hda_codec_cleanup_stream(codec, hinfo->nid);
- call_pcm_capture_hook(hinfo, codec, substream,
- HDA_GEN_PCM_ACT_CLEANUP);
- return 0;
-}
-
-static int capture_pcm_close(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_CLOSE);
- return 0;
-}
-
-static int alt_playback_pcm_open(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- struct hda_gen_spec *spec = codec->spec;
- int err = 0;
-
- mutex_lock(&spec->pcm_mutex);
- if (spec->indep_hp && !spec->indep_hp_enabled)
- err = -EBUSY;
- else
- spec->active_streams |= 1 << STREAM_INDEP_HP;
- call_pcm_playback_hook(hinfo, codec, substream,
- HDA_GEN_PCM_ACT_OPEN);
- mutex_unlock(&spec->pcm_mutex);
- return err;
-}
-
-static int alt_playback_pcm_close(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- struct hda_gen_spec *spec = codec->spec;
- mutex_lock(&spec->pcm_mutex);
- spec->active_streams &= ~(1 << STREAM_INDEP_HP);
- call_pcm_playback_hook(hinfo, codec, substream,
- HDA_GEN_PCM_ACT_CLOSE);
- mutex_unlock(&spec->pcm_mutex);
- return 0;
-}
-
-static int alt_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- unsigned int stream_tag,
- unsigned int format,
- struct snd_pcm_substream *substream)
-{
- snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
- call_pcm_playback_hook(hinfo, codec, substream,
- HDA_GEN_PCM_ACT_PREPARE);
- return 0;
-}
-
-static int alt_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- snd_hda_codec_cleanup_stream(codec, hinfo->nid);
- call_pcm_playback_hook(hinfo, codec, substream,
- HDA_GEN_PCM_ACT_CLEANUP);
- return 0;
-}
-
-/*
- * Digital out
- */
-static int dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- struct hda_gen_spec *spec = codec->spec;
- return snd_hda_multi_out_dig_open(codec, &spec->multiout);
-}
-
-static int dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- unsigned int stream_tag,
- unsigned int format,
- struct snd_pcm_substream *substream)
-{
- struct hda_gen_spec *spec = codec->spec;
- return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
- stream_tag, format, substream);
-}
-
-static int dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- struct hda_gen_spec *spec = codec->spec;
- return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
-}
-
-static int dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- struct hda_gen_spec *spec = codec->spec;
- return snd_hda_multi_out_dig_close(codec, &spec->multiout);
-}
-
-/*
- * Analog capture
- */
-#define alt_capture_pcm_open capture_pcm_open
-#define alt_capture_pcm_close capture_pcm_close
-
-static int alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- unsigned int stream_tag,
- unsigned int format,
- struct snd_pcm_substream *substream)
-{
- struct hda_gen_spec *spec = codec->spec;
-
- snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
- stream_tag, 0, format);
- call_pcm_capture_hook(hinfo, codec, substream,
- HDA_GEN_PCM_ACT_PREPARE);
- return 0;
-}
-
-static int alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- struct hda_gen_spec *spec = codec->spec;
-
- snd_hda_codec_cleanup_stream(codec,
- spec->adc_nids[substream->number + 1]);
- call_pcm_capture_hook(hinfo, codec, substream,
- HDA_GEN_PCM_ACT_CLEANUP);
- return 0;
-}
-
-/*
- */
-static const struct hda_pcm_stream pcm_analog_playback = {
- .substreams = 1,
- .channels_min = 2,
- .channels_max = 8,
- /* NID is set in build_pcms */
- .ops = {
- .open = playback_pcm_open,
- .close = playback_pcm_close,
- .prepare = playback_pcm_prepare,
- .cleanup = playback_pcm_cleanup
- },
-};
-
-static const struct hda_pcm_stream pcm_analog_capture = {
- .substreams = 1,
- .channels_min = 2,
- .channels_max = 2,
- /* NID is set in build_pcms */
- .ops = {
- .open = capture_pcm_open,
- .close = capture_pcm_close,
- .prepare = capture_pcm_prepare,
- .cleanup = capture_pcm_cleanup
- },
-};
-
-static const struct hda_pcm_stream pcm_analog_alt_playback = {
- .substreams = 1,
- .channels_min = 2,
- .channels_max = 2,
- /* NID is set in build_pcms */
- .ops = {
- .open = alt_playback_pcm_open,
- .close = alt_playback_pcm_close,
- .prepare = alt_playback_pcm_prepare,
- .cleanup = alt_playback_pcm_cleanup
- },
-};
-
-static const struct hda_pcm_stream pcm_analog_alt_capture = {
- .substreams = 2, /* can be overridden */
- .channels_min = 2,
- .channels_max = 2,
- /* NID is set in build_pcms */
- .ops = {
- .open = alt_capture_pcm_open,
- .close = alt_capture_pcm_close,
- .prepare = alt_capture_pcm_prepare,
- .cleanup = alt_capture_pcm_cleanup
- },
-};
-
-static const struct hda_pcm_stream pcm_digital_playback = {
- .substreams = 1,
- .channels_min = 2,
- .channels_max = 2,
- /* NID is set in build_pcms */
- .ops = {
- .open = dig_playback_pcm_open,
- .close = dig_playback_pcm_close,
- .prepare = dig_playback_pcm_prepare,
- .cleanup = dig_playback_pcm_cleanup
- },
-};
-
-static const struct hda_pcm_stream pcm_digital_capture = {
- .substreams = 1,
- .channels_min = 2,
- .channels_max = 2,
- /* NID is set in build_pcms */
-};
-
-/* Used by build_pcms to flag that a PCM has no playback stream */
-static const struct hda_pcm_stream pcm_null_stream = {
- .substreams = 0,
- .channels_min = 0,
- .channels_max = 0,
-};
-
-/*
- * dynamic changing ADC PCM streams
- */
-static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
-{
- struct hda_gen_spec *spec = codec->spec;
- hda_nid_t new_adc = spec->adc_nids[spec->dyn_adc_idx[cur]];
-
- if (spec->cur_adc && spec->cur_adc != new_adc) {
- /* stream is running, let's swap the current ADC */
- __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
- spec->cur_adc = new_adc;
- snd_hda_codec_setup_stream(codec, new_adc,
- spec->cur_adc_stream_tag, 0,
- spec->cur_adc_format);
- return true;
- }
- return false;
-}
-
-/* analog capture with dynamic dual-adc changes */
-static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- unsigned int stream_tag,
- unsigned int format,
- struct snd_pcm_substream *substream)
-{
- struct hda_gen_spec *spec = codec->spec;
- spec->cur_adc = spec->adc_nids[spec->dyn_adc_idx[spec->cur_mux[0]]];
- spec->cur_adc_stream_tag = stream_tag;
- spec->cur_adc_format = format;
- snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
- call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_PREPARE);
- return 0;
-}
-
-static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- struct hda_gen_spec *spec = codec->spec;
- snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
- spec->cur_adc = 0;
- call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_CLEANUP);
- return 0;
-}
-
-static const struct hda_pcm_stream dyn_adc_pcm_analog_capture = {
- .substreams = 1,
- .channels_min = 2,
- .channels_max = 2,
- .nid = 0, /* fill later */
- .ops = {
- .prepare = dyn_adc_capture_pcm_prepare,
- .cleanup = dyn_adc_capture_pcm_cleanup
- },
-};
-
-static void fill_pcm_stream_name(char *str, size_t len, const char *sfx,
- const char *chip_name)
-{
- char *p;
-
- if (*str)
- return;
- strscpy(str, chip_name, len);
-
- /* drop non-alnum chars after a space */
- for (p = strchr(str, ' '); p; p = strchr(p + 1, ' ')) {
- if (!isalnum(p[1])) {
- *p = 0;
- break;
- }
- }
- strlcat(str, sfx, len);
-}
-
-/* copy PCM stream info from @default_str, and override non-NULL entries
- * from @spec_str and @nid
- */
-static void setup_pcm_stream(struct hda_pcm_stream *str,
- const struct hda_pcm_stream *default_str,
- const struct hda_pcm_stream *spec_str,
- hda_nid_t nid)
-{
- *str = *default_str;
- if (nid)
- str->nid = nid;
- if (spec_str) {
- if (spec_str->substreams)
- str->substreams = spec_str->substreams;
- if (spec_str->channels_min)
- str->channels_min = spec_str->channels_min;
- if (spec_str->channels_max)
- str->channels_max = spec_str->channels_max;
- if (spec_str->rates)
- str->rates = spec_str->rates;
- if (spec_str->formats)
- str->formats = spec_str->formats;
- if (spec_str->maxbps)
- str->maxbps = spec_str->maxbps;
- }
-}
-
-/**
- * snd_hda_gen_build_pcms - build PCM streams based on the parsed results
- * @codec: the HDA codec
- *
- * Pass this to build_pcms patch_ops.
- */
-int snd_hda_gen_build_pcms(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct hda_pcm *info;
- bool have_multi_adcs;
-
- if (spec->no_analog)
- goto skip_analog;
-
- fill_pcm_stream_name(spec->stream_name_analog,
- sizeof(spec->stream_name_analog),
- " Analog", codec->core.chip_name);
- info = snd_hda_codec_pcm_new(codec, "%s", spec->stream_name_analog);
- if (!info)
- return -ENOMEM;
- spec->pcm_rec[0] = info;
-
- if (spec->multiout.num_dacs > 0) {
- setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_PLAYBACK],
- &pcm_analog_playback,
- spec->stream_analog_playback,
- spec->multiout.dac_nids[0]);
- info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
- spec->multiout.max_channels;
- if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT &&
- spec->autocfg.line_outs == 2)
- info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap =
- snd_pcm_2_1_chmaps;
- }
- if (spec->num_adc_nids) {
- setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_CAPTURE],
- (spec->dyn_adc_switch ?
- &dyn_adc_pcm_analog_capture : &pcm_analog_capture),
- spec->stream_analog_capture,
- spec->adc_nids[0]);
- }
-
- skip_analog:
- /* SPDIF for stream index #1 */
- if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
- fill_pcm_stream_name(spec->stream_name_digital,
- sizeof(spec->stream_name_digital),
- " Digital", codec->core.chip_name);
- info = snd_hda_codec_pcm_new(codec, "%s",
- spec->stream_name_digital);
- if (!info)
- return -ENOMEM;
- codec->follower_dig_outs = spec->multiout.follower_dig_outs;
- spec->pcm_rec[1] = info;
- if (spec->dig_out_type)
- info->pcm_type = spec->dig_out_type;
- else
- info->pcm_type = HDA_PCM_TYPE_SPDIF;
- if (spec->multiout.dig_out_nid)
- setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_PLAYBACK],
- &pcm_digital_playback,
- spec->stream_digital_playback,
- spec->multiout.dig_out_nid);
- if (spec->dig_in_nid)
- setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_CAPTURE],
- &pcm_digital_capture,
- spec->stream_digital_capture,
- spec->dig_in_nid);
- }
-
- if (spec->no_analog)
- return 0;
-
- /* If the use of more than one ADC is requested for the current
- * model, configure a second analog capture-only PCM.
- */
- have_multi_adcs = (spec->num_adc_nids > 1) &&
- !spec->dyn_adc_switch && !spec->auto_mic;
- /* Additional Analaog capture for index #2 */
- if (spec->alt_dac_nid || have_multi_adcs) {
- fill_pcm_stream_name(spec->stream_name_alt_analog,
- sizeof(spec->stream_name_alt_analog),
- " Alt Analog", codec->core.chip_name);
- info = snd_hda_codec_pcm_new(codec, "%s",
- spec->stream_name_alt_analog);
- if (!info)
- return -ENOMEM;
- spec->pcm_rec[2] = info;
- if (spec->alt_dac_nid)
- setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_PLAYBACK],
- &pcm_analog_alt_playback,
- spec->stream_analog_alt_playback,
- spec->alt_dac_nid);
- else
- setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_PLAYBACK],
- &pcm_null_stream, NULL, 0);
- if (have_multi_adcs) {
- setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_CAPTURE],
- &pcm_analog_alt_capture,
- spec->stream_analog_alt_capture,
- spec->adc_nids[1]);
- info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
- spec->num_adc_nids - 1;
- } else {
- setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_CAPTURE],
- &pcm_null_stream, NULL, 0);
- }
- }
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_gen_build_pcms);
-
-
-/*
- * Standard auto-parser initializations
- */
-
-/* configure the given path as a proper output */
-static void set_output_and_unmute(struct hda_codec *codec, int path_idx)
-{
- struct nid_path *path;
- hda_nid_t pin;
-
- path = snd_hda_get_path_from_idx(codec, path_idx);
- if (!path || !path->depth)
- return;
- pin = path->path[path->depth - 1];
- restore_pin_ctl(codec, pin);
- snd_hda_activate_path(codec, path, path->active,
- aamix_default(codec->spec));
- set_pin_eapd(codec, pin, path->active);
-}
-
-/* initialize primary output paths */
-static void init_multi_out(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
- int i;
-
- for (i = 0; i < spec->autocfg.line_outs; i++)
- set_output_and_unmute(codec, spec->out_paths[i]);
-}
-
-
-static void __init_extra_out(struct hda_codec *codec, int num_outs, int *paths)
-{
- int i;
-
- for (i = 0; i < num_outs; i++)
- set_output_and_unmute(codec, paths[i]);
-}
-
-/* initialize hp and speaker paths */
-static void init_extra_out(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
-
- if (spec->autocfg.line_out_type != AUTO_PIN_HP_OUT)
- __init_extra_out(codec, spec->autocfg.hp_outs, spec->hp_paths);
- if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT)
- __init_extra_out(codec, spec->autocfg.speaker_outs,
- spec->speaker_paths);
-}
-
-/* initialize multi-io paths */
-static void init_multi_io(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
- int i;
-
- for (i = 0; i < spec->multi_ios; i++) {
- hda_nid_t pin = spec->multi_io[i].pin;
- struct nid_path *path;
- path = get_multiio_path(codec, i);
- if (!path)
- continue;
- if (!spec->multi_io[i].ctl_in)
- spec->multi_io[i].ctl_in =
- snd_hda_codec_get_pin_target(codec, pin);
- snd_hda_activate_path(codec, path, path->active,
- aamix_default(spec));
- }
-}
-
-static void init_aamix_paths(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
-
- if (!spec->have_aamix_ctl)
- return;
- if (!has_aamix_out_paths(spec))
- return;
- update_aamix_paths(codec, spec->aamix_mode, spec->out_paths[0],
- spec->aamix_out_paths[0],
- spec->autocfg.line_out_type);
- update_aamix_paths(codec, spec->aamix_mode, spec->hp_paths[0],
- spec->aamix_out_paths[1],
- AUTO_PIN_HP_OUT);
- update_aamix_paths(codec, spec->aamix_mode, spec->speaker_paths[0],
- spec->aamix_out_paths[2],
- AUTO_PIN_SPEAKER_OUT);
-}
-
-/* set up input pins and loopback paths */
-static void init_analog_input(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->autocfg;
- int i;
-
- for (i = 0; i < cfg->num_inputs; i++) {
- hda_nid_t nid = cfg->inputs[i].pin;
- if (is_input_pin(codec, nid))
- restore_pin_ctl(codec, nid);
-
- /* init loopback inputs */
- if (spec->mixer_nid) {
- resume_path_from_idx(codec, spec->loopback_paths[i]);
- resume_path_from_idx(codec, spec->loopback_merge_path);
- }
- }
-}
-
-/* initialize ADC paths */
-static void init_input_src(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
- struct hda_input_mux *imux = &spec->input_mux;
- struct nid_path *path;
- int i, c, nums;
-
- if (spec->dyn_adc_switch)
- nums = 1;
- else
- nums = spec->num_adc_nids;
-
- for (c = 0; c < nums; c++) {
- for (i = 0; i < imux->num_items; i++) {
- path = get_input_path(codec, c, i);
- if (path) {
- bool active = path->active;
- if (i == spec->cur_mux[c])
- active = true;
- snd_hda_activate_path(codec, path, active, false);
- }
- }
- if (spec->hp_mic)
- update_hp_mic(codec, c, true);
- }
-
- if (spec->cap_sync_hook)
- spec->cap_sync_hook(codec, NULL, NULL);
-}
-
-/* set right pin controls for digital I/O */
-static void init_digital(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
- int i;
- hda_nid_t pin;
-
- for (i = 0; i < spec->autocfg.dig_outs; i++)
- set_output_and_unmute(codec, spec->digout_paths[i]);
- pin = spec->autocfg.dig_in_pin;
- if (pin) {
- restore_pin_ctl(codec, pin);
- resume_path_from_idx(codec, spec->digin_path);
- }
-}
-
-/* clear unsol-event tags on unused pins; Conexant codecs seem to leave
- * invalid unsol tags by some reason
- */
-static void clear_unsol_on_unused_pins(struct hda_codec *codec)
-{
- const struct hda_pincfg *pin;
- int i;
-
- snd_array_for_each(&codec->init_pins, i, pin) {
- hda_nid_t nid = pin->nid;
- if (is_jack_detectable(codec, nid) &&
- !snd_hda_jack_tbl_get(codec, nid))
- snd_hda_codec_write_cache(codec, nid, 0,
- AC_VERB_SET_UNSOLICITED_ENABLE, 0);
- }
-}
-
-/**
- * snd_hda_gen_init - initialize the generic spec
- * @codec: the HDA codec
- *
- * This can be put as patch_ops init function.
- */
-int snd_hda_gen_init(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
-
- if (spec->init_hook)
- spec->init_hook(codec);
-
- if (!spec->skip_verbs)
- snd_hda_apply_verbs(codec);
-
- init_multi_out(codec);
- init_extra_out(codec);
- init_multi_io(codec);
- init_aamix_paths(codec);
- init_analog_input(codec);
- init_input_src(codec);
- init_digital(codec);
-
- clear_unsol_on_unused_pins(codec);
-
- sync_all_pin_power_ctls(codec);
-
- /* call init functions of standard auto-mute helpers */
- update_automute_all(codec);
-
- snd_hda_regmap_sync(codec);
-
- if (spec->vmaster_mute.sw_kctl && spec->vmaster_mute.hook)
- snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
-
- hda_call_check_power_status(codec, 0x01);
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_gen_init);
-
-/**
- * snd_hda_gen_free - free the generic spec
- * @codec: the HDA codec
- *
- * This can be put as patch_ops free function.
- */
-void snd_hda_gen_free(struct hda_codec *codec)
-{
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_FREE);
- snd_hda_gen_spec_free(codec->spec);
- kfree(codec->spec);
- codec->spec = NULL;
-}
-EXPORT_SYMBOL_GPL(snd_hda_gen_free);
-
-/**
- * snd_hda_gen_check_power_status - check the loopback power save state
- * @codec: the HDA codec
- * @nid: NID to inspect
- *
- * This can be put as patch_ops check_power_status function.
- */
-int snd_hda_gen_check_power_status(struct hda_codec *codec, hda_nid_t nid)
-{
- struct hda_gen_spec *spec = codec->spec;
- return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
-}
-EXPORT_SYMBOL_GPL(snd_hda_gen_check_power_status);
-
-
-/*
- * the generic codec support
- */
-
-static const struct hda_codec_ops generic_patch_ops = {
- .build_controls = snd_hda_gen_build_controls,
- .build_pcms = snd_hda_gen_build_pcms,
- .init = snd_hda_gen_init,
- .free = snd_hda_gen_free,
- .unsol_event = snd_hda_jack_unsol_event,
- .check_power_status = snd_hda_gen_check_power_status,
-};
-
-/*
- * snd_hda_parse_generic_codec - Generic codec parser
- * @codec: the HDA codec
- */
-static int snd_hda_parse_generic_codec(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec;
- int err;
-
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (!spec)
- return -ENOMEM;
- snd_hda_gen_spec_init(spec);
- codec->spec = spec;
-
- err = snd_hda_parse_pin_defcfg(codec, &spec->autocfg, NULL, 0);
- if (err < 0)
- goto error;
-
- err = snd_hda_gen_parse_auto_config(codec, &spec->autocfg);
- if (err < 0)
- goto error;
-
- codec->patch_ops = generic_patch_ops;
- return 0;
-
-error:
- snd_hda_gen_free(codec);
- return err;
-}
-
-static const struct hda_device_id snd_hda_id_generic[] = {
- HDA_CODEC_ENTRY(HDA_CODEC_ID_GENERIC, "Generic", snd_hda_parse_generic_codec),
- {} /* terminator */
-};
-MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_generic);
-
-static struct hda_codec_driver generic_driver = {
- .id = snd_hda_id_generic,
-};
-
-module_hda_codec_driver(generic_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Generic HD-audio codec parser");
diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h
deleted file mode 100644
index 9612afaa61c2..000000000000
--- a/sound/pci/hda/hda_generic.h
+++ /dev/null
@@ -1,357 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Generic BIOS auto-parser helper functions for HD-audio
- *
- * Copyright (c) 2012 Takashi Iwai <tiwai@suse.de>
- */
-
-#ifndef __SOUND_HDA_GENERIC_H
-#define __SOUND_HDA_GENERIC_H
-
-#include <linux/leds.h>
-#include "hda_auto_parser.h"
-
-struct hda_jack_callback;
-
-/* table entry for multi-io paths */
-struct hda_multi_io {
- hda_nid_t pin; /* multi-io widget pin NID */
- hda_nid_t dac; /* DAC to be connected */
- unsigned int ctl_in; /* cached input-pin control value */
-};
-
-/* Widget connection path
- *
- * For output, stored in the order of DAC -> ... -> pin,
- * for input, pin -> ... -> ADC.
- *
- * idx[i] contains the source index number to select on of the widget path[i];
- * e.g. idx[1] is the index of the DAC (path[0]) selected by path[1] widget
- * multi[] indicates whether it's a selector widget with multi-connectors
- * (i.e. the connection selection is mandatory)
- * vol_ctl and mute_ctl contains the NIDs for the assigned mixers
- */
-
-#define MAX_NID_PATH_DEPTH 10
-
-enum {
- NID_PATH_VOL_CTL,
- NID_PATH_MUTE_CTL,
- NID_PATH_BOOST_CTL,
- NID_PATH_NUM_CTLS
-};
-
-struct nid_path {
- int depth;
- hda_nid_t path[MAX_NID_PATH_DEPTH];
- unsigned char idx[MAX_NID_PATH_DEPTH];
- unsigned char multi[MAX_NID_PATH_DEPTH];
- unsigned int ctls[NID_PATH_NUM_CTLS]; /* NID_PATH_XXX_CTL */
- bool active:1; /* activated by driver */
- bool pin_enabled:1; /* pins are enabled */
- bool pin_fixed:1; /* path with fixed pin */
- bool stream_enabled:1; /* stream is active */
-};
-
-/* mic/line-in auto switching entry */
-
-#define MAX_AUTO_MIC_PINS 3
-
-struct automic_entry {
- hda_nid_t pin; /* pin */
- int idx; /* imux index, -1 = invalid */
- unsigned int attr; /* pin attribute (INPUT_PIN_ATTR_*) */
-};
-
-/* active stream id */
-enum { STREAM_MULTI_OUT, STREAM_INDEP_HP };
-
-/* PCM hook action */
-enum {
- HDA_GEN_PCM_ACT_OPEN,
- HDA_GEN_PCM_ACT_PREPARE,
- HDA_GEN_PCM_ACT_CLEANUP,
- HDA_GEN_PCM_ACT_CLOSE,
-};
-
-/* DAC assignment badness table */
-struct badness_table {
- int no_primary_dac; /* no primary DAC */
- int no_dac; /* no secondary DACs */
- int shared_primary; /* primary DAC is shared with main output */
- int shared_surr; /* secondary DAC shared with main or primary */
- int shared_clfe; /* third DAC shared with main or primary */
- int shared_surr_main; /* secondary DAC sahred with main/DAC0 */
-};
-
-extern const struct badness_table hda_main_out_badness;
-extern const struct badness_table hda_extra_out_badness;
-
-struct hda_gen_spec {
- char stream_name_analog[32]; /* analog PCM stream */
- const struct hda_pcm_stream *stream_analog_playback;
- const struct hda_pcm_stream *stream_analog_capture;
-
- char stream_name_alt_analog[32]; /* alternative analog PCM stream */
- const struct hda_pcm_stream *stream_analog_alt_playback;
- const struct hda_pcm_stream *stream_analog_alt_capture;
-
- char stream_name_digital[32]; /* digital PCM stream */
- const struct hda_pcm_stream *stream_digital_playback;
- const struct hda_pcm_stream *stream_digital_capture;
-
- /* PCM */
- unsigned int active_streams;
- struct mutex pcm_mutex;
-
- /* playback */
- struct hda_multi_out multiout; /* playback set-up
- * max_channels, dacs must be set
- * dig_out_nid and hp_nid are optional
- */
- hda_nid_t alt_dac_nid;
- hda_nid_t follower_dig_outs[3]; /* optional - for auto-parsing */
- int dig_out_type;
-
- /* capture */
- unsigned int num_adc_nids;
- hda_nid_t adc_nids[AUTO_CFG_MAX_INS];
- hda_nid_t dig_in_nid; /* digital-in NID; optional */
- hda_nid_t mixer_nid; /* analog-mixer NID */
- hda_nid_t mixer_merge_nid; /* aamix merge-point NID (optional) */
- const char *input_labels[HDA_MAX_NUM_INPUTS];
- int input_label_idxs[HDA_MAX_NUM_INPUTS];
-
- /* capture setup for dynamic dual-adc switch */
- hda_nid_t cur_adc;
- unsigned int cur_adc_stream_tag;
- unsigned int cur_adc_format;
-
- /* capture source */
- struct hda_input_mux input_mux;
- unsigned int cur_mux[3];
-
- /* channel model */
- /* min_channel_count contains the minimum channel count for primary
- * outputs. When multi_ios is set, the channels can be configured
- * between min_channel_count and (min_channel_count + multi_ios * 2).
- *
- * ext_channel_count contains the current channel count of the primary
- * out. This varies in the range above.
- *
- * Meanwhile, const_channel_count is the channel count for all outputs
- * including headphone and speakers. It's a constant value, and the
- * PCM is set up as max(ext_channel_count, const_channel_count).
- */
- int min_channel_count; /* min. channel count for primary out */
- int ext_channel_count; /* current channel count for primary */
- int const_channel_count; /* channel count for all */
-
- /* PCM information */
- struct hda_pcm *pcm_rec[3]; /* used in build_pcms() */
-
- /* dynamic controls, init_verbs and input_mux */
- struct auto_pin_cfg autocfg;
- struct snd_array kctls;
- hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
- hda_nid_t imux_pins[HDA_MAX_NUM_INPUTS];
- unsigned int dyn_adc_idx[HDA_MAX_NUM_INPUTS];
- /* shared hp/mic */
- hda_nid_t shared_mic_vref_pin;
- hda_nid_t hp_mic_pin;
- int hp_mic_mux_idx;
-
- /* DAC/ADC lists */
- int num_all_dacs;
- hda_nid_t all_dacs[16];
- int num_all_adcs;
- hda_nid_t all_adcs[AUTO_CFG_MAX_INS];
-
- /* path list */
- struct snd_array paths;
-
- /* path indices */
- int out_paths[AUTO_CFG_MAX_OUTS];
- int hp_paths[AUTO_CFG_MAX_OUTS];
- int speaker_paths[AUTO_CFG_MAX_OUTS];
- int aamix_out_paths[3];
- int digout_paths[AUTO_CFG_MAX_OUTS];
- int input_paths[HDA_MAX_NUM_INPUTS][AUTO_CFG_MAX_INS];
- int loopback_paths[HDA_MAX_NUM_INPUTS];
- int loopback_merge_path;
- int digin_path;
-
- /* auto-mic stuff */
- int am_num_entries;
- struct automic_entry am_entry[MAX_AUTO_MIC_PINS];
-
- /* for pin sensing */
- /* current status; set in hda_generic.c */
- unsigned int hp_jack_present:1;
- unsigned int line_jack_present:1;
- unsigned int speaker_muted:1; /* current status of speaker mute */
- unsigned int line_out_muted:1; /* current status of LO mute */
-
- /* internal states of automute / autoswitch behavior */
- unsigned int auto_mic:1;
- unsigned int automute_speaker:1; /* automute speaker outputs */
- unsigned int automute_lo:1; /* automute LO outputs */
-
- /* capabilities detected by parser */
- unsigned int detect_hp:1; /* Headphone detection enabled */
- unsigned int detect_lo:1; /* Line-out detection enabled */
- unsigned int automute_speaker_possible:1; /* there are speakers and either LO or HP */
- unsigned int automute_lo_possible:1; /* there are line outs and HP */
-
- /* additional parameters set by codec drivers */
- unsigned int master_mute:1; /* master mute over all */
- unsigned int keep_vref_in_automute:1; /* Don't clear VREF in automute */
- unsigned int line_in_auto_switch:1; /* allow line-in auto switch */
- unsigned int auto_mute_via_amp:1; /* auto-mute via amp instead of pinctl */
-
- /* parser behavior flags; set before snd_hda_gen_parse_auto_config() */
- unsigned int suppress_auto_mute:1; /* suppress input jack auto mute */
- unsigned int suppress_auto_mic:1; /* suppress input jack auto switch */
-
- /* other parse behavior flags */
- unsigned int need_dac_fix:1; /* need to limit DACs for multi channels */
- unsigned int hp_mic:1; /* Allow HP as a mic-in */
- unsigned int suppress_hp_mic_detect:1; /* Don't detect HP/mic */
- unsigned int no_primary_hp:1; /* Don't prefer HP pins to speaker pins */
- unsigned int no_multi_io:1; /* Don't try multi I/O config */
- unsigned int multi_cap_vol:1; /* allow multiple capture xxx volumes */
- unsigned int inv_dmic_split:1; /* inverted dmic w/a for conexant */
- unsigned int own_eapd_ctl:1; /* set EAPD by own function */
- unsigned int keep_eapd_on:1; /* don't turn off EAPD automatically */
- unsigned int vmaster_mute_led:1; /* add SPK-LED flag to vmaster mute switch */
- unsigned int mic_mute_led:1; /* add MIC-LED flag to capture mute switch */
- unsigned int indep_hp:1; /* independent HP supported */
- unsigned int prefer_hp_amp:1; /* enable HP amp for speaker if any */
- unsigned int add_stereo_mix_input:2; /* add aamix as a capture src */
- unsigned int add_jack_modes:1; /* add i/o jack mode enum ctls */
- unsigned int power_down_unused:1; /* power down unused widgets */
- unsigned int dac_min_mute:1; /* minimal = mute for DACs */
- unsigned int suppress_vmaster:1; /* don't create vmaster kctls */
-
- /* other internal flags */
- unsigned int no_analog:1; /* digital I/O only */
- unsigned int dyn_adc_switch:1; /* switch ADCs (for ALC275) */
- unsigned int indep_hp_enabled:1; /* independent HP enabled */
- unsigned int have_aamix_ctl:1;
- unsigned int hp_mic_jack_modes:1;
- unsigned int skip_verbs:1; /* don't apply verbs at snd_hda_gen_init() */
-
- /* additional mute flags (only effective with auto_mute_via_amp=1) */
- u64 mute_bits;
-
- /* bitmask for skipping volume controls */
- u64 out_vol_mask;
-
- /* badness tables for output path evaluations */
- const struct badness_table *main_out_badness;
- const struct badness_table *extra_out_badness;
-
- /* preferred pin/DAC pairs; an array of paired NIDs */
- const hda_nid_t *preferred_dacs;
-
- /* loopback mixing mode */
- bool aamix_mode;
-
- /* digital beep */
- hda_nid_t beep_nid;
-
- /* for virtual master */
- hda_nid_t vmaster_nid;
- unsigned int vmaster_tlv[4];
- struct hda_vmaster_mute_hook vmaster_mute;
-
- struct hda_loopback_check loopback;
- struct snd_array loopback_list;
-
- /* multi-io */
- int multi_ios;
- struct hda_multi_io multi_io[4];
-
- /* hooks */
- void (*init_hook)(struct hda_codec *codec);
- void (*automute_hook)(struct hda_codec *codec);
- void (*cap_sync_hook)(struct hda_codec *codec,
- struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol);
-
- /* PCM hooks */
- void (*pcm_playback_hook)(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream,
- int action);
- void (*pcm_capture_hook)(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream,
- int action);
-
- /* automute / autoswitch hooks */
- void (*hp_automute_hook)(struct hda_codec *codec,
- struct hda_jack_callback *cb);
- void (*line_automute_hook)(struct hda_codec *codec,
- struct hda_jack_callback *cb);
- void (*mic_autoswitch_hook)(struct hda_codec *codec,
- struct hda_jack_callback *cb);
-
- /* leds */
- struct led_classdev *led_cdevs[NUM_AUDIO_LEDS];
-};
-
-/* values for add_stereo_mix_input flag */
-enum {
- HDA_HINT_STEREO_MIX_DISABLE, /* No stereo mix input */
- HDA_HINT_STEREO_MIX_ENABLE, /* Add stereo mix input */
- HDA_HINT_STEREO_MIX_AUTO, /* Add only if auto-mic is disabled */
-};
-
-int snd_hda_gen_spec_init(struct hda_gen_spec *spec);
-
-int snd_hda_gen_init(struct hda_codec *codec);
-void snd_hda_gen_free(struct hda_codec *codec);
-
-int snd_hda_get_path_idx(struct hda_codec *codec, struct nid_path *path);
-struct nid_path *snd_hda_get_path_from_idx(struct hda_codec *codec, int idx);
-struct nid_path *
-snd_hda_add_new_path(struct hda_codec *codec, hda_nid_t from_nid,
- hda_nid_t to_nid, int anchor_nid);
-void snd_hda_activate_path(struct hda_codec *codec, struct nid_path *path,
- bool enable, bool add_aamix);
-
-struct snd_kcontrol_new *
-snd_hda_gen_add_kctl(struct hda_gen_spec *spec, const char *name,
- const struct snd_kcontrol_new *temp);
-
-int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
- struct auto_pin_cfg *cfg);
-int snd_hda_gen_build_controls(struct hda_codec *codec);
-int snd_hda_gen_build_pcms(struct hda_codec *codec);
-
-/* standard jack event callbacks */
-void snd_hda_gen_hp_automute(struct hda_codec *codec,
- struct hda_jack_callback *jack);
-void snd_hda_gen_line_automute(struct hda_codec *codec,
- struct hda_jack_callback *jack);
-void snd_hda_gen_mic_autoswitch(struct hda_codec *codec,
- struct hda_jack_callback *jack);
-void snd_hda_gen_update_outputs(struct hda_codec *codec);
-
-int snd_hda_gen_check_power_status(struct hda_codec *codec, hda_nid_t nid);
-unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
- hda_nid_t nid,
- unsigned int power_state);
-void snd_hda_gen_stream_pm(struct hda_codec *codec, hda_nid_t nid, bool on);
-int snd_hda_gen_fix_pin_power(struct hda_codec *codec, hda_nid_t pin);
-
-int snd_hda_gen_add_mute_led_cdev(struct hda_codec *codec,
- int (*callback)(struct led_classdev *,
- enum led_brightness));
-int snd_hda_gen_add_micmute_led_cdev(struct hda_codec *codec,
- int (*callback)(struct led_classdev *,
- enum led_brightness));
-bool snd_hda_gen_shutup_speakers(struct hda_codec *codec);
-
-#endif /* __SOUND_HDA_GENERIC_H */
diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c
deleted file mode 100644
index 9325e5c3cbe6..000000000000
--- a/sound/pci/hda/hda_hwdep.c
+++ /dev/null
@@ -1,119 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * HWDEP Interface for HD-audio codec
- *
- * Copyright (c) 2007 Takashi Iwai <tiwai@suse.de>
- */
-
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/compat.h>
-#include <linux/nospec.h>
-#include <sound/core.h>
-#include <sound/hda_codec.h>
-#include "hda_local.h"
-#include <sound/hda_hwdep.h>
-#include <sound/minors.h>
-
-/*
- * write/read an out-of-bound verb
- */
-static int verb_write_ioctl(struct hda_codec *codec,
- struct hda_verb_ioctl __user *arg)
-{
- u32 verb, res;
-
- if (get_user(verb, &arg->verb))
- return -EFAULT;
- res = snd_hda_codec_read(codec, verb >> 24, 0,
- (verb >> 8) & 0xffff, verb & 0xff);
- if (put_user(res, &arg->res))
- return -EFAULT;
- return 0;
-}
-
-static int get_wcap_ioctl(struct hda_codec *codec,
- struct hda_verb_ioctl __user *arg)
-{
- u32 verb, res;
-
- if (get_user(verb, &arg->verb))
- return -EFAULT;
- /* open-code get_wcaps(verb>>24) with nospec */
- verb >>= 24;
- if (verb < codec->core.start_nid ||
- verb >= codec->core.start_nid + codec->core.num_nodes) {
- res = 0;
- } else {
- verb -= codec->core.start_nid;
- verb = array_index_nospec(verb, codec->core.num_nodes);
- res = codec->wcaps[verb];
- }
- if (put_user(res, &arg->res))
- return -EFAULT;
- return 0;
-}
-
-
-/*
- */
-static int hda_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- struct hda_codec *codec = hw->private_data;
- void __user *argp = (void __user *)arg;
-
- switch (cmd) {
- case HDA_IOCTL_PVERSION:
- return put_user(HDA_HWDEP_VERSION, (int __user *)argp);
- case HDA_IOCTL_VERB_WRITE:
- return verb_write_ioctl(codec, argp);
- case HDA_IOCTL_GET_WCAP:
- return get_wcap_ioctl(codec, argp);
- }
- return -ENOIOCTLCMD;
-}
-
-#ifdef CONFIG_COMPAT
-static int hda_hwdep_ioctl_compat(struct snd_hwdep *hw, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- return hda_hwdep_ioctl(hw, file, cmd, (unsigned long)compat_ptr(arg));
-}
-#endif
-
-static int hda_hwdep_open(struct snd_hwdep *hw, struct file *file)
-{
- if (!capable(CAP_SYS_RAWIO))
- return -EACCES;
- return 0;
-}
-
-int snd_hda_create_hwdep(struct hda_codec *codec)
-{
- char hwname[16];
- struct snd_hwdep *hwdep;
- int err;
-
- sprintf(hwname, "HDA Codec %d", codec->addr);
- err = snd_hwdep_new(codec->card, hwname, codec->addr, &hwdep);
- if (err < 0)
- return err;
- codec->hwdep = hwdep;
- sprintf(hwdep->name, "HDA Codec %d", codec->addr);
- hwdep->iface = SNDRV_HWDEP_IFACE_HDA;
- hwdep->private_data = codec;
- hwdep->exclusive = 1;
-
- hwdep->ops.open = hda_hwdep_open;
- hwdep->ops.ioctl = hda_hwdep_ioctl;
-#ifdef CONFIG_COMPAT
- hwdep->ops.ioctl_compat = hda_hwdep_ioctl_compat;
-#endif
-
- /* for sysfs */
- hwdep->dev->groups = snd_hda_dev_attr_groups;
- dev_set_drvdata(hwdep->dev, codec);
-
- return 0;
-}
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
deleted file mode 100644
index 439cf1bda6e6..000000000000
--- a/sound/pci/hda/hda_intel.c
+++ /dev/null
@@ -1,2835 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- *
- * hda_intel.c - Implementation of primary alsa driver code base
- * for Intel HD Audio.
- *
- * Copyright(c) 2004 Intel Corporation
- *
- * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
- * PeiSen Hou <pshou@realtek.com.tw>
- *
- * CONTACTS:
- *
- * Matt Jared matt.jared@intel.com
- * Andy Kopp andy.kopp@intel.com
- * Dan Kogan dan.d.kogan@intel.com
- *
- * CHANGES:
- *
- * 2004.12.01 Major rewrite by tiwai, merged the work of pshou
- */
-
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/dma-mapping.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/pci.h>
-#include <linux/mutex.h>
-#include <linux/io.h>
-#include <linux/pm_runtime.h>
-#include <linux/clocksource.h>
-#include <linux/time.h>
-#include <linux/completion.h>
-#include <linux/acpi.h>
-#include <linux/pgtable.h>
-#include <linux/dmi.h>
-
-#ifdef CONFIG_X86
-/* for snoop control */
-#include <asm/set_memory.h>
-#include <asm/cpufeature.h>
-#endif
-#include <sound/core.h>
-#include <sound/initval.h>
-#include <sound/hdaudio.h>
-#include <sound/hda_i915.h>
-#include <sound/intel-dsp-config.h>
-#include <linux/vgaarb.h>
-#include <linux/vga_switcheroo.h>
-#include <linux/apple-gmux.h>
-#include <linux/firmware.h>
-#include <sound/hda_codec.h>
-#include "hda_controller.h"
-#include "hda_intel.h"
-
-#define CREATE_TRACE_POINTS
-#include "hda_intel_trace.h"
-
-/* position fix mode */
-enum {
- POS_FIX_AUTO,
- POS_FIX_LPIB,
- POS_FIX_POSBUF,
- POS_FIX_VIACOMBO,
- POS_FIX_COMBO,
- POS_FIX_SKL,
- POS_FIX_FIFO,
-};
-
-/* Defines for ATI HD Audio support in SB450 south bridge */
-#define ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR 0x42
-#define ATI_SB450_HDAUDIO_ENABLE_SNOOP 0x02
-
-/* Defines for Nvidia HDA support */
-#define NVIDIA_HDA_TRANSREG_ADDR 0x4e
-#define NVIDIA_HDA_ENABLE_COHBITS 0x0f
-#define NVIDIA_HDA_ISTRM_COH 0x4d
-#define NVIDIA_HDA_OSTRM_COH 0x4c
-#define NVIDIA_HDA_ENABLE_COHBIT 0x01
-
-/* Defines for Intel SCH HDA snoop control */
-#define INTEL_HDA_CGCTL 0x48
-#define INTEL_HDA_CGCTL_MISCBDCGE (0x1 << 6)
-#define INTEL_SCH_HDA_DEVC 0x78
-#define INTEL_SCH_HDA_DEVC_NOSNOOP (0x1<<11)
-
-/* max number of SDs */
-/* ICH, ATI and VIA have 4 playback and 4 capture */
-#define ICH6_NUM_CAPTURE 4
-#define ICH6_NUM_PLAYBACK 4
-
-/* ULI has 6 playback and 5 capture */
-#define ULI_NUM_CAPTURE 5
-#define ULI_NUM_PLAYBACK 6
-
-/* ATI HDMI may have up to 8 playbacks and 0 capture */
-#define ATIHDMI_NUM_CAPTURE 0
-#define ATIHDMI_NUM_PLAYBACK 8
-
-
-static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
-static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
-static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
-static char *model[SNDRV_CARDS];
-static int position_fix[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
-static int bdl_pos_adj[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
-static int probe_mask[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
-static int probe_only[SNDRV_CARDS];
-static int jackpoll_ms[SNDRV_CARDS];
-static int single_cmd = -1;
-static int enable_msi = -1;
-#ifdef CONFIG_SND_HDA_PATCH_LOADER
-static char *patch[SNDRV_CARDS];
-#endif
-#ifdef CONFIG_SND_HDA_INPUT_BEEP
-static bool beep_mode[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] =
- CONFIG_SND_HDA_INPUT_BEEP_MODE};
-#endif
-static bool dmic_detect = 1;
-static bool ctl_dev_id = IS_ENABLED(CONFIG_SND_HDA_CTL_DEV_ID) ? 1 : 0;
-
-module_param_array(index, int, NULL, 0444);
-MODULE_PARM_DESC(index, "Index value for Intel HD audio interface.");
-module_param_array(id, charp, NULL, 0444);
-MODULE_PARM_DESC(id, "ID string for Intel HD audio interface.");
-module_param_array(enable, bool, NULL, 0444);
-MODULE_PARM_DESC(enable, "Enable Intel HD audio interface.");
-module_param_array(model, charp, NULL, 0444);
-MODULE_PARM_DESC(model, "Use the given board model.");
-module_param_array(position_fix, int, NULL, 0444);
-MODULE_PARM_DESC(position_fix, "DMA pointer read method."
- "(-1 = system default, 0 = auto, 1 = LPIB, 2 = POSBUF, 3 = VIACOMBO, 4 = COMBO, 5 = SKL+, 6 = FIFO).");
-module_param_array(bdl_pos_adj, int, NULL, 0644);
-MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset.");
-module_param_array(probe_mask, int, NULL, 0444);
-MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1).");
-module_param_array(probe_only, int, NULL, 0444);
-MODULE_PARM_DESC(probe_only, "Only probing and no codec initialization.");
-module_param_array(jackpoll_ms, int, NULL, 0444);
-MODULE_PARM_DESC(jackpoll_ms, "Ms between polling for jack events (default = 0, using unsol events only)");
-module_param(single_cmd, bint, 0444);
-MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs "
- "(for debugging only).");
-module_param(enable_msi, bint, 0444);
-MODULE_PARM_DESC(enable_msi, "Enable Message Signaled Interrupt (MSI)");
-#ifdef CONFIG_SND_HDA_PATCH_LOADER
-module_param_array(patch, charp, NULL, 0444);
-MODULE_PARM_DESC(patch, "Patch file for Intel HD audio interface.");
-#endif
-#ifdef CONFIG_SND_HDA_INPUT_BEEP
-module_param_array(beep_mode, bool, NULL, 0444);
-MODULE_PARM_DESC(beep_mode, "Select HDA Beep registration mode "
- "(0=off, 1=on) (default=1).");
-#endif
-module_param(dmic_detect, bool, 0444);
-MODULE_PARM_DESC(dmic_detect, "Allow DSP driver selection (bypass this driver) "
- "(0=off, 1=on) (default=1); "
- "deprecated, use snd-intel-dspcfg.dsp_driver option instead");
-module_param(ctl_dev_id, bool, 0444);
-MODULE_PARM_DESC(ctl_dev_id, "Use control device identifier (based on codec address).");
-
-#ifdef CONFIG_PM
-static int param_set_xint(const char *val, const struct kernel_param *kp);
-static const struct kernel_param_ops param_ops_xint = {
- .set = param_set_xint,
- .get = param_get_int,
-};
-#define param_check_xint param_check_int
-
-static int power_save = CONFIG_SND_HDA_POWER_SAVE_DEFAULT;
-module_param(power_save, xint, 0644);
-MODULE_PARM_DESC(power_save, "Automatic power-saving timeout "
- "(in second, 0 = disable).");
-
-static int pm_blacklist = -1;
-module_param(pm_blacklist, bint, 0644);
-MODULE_PARM_DESC(pm_blacklist, "Enable power-management denylist");
-
-/* reset the HD-audio controller in power save mode.
- * this may give more power-saving, but will take longer time to
- * wake up.
- */
-static bool power_save_controller = 1;
-module_param(power_save_controller, bool, 0644);
-MODULE_PARM_DESC(power_save_controller, "Reset controller in power save mode.");
-#else /* CONFIG_PM */
-#define power_save 0
-#define pm_blacklist 0
-#define power_save_controller false
-#endif /* CONFIG_PM */
-
-static int align_buffer_size = -1;
-module_param(align_buffer_size, bint, 0644);
-MODULE_PARM_DESC(align_buffer_size,
- "Force buffer and period sizes to be multiple of 128 bytes.");
-
-#ifdef CONFIG_X86
-static int hda_snoop = -1;
-module_param_named(snoop, hda_snoop, bint, 0444);
-MODULE_PARM_DESC(snoop, "Enable/disable snooping");
-#else
-#define hda_snoop true
-#endif
-
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Intel HDA driver");
-
-#if defined(CONFIG_PM) && defined(CONFIG_VGA_SWITCHEROO)
-#if IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI)
-#define SUPPORT_VGA_SWITCHEROO
-#endif
-#endif
-
-
-/*
- */
-
-/* driver types */
-enum {
- AZX_DRIVER_ICH,
- AZX_DRIVER_PCH,
- AZX_DRIVER_SCH,
- AZX_DRIVER_SKL,
- AZX_DRIVER_HDMI,
- AZX_DRIVER_ATI,
- AZX_DRIVER_ATIHDMI,
- AZX_DRIVER_ATIHDMI_NS,
- AZX_DRIVER_GFHDMI,
- AZX_DRIVER_VIA,
- AZX_DRIVER_SIS,
- AZX_DRIVER_ULI,
- AZX_DRIVER_NVIDIA,
- AZX_DRIVER_TERA,
- AZX_DRIVER_CTX,
- AZX_DRIVER_CTHDA,
- AZX_DRIVER_CMEDIA,
- AZX_DRIVER_ZHAOXIN,
- AZX_DRIVER_ZHAOXINHDMI,
- AZX_DRIVER_LOONGSON,
- AZX_DRIVER_GENERIC,
- AZX_NUM_DRIVERS, /* keep this as last entry */
-};
-
-#define azx_get_snoop_type(chip) \
- (((chip)->driver_caps & AZX_DCAPS_SNOOP_MASK) >> 10)
-#define AZX_DCAPS_SNOOP_TYPE(type) ((AZX_SNOOP_TYPE_ ## type) << 10)
-
-/* quirks for old Intel chipsets */
-#define AZX_DCAPS_INTEL_ICH \
- (AZX_DCAPS_OLD_SSYNC | AZX_DCAPS_NO_ALIGN_BUFSIZE)
-
-/* quirks for Intel PCH */
-#define AZX_DCAPS_INTEL_PCH_BASE \
- (AZX_DCAPS_NO_ALIGN_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY |\
- AZX_DCAPS_SNOOP_TYPE(SCH))
-
-/* PCH up to IVB; no runtime PM; bind with i915 gfx */
-#define AZX_DCAPS_INTEL_PCH_NOPM \
- (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_I915_COMPONENT)
-
-/* PCH for HSW/BDW; with runtime PM */
-/* no i915 binding for this as HSW/BDW has another controller for HDMI */
-#define AZX_DCAPS_INTEL_PCH \
- (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME)
-
-/* HSW HDMI */
-#define AZX_DCAPS_INTEL_HASWELL \
- (/*AZX_DCAPS_ALIGN_BUFSIZE |*/ AZX_DCAPS_COUNT_LPIB_DELAY |\
- AZX_DCAPS_PM_RUNTIME | AZX_DCAPS_I915_COMPONENT |\
- AZX_DCAPS_SNOOP_TYPE(SCH))
-
-/* Broadwell HDMI can't use position buffer reliably, force to use LPIB */
-#define AZX_DCAPS_INTEL_BROADWELL \
- (/*AZX_DCAPS_ALIGN_BUFSIZE |*/ AZX_DCAPS_POSFIX_LPIB |\
- AZX_DCAPS_PM_RUNTIME | AZX_DCAPS_I915_COMPONENT |\
- AZX_DCAPS_SNOOP_TYPE(SCH))
-
-#define AZX_DCAPS_INTEL_BAYTRAIL \
- (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_I915_COMPONENT)
-
-#define AZX_DCAPS_INTEL_BRASWELL \
- (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME |\
- AZX_DCAPS_I915_COMPONENT)
-
-#define AZX_DCAPS_INTEL_SKYLAKE \
- (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME |\
- AZX_DCAPS_SEPARATE_STREAM_TAG | AZX_DCAPS_I915_COMPONENT)
-
-#define AZX_DCAPS_INTEL_BROXTON AZX_DCAPS_INTEL_SKYLAKE
-
-#define AZX_DCAPS_INTEL_LNL \
- (AZX_DCAPS_INTEL_SKYLAKE | AZX_DCAPS_PIO_COMMANDS)
-
-/* quirks for ATI SB / AMD Hudson */
-#define AZX_DCAPS_PRESET_ATI_SB \
- (AZX_DCAPS_NO_TCSEL | AZX_DCAPS_POSFIX_LPIB |\
- AZX_DCAPS_SNOOP_TYPE(ATI))
-
-/* quirks for ATI/AMD HDMI */
-#define AZX_DCAPS_PRESET_ATI_HDMI \
- (AZX_DCAPS_NO_TCSEL | AZX_DCAPS_POSFIX_LPIB|\
- AZX_DCAPS_NO_MSI64)
-
-/* quirks for ATI HDMI with snoop off */
-#define AZX_DCAPS_PRESET_ATI_HDMI_NS \
- (AZX_DCAPS_PRESET_ATI_HDMI | AZX_DCAPS_SNOOP_OFF)
-
-/* quirks for AMD SB */
-#define AZX_DCAPS_PRESET_AMD_SB \
- (AZX_DCAPS_NO_TCSEL | AZX_DCAPS_AMD_WORKAROUND |\
- AZX_DCAPS_SNOOP_TYPE(ATI) | AZX_DCAPS_PM_RUNTIME |\
- AZX_DCAPS_RETRY_PROBE)
-
-/* quirks for Nvidia */
-#define AZX_DCAPS_PRESET_NVIDIA \
- (AZX_DCAPS_NO_MSI | AZX_DCAPS_CORBRP_SELF_CLEAR |\
- AZX_DCAPS_SNOOP_TYPE(NVIDIA))
-
-#define AZX_DCAPS_PRESET_CTHDA \
- (AZX_DCAPS_NO_MSI | AZX_DCAPS_POSFIX_LPIB |\
- AZX_DCAPS_NO_64BIT |\
- AZX_DCAPS_4K_BDLE_BOUNDARY | AZX_DCAPS_SNOOP_OFF)
-
-/*
- * vga_switcheroo support
- */
-#ifdef SUPPORT_VGA_SWITCHEROO
-#define use_vga_switcheroo(chip) ((chip)->use_vga_switcheroo)
-#define needs_eld_notify_link(chip) ((chip)->bus.keep_power)
-#else
-#define use_vga_switcheroo(chip) 0
-#define needs_eld_notify_link(chip) false
-#endif
-
-static const char * const driver_short_names[] = {
- [AZX_DRIVER_ICH] = "HDA Intel",
- [AZX_DRIVER_PCH] = "HDA Intel PCH",
- [AZX_DRIVER_SCH] = "HDA Intel MID",
- [AZX_DRIVER_SKL] = "HDA Intel PCH", /* kept old name for compatibility */
- [AZX_DRIVER_HDMI] = "HDA Intel HDMI",
- [AZX_DRIVER_ATI] = "HDA ATI SB",
- [AZX_DRIVER_ATIHDMI] = "HDA ATI HDMI",
- [AZX_DRIVER_ATIHDMI_NS] = "HDA ATI HDMI",
- [AZX_DRIVER_GFHDMI] = "HDA GF HDMI",
- [AZX_DRIVER_VIA] = "HDA VIA VT82xx",
- [AZX_DRIVER_SIS] = "HDA SIS966",
- [AZX_DRIVER_ULI] = "HDA ULI M5461",
- [AZX_DRIVER_NVIDIA] = "HDA NVidia",
- [AZX_DRIVER_TERA] = "HDA Teradici",
- [AZX_DRIVER_CTX] = "HDA Creative",
- [AZX_DRIVER_CTHDA] = "HDA Creative",
- [AZX_DRIVER_CMEDIA] = "HDA C-Media",
- [AZX_DRIVER_ZHAOXIN] = "HDA Zhaoxin",
- [AZX_DRIVER_ZHAOXINHDMI] = "HDA Zhaoxin HDMI",
- [AZX_DRIVER_LOONGSON] = "HDA Loongson",
- [AZX_DRIVER_GENERIC] = "HD-Audio Generic",
-};
-
-static int azx_acquire_irq(struct azx *chip, int do_disconnect);
-static void set_default_power_save(struct azx *chip);
-
-/*
- * initialize the PCI registers
- */
-/* update bits in a PCI register byte */
-static void update_pci_byte(struct pci_dev *pci, unsigned int reg,
- unsigned char mask, unsigned char val)
-{
- unsigned char data;
-
- pci_read_config_byte(pci, reg, &data);
- data &= ~mask;
- data |= (val & mask);
- pci_write_config_byte(pci, reg, data);
-}
-
-static void azx_init_pci(struct azx *chip)
-{
- int snoop_type = azx_get_snoop_type(chip);
-
- /* Clear bits 0-2 of PCI register TCSEL (at offset 0x44)
- * TCSEL == Traffic Class Select Register, which sets PCI express QOS
- * Ensuring these bits are 0 clears playback static on some HD Audio
- * codecs.
- * The PCI register TCSEL is defined in the Intel manuals.
- */
- if (!(chip->driver_caps & AZX_DCAPS_NO_TCSEL)) {
- dev_dbg(chip->card->dev, "Clearing TCSEL\n");
- update_pci_byte(chip->pci, AZX_PCIREG_TCSEL, 0x07, 0);
- }
-
- /* For ATI SB450/600/700/800/900 and AMD Hudson azalia HD audio,
- * we need to enable snoop.
- */
- if (snoop_type == AZX_SNOOP_TYPE_ATI) {
- dev_dbg(chip->card->dev, "Setting ATI snoop: %d\n",
- azx_snoop(chip));
- update_pci_byte(chip->pci,
- ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, 0x07,
- azx_snoop(chip) ? ATI_SB450_HDAUDIO_ENABLE_SNOOP : 0);
- }
-
- /* For NVIDIA HDA, enable snoop */
- if (snoop_type == AZX_SNOOP_TYPE_NVIDIA) {
- dev_dbg(chip->card->dev, "Setting Nvidia snoop: %d\n",
- azx_snoop(chip));
- update_pci_byte(chip->pci,
- NVIDIA_HDA_TRANSREG_ADDR,
- 0x0f, NVIDIA_HDA_ENABLE_COHBITS);
- update_pci_byte(chip->pci,
- NVIDIA_HDA_ISTRM_COH,
- 0x01, NVIDIA_HDA_ENABLE_COHBIT);
- update_pci_byte(chip->pci,
- NVIDIA_HDA_OSTRM_COH,
- 0x01, NVIDIA_HDA_ENABLE_COHBIT);
- }
-
- /* Enable SCH/PCH snoop if needed */
- if (snoop_type == AZX_SNOOP_TYPE_SCH) {
- unsigned short snoop;
- pci_read_config_word(chip->pci, INTEL_SCH_HDA_DEVC, &snoop);
- if ((!azx_snoop(chip) && !(snoop & INTEL_SCH_HDA_DEVC_NOSNOOP)) ||
- (azx_snoop(chip) && (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP))) {
- snoop &= ~INTEL_SCH_HDA_DEVC_NOSNOOP;
- if (!azx_snoop(chip))
- snoop |= INTEL_SCH_HDA_DEVC_NOSNOOP;
- pci_write_config_word(chip->pci, INTEL_SCH_HDA_DEVC, snoop);
- pci_read_config_word(chip->pci,
- INTEL_SCH_HDA_DEVC, &snoop);
- }
- dev_dbg(chip->card->dev, "SCH snoop: %s\n",
- (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP) ?
- "Disabled" : "Enabled");
- }
-}
-
-/*
- * In BXT-P A0, HD-Audio DMA requests is later than expected,
- * and makes an audio stream sensitive to system latencies when
- * 24/32 bits are playing.
- * Adjusting threshold of DMA fifo to force the DMA request
- * sooner to improve latency tolerance at the expense of power.
- */
-static void bxt_reduce_dma_latency(struct azx *chip)
-{
- u32 val;
-
- val = azx_readl(chip, VS_EM4L);
- val &= (0x3 << 20);
- azx_writel(chip, VS_EM4L, val);
-}
-
-/*
- * ML_LCAP bits:
- * bit 0: 6 MHz Supported
- * bit 1: 12 MHz Supported
- * bit 2: 24 MHz Supported
- * bit 3: 48 MHz Supported
- * bit 4: 96 MHz Supported
- * bit 5: 192 MHz Supported
- */
-static int intel_get_lctl_scf(struct azx *chip)
-{
- struct hdac_bus *bus = azx_bus(chip);
- static const int preferred_bits[] = { 2, 3, 1, 4, 5 };
- u32 val, t;
- int i;
-
- val = readl(bus->mlcap + AZX_ML_BASE + AZX_REG_ML_LCAP);
-
- for (i = 0; i < ARRAY_SIZE(preferred_bits); i++) {
- t = preferred_bits[i];
- if (val & (1 << t))
- return t;
- }
-
- dev_warn(chip->card->dev, "set audio clock frequency to 6MHz");
- return 0;
-}
-
-static int intel_ml_lctl_set_power(struct azx *chip, int state)
-{
- struct hdac_bus *bus = azx_bus(chip);
- u32 val;
- int timeout;
-
- /*
- * Changes to LCTL.SCF are only needed for the first multi-link dealing
- * with external codecs
- */
- val = readl(bus->mlcap + AZX_ML_BASE + AZX_REG_ML_LCTL);
- val &= ~AZX_ML_LCTL_SPA;
- val |= state << AZX_ML_LCTL_SPA_SHIFT;
- writel(val, bus->mlcap + AZX_ML_BASE + AZX_REG_ML_LCTL);
- /* wait for CPA */
- timeout = 50;
- while (timeout) {
- if (((readl(bus->mlcap + AZX_ML_BASE + AZX_REG_ML_LCTL)) &
- AZX_ML_LCTL_CPA) == (state << AZX_ML_LCTL_CPA_SHIFT))
- return 0;
- timeout--;
- udelay(10);
- }
-
- return -1;
-}
-
-static void intel_init_lctl(struct azx *chip)
-{
- struct hdac_bus *bus = azx_bus(chip);
- u32 val;
- int ret;
-
- /* 0. check lctl register value is correct or not */
- val = readl(bus->mlcap + AZX_ML_BASE + AZX_REG_ML_LCTL);
- /* only perform additional configurations if the SCF is initially based on 6MHz */
- if ((val & AZX_ML_LCTL_SCF) != 0)
- return;
-
- /*
- * Before operating on SPA, CPA must match SPA.
- * Any deviation may result in undefined behavior.
- */
- if (((val & AZX_ML_LCTL_SPA) >> AZX_ML_LCTL_SPA_SHIFT) !=
- ((val & AZX_ML_LCTL_CPA) >> AZX_ML_LCTL_CPA_SHIFT))
- return;
-
- /* 1. turn link down: set SPA to 0 and wait CPA to 0 */
- ret = intel_ml_lctl_set_power(chip, 0);
- udelay(100);
- if (ret)
- goto set_spa;
-
- /* 2. update SCF to select an audio clock different from 6MHz */
- val &= ~AZX_ML_LCTL_SCF;
- val |= intel_get_lctl_scf(chip);
- writel(val, bus->mlcap + AZX_ML_BASE + AZX_REG_ML_LCTL);
-
-set_spa:
- /* 4. turn link up: set SPA to 1 and wait CPA to 1 */
- intel_ml_lctl_set_power(chip, 1);
- udelay(100);
-}
-
-static void hda_intel_init_chip(struct azx *chip, bool full_reset)
-{
- struct hdac_bus *bus = azx_bus(chip);
- struct pci_dev *pci = chip->pci;
- u32 val;
-
- snd_hdac_set_codec_wakeup(bus, true);
- if (chip->driver_type == AZX_DRIVER_SKL) {
- pci_read_config_dword(pci, INTEL_HDA_CGCTL, &val);
- val = val & ~INTEL_HDA_CGCTL_MISCBDCGE;
- pci_write_config_dword(pci, INTEL_HDA_CGCTL, val);
- }
- azx_init_chip(chip, full_reset);
- if (chip->driver_type == AZX_DRIVER_SKL) {
- pci_read_config_dword(pci, INTEL_HDA_CGCTL, &val);
- val = val | INTEL_HDA_CGCTL_MISCBDCGE;
- pci_write_config_dword(pci, INTEL_HDA_CGCTL, val);
- }
-
- snd_hdac_set_codec_wakeup(bus, false);
-
- /* reduce dma latency to avoid noise */
- if (HDA_CONTROLLER_IS_APL(pci))
- bxt_reduce_dma_latency(chip);
-
- if (bus->mlcap != NULL)
- intel_init_lctl(chip);
-}
-
-/* calculate runtime delay from LPIB */
-static int azx_get_delay_from_lpib(struct azx *chip, struct azx_dev *azx_dev,
- unsigned int pos)
-{
- struct snd_pcm_substream *substream = azx_dev->core.substream;
- int stream = substream->stream;
- unsigned int lpib_pos = azx_get_pos_lpib(chip, azx_dev);
- int delay;
-
- if (stream == SNDRV_PCM_STREAM_PLAYBACK)
- delay = pos - lpib_pos;
- else
- delay = lpib_pos - pos;
- if (delay < 0) {
- if (delay >= azx_dev->core.delay_negative_threshold)
- delay = 0;
- else
- delay += azx_dev->core.bufsize;
- }
-
- if (delay >= azx_dev->core.period_bytes) {
- dev_info(chip->card->dev,
- "Unstable LPIB (%d >= %d); disabling LPIB delay counting\n",
- delay, azx_dev->core.period_bytes);
- delay = 0;
- chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY;
- chip->get_delay[stream] = NULL;
- }
-
- return bytes_to_frames(substream->runtime, delay);
-}
-
-static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev);
-
-/* called from IRQ */
-static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev)
-{
- struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
- int ok;
-
- ok = azx_position_ok(chip, azx_dev);
- if (ok == 1) {
- azx_dev->irq_pending = 0;
- return ok;
- } else if (ok == 0) {
- /* bogus IRQ, process it later */
- azx_dev->irq_pending = 1;
- schedule_work(&hda->irq_pending_work);
- }
- return 0;
-}
-
-#define display_power(chip, enable) \
- snd_hdac_display_power(azx_bus(chip), HDA_CODEC_IDX_CONTROLLER, enable)
-
-/*
- * Check whether the current DMA position is acceptable for updating
- * periods. Returns non-zero if it's OK.
- *
- * Many HD-audio controllers appear pretty inaccurate about
- * the update-IRQ timing. The IRQ is issued before actually the
- * data is processed. So, we need to process it afterwords in a
- * workqueue.
- *
- * Returns 1 if OK to proceed, 0 for delay handling, -1 for skipping update
- */
-static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
-{
- struct snd_pcm_substream *substream = azx_dev->core.substream;
- struct snd_pcm_runtime *runtime = substream->runtime;
- int stream = substream->stream;
- u32 wallclk;
- unsigned int pos;
- snd_pcm_uframes_t hwptr, target;
-
- /*
- * The value of the WALLCLK register is always 0
- * on the Loongson controller, so we return directly.
- */
- if (chip->driver_type == AZX_DRIVER_LOONGSON)
- return 1;
-
- wallclk = azx_readl(chip, WALLCLK) - azx_dev->core.start_wallclk;
- if (wallclk < (azx_dev->core.period_wallclk * 2) / 3)
- return -1; /* bogus (too early) interrupt */
-
- if (chip->get_position[stream])
- pos = chip->get_position[stream](chip, azx_dev);
- else { /* use the position buffer as default */
- pos = azx_get_pos_posbuf(chip, azx_dev);
- if (!pos || pos == (u32)-1) {
- dev_info(chip->card->dev,
- "Invalid position buffer, using LPIB read method instead.\n");
- chip->get_position[stream] = azx_get_pos_lpib;
- if (chip->get_position[0] == azx_get_pos_lpib &&
- chip->get_position[1] == azx_get_pos_lpib)
- azx_bus(chip)->use_posbuf = false;
- pos = azx_get_pos_lpib(chip, azx_dev);
- chip->get_delay[stream] = NULL;
- } else {
- chip->get_position[stream] = azx_get_pos_posbuf;
- if (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)
- chip->get_delay[stream] = azx_get_delay_from_lpib;
- }
- }
-
- if (pos >= azx_dev->core.bufsize)
- pos = 0;
-
- if (WARN_ONCE(!azx_dev->core.period_bytes,
- "hda-intel: zero azx_dev->period_bytes"))
- return -1; /* this shouldn't happen! */
- if (wallclk < (azx_dev->core.period_wallclk * 5) / 4 &&
- pos % azx_dev->core.period_bytes > azx_dev->core.period_bytes / 2)
- /* NG - it's below the first next period boundary */
- return chip->bdl_pos_adj ? 0 : -1;
- azx_dev->core.start_wallclk += wallclk;
-
- if (azx_dev->core.no_period_wakeup)
- return 1; /* OK, no need to check period boundary */
-
- if (runtime->hw_ptr_base != runtime->hw_ptr_interrupt)
- return 1; /* OK, already in hwptr updating process */
-
- /* check whether the period gets really elapsed */
- pos = bytes_to_frames(runtime, pos);
- hwptr = runtime->hw_ptr_base + pos;
- if (hwptr < runtime->status->hw_ptr)
- hwptr += runtime->buffer_size;
- target = runtime->hw_ptr_interrupt + runtime->period_size;
- if (hwptr < target) {
- /* too early wakeup, process it later */
- return chip->bdl_pos_adj ? 0 : -1;
- }
-
- return 1; /* OK, it's fine */
-}
-
-/*
- * The work for pending PCM period updates.
- */
-static void azx_irq_pending_work(struct work_struct *work)
-{
- struct hda_intel *hda = container_of(work, struct hda_intel, irq_pending_work);
- struct azx *chip = &hda->chip;
- struct hdac_bus *bus = azx_bus(chip);
- struct hdac_stream *s;
- int pending, ok;
-
- if (!hda->irq_pending_warned) {
- dev_info(chip->card->dev,
- "IRQ timing workaround is activated for card #%d. Suggest a bigger bdl_pos_adj.\n",
- chip->card->number);
- hda->irq_pending_warned = 1;
- }
-
- for (;;) {
- pending = 0;
- spin_lock_irq(&bus->reg_lock);
- list_for_each_entry(s, &bus->stream_list, list) {
- struct azx_dev *azx_dev = stream_to_azx_dev(s);
- if (!azx_dev->irq_pending ||
- !s->substream ||
- !s->running)
- continue;
- ok = azx_position_ok(chip, azx_dev);
- if (ok > 0) {
- azx_dev->irq_pending = 0;
- spin_unlock(&bus->reg_lock);
- snd_pcm_period_elapsed(s->substream);
- spin_lock(&bus->reg_lock);
- } else if (ok < 0) {
- pending = 0; /* too early */
- } else
- pending++;
- }
- spin_unlock_irq(&bus->reg_lock);
- if (!pending)
- return;
- msleep(1);
- }
-}
-
-/* clear irq_pending flags and assure no on-going workq */
-static void azx_clear_irq_pending(struct azx *chip)
-{
- struct hdac_bus *bus = azx_bus(chip);
- struct hdac_stream *s;
-
- spin_lock_irq(&bus->reg_lock);
- list_for_each_entry(s, &bus->stream_list, list) {
- struct azx_dev *azx_dev = stream_to_azx_dev(s);
- azx_dev->irq_pending = 0;
- }
- spin_unlock_irq(&bus->reg_lock);
-}
-
-static int azx_acquire_irq(struct azx *chip, int do_disconnect)
-{
- struct hdac_bus *bus = azx_bus(chip);
- int ret;
-
- if (!chip->msi || pci_alloc_irq_vectors(chip->pci, 1, 1, PCI_IRQ_MSI) < 0) {
- ret = pci_alloc_irq_vectors(chip->pci, 1, 1, PCI_IRQ_INTX);
- if (ret < 0)
- return ret;
- chip->msi = 0;
- }
-
- if (request_irq(chip->pci->irq, azx_interrupt,
- chip->msi ? 0 : IRQF_SHARED,
- chip->card->irq_descr, chip)) {
- dev_err(chip->card->dev,
- "unable to grab IRQ %d, disabling device\n",
- chip->pci->irq);
- if (do_disconnect)
- snd_card_disconnect(chip->card);
- return -1;
- }
- bus->irq = chip->pci->irq;
- chip->card->sync_irq = bus->irq;
- return 0;
-}
-
-/* get the current DMA position with correction on VIA chips */
-static unsigned int azx_via_get_position(struct azx *chip,
- struct azx_dev *azx_dev)
-{
- unsigned int link_pos, mini_pos, bound_pos;
- unsigned int mod_link_pos, mod_dma_pos, mod_mini_pos;
- unsigned int fifo_size;
-
- link_pos = snd_hdac_stream_get_pos_lpib(azx_stream(azx_dev));
- if (azx_dev->core.substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- /* Playback, no problem using link position */
- return link_pos;
- }
-
- /* Capture */
- /* For new chipset,
- * use mod to get the DMA position just like old chipset
- */
- mod_dma_pos = le32_to_cpu(*azx_dev->core.posbuf);
- mod_dma_pos %= azx_dev->core.period_bytes;
-
- fifo_size = azx_stream(azx_dev)->fifo_size;
-
- if (azx_dev->insufficient) {
- /* Link position never gather than FIFO size */
- if (link_pos <= fifo_size)
- return 0;
-
- azx_dev->insufficient = 0;
- }
-
- if (link_pos <= fifo_size)
- mini_pos = azx_dev->core.bufsize + link_pos - fifo_size;
- else
- mini_pos = link_pos - fifo_size;
-
- /* Find nearest previous boudary */
- mod_mini_pos = mini_pos % azx_dev->core.period_bytes;
- mod_link_pos = link_pos % azx_dev->core.period_bytes;
- if (mod_link_pos >= fifo_size)
- bound_pos = link_pos - mod_link_pos;
- else if (mod_dma_pos >= mod_mini_pos)
- bound_pos = mini_pos - mod_mini_pos;
- else {
- bound_pos = mini_pos - mod_mini_pos + azx_dev->core.period_bytes;
- if (bound_pos >= azx_dev->core.bufsize)
- bound_pos = 0;
- }
-
- /* Calculate real DMA position we want */
- return bound_pos + mod_dma_pos;
-}
-
-#define AMD_FIFO_SIZE 32
-
-/* get the current DMA position with FIFO size correction */
-static unsigned int azx_get_pos_fifo(struct azx *chip, struct azx_dev *azx_dev)
-{
- struct snd_pcm_substream *substream = azx_dev->core.substream;
- struct snd_pcm_runtime *runtime = substream->runtime;
- unsigned int pos, delay;
-
- pos = snd_hdac_stream_get_pos_lpib(azx_stream(azx_dev));
- if (!runtime)
- return pos;
-
- runtime->delay = AMD_FIFO_SIZE;
- delay = frames_to_bytes(runtime, AMD_FIFO_SIZE);
- if (azx_dev->insufficient) {
- if (pos < delay) {
- delay = pos;
- runtime->delay = bytes_to_frames(runtime, pos);
- } else {
- azx_dev->insufficient = 0;
- }
- }
-
- /* correct the DMA position for capture stream */
- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
- if (pos < delay)
- pos += azx_dev->core.bufsize;
- pos -= delay;
- }
-
- return pos;
-}
-
-static int azx_get_delay_from_fifo(struct azx *chip, struct azx_dev *azx_dev,
- unsigned int pos)
-{
- struct snd_pcm_substream *substream = azx_dev->core.substream;
-
- /* just read back the calculated value in the above */
- return substream->runtime->delay;
-}
-
-static void __azx_shutdown_chip(struct azx *chip, bool skip_link_reset)
-{
- azx_stop_chip(chip);
- if (!skip_link_reset)
- azx_enter_link_reset(chip);
- azx_clear_irq_pending(chip);
- display_power(chip, false);
-}
-
-static DEFINE_MUTEX(card_list_lock);
-static LIST_HEAD(card_list);
-
-static void azx_shutdown_chip(struct azx *chip)
-{
- __azx_shutdown_chip(chip, false);
-}
-
-static void azx_add_card_list(struct azx *chip)
-{
- struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
- mutex_lock(&card_list_lock);
- list_add(&hda->list, &card_list);
- mutex_unlock(&card_list_lock);
-}
-
-static void azx_del_card_list(struct azx *chip)
-{
- struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
- mutex_lock(&card_list_lock);
- list_del_init(&hda->list);
- mutex_unlock(&card_list_lock);
-}
-
-/* trigger power-save check at writing parameter */
-static int __maybe_unused param_set_xint(const char *val, const struct kernel_param *kp)
-{
- struct hda_intel *hda;
- struct azx *chip;
- int prev = power_save;
- int ret = param_set_int(val, kp);
-
- if (ret || prev == power_save)
- return ret;
-
- if (pm_blacklist > 0)
- return 0;
-
- mutex_lock(&card_list_lock);
- list_for_each_entry(hda, &card_list, list) {
- chip = &hda->chip;
- if (!hda->probe_continued || chip->disabled ||
- hda->runtime_pm_disabled)
- continue;
- snd_hda_set_power_save(&chip->bus, power_save * 1000);
- }
- mutex_unlock(&card_list_lock);
- return 0;
-}
-
-/*
- * power management
- */
-static bool azx_is_pm_ready(struct snd_card *card)
-{
- struct azx *chip;
- struct hda_intel *hda;
-
- if (!card)
- return false;
- chip = card->private_data;
- hda = container_of(chip, struct hda_intel, chip);
- if (chip->disabled || hda->init_failed || !chip->running)
- return false;
- return true;
-}
-
-static void __azx_runtime_resume(struct azx *chip)
-{
- struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
- struct hdac_bus *bus = azx_bus(chip);
- struct hda_codec *codec;
- int status;
-
- display_power(chip, true);
- if (hda->need_i915_power)
- snd_hdac_i915_set_bclk(bus);
-
- /* Read STATESTS before controller reset */
- status = azx_readw(chip, STATESTS);
-
- azx_init_pci(chip);
- hda_intel_init_chip(chip, true);
-
- /* Avoid codec resume if runtime resume is for system suspend */
- if (!chip->pm_prepared) {
- list_for_each_codec(codec, &chip->bus) {
- if (codec->relaxed_resume)
- continue;
-
- if (codec->forced_resume || (status & (1 << codec->addr)))
- pm_request_resume(hda_codec_dev(codec));
- }
- }
-
- /* power down again for link-controlled chips */
- if (!hda->need_i915_power)
- display_power(chip, false);
-}
-
-static int azx_prepare(struct device *dev)
-{
- struct snd_card *card = dev_get_drvdata(dev);
- struct azx *chip;
-
- if (!azx_is_pm_ready(card))
- return 0;
-
- chip = card->private_data;
- chip->pm_prepared = 1;
- snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
-
- flush_work(&azx_bus(chip)->unsol_work);
-
- /* HDA controller always requires different WAKEEN for runtime suspend
- * and system suspend, so don't use direct-complete here.
- */
- return 0;
-}
-
-static void azx_complete(struct device *dev)
-{
- struct snd_card *card = dev_get_drvdata(dev);
- struct azx *chip;
-
- if (!azx_is_pm_ready(card))
- return;
-
- chip = card->private_data;
- snd_power_change_state(card, SNDRV_CTL_POWER_D0);
- chip->pm_prepared = 0;
-}
-
-static int azx_suspend(struct device *dev)
-{
- struct snd_card *card = dev_get_drvdata(dev);
- struct azx *chip;
-
- if (!azx_is_pm_ready(card))
- return 0;
-
- chip = card->private_data;
- azx_shutdown_chip(chip);
-
- trace_azx_suspend(chip);
- return 0;
-}
-
-static int azx_resume(struct device *dev)
-{
- struct snd_card *card = dev_get_drvdata(dev);
- struct azx *chip;
-
- if (!azx_is_pm_ready(card))
- return 0;
-
- chip = card->private_data;
-
- __azx_runtime_resume(chip);
-
- trace_azx_resume(chip);
- return 0;
-}
-
-/* put codec down to D3 at hibernation for Intel SKL+;
- * otherwise BIOS may still access the codec and screw up the driver
- */
-static int azx_freeze_noirq(struct device *dev)
-{
- struct snd_card *card = dev_get_drvdata(dev);
- struct azx *chip = card->private_data;
- struct pci_dev *pci = to_pci_dev(dev);
-
- if (!azx_is_pm_ready(card))
- return 0;
- if (chip->driver_type == AZX_DRIVER_SKL)
- pci_set_power_state(pci, PCI_D3hot);
-
- return 0;
-}
-
-static int azx_thaw_noirq(struct device *dev)
-{
- struct snd_card *card = dev_get_drvdata(dev);
- struct azx *chip = card->private_data;
- struct pci_dev *pci = to_pci_dev(dev);
-
- if (!azx_is_pm_ready(card))
- return 0;
- if (chip->driver_type == AZX_DRIVER_SKL)
- pci_set_power_state(pci, PCI_D0);
-
- return 0;
-}
-
-static int azx_runtime_suspend(struct device *dev)
-{
- struct snd_card *card = dev_get_drvdata(dev);
- struct azx *chip;
-
- if (!azx_is_pm_ready(card))
- return 0;
- chip = card->private_data;
-
- /* enable controller wake up event */
- azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) | STATESTS_INT_MASK);
-
- azx_shutdown_chip(chip);
- trace_azx_runtime_suspend(chip);
- return 0;
-}
-
-static int azx_runtime_resume(struct device *dev)
-{
- struct snd_card *card = dev_get_drvdata(dev);
- struct azx *chip;
-
- if (!azx_is_pm_ready(card))
- return 0;
- chip = card->private_data;
- __azx_runtime_resume(chip);
-
- /* disable controller Wake Up event*/
- azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) & ~STATESTS_INT_MASK);
-
- trace_azx_runtime_resume(chip);
- return 0;
-}
-
-static int azx_runtime_idle(struct device *dev)
-{
- struct snd_card *card = dev_get_drvdata(dev);
- struct azx *chip;
- struct hda_intel *hda;
-
- if (!card)
- return 0;
-
- chip = card->private_data;
- hda = container_of(chip, struct hda_intel, chip);
- if (chip->disabled || hda->init_failed)
- return 0;
-
- if (!power_save_controller || !azx_has_pm_runtime(chip) ||
- azx_bus(chip)->codec_powered || !chip->running)
- return -EBUSY;
-
- /* ELD notification gets broken when HD-audio bus is off */
- if (needs_eld_notify_link(chip))
- return -EBUSY;
-
- return 0;
-}
-
-static const struct dev_pm_ops azx_pm = {
- SYSTEM_SLEEP_PM_OPS(azx_suspend, azx_resume)
- .prepare = pm_sleep_ptr(azx_prepare),
- .complete = pm_sleep_ptr(azx_complete),
- .freeze_noirq = pm_sleep_ptr(azx_freeze_noirq),
- .thaw_noirq = pm_sleep_ptr(azx_thaw_noirq),
- RUNTIME_PM_OPS(azx_runtime_suspend, azx_runtime_resume, azx_runtime_idle)
-};
-
-
-static int azx_probe_continue(struct azx *chip);
-
-#ifdef SUPPORT_VGA_SWITCHEROO
-static struct pci_dev *get_bound_vga(struct pci_dev *pci);
-
-static void azx_vs_set_state(struct pci_dev *pci,
- enum vga_switcheroo_state state)
-{
- struct snd_card *card = pci_get_drvdata(pci);
- struct azx *chip = card->private_data;
- struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
- struct hda_codec *codec;
- bool disabled;
-
- wait_for_completion(&hda->probe_wait);
- if (hda->init_failed)
- return;
-
- disabled = (state == VGA_SWITCHEROO_OFF);
- if (chip->disabled == disabled)
- return;
-
- if (!hda->probe_continued) {
- chip->disabled = disabled;
- if (!disabled) {
- dev_info(chip->card->dev,
- "Start delayed initialization\n");
- if (azx_probe_continue(chip) < 0)
- dev_err(chip->card->dev, "initialization error\n");
- }
- } else {
- dev_info(chip->card->dev, "%s via vga_switcheroo\n",
- disabled ? "Disabling" : "Enabling");
- if (disabled) {
- list_for_each_codec(codec, &chip->bus) {
- pm_runtime_suspend(hda_codec_dev(codec));
- pm_runtime_disable(hda_codec_dev(codec));
- }
- pm_runtime_suspend(card->dev);
- pm_runtime_disable(card->dev);
- /* when we get suspended by vga_switcheroo we end up in D3cold,
- * however we have no ACPI handle, so pci/acpi can't put us there,
- * put ourselves there */
- pci->current_state = PCI_D3cold;
- chip->disabled = true;
- if (snd_hda_lock_devices(&chip->bus))
- dev_warn(chip->card->dev,
- "Cannot lock devices!\n");
- } else {
- snd_hda_unlock_devices(&chip->bus);
- chip->disabled = false;
- pm_runtime_enable(card->dev);
- list_for_each_codec(codec, &chip->bus) {
- pm_runtime_enable(hda_codec_dev(codec));
- pm_runtime_resume(hda_codec_dev(codec));
- }
- }
- }
-}
-
-static bool azx_vs_can_switch(struct pci_dev *pci)
-{
- struct snd_card *card = pci_get_drvdata(pci);
- struct azx *chip = card->private_data;
- struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
-
- wait_for_completion(&hda->probe_wait);
- if (hda->init_failed)
- return false;
- if (chip->disabled || !hda->probe_continued)
- return true;
- if (snd_hda_lock_devices(&chip->bus))
- return false;
- snd_hda_unlock_devices(&chip->bus);
- return true;
-}
-
-/*
- * The discrete GPU cannot power down unless the HDA controller runtime
- * suspends, so activate runtime PM on codecs even if power_save == 0.
- */
-static void setup_vga_switcheroo_runtime_pm(struct azx *chip)
-{
- struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
- struct hda_codec *codec;
-
- if (hda->use_vga_switcheroo && !needs_eld_notify_link(chip)) {
- list_for_each_codec(codec, &chip->bus)
- codec->auto_runtime_pm = 1;
- /* reset the power save setup */
- if (chip->running)
- set_default_power_save(chip);
- }
-}
-
-static void azx_vs_gpu_bound(struct pci_dev *pci,
- enum vga_switcheroo_client_id client_id)
-{
- struct snd_card *card = pci_get_drvdata(pci);
- struct azx *chip = card->private_data;
-
- if (client_id == VGA_SWITCHEROO_DIS)
- chip->bus.keep_power = 0;
- setup_vga_switcheroo_runtime_pm(chip);
-}
-
-static void init_vga_switcheroo(struct azx *chip)
-{
- struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
- struct pci_dev *p = get_bound_vga(chip->pci);
- struct pci_dev *parent;
- if (p) {
- dev_info(chip->card->dev,
- "Handle vga_switcheroo audio client\n");
- hda->use_vga_switcheroo = 1;
-
- /* cleared in either gpu_bound op or codec probe, or when its
- * upstream port has _PR3 (i.e. dGPU).
- */
- parent = pci_upstream_bridge(p);
- chip->bus.keep_power = parent ? !pci_pr3_present(parent) : 1;
- chip->driver_caps |= AZX_DCAPS_PM_RUNTIME;
- pci_dev_put(p);
- }
-}
-
-static const struct vga_switcheroo_client_ops azx_vs_ops = {
- .set_gpu_state = azx_vs_set_state,
- .can_switch = azx_vs_can_switch,
- .gpu_bound = azx_vs_gpu_bound,
-};
-
-static int register_vga_switcheroo(struct azx *chip)
-{
- struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
- struct pci_dev *p;
- int err;
-
- if (!hda->use_vga_switcheroo)
- return 0;
-
- p = get_bound_vga(chip->pci);
- err = vga_switcheroo_register_audio_client(chip->pci, &azx_vs_ops, p);
- pci_dev_put(p);
-
- if (err < 0)
- return err;
- hda->vga_switcheroo_registered = 1;
-
- return 0;
-}
-#else
-#define init_vga_switcheroo(chip) /* NOP */
-#define register_vga_switcheroo(chip) 0
-#define check_hdmi_disabled(pci) false
-#define setup_vga_switcheroo_runtime_pm(chip) /* NOP */
-#endif /* SUPPORT_VGA_SWITCHER */
-
-/*
- * destructor
- */
-static void azx_free(struct azx *chip)
-{
- struct pci_dev *pci = chip->pci;
- struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
- struct hdac_bus *bus = azx_bus(chip);
-
- if (hda->freed)
- return;
-
- if (azx_has_pm_runtime(chip) && chip->running) {
- pm_runtime_get_noresume(&pci->dev);
- pm_runtime_forbid(&pci->dev);
- pm_runtime_dont_use_autosuspend(&pci->dev);
- }
-
- chip->running = 0;
-
- azx_del_card_list(chip);
-
- hda->init_failed = 1; /* to be sure */
- complete_all(&hda->probe_wait);
-
- if (use_vga_switcheroo(hda)) {
- if (chip->disabled && hda->probe_continued)
- snd_hda_unlock_devices(&chip->bus);
- if (hda->vga_switcheroo_registered) {
- vga_switcheroo_unregister_client(chip->pci);
-
- /* Some GPUs don't have sound, and azx_first_init fails,
- * leaving the device probed but non-functional. As long
- * as it's probed, the PCI subsystem keeps its runtime
- * PM status as active. Force it to suspended (as we
- * actually stop the chip) to allow GPU to suspend via
- * vga_switcheroo, and print a warning.
- */
- dev_warn(&pci->dev, "GPU sound probed, but not operational: please add a quirk to driver_denylist\n");
- pm_runtime_disable(&pci->dev);
- pm_runtime_set_suspended(&pci->dev);
- pm_runtime_enable(&pci->dev);
- }
- }
-
- if (bus->chip_init) {
- azx_clear_irq_pending(chip);
- azx_stop_all_streams(chip);
- azx_stop_chip(chip);
- }
-
- if (bus->irq >= 0)
- free_irq(bus->irq, (void*)chip);
-
- azx_free_stream_pages(chip);
- azx_free_streams(chip);
- snd_hdac_bus_exit(bus);
-
-#ifdef CONFIG_SND_HDA_PATCH_LOADER
- release_firmware(chip->fw);
-#endif
- display_power(chip, false);
-
- if (chip->driver_caps & AZX_DCAPS_I915_COMPONENT)
- snd_hdac_i915_exit(bus);
-
- hda->freed = 1;
-}
-
-static int azx_dev_disconnect(struct snd_device *device)
-{
- struct azx *chip = device->device_data;
- struct hdac_bus *bus = azx_bus(chip);
-
- chip->bus.shutdown = 1;
- cancel_work_sync(&bus->unsol_work);
-
- return 0;
-}
-
-static int azx_dev_free(struct snd_device *device)
-{
- azx_free(device->device_data);
- return 0;
-}
-
-#ifdef SUPPORT_VGA_SWITCHEROO
-#ifdef CONFIG_ACPI
-/* ATPX is in the integrated GPU's namespace */
-static bool atpx_present(void)
-{
- struct pci_dev *pdev = NULL;
- acpi_handle dhandle, atpx_handle;
- acpi_status status;
-
- while ((pdev = pci_get_base_class(PCI_BASE_CLASS_DISPLAY, pdev))) {
- if ((pdev->class != PCI_CLASS_DISPLAY_VGA << 8) &&
- (pdev->class != PCI_CLASS_DISPLAY_OTHER << 8))
- continue;
-
- dhandle = ACPI_HANDLE(&pdev->dev);
- if (dhandle) {
- status = acpi_get_handle(dhandle, "ATPX", &atpx_handle);
- if (ACPI_SUCCESS(status)) {
- pci_dev_put(pdev);
- return true;
- }
- }
- }
- return false;
-}
-#else
-static bool atpx_present(void)
-{
- return false;
-}
-#endif
-
-/*
- * Check of disabled HDMI controller by vga_switcheroo
- */
-static struct pci_dev *get_bound_vga(struct pci_dev *pci)
-{
- struct pci_dev *p;
-
- /* check only discrete GPU */
- switch (pci->vendor) {
- case PCI_VENDOR_ID_ATI:
- case PCI_VENDOR_ID_AMD:
- if (pci->devfn == 1) {
- p = pci_get_domain_bus_and_slot(pci_domain_nr(pci->bus),
- pci->bus->number, 0);
- if (p) {
- /* ATPX is in the integrated GPU's ACPI namespace
- * rather than the dGPU's namespace. However,
- * the dGPU is the one who is involved in
- * vgaswitcheroo.
- */
- if (((p->class >> 16) == PCI_BASE_CLASS_DISPLAY) &&
- (atpx_present() || apple_gmux_detect(NULL, NULL)))
- return p;
- pci_dev_put(p);
- }
- }
- break;
- case PCI_VENDOR_ID_NVIDIA:
- if (pci->devfn == 1) {
- p = pci_get_domain_bus_and_slot(pci_domain_nr(pci->bus),
- pci->bus->number, 0);
- if (p) {
- if ((p->class >> 16) == PCI_BASE_CLASS_DISPLAY)
- return p;
- pci_dev_put(p);
- }
- }
- break;
- }
- return NULL;
-}
-
-static bool check_hdmi_disabled(struct pci_dev *pci)
-{
- bool vga_inactive = false;
- struct pci_dev *p = get_bound_vga(pci);
-
- if (p) {
- if (vga_switcheroo_get_client_state(p) == VGA_SWITCHEROO_OFF)
- vga_inactive = true;
- pci_dev_put(p);
- }
- return vga_inactive;
-}
-#endif /* SUPPORT_VGA_SWITCHEROO */
-
-/*
- * allow/deny-listing for position_fix
- */
-static const struct snd_pci_quirk position_fix_list[] = {
- SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB),
- SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB),
- SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB),
- SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB),
- SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB),
- SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS M2V", POS_FIX_LPIB),
- SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB),
- SND_PCI_QUIRK(0x10de, 0xcb89, "Macbook Pro 7,1", POS_FIX_LPIB),
- SND_PCI_QUIRK(0x1297, 0x3166, "Shuttle", POS_FIX_LPIB),
- SND_PCI_QUIRK(0x1458, 0xa022, "ga-ma770-ud3", POS_FIX_LPIB),
- SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB),
- SND_PCI_QUIRK(0x1565, 0x8218, "Biostar Microtech", POS_FIX_LPIB),
- SND_PCI_QUIRK(0x1849, 0x0888, "775Dual-VSTA", POS_FIX_LPIB),
- SND_PCI_QUIRK(0x8086, 0x2503, "DG965OT AAD63733-203", POS_FIX_LPIB),
- {}
-};
-
-static int check_position_fix(struct azx *chip, int fix)
-{
- const struct snd_pci_quirk *q;
-
- switch (fix) {
- case POS_FIX_AUTO:
- case POS_FIX_LPIB:
- case POS_FIX_POSBUF:
- case POS_FIX_VIACOMBO:
- case POS_FIX_COMBO:
- case POS_FIX_SKL:
- case POS_FIX_FIFO:
- return fix;
- }
-
- q = snd_pci_quirk_lookup(chip->pci, position_fix_list);
- if (q) {
- dev_info(chip->card->dev,
- "position_fix set to %d for device %04x:%04x\n",
- q->value, q->subvendor, q->subdevice);
- return q->value;
- }
-
- /* Check VIA/ATI HD Audio Controller exist */
- if (chip->driver_type == AZX_DRIVER_VIA) {
- dev_dbg(chip->card->dev, "Using VIACOMBO position fix\n");
- return POS_FIX_VIACOMBO;
- }
- if (chip->driver_caps & AZX_DCAPS_AMD_WORKAROUND) {
- dev_dbg(chip->card->dev, "Using FIFO position fix\n");
- return POS_FIX_FIFO;
- }
- if (chip->driver_caps & AZX_DCAPS_POSFIX_LPIB) {
- dev_dbg(chip->card->dev, "Using LPIB position fix\n");
- return POS_FIX_LPIB;
- }
- if (chip->driver_type == AZX_DRIVER_SKL) {
- dev_dbg(chip->card->dev, "Using SKL position fix\n");
- return POS_FIX_SKL;
- }
- return POS_FIX_AUTO;
-}
-
-static void assign_position_fix(struct azx *chip, int fix)
-{
- static const azx_get_pos_callback_t callbacks[] = {
- [POS_FIX_AUTO] = NULL,
- [POS_FIX_LPIB] = azx_get_pos_lpib,
- [POS_FIX_POSBUF] = azx_get_pos_posbuf,
- [POS_FIX_VIACOMBO] = azx_via_get_position,
- [POS_FIX_COMBO] = azx_get_pos_lpib,
- [POS_FIX_SKL] = azx_get_pos_posbuf,
- [POS_FIX_FIFO] = azx_get_pos_fifo,
- };
-
- chip->get_position[0] = chip->get_position[1] = callbacks[fix];
-
- /* combo mode uses LPIB only for playback */
- if (fix == POS_FIX_COMBO)
- chip->get_position[1] = NULL;
-
- if ((fix == POS_FIX_POSBUF || fix == POS_FIX_SKL) &&
- (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) {
- chip->get_delay[0] = chip->get_delay[1] =
- azx_get_delay_from_lpib;
- }
-
- if (fix == POS_FIX_FIFO)
- chip->get_delay[0] = chip->get_delay[1] =
- azx_get_delay_from_fifo;
-}
-
-/*
- * deny-lists for probe_mask
- */
-static const struct snd_pci_quirk probe_mask_list[] = {
- /* Thinkpad often breaks the controller communication when accessing
- * to the non-working (or non-existing) modem codec slot.
- */
- SND_PCI_QUIRK(0x1014, 0x05b7, "Thinkpad Z60", 0x01),
- SND_PCI_QUIRK(0x17aa, 0x2010, "Thinkpad X/T/R60", 0x01),
- SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X/T/R61", 0x01),
- /* broken BIOS */
- SND_PCI_QUIRK(0x1028, 0x20ac, "Dell Studio Desktop", 0x01),
- /* including bogus ALC268 in slot#2 that conflicts with ALC888 */
- SND_PCI_QUIRK(0x17c0, 0x4085, "Medion MD96630", 0x01),
- /* forced codec slots */
- SND_PCI_QUIRK(0x1043, 0x1262, "ASUS W5Fm", 0x103),
- SND_PCI_QUIRK(0x1046, 0x1262, "ASUS W5F", 0x103),
- SND_PCI_QUIRK(0x1558, 0x0351, "Schenker Dock 15", 0x105),
- /* WinFast VP200 H (Teradici) user reported broken communication */
- SND_PCI_QUIRK(0x3a21, 0x040d, "WinFast VP200 H", 0x101),
- {}
-};
-
-#define AZX_FORCE_CODEC_MASK 0x100
-
-static void check_probe_mask(struct azx *chip, int dev)
-{
- const struct snd_pci_quirk *q;
-
- chip->codec_probe_mask = probe_mask[dev];
- if (chip->codec_probe_mask == -1) {
- q = snd_pci_quirk_lookup(chip->pci, probe_mask_list);
- if (q) {
- dev_info(chip->card->dev,
- "probe_mask set to 0x%x for device %04x:%04x\n",
- q->value, q->subvendor, q->subdevice);
- chip->codec_probe_mask = q->value;
- }
- }
-
- /* check forced option */
- if (chip->codec_probe_mask != -1 &&
- (chip->codec_probe_mask & AZX_FORCE_CODEC_MASK)) {
- azx_bus(chip)->codec_mask = chip->codec_probe_mask & 0xff;
- dev_info(chip->card->dev, "codec_mask forced to 0x%x\n",
- (int)azx_bus(chip)->codec_mask);
- }
-}
-
-/*
- * allow/deny-list for enable_msi
- */
-static const struct snd_pci_quirk msi_deny_list[] = {
- SND_PCI_QUIRK(0x103c, 0x2191, "HP", 0), /* AMD Hudson */
- SND_PCI_QUIRK(0x103c, 0x2192, "HP", 0), /* AMD Hudson */
- SND_PCI_QUIRK(0x103c, 0x21f7, "HP", 0), /* AMD Hudson */
- SND_PCI_QUIRK(0x103c, 0x21fa, "HP", 0), /* AMD Hudson */
- SND_PCI_QUIRK(0x1043, 0x81f2, "ASUS", 0), /* Athlon64 X2 + nvidia */
- SND_PCI_QUIRK(0x1043, 0x81f6, "ASUS", 0), /* nvidia */
- SND_PCI_QUIRK(0x1043, 0x822d, "ASUS", 0), /* Athlon64 X2 + nvidia MCP55 */
- SND_PCI_QUIRK(0x1179, 0xfb44, "Toshiba Satellite C870", 0), /* AMD Hudson */
- SND_PCI_QUIRK(0x1849, 0x0888, "ASRock", 0), /* Athlon64 X2 + nvidia */
- SND_PCI_QUIRK(0xa0a0, 0x0575, "Aopen MZ915-M", 0), /* ICH6 */
- {}
-};
-
-static void check_msi(struct azx *chip)
-{
- const struct snd_pci_quirk *q;
-
- if (enable_msi >= 0) {
- chip->msi = !!enable_msi;
- return;
- }
- chip->msi = 1; /* enable MSI as default */
- q = snd_pci_quirk_lookup(chip->pci, msi_deny_list);
- if (q) {
- dev_info(chip->card->dev,
- "msi for device %04x:%04x set to %d\n",
- q->subvendor, q->subdevice, q->value);
- chip->msi = q->value;
- return;
- }
-
- /* NVidia chipsets seem to cause troubles with MSI */
- if (chip->driver_caps & AZX_DCAPS_NO_MSI) {
- dev_info(chip->card->dev, "Disabling MSI\n");
- chip->msi = 0;
- }
-}
-
-/* check the snoop mode availability */
-static void azx_check_snoop_available(struct azx *chip)
-{
- int snoop = hda_snoop;
-
- if (snoop >= 0) {
- dev_info(chip->card->dev, "Force to %s mode by module option\n",
- snoop ? "snoop" : "non-snoop");
- chip->snoop = snoop;
- chip->uc_buffer = !snoop;
- return;
- }
-
- snoop = true;
- if (azx_get_snoop_type(chip) == AZX_SNOOP_TYPE_NONE &&
- chip->driver_type == AZX_DRIVER_VIA) {
- /* force to non-snoop mode for a new VIA controller
- * when BIOS is set
- */
- u8 val;
- pci_read_config_byte(chip->pci, 0x42, &val);
- if (!(val & 0x80) && (chip->pci->revision == 0x30 ||
- chip->pci->revision == 0x20))
- snoop = false;
- }
-
- if (chip->driver_caps & AZX_DCAPS_SNOOP_OFF)
- snoop = false;
-
- chip->snoop = snoop;
- if (!snoop) {
- dev_info(chip->card->dev, "Force to non-snoop mode\n");
- /* C-Media requires non-cached pages only for CORB/RIRB */
- if (chip->driver_type != AZX_DRIVER_CMEDIA)
- chip->uc_buffer = true;
- }
-}
-
-static void azx_probe_work(struct work_struct *work)
-{
- struct hda_intel *hda = container_of(work, struct hda_intel, probe_work.work);
- azx_probe_continue(&hda->chip);
-}
-
-static int default_bdl_pos_adj(struct azx *chip)
-{
- /* some exceptions: Atoms seem problematic with value 1 */
- if (chip->pci->vendor == PCI_VENDOR_ID_INTEL) {
- switch (chip->pci->device) {
- case PCI_DEVICE_ID_INTEL_HDA_BYT:
- case PCI_DEVICE_ID_INTEL_HDA_BSW:
- return 32;
- case PCI_DEVICE_ID_INTEL_HDA_APL:
- return 64;
- }
- }
-
- switch (chip->driver_type) {
- /*
- * increase the bdl size for Glenfly Gpus for hardware
- * limitation on hdac interrupt interval
- */
- case AZX_DRIVER_GFHDMI:
- return 128;
- case AZX_DRIVER_ICH:
- case AZX_DRIVER_PCH:
- return 1;
- case AZX_DRIVER_ZHAOXINHDMI:
- return 128;
- default:
- return 32;
- }
-}
-
-/*
- * constructor
- */
-static const struct hda_controller_ops pci_hda_ops;
-
-static int azx_create(struct snd_card *card, struct pci_dev *pci,
- int dev, unsigned int driver_caps,
- struct azx **rchip)
-{
- static const struct snd_device_ops ops = {
- .dev_disconnect = azx_dev_disconnect,
- .dev_free = azx_dev_free,
- };
- struct hda_intel *hda;
- struct azx *chip;
- int err;
-
- *rchip = NULL;
-
- err = pcim_enable_device(pci);
- if (err < 0)
- return err;
-
- hda = devm_kzalloc(&pci->dev, sizeof(*hda), GFP_KERNEL);
- if (!hda)
- return -ENOMEM;
-
- chip = &hda->chip;
- mutex_init(&chip->open_mutex);
- chip->card = card;
- chip->pci = pci;
- chip->ops = &pci_hda_ops;
- chip->driver_caps = driver_caps;
- chip->driver_type = driver_caps & 0xff;
- check_msi(chip);
- chip->dev_index = dev;
- if (jackpoll_ms[dev] >= 50 && jackpoll_ms[dev] <= 60000)
- chip->jackpoll_interval = msecs_to_jiffies(jackpoll_ms[dev]);
- INIT_LIST_HEAD(&chip->pcm_list);
- INIT_WORK(&hda->irq_pending_work, azx_irq_pending_work);
- INIT_LIST_HEAD(&hda->list);
- init_vga_switcheroo(chip);
- init_completion(&hda->probe_wait);
-
- assign_position_fix(chip, check_position_fix(chip, position_fix[dev]));
-
- if (single_cmd < 0) /* allow fallback to single_cmd at errors */
- chip->fallback_to_single_cmd = 1;
- else /* explicitly set to single_cmd or not */
- chip->single_cmd = single_cmd;
-
- azx_check_snoop_available(chip);
-
- if (bdl_pos_adj[dev] < 0)
- chip->bdl_pos_adj = default_bdl_pos_adj(chip);
- else
- chip->bdl_pos_adj = bdl_pos_adj[dev];
-
- err = azx_bus_init(chip, model[dev]);
- if (err < 0)
- return err;
-
- /* use the non-cached pages in non-snoop mode */
- if (!azx_snoop(chip))
- azx_bus(chip)->dma_type = SNDRV_DMA_TYPE_DEV_WC;
-
- if (chip->driver_type == AZX_DRIVER_NVIDIA) {
- dev_dbg(chip->card->dev, "Enable delay in RIRB handling\n");
- chip->bus.core.needs_damn_long_delay = 1;
- }
-
- check_probe_mask(chip, dev);
-
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0) {
- dev_err(card->dev, "Error creating device [card]!\n");
- azx_free(chip);
- return err;
- }
-
- /* continue probing in work context as may trigger request module */
- INIT_DELAYED_WORK(&hda->probe_work, azx_probe_work);
-
- *rchip = chip;
-
- return 0;
-}
-
-static int azx_first_init(struct azx *chip)
-{
- int dev = chip->dev_index;
- struct pci_dev *pci = chip->pci;
- struct snd_card *card = chip->card;
- struct hdac_bus *bus = azx_bus(chip);
- int err;
- unsigned short gcap;
- unsigned int dma_bits = 64;
-
-#if BITS_PER_LONG != 64
- /* Fix up base address on ULI M5461 */
- if (chip->driver_type == AZX_DRIVER_ULI) {
- u16 tmp3;
- pci_read_config_word(pci, 0x40, &tmp3);
- pci_write_config_word(pci, 0x40, tmp3 | 0x10);
- pci_write_config_dword(pci, PCI_BASE_ADDRESS_1, 0);
- }
-#endif
- /*
- * Fix response write request not synced to memory when handle
- * hdac interrupt on Glenfly Gpus
- */
- if (chip->driver_type == AZX_DRIVER_GFHDMI)
- bus->polling_mode = 1;
-
- if (chip->driver_type == AZX_DRIVER_LOONGSON) {
- bus->polling_mode = 1;
- bus->not_use_interrupts = 1;
- bus->access_sdnctl_in_dword = 1;
- if (!chip->jackpoll_interval)
- chip->jackpoll_interval = msecs_to_jiffies(1500);
- }
-
- if (chip->driver_type == AZX_DRIVER_ZHAOXINHDMI)
- bus->polling_mode = 1;
-
- bus->remap_addr = pcim_iomap_region(pci, 0, "ICH HD audio");
- if (IS_ERR(bus->remap_addr))
- return PTR_ERR(bus->remap_addr);
-
- bus->addr = pci_resource_start(pci, 0);
-
- if (chip->driver_type == AZX_DRIVER_SKL)
- snd_hdac_bus_parse_capabilities(bus);
-
- /*
- * Some Intel CPUs has always running timer (ART) feature and
- * controller may have Global time sync reporting capability, so
- * check both of these before declaring synchronized time reporting
- * capability SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME
- */
- chip->gts_present = false;
-
-#ifdef CONFIG_X86
- if (bus->ppcap && boot_cpu_has(X86_FEATURE_ART))
- chip->gts_present = true;
-#endif
-
- if (chip->msi && chip->driver_caps & AZX_DCAPS_NO_MSI64) {
- dev_dbg(card->dev, "Disabling 64bit MSI\n");
- pci->no_64bit_msi = true;
- }
-
- pci_set_master(pci);
-
- gcap = azx_readw(chip, GCAP);
- dev_dbg(card->dev, "chipset global capabilities = 0x%x\n", gcap);
-
- /* AMD devices support 40 or 48bit DMA, take the safe one */
- if (chip->pci->vendor == PCI_VENDOR_ID_AMD)
- dma_bits = 40;
-
- /* disable SB600 64bit support for safety */
- if (chip->pci->vendor == PCI_VENDOR_ID_ATI) {
- struct pci_dev *p_smbus;
- dma_bits = 40;
- p_smbus = pci_get_device(PCI_VENDOR_ID_ATI,
- PCI_DEVICE_ID_ATI_SBX00_SMBUS,
- NULL);
- if (p_smbus) {
- if (p_smbus->revision < 0x30)
- gcap &= ~AZX_GCAP_64OK;
- pci_dev_put(p_smbus);
- }
- }
-
- /* NVidia hardware normally only supports up to 40 bits of DMA */
- if (chip->pci->vendor == PCI_VENDOR_ID_NVIDIA)
- dma_bits = 40;
-
- /* disable 64bit DMA address on some devices */
- if (chip->driver_caps & AZX_DCAPS_NO_64BIT) {
- dev_dbg(card->dev, "Disabling 64bit DMA\n");
- gcap &= ~AZX_GCAP_64OK;
- }
-
- /* disable buffer size rounding to 128-byte multiples if supported */
- if (align_buffer_size >= 0)
- chip->align_buffer_size = !!align_buffer_size;
- else {
- if (chip->driver_caps & AZX_DCAPS_NO_ALIGN_BUFSIZE)
- chip->align_buffer_size = 0;
- else
- chip->align_buffer_size = 1;
- }
-
- /* allow 64bit DMA address if supported by H/W */
- if (!(gcap & AZX_GCAP_64OK))
- dma_bits = 32;
- if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(dma_bits)))
- dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32));
- dma_set_max_seg_size(&pci->dev, UINT_MAX);
-
- /* read number of streams from GCAP register instead of using
- * hardcoded value
- */
- chip->capture_streams = (gcap >> 8) & 0x0f;
- chip->playback_streams = (gcap >> 12) & 0x0f;
- if (!chip->playback_streams && !chip->capture_streams) {
- /* gcap didn't give any info, switching to old method */
-
- switch (chip->driver_type) {
- case AZX_DRIVER_ULI:
- chip->playback_streams = ULI_NUM_PLAYBACK;
- chip->capture_streams = ULI_NUM_CAPTURE;
- break;
- case AZX_DRIVER_ATIHDMI:
- case AZX_DRIVER_ATIHDMI_NS:
- chip->playback_streams = ATIHDMI_NUM_PLAYBACK;
- chip->capture_streams = ATIHDMI_NUM_CAPTURE;
- break;
- case AZX_DRIVER_GFHDMI:
- case AZX_DRIVER_ZHAOXINHDMI:
- case AZX_DRIVER_GENERIC:
- default:
- chip->playback_streams = ICH6_NUM_PLAYBACK;
- chip->capture_streams = ICH6_NUM_CAPTURE;
- break;
- }
- }
- chip->capture_index_offset = 0;
- chip->playback_index_offset = chip->capture_streams;
- chip->num_streams = chip->playback_streams + chip->capture_streams;
-
- /* sanity check for the SDxCTL.STRM field overflow */
- if (chip->num_streams > 15 &&
- (chip->driver_caps & AZX_DCAPS_SEPARATE_STREAM_TAG) == 0) {
- dev_warn(chip->card->dev, "number of I/O streams is %d, "
- "forcing separate stream tags", chip->num_streams);
- chip->driver_caps |= AZX_DCAPS_SEPARATE_STREAM_TAG;
- }
-
- /* initialize streams */
- err = azx_init_streams(chip);
- if (err < 0)
- return err;
-
- err = azx_alloc_stream_pages(chip);
- if (err < 0)
- return err;
-
- /* initialize chip */
- azx_init_pci(chip);
-
- snd_hdac_i915_set_bclk(bus);
-
- hda_intel_init_chip(chip, (probe_only[dev] & 2) == 0);
-
- /* codec detection */
- if (!azx_bus(chip)->codec_mask) {
- dev_err(card->dev, "no codecs found!\n");
- /* keep running the rest for the runtime PM */
- }
-
- if (azx_acquire_irq(chip, 0) < 0)
- return -EBUSY;
-
- strcpy(card->driver, "HDA-Intel");
- strscpy(card->shortname, driver_short_names[chip->driver_type],
- sizeof(card->shortname));
- snprintf(card->longname, sizeof(card->longname),
- "%s at 0x%lx irq %i",
- card->shortname, bus->addr, bus->irq);
-
- return 0;
-}
-
-#ifdef CONFIG_SND_HDA_PATCH_LOADER
-/* callback from request_firmware_nowait() */
-static void azx_firmware_cb(const struct firmware *fw, void *context)
-{
- struct snd_card *card = context;
- struct azx *chip = card->private_data;
-
- if (fw)
- chip->fw = fw;
- else
- dev_err(card->dev, "Cannot load firmware, continue without patching\n");
- if (!chip->disabled) {
- /* continue probing */
- azx_probe_continue(chip);
- }
-}
-#endif
-
-static int disable_msi_reset_irq(struct azx *chip)
-{
- struct hdac_bus *bus = azx_bus(chip);
- int err;
-
- free_irq(bus->irq, chip);
- bus->irq = -1;
- chip->card->sync_irq = -1;
- pci_free_irq_vectors(chip->pci);
- chip->msi = 0;
- err = azx_acquire_irq(chip, 1);
- if (err < 0)
- return err;
-
- return 0;
-}
-
-/* Denylist for skipping the whole probe:
- * some HD-audio PCI entries are exposed without any codecs, and such devices
- * should be ignored from the beginning.
- */
-static const struct pci_device_id driver_denylist[] = {
- { PCI_DEVICE_SUB(0x1022, 0x1487, 0x1043, 0x874f) }, /* ASUS ROG Zenith II / Strix */
- { PCI_DEVICE_SUB(0x1022, 0x1487, 0x1462, 0xcb59) }, /* MSI TRX40 Creator */
- { PCI_DEVICE_SUB(0x1022, 0x1487, 0x1462, 0xcb60) }, /* MSI TRX40 */
- { PCI_DEVICE_SUB(0x1022, 0x15e3, 0x1022, 0xd601) }, /* ASRock X670E Taichi */
- {}
-};
-
-static struct pci_device_id driver_denylist_ideapad_z570[] = {
- { PCI_DEVICE_SUB(0x10de, 0x0bea, 0x0000, 0x0000) }, /* NVIDIA GF108 HDA */
- {}
-};
-
-/* DMI-based denylist, to be used when:
- * - PCI subsystem IDs are zero, impossible to distinguish from valid sound cards.
- * - Different modifications of the same laptop use different GPU models.
- */
-static const struct dmi_system_id driver_denylist_dmi[] = {
- {
- /* No HDA in NVIDIA DGPU. BIOS disables it, but quirk_nvidia_hda() reenables. */
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "Ideapad Z570"),
- },
- .driver_data = &driver_denylist_ideapad_z570,
- },
- {}
-};
-
-static const struct hda_controller_ops pci_hda_ops = {
- .disable_msi_reset_irq = disable_msi_reset_irq,
- .position_check = azx_position_check,
-};
-
-static DECLARE_BITMAP(probed_devs, SNDRV_CARDS);
-
-static int azx_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
-{
- const struct dmi_system_id *dmi;
- struct snd_card *card;
- struct hda_intel *hda;
- struct azx *chip;
- bool schedule_probe;
- int dev;
- int err;
-
- if (pci_match_id(driver_denylist, pci)) {
- dev_info(&pci->dev, "Skipping the device on the denylist\n");
- return -ENODEV;
- }
-
- dmi = dmi_first_match(driver_denylist_dmi);
- if (dmi && pci_match_id(dmi->driver_data, pci)) {
- dev_info(&pci->dev, "Skipping the device on the DMI denylist\n");
- return -ENODEV;
- }
-
- dev = find_first_zero_bit(probed_devs, SNDRV_CARDS);
- if (dev >= SNDRV_CARDS)
- return -ENODEV;
- if (!enable[dev]) {
- set_bit(dev, probed_devs);
- return -ENOENT;
- }
-
- /*
- * stop probe if another Intel's DSP driver should be activated
- */
- if (dmic_detect) {
- err = snd_intel_dsp_driver_probe(pci);
- if (err != SND_INTEL_DSP_DRIVER_ANY && err != SND_INTEL_DSP_DRIVER_LEGACY) {
- dev_dbg(&pci->dev, "HDAudio driver not selected, aborting probe\n");
- return -ENODEV;
- }
- } else {
- dev_warn(&pci->dev, "dmic_detect option is deprecated, pass snd-intel-dspcfg.dsp_driver=1 option instead\n");
- }
-
- err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
- 0, &card);
- if (err < 0) {
- dev_err(&pci->dev, "Error creating card!\n");
- return err;
- }
-
- err = azx_create(card, pci, dev, pci_id->driver_data, &chip);
- if (err < 0)
- goto out_free;
- card->private_data = chip;
- hda = container_of(chip, struct hda_intel, chip);
-
- pci_set_drvdata(pci, card);
-
-#ifdef CONFIG_SND_HDA_I915
- /* bind with i915 if needed */
- if (chip->driver_caps & AZX_DCAPS_I915_COMPONENT) {
- err = snd_hdac_i915_init(azx_bus(chip));
- if (err < 0) {
- if (err == -EPROBE_DEFER)
- goto out_free;
-
- /* if the controller is bound only with HDMI/DP
- * (for HSW and BDW), we need to abort the probe;
- * for other chips, still continue probing as other
- * codecs can be on the same link.
- */
- if (HDA_CONTROLLER_IN_GPU(pci)) {
- dev_err_probe(card->dev, err,
- "HSW/BDW HD-audio HDMI/DP requires binding with gfx driver\n");
-
- goto out_free;
- } else {
- /* don't bother any longer */
- chip->driver_caps &= ~AZX_DCAPS_I915_COMPONENT;
- }
- }
-
- /* HSW/BDW controllers need this power */
- if (HDA_CONTROLLER_IN_GPU(pci))
- hda->need_i915_power = true;
- }
-#else
- if (HDA_CONTROLLER_IN_GPU(pci))
- dev_err(card->dev, "Haswell/Broadwell HDMI/DP must build in CONFIG_SND_HDA_I915\n");
-#endif
-
- err = register_vga_switcheroo(chip);
- if (err < 0) {
- dev_err(card->dev, "Error registering vga_switcheroo client\n");
- goto out_free;
- }
-
- if (check_hdmi_disabled(pci)) {
- dev_info(card->dev, "VGA controller is disabled\n");
- dev_info(card->dev, "Delaying initialization\n");
- chip->disabled = true;
- }
-
- schedule_probe = !chip->disabled;
-
-#ifdef CONFIG_SND_HDA_PATCH_LOADER
- if (patch[dev] && *patch[dev]) {
- dev_info(card->dev, "Applying patch firmware '%s'\n",
- patch[dev]);
- err = request_firmware_nowait(THIS_MODULE, true, patch[dev],
- &pci->dev, GFP_KERNEL, card,
- azx_firmware_cb);
- if (err < 0)
- goto out_free;
- schedule_probe = false; /* continued in azx_firmware_cb() */
- }
-#endif /* CONFIG_SND_HDA_PATCH_LOADER */
-
- if (schedule_probe)
- schedule_delayed_work(&hda->probe_work, 0);
-
- set_bit(dev, probed_devs);
- if (chip->disabled)
- complete_all(&hda->probe_wait);
- return 0;
-
-out_free:
- pci_set_drvdata(pci, NULL);
- snd_card_free(card);
- return err;
-}
-
-/* On some boards setting power_save to a non 0 value leads to clicking /
- * popping sounds when ever we enter/leave powersaving mode. Ideally we would
- * figure out how to avoid these sounds, but that is not always feasible.
- * So we keep a list of devices where we disable powersaving as its known
- * to causes problems on these devices.
- */
-static const struct snd_pci_quirk power_save_denylist[] = {
- /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
- SND_PCI_QUIRK(0x1849, 0xc892, "Asrock B85M-ITX", 0),
- /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
- SND_PCI_QUIRK(0x1849, 0x0397, "Asrock N68C-S UCC", 0),
- /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
- SND_PCI_QUIRK(0x1849, 0x7662, "Asrock H81M-HDS", 0),
- /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
- SND_PCI_QUIRK(0x1043, 0x8733, "Asus Prime X370-Pro", 0),
- /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
- SND_PCI_QUIRK(0x1028, 0x0497, "Dell Precision T3600", 0),
- /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
- /* Note the P55A-UD3 and Z87-D3HP share the subsys id for the HDA dev */
- SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte P55A-UD3 / Z87-D3HP", 0),
- /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
- SND_PCI_QUIRK(0x8086, 0x2040, "Intel DZ77BH-55K", 0),
- /* https://bugzilla.kernel.org/show_bug.cgi?id=199607 */
- SND_PCI_QUIRK(0x8086, 0x2057, "Intel NUC5i7RYB", 0),
- /* https://bugs.launchpad.net/bugs/1821663 */
- SND_PCI_QUIRK(0x8086, 0x2064, "Intel SDP 8086:2064", 0),
- /* https://bugzilla.redhat.com/show_bug.cgi?id=1520902 */
- SND_PCI_QUIRK(0x8086, 0x2068, "Intel NUC7i3BNB", 0),
- /* https://bugzilla.kernel.org/show_bug.cgi?id=198611 */
- SND_PCI_QUIRK(0x17aa, 0x2227, "Lenovo X1 Carbon 3rd Gen", 0),
- SND_PCI_QUIRK(0x17aa, 0x316e, "Lenovo ThinkCentre M70q", 0),
- /* https://bugzilla.redhat.com/show_bug.cgi?id=1689623 */
- SND_PCI_QUIRK(0x17aa, 0x367b, "Lenovo IdeaCentre B550", 0),
- /* https://bugzilla.redhat.com/show_bug.cgi?id=1572975 */
- SND_PCI_QUIRK(0x17aa, 0x36a7, "Lenovo C50 All in one", 0),
- /* https://bugs.launchpad.net/bugs/1821663 */
- SND_PCI_QUIRK(0x1631, 0xe017, "Packard Bell NEC IMEDIA 5204", 0),
- /* KONTRON SinglePC may cause a stall at runtime resume */
- SND_PCI_QUIRK(0x1734, 0x1232, "KONTRON SinglePC", 0),
- /* Dell ALC3271 */
- SND_PCI_QUIRK(0x1028, 0x0962, "Dell ALC3271", 0),
- /* https://bugzilla.kernel.org/show_bug.cgi?id=220210 */
- SND_PCI_QUIRK(0x17aa, 0x5079, "Lenovo Thinkpad E15", 0),
- {}
-};
-
-static void set_default_power_save(struct azx *chip)
-{
- struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
- int val = power_save;
-
- if (pm_blacklist < 0) {
- const struct snd_pci_quirk *q;
-
- q = snd_pci_quirk_lookup(chip->pci, power_save_denylist);
- if (q && val) {
- dev_info(chip->card->dev, "device %04x:%04x is on the power_save denylist, forcing power_save to 0\n",
- q->subvendor, q->subdevice);
- val = 0;
- hda->runtime_pm_disabled = 1;
- }
- } else if (pm_blacklist > 0) {
- dev_info(chip->card->dev, "Forcing power_save to 0 via option\n");
- val = 0;
- }
- snd_hda_set_power_save(&chip->bus, val * 1000);
-}
-
-/* number of codec slots for each chipset: 0 = default slots (i.e. 4) */
-static const unsigned int azx_max_codecs[AZX_NUM_DRIVERS] = {
- [AZX_DRIVER_NVIDIA] = 8,
- [AZX_DRIVER_TERA] = 1,
-};
-
-static int azx_probe_continue(struct azx *chip)
-{
- struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
- struct hdac_bus *bus = azx_bus(chip);
- struct pci_dev *pci = chip->pci;
- int dev = chip->dev_index;
- int err;
-
- if (chip->disabled || hda->init_failed)
- return -EIO;
- if (hda->probe_retry)
- goto probe_retry;
-
- to_hda_bus(bus)->bus_probing = 1;
- hda->probe_continued = 1;
-
- /* Request display power well for the HDA controller or codec. For
- * Haswell/Broadwell, both the display HDA controller and codec need
- * this power. For other platforms, like Baytrail/Braswell, only the
- * display codec needs the power and it can be released after probe.
- */
- display_power(chip, true);
-
- err = azx_first_init(chip);
- if (err < 0)
- goto out_free;
-
-#ifdef CONFIG_SND_HDA_INPUT_BEEP
- chip->beep_mode = beep_mode[dev];
-#endif
-
- chip->ctl_dev_id = ctl_dev_id;
-
- /* create codec instances */
- if (bus->codec_mask) {
- err = azx_probe_codecs(chip, azx_max_codecs[chip->driver_type]);
- if (err < 0)
- goto out_free;
- }
-
-#ifdef CONFIG_SND_HDA_PATCH_LOADER
- if (chip->fw) {
- err = snd_hda_load_patch(&chip->bus, chip->fw->size,
- chip->fw->data);
- if (err < 0)
- goto out_free;
- }
-#endif
-
- probe_retry:
- if (bus->codec_mask && !(probe_only[dev] & 1)) {
- err = azx_codec_configure(chip);
- if (err) {
- if ((chip->driver_caps & AZX_DCAPS_RETRY_PROBE) &&
- ++hda->probe_retry < 60) {
- schedule_delayed_work(&hda->probe_work,
- msecs_to_jiffies(1000));
- return 0; /* keep things up */
- }
- dev_err(chip->card->dev, "Cannot probe codecs, giving up\n");
- goto out_free;
- }
- }
-
- err = snd_card_register(chip->card);
- if (err < 0)
- goto out_free;
-
- setup_vga_switcheroo_runtime_pm(chip);
-
- chip->running = 1;
- azx_add_card_list(chip);
-
- set_default_power_save(chip);
-
- if (azx_has_pm_runtime(chip)) {
- pm_runtime_use_autosuspend(&pci->dev);
- pm_runtime_allow(&pci->dev);
- pm_runtime_put_autosuspend(&pci->dev);
- }
-
-out_free:
- if (err < 0) {
- pci_set_drvdata(pci, NULL);
- snd_card_free(chip->card);
- return err;
- }
-
- if (!hda->need_i915_power)
- display_power(chip, false);
- complete_all(&hda->probe_wait);
- to_hda_bus(bus)->bus_probing = 0;
- hda->probe_retry = 0;
- return 0;
-}
-
-static void azx_remove(struct pci_dev *pci)
-{
- struct snd_card *card = pci_get_drvdata(pci);
- struct azx *chip;
- struct hda_intel *hda;
-
- if (card) {
- /* cancel the pending probing work */
- chip = card->private_data;
- hda = container_of(chip, struct hda_intel, chip);
- /* FIXME: below is an ugly workaround.
- * Both device_release_driver() and driver_probe_device()
- * take *both* the device's and its parent's lock before
- * calling the remove() and probe() callbacks. The codec
- * probe takes the locks of both the codec itself and its
- * parent, i.e. the PCI controller dev. Meanwhile, when
- * the PCI controller is unbound, it takes its lock, too
- * ==> ouch, a deadlock!
- * As a workaround, we unlock temporarily here the controller
- * device during cancel_work_sync() call.
- */
- device_unlock(&pci->dev);
- cancel_delayed_work_sync(&hda->probe_work);
- device_lock(&pci->dev);
-
- clear_bit(chip->dev_index, probed_devs);
- pci_set_drvdata(pci, NULL);
- snd_card_free(card);
- }
-}
-
-static void azx_shutdown(struct pci_dev *pci)
-{
- struct snd_card *card = pci_get_drvdata(pci);
- struct azx *chip;
-
- if (!card)
- return;
- chip = card->private_data;
- if (chip && chip->running)
- __azx_shutdown_chip(chip, true);
-}
-
-/* PCI IDs */
-static const struct pci_device_id azx_ids[] = {
- /* CPT */
- { PCI_DEVICE_DATA(INTEL, HDA_CPT, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM) },
- /* PBG */
- { PCI_DEVICE_DATA(INTEL, HDA_PBG, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM) },
- /* Panther Point */
- { PCI_DEVICE_DATA(INTEL, HDA_PPT, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM) },
- /* Lynx Point */
- { PCI_DEVICE_DATA(INTEL, HDA_LPT, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH) },
- /* 9 Series */
- { PCI_DEVICE_DATA(INTEL, HDA_9_SERIES, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH) },
- /* Wellsburg */
- { PCI_DEVICE_DATA(INTEL, HDA_WBG_0, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH) },
- { PCI_DEVICE_DATA(INTEL, HDA_WBG_1, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH) },
- /* Lewisburg */
- { PCI_DEVICE_DATA(INTEL, HDA_LBG_0, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE) },
- { PCI_DEVICE_DATA(INTEL, HDA_LBG_1, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE) },
- /* Lynx Point-LP */
- { PCI_DEVICE_DATA(INTEL, HDA_LPT_LP_0, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH) },
- /* Lynx Point-LP */
- { PCI_DEVICE_DATA(INTEL, HDA_LPT_LP_1, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH) },
- /* Wildcat Point-LP */
- { PCI_DEVICE_DATA(INTEL, HDA_WPT_LP, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH) },
- /* Skylake (Sunrise Point) */
- { PCI_DEVICE_DATA(INTEL, HDA_SKL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- /* Skylake-LP (Sunrise Point-LP) */
- { PCI_DEVICE_DATA(INTEL, HDA_SKL_LP, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- /* Kabylake */
- { PCI_DEVICE_DATA(INTEL, HDA_KBL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- /* Kabylake-LP */
- { PCI_DEVICE_DATA(INTEL, HDA_KBL_LP, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- /* Kabylake-H */
- { PCI_DEVICE_DATA(INTEL, HDA_KBL_H, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- /* Coffelake */
- { PCI_DEVICE_DATA(INTEL, HDA_CNL_H, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- /* Cannonlake */
- { PCI_DEVICE_DATA(INTEL, HDA_CNL_LP, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- /* CometLake-LP */
- { PCI_DEVICE_DATA(INTEL, HDA_CML_LP, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- /* CometLake-H */
- { PCI_DEVICE_DATA(INTEL, HDA_CML_H, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- { PCI_DEVICE_DATA(INTEL, HDA_RKL_S, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- /* CometLake-S */
- { PCI_DEVICE_DATA(INTEL, HDA_CML_S, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- /* CometLake-R */
- { PCI_DEVICE_DATA(INTEL, HDA_CML_R, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- /* Icelake */
- { PCI_DEVICE_DATA(INTEL, HDA_ICL_LP, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- /* Icelake-H */
- { PCI_DEVICE_DATA(INTEL, HDA_ICL_H, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- /* Jasperlake */
- { PCI_DEVICE_DATA(INTEL, HDA_ICL_N, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- { PCI_DEVICE_DATA(INTEL, HDA_JSL_N, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- /* Tigerlake */
- { PCI_DEVICE_DATA(INTEL, HDA_TGL_LP, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- /* Tigerlake-H */
- { PCI_DEVICE_DATA(INTEL, HDA_TGL_H, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- /* DG1 */
- { PCI_DEVICE_DATA(INTEL, HDA_DG1, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- /* DG2 */
- { PCI_DEVICE_DATA(INTEL, HDA_DG2_0, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- { PCI_DEVICE_DATA(INTEL, HDA_DG2_1, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- { PCI_DEVICE_DATA(INTEL, HDA_DG2_2, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- /* Alderlake-S */
- { PCI_DEVICE_DATA(INTEL, HDA_ADL_S, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- /* Alderlake-P */
- { PCI_DEVICE_DATA(INTEL, HDA_ADL_P, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- { PCI_DEVICE_DATA(INTEL, HDA_ADL_PS, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- { PCI_DEVICE_DATA(INTEL, HDA_ADL_PX, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- /* Alderlake-M */
- { PCI_DEVICE_DATA(INTEL, HDA_ADL_M, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- /* Alderlake-N */
- { PCI_DEVICE_DATA(INTEL, HDA_ADL_N, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- /* Elkhart Lake */
- { PCI_DEVICE_DATA(INTEL, HDA_EHL_0, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- { PCI_DEVICE_DATA(INTEL, HDA_EHL_3, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- /* Raptor Lake */
- { PCI_DEVICE_DATA(INTEL, HDA_RPL_S, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- { PCI_DEVICE_DATA(INTEL, HDA_RPL_P_0, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- { PCI_DEVICE_DATA(INTEL, HDA_RPL_P_1, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- { PCI_DEVICE_DATA(INTEL, HDA_RPL_M, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- { PCI_DEVICE_DATA(INTEL, HDA_RPL_PX, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- { PCI_DEVICE_DATA(INTEL, HDA_MTL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- /* Battlemage */
- { PCI_DEVICE_DATA(INTEL, HDA_BMG, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- /* Lunarlake-P */
- { PCI_DEVICE_DATA(INTEL, HDA_LNL_P, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_LNL) },
- /* Arrow Lake-S */
- { PCI_DEVICE_DATA(INTEL, HDA_ARL_S, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- /* Arrow Lake */
- { PCI_DEVICE_DATA(INTEL, HDA_ARL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) },
- /* Panther Lake */
- { PCI_DEVICE_DATA(INTEL, HDA_PTL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_LNL) },
- /* Panther Lake-H */
- { PCI_DEVICE_DATA(INTEL, HDA_PTL_H, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_LNL) },
- /* Wildcat Lake */
- { PCI_DEVICE_DATA(INTEL, HDA_WCL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_LNL) },
- /* Apollolake (Broxton-P) */
- { PCI_DEVICE_DATA(INTEL, HDA_APL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON) },
- /* Gemini-Lake */
- { PCI_DEVICE_DATA(INTEL, HDA_GML, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON) },
- /* Haswell */
- { PCI_DEVICE_DATA(INTEL, HDA_HSW_0, AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL) },
- { PCI_DEVICE_DATA(INTEL, HDA_HSW_2, AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL) },
- { PCI_DEVICE_DATA(INTEL, HDA_HSW_3, AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL) },
- /* Broadwell */
- { PCI_DEVICE_DATA(INTEL, HDA_BDW, AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_BROADWELL) },
- /* 5 Series/3400 */
- { PCI_DEVICE_DATA(INTEL, HDA_5_3400_SERIES_0, AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM) },
- { PCI_DEVICE_DATA(INTEL, HDA_5_3400_SERIES_1, AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM) },
- /* Poulsbo */
- { PCI_DEVICE_DATA(INTEL, HDA_POULSBO, AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_BASE |
- AZX_DCAPS_POSFIX_LPIB) },
- /* Oaktrail */
- { PCI_DEVICE_DATA(INTEL, HDA_OAKTRAIL, AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_BASE) },
- /* BayTrail */
- { PCI_DEVICE_DATA(INTEL, HDA_BYT, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_BAYTRAIL) },
- /* Braswell */
- { PCI_DEVICE_DATA(INTEL, HDA_BSW, AZX_DRIVER_PCH | AZX_DCAPS_INTEL_BRASWELL) },
- /* ICH6 */
- { PCI_DEVICE_DATA(INTEL, HDA_ICH6, AZX_DRIVER_ICH | AZX_DCAPS_INTEL_ICH) },
- /* ICH7 */
- { PCI_DEVICE_DATA(INTEL, HDA_ICH7, AZX_DRIVER_ICH | AZX_DCAPS_INTEL_ICH) },
- /* ESB2 */
- { PCI_DEVICE_DATA(INTEL, HDA_ESB2, AZX_DRIVER_ICH | AZX_DCAPS_INTEL_ICH) },
- /* ICH8 */
- { PCI_DEVICE_DATA(INTEL, HDA_ICH8, AZX_DRIVER_ICH | AZX_DCAPS_INTEL_ICH) },
- /* ICH9 */
- { PCI_DEVICE_DATA(INTEL, HDA_ICH9_0, AZX_DRIVER_ICH | AZX_DCAPS_INTEL_ICH) },
- /* ICH9 */
- { PCI_DEVICE_DATA(INTEL, HDA_ICH9_1, AZX_DRIVER_ICH | AZX_DCAPS_INTEL_ICH) },
- /* ICH10 */
- { PCI_DEVICE_DATA(INTEL, HDA_ICH10_0, AZX_DRIVER_ICH | AZX_DCAPS_INTEL_ICH) },
- /* ICH10 */
- { PCI_DEVICE_DATA(INTEL, HDA_ICH10_1, AZX_DRIVER_ICH | AZX_DCAPS_INTEL_ICH) },
- /* Generic Intel */
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_ANY_ID),
- .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
- .class_mask = 0xffffff,
- .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_NO_ALIGN_BUFSIZE },
- /* ATI SB 450/600/700/800/900 */
- { PCI_VDEVICE(ATI, 0x437b),
- .driver_data = AZX_DRIVER_ATI | AZX_DCAPS_PRESET_ATI_SB },
- { PCI_VDEVICE(ATI, 0x4383),
- .driver_data = AZX_DRIVER_ATI | AZX_DCAPS_PRESET_ATI_SB },
- /* AMD Hudson */
- { PCI_VDEVICE(AMD, 0x780d),
- .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB },
- /* AMD, X370 & co */
- { PCI_VDEVICE(AMD, 0x1457),
- .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_AMD_SB },
- /* AMD, X570 & co */
- { PCI_VDEVICE(AMD, 0x1487),
- .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_AMD_SB },
- /* AMD Stoney */
- { PCI_VDEVICE(AMD, 0x157a),
- .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB |
- AZX_DCAPS_PM_RUNTIME },
- /* AMD Raven */
- { PCI_VDEVICE(AMD, 0x15e3),
- .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_AMD_SB },
- /* ATI HDMI */
- { PCI_VDEVICE(ATI, 0x0002),
- .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
- AZX_DCAPS_PM_RUNTIME },
- { PCI_VDEVICE(ATI, 0x1308),
- .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
- { PCI_VDEVICE(ATI, 0x157a),
- .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
- { PCI_VDEVICE(ATI, 0x15b3),
- .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
- { PCI_VDEVICE(ATI, 0x793b),
- .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
- { PCI_VDEVICE(ATI, 0x7919),
- .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
- { PCI_VDEVICE(ATI, 0x960f),
- .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
- { PCI_VDEVICE(ATI, 0x970f),
- .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
- { PCI_VDEVICE(ATI, 0x9840),
- .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
- { PCI_VDEVICE(ATI, 0xaa00),
- .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
- { PCI_VDEVICE(ATI, 0xaa08),
- .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
- { PCI_VDEVICE(ATI, 0xaa10),
- .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
- { PCI_VDEVICE(ATI, 0xaa18),
- .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
- { PCI_VDEVICE(ATI, 0xaa20),
- .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
- { PCI_VDEVICE(ATI, 0xaa28),
- .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
- { PCI_VDEVICE(ATI, 0xaa30),
- .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
- { PCI_VDEVICE(ATI, 0xaa38),
- .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
- { PCI_VDEVICE(ATI, 0xaa40),
- .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
- { PCI_VDEVICE(ATI, 0xaa48),
- .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
- { PCI_VDEVICE(ATI, 0xaa50),
- .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
- { PCI_VDEVICE(ATI, 0xaa58),
- .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
- { PCI_VDEVICE(ATI, 0xaa60),
- .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
- { PCI_VDEVICE(ATI, 0xaa68),
- .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
- { PCI_VDEVICE(ATI, 0xaa80),
- .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
- { PCI_VDEVICE(ATI, 0xaa88),
- .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
- { PCI_VDEVICE(ATI, 0xaa90),
- .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
- { PCI_VDEVICE(ATI, 0xaa98),
- .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
- { PCI_VDEVICE(ATI, 0x9902),
- .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
- { PCI_VDEVICE(ATI, 0xaaa0),
- .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
- { PCI_VDEVICE(ATI, 0xaaa8),
- .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
- { PCI_VDEVICE(ATI, 0xaab0),
- .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
- { PCI_VDEVICE(ATI, 0xaac0),
- .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
- AZX_DCAPS_PM_RUNTIME },
- { PCI_VDEVICE(ATI, 0xaac8),
- .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
- AZX_DCAPS_PM_RUNTIME },
- { PCI_VDEVICE(ATI, 0xaad8),
- .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
- AZX_DCAPS_PM_RUNTIME },
- { PCI_VDEVICE(ATI, 0xaae0),
- .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
- AZX_DCAPS_PM_RUNTIME },
- { PCI_VDEVICE(ATI, 0xaae8),
- .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
- AZX_DCAPS_PM_RUNTIME },
- { PCI_VDEVICE(ATI, 0xaaf0),
- .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
- AZX_DCAPS_PM_RUNTIME },
- { PCI_VDEVICE(ATI, 0xaaf8),
- .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
- AZX_DCAPS_PM_RUNTIME },
- { PCI_VDEVICE(ATI, 0xab00),
- .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
- AZX_DCAPS_PM_RUNTIME },
- { PCI_VDEVICE(ATI, 0xab08),
- .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
- AZX_DCAPS_PM_RUNTIME },
- { PCI_VDEVICE(ATI, 0xab10),
- .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
- AZX_DCAPS_PM_RUNTIME },
- { PCI_VDEVICE(ATI, 0xab18),
- .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
- AZX_DCAPS_PM_RUNTIME },
- { PCI_VDEVICE(ATI, 0xab20),
- .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
- AZX_DCAPS_PM_RUNTIME },
- { PCI_VDEVICE(ATI, 0xab28),
- .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
- AZX_DCAPS_PM_RUNTIME },
- { PCI_VDEVICE(ATI, 0xab30),
- .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
- AZX_DCAPS_PM_RUNTIME },
- { PCI_VDEVICE(ATI, 0xab38),
- .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
- AZX_DCAPS_PM_RUNTIME },
- { PCI_VDEVICE(ATI, 0xab40),
- .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
- AZX_DCAPS_PM_RUNTIME },
- /* GLENFLY */
- { PCI_DEVICE(PCI_VENDOR_ID_GLENFLY, PCI_ANY_ID),
- .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
- .class_mask = 0xffffff,
- .driver_data = AZX_DRIVER_GFHDMI | AZX_DCAPS_POSFIX_LPIB |
- AZX_DCAPS_NO_MSI | AZX_DCAPS_NO_64BIT },
- /* VIA VT8251/VT8237A */
- { PCI_VDEVICE(VIA, 0x3288), .driver_data = AZX_DRIVER_VIA },
- /* VIA GFX VT7122/VX900 */
- { PCI_VDEVICE(VIA, 0x9170), .driver_data = AZX_DRIVER_GENERIC },
- /* VIA GFX VT6122/VX11 */
- { PCI_VDEVICE(VIA, 0x9140), .driver_data = AZX_DRIVER_GENERIC },
- /* SIS966 */
- { PCI_VDEVICE(SI, 0x7502), .driver_data = AZX_DRIVER_SIS },
- /* ULI M5461 */
- { PCI_VDEVICE(AL, 0x5461), .driver_data = AZX_DRIVER_ULI },
- /* NVIDIA MCP */
- { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID),
- .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
- .class_mask = 0xffffff,
- .driver_data = AZX_DRIVER_NVIDIA | AZX_DCAPS_PRESET_NVIDIA },
- /* Teradici */
- { PCI_DEVICE(0x6549, 0x1200),
- .driver_data = AZX_DRIVER_TERA | AZX_DCAPS_NO_64BIT },
- { PCI_DEVICE(0x6549, 0x2200),
- .driver_data = AZX_DRIVER_TERA | AZX_DCAPS_NO_64BIT },
- /* Creative X-Fi (CA0110-IBG) */
- /* CTHDA chips */
- { PCI_VDEVICE(CREATIVE, 0x0010),
- .driver_data = AZX_DRIVER_CTHDA | AZX_DCAPS_PRESET_CTHDA },
- { PCI_VDEVICE(CREATIVE, 0x0012),
- .driver_data = AZX_DRIVER_CTHDA | AZX_DCAPS_PRESET_CTHDA },
-#if !IS_ENABLED(CONFIG_SND_CTXFI)
- /* the following entry conflicts with snd-ctxfi driver,
- * as ctxfi driver mutates from HD-audio to native mode with
- * a special command sequence.
- */
- { PCI_DEVICE(PCI_VENDOR_ID_CREATIVE, PCI_ANY_ID),
- .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
- .class_mask = 0xffffff,
- .driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND |
- AZX_DCAPS_NO_64BIT | AZX_DCAPS_POSFIX_LPIB },
-#else
- /* this entry seems still valid -- i.e. without emu20kx chip */
- { PCI_VDEVICE(CREATIVE, 0x0009),
- .driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND |
- AZX_DCAPS_NO_64BIT | AZX_DCAPS_POSFIX_LPIB },
-#endif
- /* CM8888 */
- { PCI_VDEVICE(CMEDIA, 0x5011),
- .driver_data = AZX_DRIVER_CMEDIA |
- AZX_DCAPS_NO_MSI | AZX_DCAPS_POSFIX_LPIB | AZX_DCAPS_SNOOP_OFF },
- /* Vortex86MX */
- { PCI_VDEVICE(RDC, 0x3010), .driver_data = AZX_DRIVER_GENERIC },
- /* VMware HDAudio */
- { PCI_VDEVICE(VMWARE, 0x1977), .driver_data = AZX_DRIVER_GENERIC },
- /* AMD/ATI Generic, PCI class code and Vendor ID for HD Audio */
- { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_ANY_ID),
- .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
- .class_mask = 0xffffff,
- .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_HDMI },
- { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_ANY_ID),
- .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
- .class_mask = 0xffffff,
- .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_HDMI },
- /* Zhaoxin */
- { PCI_VDEVICE(ZHAOXIN, 0x3288), .driver_data = AZX_DRIVER_ZHAOXIN },
- { PCI_VDEVICE(ZHAOXIN, 0x9141),
- .driver_data = AZX_DRIVER_ZHAOXINHDMI | AZX_DCAPS_POSFIX_LPIB |
- AZX_DCAPS_NO_MSI | AZX_DCAPS_NO_64BIT },
- { PCI_VDEVICE(ZHAOXIN, 0x9142),
- .driver_data = AZX_DRIVER_ZHAOXINHDMI | AZX_DCAPS_POSFIX_LPIB |
- AZX_DCAPS_NO_MSI | AZX_DCAPS_NO_64BIT },
- { PCI_VDEVICE(ZHAOXIN, 0x9144),
- .driver_data = AZX_DRIVER_ZHAOXINHDMI | AZX_DCAPS_POSFIX_LPIB |
- AZX_DCAPS_NO_MSI | AZX_DCAPS_NO_64BIT },
- { PCI_VDEVICE(ZHAOXIN, 0x9145),
- .driver_data = AZX_DRIVER_ZHAOXINHDMI | AZX_DCAPS_POSFIX_LPIB |
- AZX_DCAPS_NO_MSI | AZX_DCAPS_NO_64BIT },
- { PCI_VDEVICE(ZHAOXIN, 0x9146),
- .driver_data = AZX_DRIVER_ZHAOXINHDMI | AZX_DCAPS_POSFIX_LPIB |
- AZX_DCAPS_NO_MSI | AZX_DCAPS_NO_64BIT },
- /* Loongson HDAudio*/
- { PCI_VDEVICE(LOONGSON, PCI_DEVICE_ID_LOONGSON_HDA),
- .driver_data = AZX_DRIVER_LOONGSON | AZX_DCAPS_NO_TCSEL },
- { PCI_VDEVICE(LOONGSON, PCI_DEVICE_ID_LOONGSON_HDMI),
- .driver_data = AZX_DRIVER_LOONGSON | AZX_DCAPS_NO_TCSEL },
- { 0, }
-};
-MODULE_DEVICE_TABLE(pci, azx_ids);
-
-/* pci_driver definition */
-static struct pci_driver azx_driver = {
- .name = KBUILD_MODNAME,
- .id_table = azx_ids,
- .probe = azx_probe,
- .remove = azx_remove,
- .shutdown = azx_shutdown,
- .driver = {
- .pm = pm_ptr(&azx_pm),
- },
-};
-
-module_pci_driver(azx_driver);
diff --git a/sound/pci/hda/hda_intel.h b/sound/pci/hda/hda_intel.h
deleted file mode 100644
index 2d1725f86ef1..000000000000
--- a/sound/pci/hda/hda_intel.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- */
-#ifndef __SOUND_HDA_INTEL_H
-#define __SOUND_HDA_INTEL_H
-
-#include "hda_controller.h"
-
-struct hda_intel {
- struct azx chip;
-
- /* for pending irqs */
- struct work_struct irq_pending_work;
-
- /* sync probing */
- struct completion probe_wait;
- struct delayed_work probe_work;
-
- /* card list (for power_save trigger) */
- struct list_head list;
-
- /* extra flags */
- unsigned int irq_pending_warned:1;
- unsigned int probe_continued:1;
- unsigned int runtime_pm_disabled:1;
-
- /* vga_switcheroo setup */
- unsigned int use_vga_switcheroo:1;
- unsigned int vga_switcheroo_registered:1;
- unsigned int init_failed:1; /* delayed init failed */
- unsigned int freed:1; /* resources already released */
-
- bool need_i915_power:1; /* the hda controller needs i915 power */
-
- int probe_retry; /* being probe-retry */
-};
-
-#endif
diff --git a/sound/pci/hda/hda_intel_trace.h b/sound/pci/hda/hda_intel_trace.h
deleted file mode 100644
index 2775fa81a500..000000000000
--- a/sound/pci/hda/hda_intel_trace.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM hda_intel
-#define TRACE_INCLUDE_FILE hda_intel_trace
-
-#if !defined(_TRACE_HDA_INTEL_H) || defined(TRACE_HEADER_MULTI_READ)
-#define _TRACE_HDA_INTEL_H
-
-#include <linux/tracepoint.h>
-
-DECLARE_EVENT_CLASS(hda_pm,
- TP_PROTO(struct azx *chip),
-
- TP_ARGS(chip),
-
- TP_STRUCT__entry(
- __field(int, dev_index)
- ),
-
- TP_fast_assign(
- __entry->dev_index = (chip)->dev_index;
- ),
-
- TP_printk("card index: %d", __entry->dev_index)
-);
-
-DEFINE_EVENT(hda_pm, azx_suspend,
- TP_PROTO(struct azx *chip),
- TP_ARGS(chip)
-);
-
-DEFINE_EVENT(hda_pm, azx_resume,
- TP_PROTO(struct azx *chip),
- TP_ARGS(chip)
-);
-
-DEFINE_EVENT(hda_pm, azx_runtime_suspend,
- TP_PROTO(struct azx *chip),
- TP_ARGS(chip)
-);
-
-DEFINE_EVENT(hda_pm, azx_runtime_resume,
- TP_PROTO(struct azx *chip),
- TP_ARGS(chip)
-);
-
-#endif /* _TRACE_HDA_INTEL_H */
-
-/* This part must be outside protection */
-#undef TRACE_INCLUDE_PATH
-#define TRACE_INCLUDE_PATH .
-#include <trace/define_trace.h>
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c
deleted file mode 100644
index 7d7786df60ea..000000000000
--- a/sound/pci/hda/hda_jack.c
+++ /dev/null
@@ -1,770 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Jack-detection handling for HD-audio
- *
- * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>
- */
-
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/export.h>
-#include <sound/core.h>
-#include <sound/control.h>
-#include <sound/jack.h>
-#include <sound/hda_codec.h>
-#include "hda_local.h"
-#include "hda_auto_parser.h"
-#include "hda_jack.h"
-
-/**
- * is_jack_detectable - Check whether the given pin is jack-detectable
- * @codec: the HDA codec
- * @nid: pin NID
- *
- * Check whether the given pin is capable to report the jack detection.
- * The jack detection might not work by various reasons, e.g. the jack
- * detection is prohibited in the codec level, the pin config has
- * AC_DEFCFG_MISC_NO_PRESENCE bit, no unsol support, etc.
- */
-bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid)
-{
- if (codec->no_jack_detect)
- return false;
- if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT))
- return false;
- if (get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) &
- AC_DEFCFG_MISC_NO_PRESENCE)
- return false;
- if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) &&
- !codec->jackpoll_interval)
- return false;
- return true;
-}
-EXPORT_SYMBOL_GPL(is_jack_detectable);
-
-/* execute pin sense measurement */
-static u32 read_pin_sense(struct hda_codec *codec, hda_nid_t nid, int dev_id)
-{
- u32 pincap;
- u32 val;
-
- if (!codec->no_trigger_sense) {
- pincap = snd_hda_query_pin_caps(codec, nid);
- if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */
- snd_hda_codec_read(codec, nid, 0,
- AC_VERB_SET_PIN_SENSE, 0);
- }
- val = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_PIN_SENSE, dev_id);
- if (codec->inv_jack_detect)
- val ^= AC_PINSENSE_PRESENCE;
- return val;
-}
-
-/**
- * snd_hda_jack_tbl_get_mst - query the jack-table entry for the given NID
- * @codec: the HDA codec
- * @nid: pin NID to refer to
- * @dev_id: pin device entry id
- */
-struct hda_jack_tbl *
-snd_hda_jack_tbl_get_mst(struct hda_codec *codec, hda_nid_t nid, int dev_id)
-{
- struct hda_jack_tbl *jack = codec->jacktbl.list;
- int i;
-
- if (!nid || !jack)
- return NULL;
- for (i = 0; i < codec->jacktbl.used; i++, jack++)
- if (jack->nid == nid && jack->dev_id == dev_id)
- return jack;
- return NULL;
-}
-EXPORT_SYMBOL_GPL(snd_hda_jack_tbl_get_mst);
-
-/**
- * snd_hda_jack_tbl_get_from_tag - query the jack-table entry for the given tag
- * @codec: the HDA codec
- * @tag: tag value to refer to
- * @dev_id: pin device entry id
- */
-struct hda_jack_tbl *
-snd_hda_jack_tbl_get_from_tag(struct hda_codec *codec,
- unsigned char tag, int dev_id)
-{
- struct hda_jack_tbl *jack = codec->jacktbl.list;
- int i;
-
- if (!tag || !jack)
- return NULL;
- for (i = 0; i < codec->jacktbl.used; i++, jack++)
- if (jack->tag == tag && jack->dev_id == dev_id)
- return jack;
- return NULL;
-}
-EXPORT_SYMBOL_GPL(snd_hda_jack_tbl_get_from_tag);
-
-static struct hda_jack_tbl *
-any_jack_tbl_get_from_nid(struct hda_codec *codec, hda_nid_t nid)
-{
- struct hda_jack_tbl *jack = codec->jacktbl.list;
- int i;
-
- if (!nid || !jack)
- return NULL;
- for (i = 0; i < codec->jacktbl.used; i++, jack++)
- if (jack->nid == nid)
- return jack;
- return NULL;
-}
-
-/**
- * snd_hda_jack_tbl_new - create a jack-table entry for the given NID
- * @codec: the HDA codec
- * @nid: pin NID to assign
- * @dev_id: pin device entry id
- */
-static struct hda_jack_tbl *
-snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid, int dev_id)
-{
- struct hda_jack_tbl *jack =
- snd_hda_jack_tbl_get_mst(codec, nid, dev_id);
- struct hda_jack_tbl *existing_nid_jack =
- any_jack_tbl_get_from_nid(codec, nid);
-
- WARN_ON(dev_id != 0 && !codec->dp_mst);
-
- if (jack)
- return jack;
- jack = snd_array_new(&codec->jacktbl);
- if (!jack)
- return NULL;
- jack->nid = nid;
- jack->dev_id = dev_id;
- jack->jack_dirty = 1;
- if (existing_nid_jack) {
- jack->tag = existing_nid_jack->tag;
-
- /*
- * Copy jack_detect from existing_nid_jack to avoid
- * snd_hda_jack_detect_enable_callback_mst() making multiple
- * SET_UNSOLICITED_ENABLE calls on the same pin.
- */
- jack->jack_detect = existing_nid_jack->jack_detect;
- } else {
- jack->tag = codec->jacktbl.used;
- }
-
- return jack;
-}
-
-void snd_hda_jack_tbl_disconnect(struct hda_codec *codec)
-{
- struct hda_jack_tbl *jack = codec->jacktbl.list;
- int i;
-
- for (i = 0; i < codec->jacktbl.used; i++, jack++) {
- if (!codec->bus->shutdown && jack->jack)
- snd_device_disconnect(codec->card, jack->jack);
- }
-}
-
-void snd_hda_jack_tbl_clear(struct hda_codec *codec)
-{
- struct hda_jack_tbl *jack = codec->jacktbl.list;
- int i;
-
- for (i = 0; i < codec->jacktbl.used; i++, jack++) {
- struct hda_jack_callback *cb, *next;
-
- /* free jack instances manually when clearing/reconfiguring */
- if (!codec->bus->shutdown && jack->jack)
- snd_device_free(codec->card, jack->jack);
-
- for (cb = jack->callback; cb; cb = next) {
- next = cb->next;
- kfree(cb);
- }
- }
- snd_array_free(&codec->jacktbl);
-}
-
-#define get_jack_plug_state(sense) !!(sense & AC_PINSENSE_PRESENCE)
-
-/* update the cached value and notification flag if needed */
-static void jack_detect_update(struct hda_codec *codec,
- struct hda_jack_tbl *jack)
-{
- if (!jack->jack_dirty)
- return;
-
- if (jack->phantom_jack)
- jack->pin_sense = AC_PINSENSE_PRESENCE;
- else
- jack->pin_sense = read_pin_sense(codec, jack->nid,
- jack->dev_id);
-
- /* A gating jack indicates the jack is invalid if gating is unplugged */
- if (jack->gating_jack &&
- !snd_hda_jack_detect_mst(codec, jack->gating_jack, jack->dev_id))
- jack->pin_sense &= ~AC_PINSENSE_PRESENCE;
-
- jack->jack_dirty = 0;
-
- /* If a jack is gated by this one update it. */
- if (jack->gated_jack) {
- struct hda_jack_tbl *gated =
- snd_hda_jack_tbl_get_mst(codec, jack->gated_jack,
- jack->dev_id);
- if (gated) {
- gated->jack_dirty = 1;
- jack_detect_update(codec, gated);
- }
- }
-}
-
-/**
- * snd_hda_jack_set_dirty_all - Mark all the cached as dirty
- * @codec: the HDA codec
- *
- * This function sets the dirty flag to all entries of jack table.
- * It's called from the resume path in hda_codec.c.
- */
-void snd_hda_jack_set_dirty_all(struct hda_codec *codec)
-{
- struct hda_jack_tbl *jack = codec->jacktbl.list;
- int i;
-
- for (i = 0; i < codec->jacktbl.used; i++, jack++)
- if (jack->nid)
- jack->jack_dirty = 1;
-}
-EXPORT_SYMBOL_GPL(snd_hda_jack_set_dirty_all);
-
-/**
- * snd_hda_jack_pin_sense - execute pin sense measurement
- * @codec: the CODEC to sense
- * @nid: the pin NID to sense
- * @dev_id: pin device entry id
- *
- * Execute necessary pin sense measurement and return its Presence Detect,
- * Impedance, ELD Valid etc. status bits.
- */
-u32 snd_hda_jack_pin_sense(struct hda_codec *codec, hda_nid_t nid, int dev_id)
-{
- struct hda_jack_tbl *jack =
- snd_hda_jack_tbl_get_mst(codec, nid, dev_id);
- if (jack) {
- jack_detect_update(codec, jack);
- return jack->pin_sense;
- }
- return read_pin_sense(codec, nid, dev_id);
-}
-EXPORT_SYMBOL_GPL(snd_hda_jack_pin_sense);
-
-/**
- * snd_hda_jack_detect_state_mst - query pin Presence Detect status
- * @codec: the CODEC to sense
- * @nid: the pin NID to sense
- * @dev_id: pin device entry id
- *
- * Query and return the pin's Presence Detect status, as either
- * HDA_JACK_NOT_PRESENT, HDA_JACK_PRESENT or HDA_JACK_PHANTOM.
- */
-int snd_hda_jack_detect_state_mst(struct hda_codec *codec,
- hda_nid_t nid, int dev_id)
-{
- struct hda_jack_tbl *jack =
- snd_hda_jack_tbl_get_mst(codec, nid, dev_id);
- if (jack && jack->phantom_jack)
- return HDA_JACK_PHANTOM;
- else if (snd_hda_jack_pin_sense(codec, nid, dev_id) &
- AC_PINSENSE_PRESENCE)
- return HDA_JACK_PRESENT;
- else
- return HDA_JACK_NOT_PRESENT;
-}
-EXPORT_SYMBOL_GPL(snd_hda_jack_detect_state_mst);
-
-static struct hda_jack_callback *
-find_callback_from_list(struct hda_jack_tbl *jack,
- hda_jack_callback_fn func)
-{
- struct hda_jack_callback *cb;
-
- if (!func)
- return NULL;
-
- for (cb = jack->callback; cb; cb = cb->next) {
- if (cb->func == func)
- return cb;
- }
-
- return NULL;
-}
-
-/**
- * snd_hda_jack_detect_enable_callback_mst - enable the jack-detection
- * @codec: the HDA codec
- * @nid: pin NID to enable
- * @func: callback function to register
- * @dev_id: pin device entry id
- *
- * In the case of error, the return value will be a pointer embedded with
- * errno. Check and handle the return value appropriately with standard
- * macros such as @IS_ERR() and @PTR_ERR().
- */
-struct hda_jack_callback *
-snd_hda_jack_detect_enable_callback_mst(struct hda_codec *codec, hda_nid_t nid,
- int dev_id, hda_jack_callback_fn func)
-{
- struct hda_jack_tbl *jack;
- struct hda_jack_callback *callback = NULL;
- int err;
-
- jack = snd_hda_jack_tbl_new(codec, nid, dev_id);
- if (!jack)
- return ERR_PTR(-ENOMEM);
-
- callback = find_callback_from_list(jack, func);
-
- if (func && !callback) {
- callback = kzalloc(sizeof(*callback), GFP_KERNEL);
- if (!callback)
- return ERR_PTR(-ENOMEM);
- callback->func = func;
- callback->nid = jack->nid;
- callback->dev_id = jack->dev_id;
- callback->next = jack->callback;
- jack->callback = callback;
- }
-
- if (jack->jack_detect)
- return callback; /* already registered */
- jack->jack_detect = 1;
- if (codec->jackpoll_interval > 0)
- return callback; /* No unsol if we're polling instead */
- err = snd_hda_codec_write_cache(codec, nid, 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- AC_USRSP_EN | jack->tag);
- if (err < 0)
- return ERR_PTR(err);
- return callback;
-}
-EXPORT_SYMBOL_GPL(snd_hda_jack_detect_enable_callback_mst);
-
-/**
- * snd_hda_jack_detect_enable - Enable the jack detection on the given pin
- * @codec: the HDA codec
- * @nid: pin NID to enable jack detection
- * @dev_id: pin device entry id
- *
- * Enable the jack detection with the default callback. Returns zero if
- * successful or a negative error code.
- */
-int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid,
- int dev_id)
-{
- return PTR_ERR_OR_ZERO(snd_hda_jack_detect_enable_callback_mst(codec,
- nid,
- dev_id,
- NULL));
-}
-EXPORT_SYMBOL_GPL(snd_hda_jack_detect_enable);
-
-/**
- * snd_hda_jack_set_gating_jack - Set gating jack.
- * @codec: the HDA codec
- * @gated_nid: gated pin NID
- * @gating_nid: gating pin NID
- *
- * Indicates the gated jack is only valid when the gating jack is plugged.
- */
-int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid,
- hda_nid_t gating_nid)
-{
- struct hda_jack_tbl *gated = snd_hda_jack_tbl_new(codec, gated_nid, 0);
- struct hda_jack_tbl *gating =
- snd_hda_jack_tbl_new(codec, gating_nid, 0);
-
- WARN_ON(codec->dp_mst);
-
- if (!gated || !gating)
- return -EINVAL;
-
- gated->gating_jack = gating_nid;
- gating->gated_jack = gated_nid;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_jack_set_gating_jack);
-
-/**
- * snd_hda_jack_bind_keymap - bind keys generated from one NID to another jack.
- * @codec: the HDA codec
- * @key_nid: key event is generated by this pin NID
- * @keymap: map of key type and key code
- * @jack_nid: key reports to the jack of this pin NID
- *
- * This function is used in the case of key is generated from one NID while is
- * reported to the jack of another NID.
- */
-int snd_hda_jack_bind_keymap(struct hda_codec *codec, hda_nid_t key_nid,
- const struct hda_jack_keymap *keymap,
- hda_nid_t jack_nid)
-{
- const struct hda_jack_keymap *map;
- struct hda_jack_tbl *key_gen = snd_hda_jack_tbl_get(codec, key_nid);
- struct hda_jack_tbl *report_to = snd_hda_jack_tbl_get(codec, jack_nid);
-
- WARN_ON(codec->dp_mst);
-
- if (!key_gen || !report_to || !report_to->jack)
- return -EINVAL;
-
- key_gen->key_report_jack = jack_nid;
-
- if (keymap)
- for (map = keymap; map->type; map++)
- snd_jack_set_key(report_to->jack, map->type, map->key);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_jack_bind_keymap);
-
-/**
- * snd_hda_jack_set_button_state - report button event to the hda_jack_tbl button_state.
- * @codec: the HDA codec
- * @jack_nid: the button event reports to the jack_tbl of this NID
- * @button_state: the button event captured by codec
- *
- * Codec driver calls this function to report the button event.
- */
-void snd_hda_jack_set_button_state(struct hda_codec *codec, hda_nid_t jack_nid,
- int button_state)
-{
- struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, jack_nid);
-
- if (!jack)
- return;
-
- if (jack->key_report_jack) {
- struct hda_jack_tbl *report_to =
- snd_hda_jack_tbl_get(codec, jack->key_report_jack);
-
- if (report_to) {
- report_to->button_state = button_state;
- return;
- }
- }
-
- jack->button_state = button_state;
-}
-EXPORT_SYMBOL_GPL(snd_hda_jack_set_button_state);
-
-/**
- * snd_hda_jack_report_sync - sync the states of all jacks and report if changed
- * @codec: the HDA codec
- */
-void snd_hda_jack_report_sync(struct hda_codec *codec)
-{
- struct hda_jack_tbl *jack;
- int i, state;
-
- /* update all jacks at first */
- jack = codec->jacktbl.list;
- for (i = 0; i < codec->jacktbl.used; i++, jack++)
- if (jack->nid)
- jack_detect_update(codec, jack);
-
- /* report the updated jacks; it's done after updating all jacks
- * to make sure that all gating jacks properly have been set
- */
- jack = codec->jacktbl.list;
- for (i = 0; i < codec->jacktbl.used; i++, jack++)
- if (jack->nid) {
- if (!jack->jack || jack->block_report)
- continue;
- state = jack->button_state;
- if (get_jack_plug_state(jack->pin_sense))
- state |= jack->type;
- snd_jack_report(jack->jack, state);
- if (jack->button_state) {
- snd_jack_report(jack->jack,
- state & ~jack->button_state);
- jack->button_state = 0; /* button released */
- }
- }
-}
-EXPORT_SYMBOL_GPL(snd_hda_jack_report_sync);
-
-/* guess the jack type from the pin-config */
-static int get_input_jack_type(struct hda_codec *codec, hda_nid_t nid)
-{
- unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);
- switch (get_defcfg_device(def_conf)) {
- case AC_JACK_LINE_OUT:
- case AC_JACK_SPEAKER:
- return SND_JACK_LINEOUT;
- case AC_JACK_HP_OUT:
- return SND_JACK_HEADPHONE;
- case AC_JACK_SPDIF_OUT:
- case AC_JACK_DIG_OTHER_OUT:
- return SND_JACK_AVOUT;
- case AC_JACK_MIC_IN:
- return SND_JACK_MICROPHONE;
- default:
- return SND_JACK_LINEIN;
- }
-}
-
-static void hda_free_jack_priv(struct snd_jack *jack)
-{
- struct hda_jack_tbl *jacks = jack->private_data;
- jacks->nid = 0;
- jacks->jack = NULL;
-}
-
-/**
- * snd_hda_jack_add_kctl_mst - Add a kctl for the given pin
- * @codec: the HDA codec
- * @nid: pin NID to assign
- * @dev_id : pin device entry id
- * @name: string name for the jack
- * @phantom_jack: flag to deal as a phantom jack
- * @type: jack type bits to be reported, 0 for guessing from pincfg
- * @keymap: optional jack / key mapping
- *
- * This assigns a jack-detection kctl to the given pin. The kcontrol
- * will have the given name and index.
- */
-int snd_hda_jack_add_kctl_mst(struct hda_codec *codec, hda_nid_t nid,
- int dev_id, const char *name, bool phantom_jack,
- int type, const struct hda_jack_keymap *keymap)
-{
- struct hda_jack_tbl *jack;
- const struct hda_jack_keymap *map;
- int err, state, buttons;
-
- jack = snd_hda_jack_tbl_new(codec, nid, dev_id);
- if (!jack)
- return 0;
- if (jack->jack)
- return 0; /* already created */
-
- if (!type)
- type = get_input_jack_type(codec, nid);
-
- buttons = 0;
- if (keymap) {
- for (map = keymap; map->type; map++)
- buttons |= map->type;
- }
-
- err = snd_jack_new(codec->card, name, type | buttons,
- &jack->jack, true, phantom_jack);
- if (err < 0)
- return err;
-
- jack->phantom_jack = !!phantom_jack;
- jack->type = type;
- jack->button_state = 0;
- jack->jack->private_data = jack;
- jack->jack->private_free = hda_free_jack_priv;
- if (keymap) {
- for (map = keymap; map->type; map++)
- snd_jack_set_key(jack->jack, map->type, map->key);
- }
-
- state = snd_hda_jack_detect_mst(codec, nid, dev_id);
- snd_jack_report(jack->jack, state ? jack->type : 0);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_jack_add_kctl_mst);
-
-static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid,
- const struct auto_pin_cfg *cfg,
- const char *base_name)
-{
- unsigned int def_conf, conn;
- char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
- int err;
- bool phantom_jack;
-
- WARN_ON(codec->dp_mst);
-
- if (!nid)
- return 0;
- def_conf = snd_hda_codec_get_pincfg(codec, nid);
- conn = get_defcfg_connect(def_conf);
- if (conn == AC_JACK_PORT_NONE)
- return 0;
- phantom_jack = (conn != AC_JACK_PORT_COMPLEX) ||
- !is_jack_detectable(codec, nid);
-
- if (base_name)
- strscpy(name, base_name, sizeof(name));
- else
- snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), NULL);
- if (phantom_jack)
- /* Example final name: "Internal Mic Phantom Jack" */
- strncat(name, " Phantom", sizeof(name) - strlen(name) - 1);
- err = snd_hda_jack_add_kctl(codec, nid, name, phantom_jack, 0, NULL);
- if (err < 0)
- return err;
-
- if (!phantom_jack)
- return snd_hda_jack_detect_enable(codec, nid, 0);
- return 0;
-}
-
-/**
- * snd_hda_jack_add_kctls - Add kctls for all pins included in the given pincfg
- * @codec: the HDA codec
- * @cfg: pin config table to parse
- */
-int snd_hda_jack_add_kctls(struct hda_codec *codec,
- const struct auto_pin_cfg *cfg)
-{
- const hda_nid_t *p;
- int i, err;
-
- for (i = 0; i < cfg->num_inputs; i++) {
- /* If we have headphone mics; make sure they get the right name
- before grabbed by output pins */
- if (cfg->inputs[i].is_headphone_mic) {
- if (auto_cfg_hp_outs(cfg) == 1)
- err = add_jack_kctl(codec, auto_cfg_hp_pins(cfg)[0],
- cfg, "Headphone Mic");
- else
- err = add_jack_kctl(codec, cfg->inputs[i].pin,
- cfg, "Headphone Mic");
- } else
- err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg,
- NULL);
- if (err < 0)
- return err;
- }
-
- for (i = 0, p = cfg->line_out_pins; i < cfg->line_outs; i++, p++) {
- err = add_jack_kctl(codec, *p, cfg, NULL);
- if (err < 0)
- return err;
- }
- for (i = 0, p = cfg->hp_pins; i < cfg->hp_outs; i++, p++) {
- if (*p == *cfg->line_out_pins) /* might be duplicated */
- break;
- err = add_jack_kctl(codec, *p, cfg, NULL);
- if (err < 0)
- return err;
- }
- for (i = 0, p = cfg->speaker_pins; i < cfg->speaker_outs; i++, p++) {
- if (*p == *cfg->line_out_pins) /* might be duplicated */
- break;
- err = add_jack_kctl(codec, *p, cfg, NULL);
- if (err < 0)
- return err;
- }
- for (i = 0, p = cfg->dig_out_pins; i < cfg->dig_outs; i++, p++) {
- err = add_jack_kctl(codec, *p, cfg, NULL);
- if (err < 0)
- return err;
- }
- err = add_jack_kctl(codec, cfg->dig_in_pin, cfg, NULL);
- if (err < 0)
- return err;
- err = add_jack_kctl(codec, cfg->mono_out_pin, cfg, NULL);
- if (err < 0)
- return err;
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_jack_add_kctls);
-
-static void call_jack_callback(struct hda_codec *codec, unsigned int res,
- struct hda_jack_tbl *jack)
-{
- struct hda_jack_callback *cb;
-
- for (cb = jack->callback; cb; cb = cb->next) {
- cb->jack = jack;
- cb->unsol_res = res;
- cb->func(codec, cb);
- }
- if (jack->gated_jack) {
- struct hda_jack_tbl *gated =
- snd_hda_jack_tbl_get_mst(codec, jack->gated_jack,
- jack->dev_id);
- if (gated) {
- for (cb = gated->callback; cb; cb = cb->next) {
- cb->jack = gated;
- cb->unsol_res = res;
- cb->func(codec, cb);
- }
- }
- }
-}
-
-/**
- * snd_hda_jack_unsol_event - Handle an unsolicited event
- * @codec: the HDA codec
- * @res: the unsolicited event data
- */
-void snd_hda_jack_unsol_event(struct hda_codec *codec, unsigned int res)
-{
- struct hda_jack_tbl *event;
- int tag = (res & AC_UNSOL_RES_TAG) >> AC_UNSOL_RES_TAG_SHIFT;
-
- if (codec->dp_mst) {
- int dev_entry =
- (res & AC_UNSOL_RES_DE) >> AC_UNSOL_RES_DE_SHIFT;
-
- event = snd_hda_jack_tbl_get_from_tag(codec, tag, dev_entry);
- } else {
- event = snd_hda_jack_tbl_get_from_tag(codec, tag, 0);
- }
- if (!event)
- return;
-
- if (event->key_report_jack) {
- struct hda_jack_tbl *report_to =
- snd_hda_jack_tbl_get_mst(codec, event->key_report_jack,
- event->dev_id);
- if (report_to)
- report_to->jack_dirty = 1;
- } else
- event->jack_dirty = 1;
-
- call_jack_callback(codec, res, event);
- snd_hda_jack_report_sync(codec);
-}
-EXPORT_SYMBOL_GPL(snd_hda_jack_unsol_event);
-
-/**
- * snd_hda_jack_poll_all - Poll all jacks
- * @codec: the HDA codec
- *
- * Poll all detectable jacks with dirty flag, update the status, call
- * callbacks and call snd_hda_jack_report_sync() if any changes are found.
- */
-void snd_hda_jack_poll_all(struct hda_codec *codec)
-{
- struct hda_jack_tbl *jack = codec->jacktbl.list;
- int i, changes = 0;
-
- for (i = 0; i < codec->jacktbl.used; i++, jack++) {
- unsigned int old_sense;
- if (!jack->nid || !jack->jack_dirty || jack->phantom_jack)
- continue;
- old_sense = get_jack_plug_state(jack->pin_sense);
- jack_detect_update(codec, jack);
- if (old_sense == get_jack_plug_state(jack->pin_sense))
- continue;
- changes = 1;
- call_jack_callback(codec, 0, jack);
- }
- if (changes)
- snd_hda_jack_report_sync(codec);
-}
-EXPORT_SYMBOL_GPL(snd_hda_jack_poll_all);
-
diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h
deleted file mode 100644
index ff7d289c034b..000000000000
--- a/sound/pci/hda/hda_jack.h
+++ /dev/null
@@ -1,195 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Jack-detection handling for HD-audio
- *
- * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>
- */
-
-#ifndef __SOUND_HDA_JACK_H
-#define __SOUND_HDA_JACK_H
-
-#include <linux/err.h>
-#include <sound/jack.h>
-
-struct auto_pin_cfg;
-struct hda_jack_tbl;
-struct hda_jack_callback;
-
-typedef void (*hda_jack_callback_fn) (struct hda_codec *, struct hda_jack_callback *);
-
-struct hda_jack_callback {
- hda_nid_t nid;
- int dev_id;
- hda_jack_callback_fn func;
- unsigned int private_data; /* arbitrary data */
- unsigned int unsol_res; /* unsolicited event bits */
- struct hda_jack_tbl *jack; /* associated jack entry */
- struct hda_jack_callback *next;
-};
-
-struct hda_jack_tbl {
- hda_nid_t nid;
- int dev_id;
- unsigned char tag; /* unsol event tag */
- struct hda_jack_callback *callback;
- /* jack-detection stuff */
- unsigned int pin_sense; /* cached pin-sense value */
- unsigned int jack_detect:1; /* capable of jack-detection? */
- unsigned int jack_dirty:1; /* needs to update? */
- unsigned int phantom_jack:1; /* a fixed, always present port? */
- unsigned int block_report:1; /* in a transitional state - do not report to userspace */
- hda_nid_t gating_jack; /* valid when gating jack plugged */
- hda_nid_t gated_jack; /* gated is dependent on this jack */
- hda_nid_t key_report_jack; /* key reports to this jack */
- int type;
- int button_state;
- struct snd_jack *jack;
-};
-
-struct hda_jack_keymap {
- enum snd_jack_types type;
- int key;
-};
-
-struct hda_jack_tbl *
-snd_hda_jack_tbl_get_mst(struct hda_codec *codec, hda_nid_t nid, int dev_id);
-
-/**
- * snd_hda_jack_tbl_get - query the jack-table entry for the given NID
- * @codec: the HDA codec
- * @nid: pin NID to refer to
- */
-static inline struct hda_jack_tbl *
-snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid)
-{
- return snd_hda_jack_tbl_get_mst(codec, nid, 0);
-}
-
-struct hda_jack_tbl *
-snd_hda_jack_tbl_get_from_tag(struct hda_codec *codec,
- unsigned char tag, int dev_id);
-
-void snd_hda_jack_tbl_disconnect(struct hda_codec *codec);
-void snd_hda_jack_tbl_clear(struct hda_codec *codec);
-
-void snd_hda_jack_set_dirty_all(struct hda_codec *codec);
-
-int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid,
- int dev_id);
-
-struct hda_jack_callback *
-snd_hda_jack_detect_enable_callback_mst(struct hda_codec *codec, hda_nid_t nid,
- int dev_id, hda_jack_callback_fn func);
-
-/**
- * snd_hda_jack_detect_enable - enable the jack-detection
- * @codec: the HDA codec
- * @nid: pin NID to enable
- * @func: callback function to register
- *
- * In the case of error, the return value will be a pointer embedded with
- * errno. Check and handle the return value appropriately with standard
- * macros such as @IS_ERR() and @PTR_ERR().
- */
-static inline struct hda_jack_callback *
-snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid,
- hda_jack_callback_fn cb)
-{
- return snd_hda_jack_detect_enable_callback_mst(codec, nid, 0, cb);
-}
-
-int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid,
- hda_nid_t gating_nid);
-
-int snd_hda_jack_bind_keymap(struct hda_codec *codec, hda_nid_t key_nid,
- const struct hda_jack_keymap *keymap,
- hda_nid_t jack_nid);
-
-void snd_hda_jack_set_button_state(struct hda_codec *codec, hda_nid_t jack_nid,
- int button_state);
-
-u32 snd_hda_jack_pin_sense(struct hda_codec *codec, hda_nid_t nid, int dev_id);
-
-/* the jack state returned from snd_hda_jack_detect_state() */
-enum {
- HDA_JACK_NOT_PRESENT, HDA_JACK_PRESENT, HDA_JACK_PHANTOM,
-};
-
-int snd_hda_jack_detect_state_mst(struct hda_codec *codec, hda_nid_t nid,
- int dev_id);
-
-/**
- * snd_hda_jack_detect_state - query pin Presence Detect status
- * @codec: the CODEC to sense
- * @nid: the pin NID to sense
- *
- * Query and return the pin's Presence Detect status, as either
- * HDA_JACK_NOT_PRESENT, HDA_JACK_PRESENT or HDA_JACK_PHANTOM.
- */
-static inline int
-snd_hda_jack_detect_state(struct hda_codec *codec, hda_nid_t nid)
-{
- return snd_hda_jack_detect_state_mst(codec, nid, 0);
-}
-
-/**
- * snd_hda_jack_detect_mst - Detect the jack
- * @codec: the HDA codec
- * @nid: pin NID to check jack detection
- * @dev_id: pin device entry id
- */
-static inline bool
-snd_hda_jack_detect_mst(struct hda_codec *codec, hda_nid_t nid, int dev_id)
-{
- return snd_hda_jack_detect_state_mst(codec, nid, dev_id) !=
- HDA_JACK_NOT_PRESENT;
-}
-
-/**
- * snd_hda_jack_detect - Detect the jack
- * @codec: the HDA codec
- * @nid: pin NID to check jack detection
- */
-static inline bool
-snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid)
-{
- return snd_hda_jack_detect_mst(codec, nid, 0);
-}
-
-bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid);
-
-int snd_hda_jack_add_kctl_mst(struct hda_codec *codec, hda_nid_t nid,
- int dev_id, const char *name, bool phantom_jack,
- int type, const struct hda_jack_keymap *keymap);
-
-/**
- * snd_hda_jack_add_kctl - Add a kctl for the given pin
- * @codec: the HDA codec
- * @nid: pin NID to assign
- * @name: string name for the jack
- * @phantom_jack: flag to deal as a phantom jack
- * @type: jack type bits to be reported, 0 for guessing from pincfg
- * @keymap: optional jack / key mapping
- *
- * This assigns a jack-detection kctl to the given pin. The kcontrol
- * will have the given name and index.
- */
-static inline int
-snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
- const char *name, bool phantom_jack,
- int type, const struct hda_jack_keymap *keymap)
-{
- return snd_hda_jack_add_kctl_mst(codec, nid, 0,
- name, phantom_jack, type, keymap);
-}
-
-int snd_hda_jack_add_kctls(struct hda_codec *codec,
- const struct auto_pin_cfg *cfg);
-
-void snd_hda_jack_report_sync(struct hda_codec *codec);
-
-void snd_hda_jack_unsol_event(struct hda_codec *codec, unsigned int res);
-
-void snd_hda_jack_poll_all(struct hda_codec *codec);
-
-#endif /* __SOUND_HDA_JACK_H */
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
deleted file mode 100644
index 68c31f5354b7..000000000000
--- a/sound/pci/hda/hda_local.h
+++ /dev/null
@@ -1,720 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Universal Interface for Intel High Definition Audio Codec
- *
- * Local helper functions
- *
- * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
- */
-
-#ifndef __SOUND_HDA_LOCAL_H
-#define __SOUND_HDA_LOCAL_H
-
-#include <sound/pcm_drm_eld.h>
-
-/* We abuse kcontrol_new.subdev field to pass the NID corresponding to
- * the given new control. If id.subdev has a bit flag HDA_SUBDEV_NID_FLAG,
- * snd_hda_ctl_add() takes the lower-bit subdev value as a valid NID.
- *
- * Note that the subdevice field is cleared again before the real registration
- * in snd_hda_ctl_add(), so that this value won't appear in the outside.
- */
-#define HDA_SUBDEV_NID_FLAG (1U << 31)
-#define HDA_SUBDEV_AMP_FLAG (1U << 30)
-
-/*
- * for mixer controls
- */
-#define HDA_COMPOSE_AMP_VAL_OFS(nid,chs,idx,dir,ofs) \
- ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19) | ((ofs)<<23))
-#define HDA_AMP_VAL_MIN_MUTE (1<<29)
-#define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) \
- HDA_COMPOSE_AMP_VAL_OFS(nid, chs, idx, dir, 0)
-/* mono volume with index (index=0,1,...) (channel=1,2) */
-#define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, dir, flags) \
- { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \
- .subdevice = HDA_SUBDEV_AMP_FLAG, \
- .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
- SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
- SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \
- .info = snd_hda_mixer_amp_volume_info, \
- .get = snd_hda_mixer_amp_volume_get, \
- .put = snd_hda_mixer_amp_volume_put, \
- .tlv = { .c = snd_hda_mixer_amp_tlv }, \
- .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, dir) | flags }
-/* stereo volume with index */
-#define HDA_CODEC_VOLUME_IDX(xname, xcidx, nid, xindex, direction) \
- HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, 3, xindex, direction, 0)
-/* mono volume */
-#define HDA_CODEC_VOLUME_MONO(xname, nid, channel, xindex, direction) \
- HDA_CODEC_VOLUME_MONO_IDX(xname, 0, nid, channel, xindex, direction, 0)
-/* stereo volume */
-#define HDA_CODEC_VOLUME(xname, nid, xindex, direction) \
- HDA_CODEC_VOLUME_MONO(xname, nid, 3, xindex, direction)
-/* stereo volume with min=mute */
-#define HDA_CODEC_VOLUME_MIN_MUTE(xname, nid, xindex, direction) \
- HDA_CODEC_VOLUME_MONO_IDX(xname, 0, nid, 3, xindex, direction, \
- HDA_AMP_VAL_MIN_MUTE)
-/* mono mute switch with index (index=0,1,...) (channel=1,2) */
-#define HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \
- { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \
- .subdevice = HDA_SUBDEV_AMP_FLAG, \
- .info = snd_hda_mixer_amp_switch_info, \
- .get = snd_hda_mixer_amp_switch_get, \
- .put = snd_hda_mixer_amp_switch_put, \
- .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) }
-/* stereo mute switch with index */
-#define HDA_CODEC_MUTE_IDX(xname, xcidx, nid, xindex, direction) \
- HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, 3, xindex, direction)
-/* mono mute switch */
-#define HDA_CODEC_MUTE_MONO(xname, nid, channel, xindex, direction) \
- HDA_CODEC_MUTE_MONO_IDX(xname, 0, nid, channel, xindex, direction)
-/* stereo mute switch */
-#define HDA_CODEC_MUTE(xname, nid, xindex, direction) \
- HDA_CODEC_MUTE_MONO(xname, nid, 3, xindex, direction)
-#ifdef CONFIG_SND_HDA_INPUT_BEEP
-/* special beep mono mute switch with index (index=0,1,...) (channel=1,2) */
-#define HDA_CODEC_MUTE_BEEP_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \
- { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \
- .subdevice = HDA_SUBDEV_AMP_FLAG, \
- .info = snd_hda_mixer_amp_switch_info, \
- .get = snd_hda_mixer_amp_switch_get_beep, \
- .put = snd_hda_mixer_amp_switch_put_beep, \
- .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) }
-#else
-/* no digital beep - just the standard one */
-#define HDA_CODEC_MUTE_BEEP_MONO_IDX(xname, xcidx, nid, ch, xidx, dir) \
- HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, ch, xidx, dir)
-#endif /* CONFIG_SND_HDA_INPUT_BEEP */
-/* special beep mono mute switch */
-#define HDA_CODEC_MUTE_BEEP_MONO(xname, nid, channel, xindex, direction) \
- HDA_CODEC_MUTE_BEEP_MONO_IDX(xname, 0, nid, channel, xindex, direction)
-/* special beep stereo mute switch */
-#define HDA_CODEC_MUTE_BEEP(xname, nid, xindex, direction) \
- HDA_CODEC_MUTE_BEEP_MONO(xname, nid, 3, xindex, direction)
-
-extern const char *snd_hda_pcm_type_name[];
-
-int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo);
-int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol);
-int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol);
-int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
- unsigned int size, unsigned int __user *_tlv);
-int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo);
-int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol);
-int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol);
-#ifdef CONFIG_SND_HDA_INPUT_BEEP
-int snd_hda_mixer_amp_switch_get_beep(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol);
-int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol);
-#endif
-/* lowlevel accessor with caching; use carefully */
-#define snd_hda_codec_amp_read(codec, nid, ch, dir, idx) \
- snd_hdac_regmap_get_amp(&(codec)->core, nid, ch, dir, idx)
-int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid,
- int ch, int dir, int idx, int mask, int val);
-int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
- int direction, int idx, int mask, int val);
-int snd_hda_codec_amp_init(struct hda_codec *codec, hda_nid_t nid, int ch,
- int direction, int idx, int mask, int val);
-int snd_hda_codec_amp_init_stereo(struct hda_codec *codec, hda_nid_t nid,
- int dir, int idx, int mask, int val);
-void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
- unsigned int *tlv);
-struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
- const char *name);
-int __snd_hda_add_vmaster(struct hda_codec *codec, char *name,
- unsigned int *tlv, const char * const *followers,
- const char *suffix, bool init_follower_vol,
- unsigned int access, struct snd_kcontrol **ctl_ret);
-#define snd_hda_add_vmaster(codec, name, tlv, followers, suffix, access) \
- __snd_hda_add_vmaster(codec, name, tlv, followers, suffix, true, access, NULL)
-int snd_hda_codec_reset(struct hda_codec *codec);
-void snd_hda_codec_disconnect_pcms(struct hda_codec *codec);
-
-#define snd_hda_regmap_sync(codec) snd_hdac_regmap_sync(&(codec)->core)
-
-struct hda_vmaster_mute_hook {
- /* below two fields must be filled by the caller of
- * snd_hda_add_vmaster_hook() beforehand
- */
- struct snd_kcontrol *sw_kctl;
- void (*hook)(void *, int);
- /* below are initialized automatically */
- struct hda_codec *codec;
-};
-
-int snd_hda_add_vmaster_hook(struct hda_codec *codec,
- struct hda_vmaster_mute_hook *hook);
-void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook);
-
-/* amp value bits */
-#define HDA_AMP_MUTE 0x80
-#define HDA_AMP_UNMUTE 0x00
-#define HDA_AMP_VOLMASK 0x7f
-
-/*
- * SPDIF I/O
- */
-int snd_hda_create_dig_out_ctls(struct hda_codec *codec,
- hda_nid_t associated_nid,
- hda_nid_t cvt_nid, int type);
-#define snd_hda_create_spdif_out_ctls(codec, anid, cnid) \
- snd_hda_create_dig_out_ctls(codec, anid, cnid, HDA_PCM_TYPE_SPDIF)
-int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid);
-
-/*
- * input MUX helper
- */
-#define HDA_MAX_NUM_INPUTS 36
-struct hda_input_mux_item {
- char label[32];
- unsigned int index;
-};
-struct hda_input_mux {
- unsigned int num_items;
- struct hda_input_mux_item items[HDA_MAX_NUM_INPUTS];
-};
-
-int snd_hda_input_mux_info(const struct hda_input_mux *imux,
- struct snd_ctl_elem_info *uinfo);
-int snd_hda_input_mux_put(struct hda_codec *codec,
- const struct hda_input_mux *imux,
- struct snd_ctl_elem_value *ucontrol, hda_nid_t nid,
- unsigned int *cur_val);
-int snd_hda_add_imux_item(struct hda_codec *codec,
- struct hda_input_mux *imux, const char *label,
- int index, int *type_idx);
-
-/*
- * Multi-channel / digital-out PCM helper
- */
-
-enum { HDA_FRONT, HDA_REAR, HDA_CLFE, HDA_SIDE }; /* index for dac_nidx */
-enum { HDA_DIG_NONE, HDA_DIG_EXCLUSIVE, HDA_DIG_ANALOG_DUP }; /* dig_out_used */
-
-#define HDA_MAX_OUTS 5
-
-struct hda_multi_out {
- int num_dacs; /* # of DACs, must be more than 1 */
- const hda_nid_t *dac_nids; /* DAC list */
- hda_nid_t hp_nid; /* optional DAC for HP, 0 when not exists */
- hda_nid_t hp_out_nid[HDA_MAX_OUTS]; /* DACs for multiple HPs */
- hda_nid_t extra_out_nid[HDA_MAX_OUTS]; /* other (e.g. speaker) DACs */
- hda_nid_t dig_out_nid; /* digital out audio widget */
- const hda_nid_t *follower_dig_outs;
- int max_channels; /* currently supported analog channels */
- int dig_out_used; /* current usage of digital out (HDA_DIG_XXX) */
- int no_share_stream; /* don't share a stream with multiple pins */
- int share_spdif; /* share SPDIF pin */
- /* PCM information for both analog and SPDIF DACs */
- unsigned int analog_rates;
- unsigned int analog_maxbps;
- u64 analog_formats;
- unsigned int spdif_rates;
- unsigned int spdif_maxbps;
- u64 spdif_formats;
-};
-
-int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
- struct hda_multi_out *mout);
-int snd_hda_multi_out_dig_open(struct hda_codec *codec,
- struct hda_multi_out *mout);
-int snd_hda_multi_out_dig_close(struct hda_codec *codec,
- struct hda_multi_out *mout);
-int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
- struct hda_multi_out *mout,
- unsigned int stream_tag,
- unsigned int format,
- struct snd_pcm_substream *substream);
-int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec,
- struct hda_multi_out *mout);
-int snd_hda_multi_out_analog_open(struct hda_codec *codec,
- struct hda_multi_out *mout,
- struct snd_pcm_substream *substream,
- struct hda_pcm_stream *hinfo);
-int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
- struct hda_multi_out *mout,
- unsigned int stream_tag,
- unsigned int format,
- struct snd_pcm_substream *substream);
-int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
- struct hda_multi_out *mout);
-
-/*
- * generic proc interface
- */
-#ifdef CONFIG_SND_PROC_FS
-int snd_hda_codec_proc_new(struct hda_codec *codec);
-#else
-static inline int snd_hda_codec_proc_new(struct hda_codec *codec) { return 0; }
-#endif
-
-#define SND_PRINT_BITS_ADVISED_BUFSIZE 16
-void snd_print_pcm_bits(int pcm, char *buf, int buflen);
-
-/*
- * Misc
- */
-int snd_hda_add_new_ctls(struct hda_codec *codec,
- const struct snd_kcontrol_new *knew);
-
-/*
- * Fix-up pin default configurations and add default verbs
- */
-
-struct hda_pintbl {
- hda_nid_t nid;
- u32 val;
-};
-
-struct hda_model_fixup {
- const int id;
- const char *name;
-};
-
-struct hda_fixup {
- int type;
- bool chained:1; /* call the chained fixup(s) after this */
- bool chained_before:1; /* call the chained fixup(s) before this */
- int chain_id;
- union {
- const struct hda_pintbl *pins;
- const struct hda_verb *verbs;
- void (*func)(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action);
- } v;
-};
-
-/*
- * extended form of snd_pci_quirk:
- * for PCI SSID matching, use SND_PCI_QUIRK() like before;
- * for codec SSID matching, use the new HDA_CODEC_QUIRK() instead
- */
-struct hda_quirk {
- unsigned short subvendor; /* PCI subvendor ID */
- unsigned short subdevice; /* PCI subdevice ID */
- unsigned short subdevice_mask; /* bitmask to match */
- bool match_codec_ssid; /* match only with codec SSID */
- int value; /* value */
-#ifdef CONFIG_SND_DEBUG_VERBOSE
- const char *name; /* name of the device (optional) */
-#endif
-};
-
-#ifdef CONFIG_SND_DEBUG_VERBOSE
-#define HDA_CODEC_QUIRK(vend, dev, xname, val) \
- { _SND_PCI_QUIRK_ID(vend, dev), .value = (val), .name = (xname),\
- .match_codec_ssid = true }
-#else
-#define HDA_CODEC_QUIRK(vend, dev, xname, val) \
- { _SND_PCI_QUIRK_ID(vend, dev), .value = (val), \
- .match_codec_ssid = true }
-#endif
-
-struct snd_hda_pin_quirk {
- unsigned int codec; /* Codec vendor/device ID */
- unsigned short subvendor; /* PCI subvendor ID */
- const struct hda_pintbl *pins; /* list of matching pins */
-#ifdef CONFIG_SND_DEBUG_VERBOSE
- const char *name;
-#endif
- int value; /* quirk value */
-};
-
-#ifdef CONFIG_SND_DEBUG_VERBOSE
-
-#define SND_HDA_PIN_QUIRK(_codec, _subvendor, _name, _value, _pins...) \
- { .codec = _codec,\
- .subvendor = _subvendor,\
- .name = _name,\
- .value = _value,\
- .pins = (const struct hda_pintbl[]) { _pins, {0, 0}} \
- }
-#else
-
-#define SND_HDA_PIN_QUIRK(_codec, _subvendor, _name, _value, _pins...) \
- { .codec = _codec,\
- .subvendor = _subvendor,\
- .value = _value,\
- .pins = (const struct hda_pintbl[]) { _pins, {0, 0}} \
- }
-
-#endif
-
-#define HDA_FIXUP_ID_NOT_SET -1
-#define HDA_FIXUP_ID_NO_FIXUP -2
-
-/* fixup types */
-enum {
- HDA_FIXUP_INVALID,
- HDA_FIXUP_PINS,
- HDA_FIXUP_VERBS,
- HDA_FIXUP_FUNC,
- HDA_FIXUP_PINCTLS,
-};
-
-/* fixup action definitions */
-enum {
- HDA_FIXUP_ACT_PRE_PROBE,
- HDA_FIXUP_ACT_PROBE,
- HDA_FIXUP_ACT_INIT,
- HDA_FIXUP_ACT_BUILD,
- HDA_FIXUP_ACT_FREE,
-};
-
-int snd_hda_add_verbs(struct hda_codec *codec, const struct hda_verb *list);
-void snd_hda_apply_verbs(struct hda_codec *codec);
-void snd_hda_apply_pincfgs(struct hda_codec *codec,
- const struct hda_pintbl *cfg);
-void snd_hda_apply_fixup(struct hda_codec *codec, int action);
-void __snd_hda_apply_fixup(struct hda_codec *codec, int id, int action, int depth);
-void snd_hda_pick_fixup(struct hda_codec *codec,
- const struct hda_model_fixup *models,
- const struct hda_quirk *quirk,
- const struct hda_fixup *fixlist);
-void snd_hda_pick_pin_fixup(struct hda_codec *codec,
- const struct snd_hda_pin_quirk *pin_quirk,
- const struct hda_fixup *fixlist,
- bool match_all_pins);
-
-/* helper macros to retrieve pin default-config values */
-#define get_defcfg_connect(cfg) \
- ((cfg & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT)
-#define get_defcfg_association(cfg) \
- ((cfg & AC_DEFCFG_DEF_ASSOC) >> AC_DEFCFG_ASSOC_SHIFT)
-#define get_defcfg_location(cfg) \
- ((cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT)
-#define get_defcfg_sequence(cfg) \
- (cfg & AC_DEFCFG_SEQUENCE)
-#define get_defcfg_device(cfg) \
- ((cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT)
-#define get_defcfg_misc(cfg) \
- ((cfg & AC_DEFCFG_MISC) >> AC_DEFCFG_MISC_SHIFT)
-
-/* amp values */
-#define AMP_IN_MUTE(idx) (0x7080 | ((idx)<<8))
-#define AMP_IN_UNMUTE(idx) (0x7000 | ((idx)<<8))
-#define AMP_OUT_MUTE 0xb080
-#define AMP_OUT_UNMUTE 0xb000
-#define AMP_OUT_ZERO 0xb000
-/* pinctl values */
-#define PIN_IN (AC_PINCTL_IN_EN)
-#define PIN_VREFHIZ (AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ)
-#define PIN_VREF50 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_50)
-#define PIN_VREFGRD (AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD)
-#define PIN_VREF80 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_80)
-#define PIN_VREF100 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_100)
-#define PIN_OUT (AC_PINCTL_OUT_EN)
-#define PIN_HP (AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN)
-#define PIN_HP_AMP (AC_PINCTL_HP_EN)
-
-unsigned int snd_hda_get_default_vref(struct hda_codec *codec, hda_nid_t pin);
-unsigned int snd_hda_correct_pin_ctl(struct hda_codec *codec,
- hda_nid_t pin, unsigned int val);
-int _snd_hda_set_pin_ctl(struct hda_codec *codec, hda_nid_t pin,
- unsigned int val, bool cached);
-
-/**
- * _snd_hda_set_pin_ctl - Set a pin-control value safely
- * @codec: the codec instance
- * @pin: the pin NID to set the control
- * @val: the pin-control value (AC_PINCTL_* bits)
- *
- * This function sets the pin-control value to the given pin, but
- * filters out the invalid pin-control bits when the pin has no such
- * capabilities. For example, when PIN_HP is passed but the pin has no
- * HP-drive capability, the HP bit is omitted.
- *
- * The function doesn't check the input VREF capability bits, though.
- * Use snd_hda_get_default_vref() to guess the right value.
- * Also, this function is only for analog pins, not for HDMI pins.
- */
-static inline int
-snd_hda_set_pin_ctl(struct hda_codec *codec, hda_nid_t pin, unsigned int val)
-{
- return _snd_hda_set_pin_ctl(codec, pin, val, false);
-}
-
-/**
- * snd_hda_set_pin_ctl_cache - Set a pin-control value safely
- * @codec: the codec instance
- * @pin: the pin NID to set the control
- * @val: the pin-control value (AC_PINCTL_* bits)
- *
- * Just like snd_hda_set_pin_ctl() but write to cache as well.
- */
-static inline int
-snd_hda_set_pin_ctl_cache(struct hda_codec *codec, hda_nid_t pin,
- unsigned int val)
-{
- return _snd_hda_set_pin_ctl(codec, pin, val, true);
-}
-
-int snd_hda_codec_get_pin_target(struct hda_codec *codec, hda_nid_t nid);
-int snd_hda_codec_set_pin_target(struct hda_codec *codec, hda_nid_t nid,
- unsigned int val);
-
-#define for_each_hda_codec_node(nid, codec) \
- for ((nid) = (codec)->core.start_nid; (nid) < (codec)->core.end_nid; (nid)++)
-
-/* Set the codec power_state flag to indicate to allow unsol event handling;
- * see hda_codec_unsol_event() in hda_bind.c. Calling this might confuse the
- * state tracking, so use with care.
- */
-static inline void snd_hda_codec_allow_unsol_events(struct hda_codec *codec)
-{
- codec->core.dev.power.power_state = PMSG_ON;
-}
-
-/*
- * get widget capabilities
- */
-static inline u32 get_wcaps(struct hda_codec *codec, hda_nid_t nid)
-{
- if (nid < codec->core.start_nid ||
- nid >= codec->core.start_nid + codec->core.num_nodes)
- return 0;
- return codec->wcaps[nid - codec->core.start_nid];
-}
-
-/* get the widget type from widget capability bits */
-static inline int get_wcaps_type(unsigned int wcaps)
-{
- if (!wcaps)
- return -1; /* invalid type */
- return (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
-}
-
-static inline unsigned int get_wcaps_channels(u32 wcaps)
-{
- unsigned int chans;
-
- chans = (wcaps & AC_WCAP_CHAN_CNT_EXT) >> 13;
- chans = ((chans << 1) | 1) + 1;
-
- return chans;
-}
-
-static inline void snd_hda_override_wcaps(struct hda_codec *codec,
- hda_nid_t nid, u32 val)
-{
- if (nid >= codec->core.start_nid &&
- nid < codec->core.start_nid + codec->core.num_nodes)
- codec->wcaps[nid - codec->core.start_nid] = val;
-}
-
-u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction);
-int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
- unsigned int caps);
-/**
- * snd_hda_query_pin_caps - Query PIN capabilities
- * @codec: the HD-auio codec
- * @nid: the NID to query
- *
- * Query PIN capabilities for the given widget.
- * Returns the obtained capability bits.
- *
- * When cap bits have been already read, this doesn't read again but
- * returns the cached value.
- */
-static inline u32
-snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
-{
- return snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
-
-}
-
-/**
- * snd_hda_override_pin_caps - Override the pin capabilities
- * @codec: the CODEC
- * @nid: the NID to override
- * @caps: the capability bits to set
- *
- * Override the cached PIN capabilitiy bits value by the given one.
- *
- * Returns zero if successful or a negative error code.
- */
-static inline int
-snd_hda_override_pin_caps(struct hda_codec *codec, hda_nid_t nid,
- unsigned int caps)
-{
- return snd_hdac_override_parm(&codec->core, nid, AC_PAR_PIN_CAP, caps);
-}
-
-bool snd_hda_check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
- int dir, unsigned int bits);
-
-#define nid_has_mute(codec, nid, dir) \
- snd_hda_check_amp_caps(codec, nid, dir, (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE))
-#define nid_has_volume(codec, nid, dir) \
- snd_hda_check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS)
-
-
-/* flags for hda_nid_item */
-#define HDA_NID_ITEM_AMP (1<<0)
-
-struct hda_nid_item {
- struct snd_kcontrol *kctl;
- unsigned int index;
- hda_nid_t nid;
- unsigned short flags;
-};
-
-int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid,
- struct snd_kcontrol *kctl);
-void snd_hda_ctls_clear(struct hda_codec *codec);
-
-/*
- * hwdep interface
- */
-#ifdef CONFIG_SND_HDA_HWDEP
-int snd_hda_create_hwdep(struct hda_codec *codec);
-#else
-static inline int snd_hda_create_hwdep(struct hda_codec *codec) { return 0; }
-#endif
-
-void snd_hda_sysfs_init(struct hda_codec *codec);
-void snd_hda_sysfs_clear(struct hda_codec *codec);
-
-extern const struct attribute_group *snd_hda_dev_attr_groups[];
-
-#ifdef CONFIG_SND_HDA_RECONFIG
-const char *snd_hda_get_hint(struct hda_codec *codec, const char *key);
-int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key);
-int snd_hda_get_int_hint(struct hda_codec *codec, const char *key, int *valp);
-#else
-static inline
-const char *snd_hda_get_hint(struct hda_codec *codec, const char *key)
-{
- return NULL;
-}
-
-static inline
-int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key)
-{
- return -ENOENT;
-}
-
-static inline
-int snd_hda_get_int_hint(struct hda_codec *codec, const char *key, int *valp)
-{
- return -ENOENT;
-}
-#endif
-
-/*
- * power-management
- */
-
-void snd_hda_schedule_power_save(struct hda_codec *codec);
-
-struct hda_amp_list {
- hda_nid_t nid;
- unsigned char dir;
- unsigned char idx;
-};
-
-struct hda_loopback_check {
- const struct hda_amp_list *amplist;
- int power_on;
-};
-
-int snd_hda_check_amp_list_power(struct hda_codec *codec,
- struct hda_loopback_check *check,
- hda_nid_t nid);
-
-/* check whether the actual power state matches with the target state */
-static inline bool
-snd_hda_check_power_state(struct hda_codec *codec, hda_nid_t nid,
- unsigned int target_state)
-{
- return snd_hdac_check_power_state(&codec->core, nid, target_state);
-}
-
-static inline unsigned int snd_hda_sync_power_state(struct hda_codec *codec,
- hda_nid_t nid,
- unsigned int target_state)
-{
- return snd_hdac_sync_power_state(&codec->core, nid, target_state);
-}
-unsigned int snd_hda_codec_eapd_power_filter(struct hda_codec *codec,
- hda_nid_t nid,
- unsigned int power_state);
-
-void snd_hda_codec_shutdown(struct hda_codec *codec);
-
-/*
- * AMP control callbacks
- */
-/* retrieve parameters from private_value */
-#define get_amp_nid_(pv) ((pv) & 0xffff)
-#define get_amp_nid(kc) get_amp_nid_((kc)->private_value)
-#define get_amp_channels(kc) (((kc)->private_value >> 16) & 0x3)
-#define get_amp_direction_(pv) (((pv) >> 18) & 0x1)
-#define get_amp_direction(kc) get_amp_direction_((kc)->private_value)
-#define get_amp_index_(pv) (((pv) >> 19) & 0xf)
-#define get_amp_index(kc) get_amp_index_((kc)->private_value)
-#define get_amp_offset(kc) (((kc)->private_value >> 23) & 0x3f)
-#define get_amp_min_mute(kc) (((kc)->private_value >> 29) & 0x1)
-
-/*
- * enum control helper
- */
-int snd_hda_enum_helper_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo,
- int num_items, const char * const *texts);
-#define snd_hda_enum_bool_helper_info(kcontrol, uinfo) \
- snd_hda_enum_helper_info(kcontrol, uinfo, 0, NULL)
-
-struct hdmi_eld {
- bool monitor_present;
- bool eld_valid;
- int eld_size;
- char eld_buffer[ELD_MAX_SIZE];
- struct snd_parsed_hdmi_eld info;
-};
-
-int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid);
-int snd_hdmi_get_eld(struct hda_codec *codec, hda_nid_t nid,
- unsigned char *buf, int *eld_size);
-void snd_hdmi_eld_update_pcm_info(struct snd_parsed_hdmi_eld *e,
- struct hda_pcm_stream *hinfo);
-
-int snd_hdmi_get_eld_ati(struct hda_codec *codec, hda_nid_t nid,
- unsigned char *buf, int *eld_size,
- bool rev3_or_later);
-
-#ifdef CONFIG_SND_PROC_FS
-void snd_hdmi_print_eld_info(struct hdmi_eld *eld,
- struct snd_info_buffer *buffer,
- hda_nid_t pin_nid, int dev_id, hda_nid_t cvt_nid);
-void snd_hdmi_write_eld_info(struct hdmi_eld *eld,
- struct snd_info_buffer *buffer);
-#endif
-
-#define SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE 80
-void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen);
-
-void snd_hda_codec_display_power(struct hda_codec *codec, bool enable);
-
-/*
- */
-#define codec_err(codec, fmt, args...) \
- dev_err(hda_codec_dev(codec), fmt, ##args)
-#define codec_warn(codec, fmt, args...) \
- dev_warn(hda_codec_dev(codec), fmt, ##args)
-#define codec_info(codec, fmt, args...) \
- dev_info(hda_codec_dev(codec), fmt, ##args)
-#define codec_dbg(codec, fmt, args...) \
- dev_dbg(hda_codec_dev(codec), fmt, ##args)
-
-#endif /* __SOUND_HDA_LOCAL_H */
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c
deleted file mode 100644
index 00c2eeb2c472..000000000000
--- a/sound/pci/hda/hda_proc.c
+++ /dev/null
@@ -1,948 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Universal Interface for Intel High Definition Audio Codec
- *
- * Generic proc interface
- *
- * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
- */
-
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <sound/core.h>
-#include <linux/module.h>
-#include <sound/hda_codec.h>
-#include "hda_local.h"
-
-static int dump_coef = -1;
-module_param(dump_coef, int, 0644);
-MODULE_PARM_DESC(dump_coef, "Dump processing coefficients in codec proc file (-1=auto, 0=disable, 1=enable)");
-
-/* always use noncached version */
-#define param_read(codec, nid, parm) \
- snd_hdac_read_parm_uncached(&(codec)->core, nid, parm)
-
-static const char *get_wid_type_name(unsigned int wid_value)
-{
- static const char * const names[16] = {
- [AC_WID_AUD_OUT] = "Audio Output",
- [AC_WID_AUD_IN] = "Audio Input",
- [AC_WID_AUD_MIX] = "Audio Mixer",
- [AC_WID_AUD_SEL] = "Audio Selector",
- [AC_WID_PIN] = "Pin Complex",
- [AC_WID_POWER] = "Power Widget",
- [AC_WID_VOL_KNB] = "Volume Knob Widget",
- [AC_WID_BEEP] = "Beep Generator Widget",
- [AC_WID_VENDOR] = "Vendor Defined Widget",
- };
- if (wid_value == -1)
- return "UNKNOWN Widget";
- wid_value &= 0xf;
- if (names[wid_value])
- return names[wid_value];
- else
- return "UNKNOWN Widget";
-}
-
-static void print_nid_array(struct snd_info_buffer *buffer,
- struct hda_codec *codec, hda_nid_t nid,
- struct snd_array *array)
-{
- int i;
- struct hda_nid_item *items = array->list, *item;
- struct snd_kcontrol *kctl;
- for (i = 0; i < array->used; i++) {
- item = &items[i];
- if (item->nid == nid) {
- kctl = item->kctl;
- snd_iprintf(buffer,
- " Control: name=\"%s\", index=%i, device=%i\n",
- kctl->id.name, kctl->id.index + item->index,
- kctl->id.device);
- if (item->flags & HDA_NID_ITEM_AMP)
- snd_iprintf(buffer,
- " ControlAmp: chs=%lu, dir=%s, "
- "idx=%lu, ofs=%lu\n",
- get_amp_channels(kctl),
- get_amp_direction(kctl) ? "Out" : "In",
- get_amp_index(kctl),
- get_amp_offset(kctl));
- }
- }
-}
-
-static void print_nid_pcms(struct snd_info_buffer *buffer,
- struct hda_codec *codec, hda_nid_t nid)
-{
- int type;
- struct hda_pcm *cpcm;
-
- list_for_each_entry(cpcm, &codec->pcm_list_head, list) {
- for (type = 0; type < 2; type++) {
- if (cpcm->stream[type].nid != nid || cpcm->pcm == NULL)
- continue;
- snd_iprintf(buffer, " Device: name=\"%s\", "
- "type=\"%s\", device=%i\n",
- cpcm->name,
- snd_hda_pcm_type_name[cpcm->pcm_type],
- cpcm->pcm->device);
- }
- }
-}
-
-static void print_amp_caps(struct snd_info_buffer *buffer,
- struct hda_codec *codec, hda_nid_t nid, int dir)
-{
- unsigned int caps;
- caps = param_read(codec, nid, dir == HDA_OUTPUT ?
- AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP);
- if (caps == -1 || caps == 0) {
- snd_iprintf(buffer, "N/A\n");
- return;
- }
- snd_iprintf(buffer, "ofs=0x%02x, nsteps=0x%02x, stepsize=0x%02x, "
- "mute=%x\n",
- caps & AC_AMPCAP_OFFSET,
- (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT,
- (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT,
- (caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT);
-}
-
-/* is this a stereo widget or a stereo-to-mono mix? */
-static bool is_stereo_amps(struct hda_codec *codec, hda_nid_t nid,
- int dir, unsigned int wcaps, int indices)
-{
- hda_nid_t conn;
-
- if (wcaps & AC_WCAP_STEREO)
- return true;
- /* check for a stereo-to-mono mix; it must be:
- * only a single connection, only for input, and only a mixer widget
- */
- if (indices != 1 || dir != HDA_INPUT ||
- get_wcaps_type(wcaps) != AC_WID_AUD_MIX)
- return false;
-
- if (snd_hda_get_raw_connections(codec, nid, &conn, 1) < 0)
- return false;
- /* the connection source is a stereo? */
- wcaps = snd_hda_param_read(codec, conn, AC_PAR_AUDIO_WIDGET_CAP);
- return !!(wcaps & AC_WCAP_STEREO);
-}
-
-static void print_amp_vals(struct snd_info_buffer *buffer,
- struct hda_codec *codec, hda_nid_t nid,
- int dir, unsigned int wcaps, int indices)
-{
- unsigned int val;
- bool stereo;
- int i;
-
- stereo = is_stereo_amps(codec, nid, dir, wcaps, indices);
-
- dir = dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
- for (i = 0; i < indices; i++) {
- snd_iprintf(buffer, " [");
- val = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_AMP_GAIN_MUTE,
- AC_AMP_GET_LEFT | dir | i);
- snd_iprintf(buffer, "0x%02x", val);
- if (stereo) {
- val = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_AMP_GAIN_MUTE,
- AC_AMP_GET_RIGHT | dir | i);
- snd_iprintf(buffer, " 0x%02x", val);
- }
- snd_iprintf(buffer, "]");
- }
- snd_iprintf(buffer, "\n");
-}
-
-static void print_pcm_rates(struct snd_info_buffer *buffer, unsigned int pcm)
-{
- static const unsigned int rates[] = {
- 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
- 96000, 176400, 192000, 384000
- };
- int i;
-
- pcm &= AC_SUPPCM_RATES;
- snd_iprintf(buffer, " rates [0x%x]:", pcm);
- for (i = 0; i < ARRAY_SIZE(rates); i++)
- if (pcm & (1 << i))
- snd_iprintf(buffer, " %d", rates[i]);
- snd_iprintf(buffer, "\n");
-}
-
-static void print_pcm_bits(struct snd_info_buffer *buffer, unsigned int pcm)
-{
- char buf[SND_PRINT_BITS_ADVISED_BUFSIZE];
-
- snd_iprintf(buffer, " bits [0x%x]:", (pcm >> 16) & 0xff);
- snd_print_pcm_bits(pcm, buf, sizeof(buf));
- snd_iprintf(buffer, "%s\n", buf);
-}
-
-static void print_pcm_formats(struct snd_info_buffer *buffer,
- unsigned int streams)
-{
- snd_iprintf(buffer, " formats [0x%x]:", streams & 0xf);
- if (streams & AC_SUPFMT_PCM)
- snd_iprintf(buffer, " PCM");
- if (streams & AC_SUPFMT_FLOAT32)
- snd_iprintf(buffer, " FLOAT");
- if (streams & AC_SUPFMT_AC3)
- snd_iprintf(buffer, " AC3");
- snd_iprintf(buffer, "\n");
-}
-
-static void print_pcm_caps(struct snd_info_buffer *buffer,
- struct hda_codec *codec, hda_nid_t nid)
-{
- unsigned int pcm = param_read(codec, nid, AC_PAR_PCM);
- unsigned int stream = param_read(codec, nid, AC_PAR_STREAM);
- if (pcm == -1 || stream == -1) {
- snd_iprintf(buffer, "N/A\n");
- return;
- }
- print_pcm_rates(buffer, pcm);
- print_pcm_bits(buffer, pcm);
- print_pcm_formats(buffer, stream);
-}
-
-static const char *get_jack_connection(u32 cfg)
-{
- static const char * const names[16] = {
- "Unknown", "1/8", "1/4", "ATAPI",
- "RCA", "Optical","Digital", "Analog",
- "DIN", "XLR", "RJ11", "Comb",
- NULL, NULL, NULL, "Other"
- };
- cfg = (cfg & AC_DEFCFG_CONN_TYPE) >> AC_DEFCFG_CONN_TYPE_SHIFT;
- if (names[cfg])
- return names[cfg];
- else
- return "UNKNOWN";
-}
-
-static const char *get_jack_color(u32 cfg)
-{
- static const char * const names[16] = {
- "Unknown", "Black", "Grey", "Blue",
- "Green", "Red", "Orange", "Yellow",
- "Purple", "Pink", NULL, NULL,
- NULL, NULL, "White", "Other",
- };
- cfg = (cfg & AC_DEFCFG_COLOR) >> AC_DEFCFG_COLOR_SHIFT;
- if (names[cfg])
- return names[cfg];
- else
- return "UNKNOWN";
-}
-
-/*
- * Parse the pin default config value and returns the string of the
- * jack location, e.g. "Rear", "Front", etc.
- */
-static const char *get_jack_location(u32 cfg)
-{
- static const char * const bases[7] = {
- "N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom",
- };
- static const unsigned char specials_idx[] = {
- 0x07, 0x08,
- 0x17, 0x18, 0x19,
- 0x37, 0x38
- };
- static const char * const specials[] = {
- "Rear Panel", "Drive Bar",
- "Riser", "HDMI", "ATAPI",
- "Mobile-In", "Mobile-Out"
- };
- int i;
-
- cfg = (cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT;
- if ((cfg & 0x0f) < 7)
- return bases[cfg & 0x0f];
- for (i = 0; i < ARRAY_SIZE(specials_idx); i++) {
- if (cfg == specials_idx[i])
- return specials[i];
- }
- return "UNKNOWN";
-}
-
-/*
- * Parse the pin default config value and returns the string of the
- * jack connectivity, i.e. external or internal connection.
- */
-static const char *get_jack_connectivity(u32 cfg)
-{
- static const char * const jack_locations[4] = {
- "Ext", "Int", "Sep", "Oth"
- };
-
- return jack_locations[(cfg >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3];
-}
-
-/*
- * Parse the pin default config value and returns the string of the
- * jack type, i.e. the purpose of the jack, such as Line-Out or CD.
- */
-static const char *get_jack_type(u32 cfg)
-{
- static const char * const jack_types[16] = {
- "Line Out", "Speaker", "HP Out", "CD",
- "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand",
- "Line In", "Aux", "Mic", "Telephony",
- "SPDIF In", "Digital In", "Reserved", "Other"
- };
-
- return jack_types[(cfg & AC_DEFCFG_DEVICE)
- >> AC_DEFCFG_DEVICE_SHIFT];
-}
-
-static void print_pin_caps(struct snd_info_buffer *buffer,
- struct hda_codec *codec, hda_nid_t nid,
- int *supports_vref)
-{
- static const char * const jack_conns[4] = {
- "Jack", "N/A", "Fixed", "Both"
- };
- unsigned int caps, val;
-
- caps = param_read(codec, nid, AC_PAR_PIN_CAP);
- snd_iprintf(buffer, " Pincap 0x%08x:", caps);
- if (caps & AC_PINCAP_IN)
- snd_iprintf(buffer, " IN");
- if (caps & AC_PINCAP_OUT)
- snd_iprintf(buffer, " OUT");
- if (caps & AC_PINCAP_HP_DRV)
- snd_iprintf(buffer, " HP");
- if (caps & AC_PINCAP_EAPD)
- snd_iprintf(buffer, " EAPD");
- if (caps & AC_PINCAP_PRES_DETECT)
- snd_iprintf(buffer, " Detect");
- if (caps & AC_PINCAP_BALANCE)
- snd_iprintf(buffer, " Balanced");
- if (caps & AC_PINCAP_HDMI) {
- /* Realtek uses this bit as a different meaning */
- if ((codec->core.vendor_id >> 16) == 0x10ec)
- snd_iprintf(buffer, " R/L");
- else {
- if (caps & AC_PINCAP_HBR)
- snd_iprintf(buffer, " HBR");
- snd_iprintf(buffer, " HDMI");
- }
- }
- if (caps & AC_PINCAP_DP)
- snd_iprintf(buffer, " DP");
- if (caps & AC_PINCAP_TRIG_REQ)
- snd_iprintf(buffer, " Trigger");
- if (caps & AC_PINCAP_IMP_SENSE)
- snd_iprintf(buffer, " ImpSense");
- snd_iprintf(buffer, "\n");
- if (caps & AC_PINCAP_VREF) {
- unsigned int vref =
- (caps & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
- snd_iprintf(buffer, " Vref caps:");
- if (vref & AC_PINCAP_VREF_HIZ)
- snd_iprintf(buffer, " HIZ");
- if (vref & AC_PINCAP_VREF_50)
- snd_iprintf(buffer, " 50");
- if (vref & AC_PINCAP_VREF_GRD)
- snd_iprintf(buffer, " GRD");
- if (vref & AC_PINCAP_VREF_80)
- snd_iprintf(buffer, " 80");
- if (vref & AC_PINCAP_VREF_100)
- snd_iprintf(buffer, " 100");
- snd_iprintf(buffer, "\n");
- *supports_vref = 1;
- } else
- *supports_vref = 0;
- if (caps & AC_PINCAP_EAPD) {
- val = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_EAPD_BTLENABLE, 0);
- snd_iprintf(buffer, " EAPD 0x%x:", val);
- if (val & AC_EAPDBTL_BALANCED)
- snd_iprintf(buffer, " BALANCED");
- if (val & AC_EAPDBTL_EAPD)
- snd_iprintf(buffer, " EAPD");
- if (val & AC_EAPDBTL_LR_SWAP)
- snd_iprintf(buffer, " R/L");
- snd_iprintf(buffer, "\n");
- }
- caps = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
- snd_iprintf(buffer, " Pin Default 0x%08x: [%s] %s at %s %s\n", caps,
- jack_conns[(caps & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT],
- get_jack_type(caps),
- get_jack_connectivity(caps),
- get_jack_location(caps));
- snd_iprintf(buffer, " Conn = %s, Color = %s\n",
- get_jack_connection(caps),
- get_jack_color(caps));
- /* Default association and sequence values refer to default grouping
- * of pin complexes and their sequence within the group. This is used
- * for priority and resource allocation.
- */
- snd_iprintf(buffer, " DefAssociation = 0x%x, Sequence = 0x%x\n",
- (caps & AC_DEFCFG_DEF_ASSOC) >> AC_DEFCFG_ASSOC_SHIFT,
- caps & AC_DEFCFG_SEQUENCE);
- if (((caps & AC_DEFCFG_MISC) >> AC_DEFCFG_MISC_SHIFT) &
- AC_DEFCFG_MISC_NO_PRESENCE) {
- /* Miscellaneous bit indicates external hardware does not
- * support presence detection even if the pin complex
- * indicates it is supported.
- */
- snd_iprintf(buffer, " Misc = NO_PRESENCE\n");
- }
-}
-
-static void print_pin_ctls(struct snd_info_buffer *buffer,
- struct hda_codec *codec, hda_nid_t nid,
- int supports_vref)
-{
- unsigned int pinctls;
-
- pinctls = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
- snd_iprintf(buffer, " Pin-ctls: 0x%02x:", pinctls);
- if (pinctls & AC_PINCTL_IN_EN)
- snd_iprintf(buffer, " IN");
- if (pinctls & AC_PINCTL_OUT_EN)
- snd_iprintf(buffer, " OUT");
- if (pinctls & AC_PINCTL_HP_EN)
- snd_iprintf(buffer, " HP");
- if (supports_vref) {
- int vref = pinctls & AC_PINCTL_VREFEN;
- switch (vref) {
- case AC_PINCTL_VREF_HIZ:
- snd_iprintf(buffer, " VREF_HIZ");
- break;
- case AC_PINCTL_VREF_50:
- snd_iprintf(buffer, " VREF_50");
- break;
- case AC_PINCTL_VREF_GRD:
- snd_iprintf(buffer, " VREF_GRD");
- break;
- case AC_PINCTL_VREF_80:
- snd_iprintf(buffer, " VREF_80");
- break;
- case AC_PINCTL_VREF_100:
- snd_iprintf(buffer, " VREF_100");
- break;
- }
- }
- snd_iprintf(buffer, "\n");
-}
-
-static void print_vol_knob(struct snd_info_buffer *buffer,
- struct hda_codec *codec, hda_nid_t nid)
-{
- unsigned int cap = param_read(codec, nid, AC_PAR_VOL_KNB_CAP);
- snd_iprintf(buffer, " Volume-Knob: delta=%d, steps=%d, ",
- (cap >> 7) & 1, cap & 0x7f);
- cap = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_VOLUME_KNOB_CONTROL, 0);
- snd_iprintf(buffer, "direct=%d, val=%d\n",
- (cap >> 7) & 1, cap & 0x7f);
-}
-
-static void print_audio_io(struct snd_info_buffer *buffer,
- struct hda_codec *codec, hda_nid_t nid,
- unsigned int wid_type)
-{
- int conv = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0);
- snd_iprintf(buffer,
- " Converter: stream=%d, channel=%d\n",
- (conv & AC_CONV_STREAM) >> AC_CONV_STREAM_SHIFT,
- conv & AC_CONV_CHANNEL);
-
- if (wid_type == AC_WID_AUD_IN && (conv & AC_CONV_CHANNEL) == 0) {
- int sdi = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_SDI_SELECT, 0);
- snd_iprintf(buffer, " SDI-Select: %d\n",
- sdi & AC_SDI_SELECT);
- }
-}
-
-static void print_digital_conv(struct snd_info_buffer *buffer,
- struct hda_codec *codec, hda_nid_t nid)
-{
- unsigned int digi1 = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_DIGI_CONVERT_1, 0);
- unsigned char digi2 = digi1 >> 8;
- unsigned char digi3 = digi1 >> 16;
-
- snd_iprintf(buffer, " Digital:");
- if (digi1 & AC_DIG1_ENABLE)
- snd_iprintf(buffer, " Enabled");
- if (digi1 & AC_DIG1_V)
- snd_iprintf(buffer, " Validity");
- if (digi1 & AC_DIG1_VCFG)
- snd_iprintf(buffer, " ValidityCfg");
- if (digi1 & AC_DIG1_EMPHASIS)
- snd_iprintf(buffer, " Preemphasis");
- if (digi1 & AC_DIG1_COPYRIGHT)
- snd_iprintf(buffer, " Non-Copyright");
- if (digi1 & AC_DIG1_NONAUDIO)
- snd_iprintf(buffer, " Non-Audio");
- if (digi1 & AC_DIG1_PROFESSIONAL)
- snd_iprintf(buffer, " Pro");
- if (digi1 & AC_DIG1_LEVEL)
- snd_iprintf(buffer, " GenLevel");
- if (digi3 & AC_DIG3_KAE)
- snd_iprintf(buffer, " KAE");
- snd_iprintf(buffer, "\n");
- snd_iprintf(buffer, " Digital category: 0x%x\n",
- digi2 & AC_DIG2_CC);
- snd_iprintf(buffer, " IEC Coding Type: 0x%x\n",
- digi3 & AC_DIG3_ICT);
-}
-
-static const char *get_pwr_state(u32 state)
-{
- static const char * const buf[] = {
- "D0", "D1", "D2", "D3", "D3cold"
- };
- if (state < ARRAY_SIZE(buf))
- return buf[state];
- return "UNKNOWN";
-}
-
-static void print_power_state(struct snd_info_buffer *buffer,
- struct hda_codec *codec, hda_nid_t nid)
-{
- static const char * const names[] = {
- [ilog2(AC_PWRST_D0SUP)] = "D0",
- [ilog2(AC_PWRST_D1SUP)] = "D1",
- [ilog2(AC_PWRST_D2SUP)] = "D2",
- [ilog2(AC_PWRST_D3SUP)] = "D3",
- [ilog2(AC_PWRST_D3COLDSUP)] = "D3cold",
- [ilog2(AC_PWRST_S3D3COLDSUP)] = "S3D3cold",
- [ilog2(AC_PWRST_CLKSTOP)] = "CLKSTOP",
- [ilog2(AC_PWRST_EPSS)] = "EPSS",
- };
-
- int sup = param_read(codec, nid, AC_PAR_POWER_STATE);
- int pwr = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_POWER_STATE, 0);
- if (sup != -1) {
- int i;
-
- snd_iprintf(buffer, " Power states: ");
- for (i = 0; i < ARRAY_SIZE(names); i++) {
- if (sup & (1U << i))
- snd_iprintf(buffer, " %s", names[i]);
- }
- snd_iprintf(buffer, "\n");
- }
-
- snd_iprintf(buffer, " Power: setting=%s, actual=%s",
- get_pwr_state(pwr & AC_PWRST_SETTING),
- get_pwr_state((pwr & AC_PWRST_ACTUAL) >>
- AC_PWRST_ACTUAL_SHIFT));
- if (pwr & AC_PWRST_ERROR)
- snd_iprintf(buffer, ", Error");
- if (pwr & AC_PWRST_CLK_STOP_OK)
- snd_iprintf(buffer, ", Clock-stop-OK");
- if (pwr & AC_PWRST_SETTING_RESET)
- snd_iprintf(buffer, ", Setting-reset");
- snd_iprintf(buffer, "\n");
-}
-
-static void print_unsol_cap(struct snd_info_buffer *buffer,
- struct hda_codec *codec, hda_nid_t nid)
-{
- int unsol = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_UNSOLICITED_RESPONSE, 0);
- snd_iprintf(buffer,
- " Unsolicited: tag=%02x, enabled=%d\n",
- unsol & AC_UNSOL_TAG,
- (unsol & AC_UNSOL_ENABLED) ? 1 : 0);
-}
-
-static inline bool can_dump_coef(struct hda_codec *codec)
-{
- switch (dump_coef) {
- case 0: return false;
- case 1: return true;
- default: return codec->dump_coef;
- }
-}
-
-static void print_proc_caps(struct snd_info_buffer *buffer,
- struct hda_codec *codec, hda_nid_t nid)
-{
- unsigned int i, ncoeff, oldindex;
- unsigned int proc_caps = param_read(codec, nid, AC_PAR_PROC_CAP);
- ncoeff = (proc_caps & AC_PCAP_NUM_COEF) >> AC_PCAP_NUM_COEF_SHIFT;
- snd_iprintf(buffer, " Processing caps: benign=%d, ncoeff=%d\n",
- proc_caps & AC_PCAP_BENIGN, ncoeff);
-
- if (!can_dump_coef(codec))
- return;
-
- /* Note: This is racy - another process could run in parallel and change
- the coef index too. */
- oldindex = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_COEF_INDEX, 0);
- for (i = 0; i < ncoeff; i++) {
- unsigned int val;
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_COEF_INDEX, i);
- val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PROC_COEF,
- 0);
- snd_iprintf(buffer, " Coeff 0x%02x: 0x%04x\n", i, val);
- }
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_COEF_INDEX, oldindex);
-}
-
-static void print_conn_list(struct snd_info_buffer *buffer,
- struct hda_codec *codec, hda_nid_t nid,
- unsigned int wid_type, hda_nid_t *conn,
- int conn_len)
-{
- int c, curr = -1;
- const hda_nid_t *list;
- int cache_len;
-
- if (conn_len > 1 &&
- wid_type != AC_WID_AUD_MIX &&
- wid_type != AC_WID_VOL_KNB &&
- wid_type != AC_WID_POWER)
- curr = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_CONNECT_SEL, 0);
- snd_iprintf(buffer, " Connection: %d\n", conn_len);
- if (conn_len > 0) {
- snd_iprintf(buffer, " ");
- for (c = 0; c < conn_len; c++) {
- snd_iprintf(buffer, " 0x%02x", conn[c]);
- if (c == curr)
- snd_iprintf(buffer, "*");
- }
- snd_iprintf(buffer, "\n");
- }
-
- /* Get Cache connections info */
- cache_len = snd_hda_get_conn_list(codec, nid, &list);
- if (cache_len >= 0 && (cache_len != conn_len ||
- memcmp(list, conn, conn_len) != 0)) {
- snd_iprintf(buffer, " In-driver Connection: %d\n", cache_len);
- if (cache_len > 0) {
- snd_iprintf(buffer, " ");
- for (c = 0; c < cache_len; c++)
- snd_iprintf(buffer, " 0x%02x", list[c]);
- snd_iprintf(buffer, "\n");
- }
- }
-}
-
-static void print_gpio(struct snd_info_buffer *buffer,
- struct hda_codec *codec, hda_nid_t nid)
-{
- unsigned int gpio =
- param_read(codec, codec->core.afg, AC_PAR_GPIO_CAP);
- unsigned int enable, direction, wake, unsol, sticky, data;
- int i, max;
- snd_iprintf(buffer, "GPIO: io=%d, o=%d, i=%d, "
- "unsolicited=%d, wake=%d\n",
- gpio & AC_GPIO_IO_COUNT,
- (gpio & AC_GPIO_O_COUNT) >> AC_GPIO_O_COUNT_SHIFT,
- (gpio & AC_GPIO_I_COUNT) >> AC_GPIO_I_COUNT_SHIFT,
- (gpio & AC_GPIO_UNSOLICITED) ? 1 : 0,
- (gpio & AC_GPIO_WAKE) ? 1 : 0);
- max = gpio & AC_GPIO_IO_COUNT;
- if (!max || max > 8)
- return;
- enable = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_GPIO_MASK, 0);
- direction = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_GPIO_DIRECTION, 0);
- wake = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_GPIO_WAKE_MASK, 0);
- unsol = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_GPIO_UNSOLICITED_RSP_MASK, 0);
- sticky = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_GPIO_STICKY_MASK, 0);
- data = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_GPIO_DATA, 0);
- for (i = 0; i < max; ++i)
- snd_iprintf(buffer,
- " IO[%d]: enable=%d, dir=%d, wake=%d, "
- "sticky=%d, data=%d, unsol=%d\n", i,
- (enable & (1<<i)) ? 1 : 0,
- (direction & (1<<i)) ? 1 : 0,
- (wake & (1<<i)) ? 1 : 0,
- (sticky & (1<<i)) ? 1 : 0,
- (data & (1<<i)) ? 1 : 0,
- (unsol & (1<<i)) ? 1 : 0);
- /* FIXME: add GPO and GPI pin information */
- print_nid_array(buffer, codec, nid, &codec->mixers);
- print_nid_array(buffer, codec, nid, &codec->nids);
-}
-
-static void print_dpmst_connections(struct snd_info_buffer *buffer, struct hda_codec *codec,
- hda_nid_t nid, int dev_num)
-{
- int c, conn_len, curr, dev_id_saved;
- hda_nid_t *conn;
-
- conn_len = snd_hda_get_num_raw_conns(codec, nid);
- if (conn_len <= 0)
- return;
-
- conn = kmalloc_array(conn_len, sizeof(hda_nid_t), GFP_KERNEL);
- if (!conn)
- return;
-
- dev_id_saved = snd_hda_get_dev_select(codec, nid);
-
- snd_hda_set_dev_select(codec, nid, dev_num);
- curr = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0);
- if (snd_hda_get_raw_connections(codec, nid, conn, conn_len) < 0)
- goto out;
-
- for (c = 0; c < conn_len; c++) {
- snd_iprintf(buffer, " 0x%02x", conn[c]);
- if (c == curr)
- snd_iprintf(buffer, "*");
- }
-
-out:
- kfree(conn);
- snd_hda_set_dev_select(codec, nid, dev_id_saved);
-}
-
-static void print_device_list(struct snd_info_buffer *buffer,
- struct hda_codec *codec, hda_nid_t nid)
-{
- int i, curr = -1;
- u8 dev_list[AC_MAX_DEV_LIST_LEN];
- int devlist_len;
-
- devlist_len = snd_hda_get_devices(codec, nid, dev_list,
- AC_MAX_DEV_LIST_LEN);
- snd_iprintf(buffer, " Devices: %d\n", devlist_len);
- if (devlist_len <= 0)
- return;
-
- curr = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_DEVICE_SEL, 0);
-
- for (i = 0; i < devlist_len; i++) {
- if (i == curr)
- snd_iprintf(buffer, " *");
- else
- snd_iprintf(buffer, " ");
-
- snd_iprintf(buffer,
- "Dev %02d: PD = %d, ELDV = %d, IA = %d, Connections [", i,
- !!(dev_list[i] & AC_DE_PD),
- !!(dev_list[i] & AC_DE_ELDV),
- !!(dev_list[i] & AC_DE_IA));
-
- print_dpmst_connections(buffer, codec, nid, i);
-
- snd_iprintf(buffer, " ]\n");
- }
-}
-
-static void print_codec_core_info(struct hdac_device *codec,
- struct snd_info_buffer *buffer)
-{
- snd_iprintf(buffer, "Codec: ");
- if (codec->vendor_name && codec->chip_name)
- snd_iprintf(buffer, "%s %s\n",
- codec->vendor_name, codec->chip_name);
- else
- snd_iprintf(buffer, "Not Set\n");
- snd_iprintf(buffer, "Address: %d\n", codec->addr);
- if (codec->afg)
- snd_iprintf(buffer, "AFG Function Id: 0x%x (unsol %u)\n",
- codec->afg_function_id, codec->afg_unsol);
- if (codec->mfg)
- snd_iprintf(buffer, "MFG Function Id: 0x%x (unsol %u)\n",
- codec->mfg_function_id, codec->mfg_unsol);
- snd_iprintf(buffer, "Vendor Id: 0x%08x\n", codec->vendor_id);
- snd_iprintf(buffer, "Subsystem Id: 0x%08x\n", codec->subsystem_id);
- snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id);
-
- if (codec->mfg)
- snd_iprintf(buffer, "Modem Function Group: 0x%x\n", codec->mfg);
- else
- snd_iprintf(buffer, "No Modem Function Group found\n");
-}
-
-static void print_codec_info(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- struct hda_codec *codec = entry->private_data;
- hda_nid_t nid, fg;
- int i, nodes;
-
- print_codec_core_info(&codec->core, buffer);
- fg = codec->core.afg;
- if (!fg)
- return;
- snd_hda_power_up(codec);
- snd_iprintf(buffer, "Default PCM:\n");
- print_pcm_caps(buffer, codec, fg);
- snd_iprintf(buffer, "Default Amp-In caps: ");
- print_amp_caps(buffer, codec, fg, HDA_INPUT);
- snd_iprintf(buffer, "Default Amp-Out caps: ");
- print_amp_caps(buffer, codec, fg, HDA_OUTPUT);
- snd_iprintf(buffer, "State of AFG node 0x%02x:\n", fg);
- print_power_state(buffer, codec, fg);
-
- nodes = snd_hda_get_sub_nodes(codec, fg, &nid);
- if (! nid || nodes < 0) {
- snd_iprintf(buffer, "Invalid AFG subtree\n");
- snd_hda_power_down(codec);
- return;
- }
-
- print_gpio(buffer, codec, fg);
- if (codec->proc_widget_hook)
- codec->proc_widget_hook(buffer, codec, fg);
-
- for (i = 0; i < nodes; i++, nid++) {
- unsigned int wid_caps =
- param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
- unsigned int wid_type = get_wcaps_type(wid_caps);
- hda_nid_t *conn = NULL;
- int conn_len = 0;
-
- snd_iprintf(buffer, "Node 0x%02x [%s] wcaps 0x%x:", nid,
- get_wid_type_name(wid_type), wid_caps);
- if (wid_caps & AC_WCAP_STEREO) {
- unsigned int chans = get_wcaps_channels(wid_caps);
- if (chans == 2)
- snd_iprintf(buffer, " Stereo");
- else
- snd_iprintf(buffer, " %d-Channels", chans);
- } else
- snd_iprintf(buffer, " Mono");
- if (wid_caps & AC_WCAP_DIGITAL)
- snd_iprintf(buffer, " Digital");
- if (wid_caps & AC_WCAP_IN_AMP)
- snd_iprintf(buffer, " Amp-In");
- if (wid_caps & AC_WCAP_OUT_AMP)
- snd_iprintf(buffer, " Amp-Out");
- if (wid_caps & AC_WCAP_STRIPE)
- snd_iprintf(buffer, " Stripe");
- if (wid_caps & AC_WCAP_LR_SWAP)
- snd_iprintf(buffer, " R/L");
- if (wid_caps & AC_WCAP_CP_CAPS)
- snd_iprintf(buffer, " CP");
- snd_iprintf(buffer, "\n");
-
- print_nid_array(buffer, codec, nid, &codec->mixers);
- print_nid_array(buffer, codec, nid, &codec->nids);
- print_nid_pcms(buffer, codec, nid);
-
- /* volume knob is a special widget that always have connection
- * list
- */
- if (wid_type == AC_WID_VOL_KNB)
- wid_caps |= AC_WCAP_CONN_LIST;
-
- if (wid_caps & AC_WCAP_CONN_LIST) {
- conn_len = snd_hda_get_num_raw_conns(codec, nid);
- if (conn_len > 0) {
- conn = kmalloc_array(conn_len,
- sizeof(hda_nid_t),
- GFP_KERNEL);
- if (!conn)
- return;
- if (snd_hda_get_raw_connections(codec, nid, conn,
- conn_len) < 0)
- conn_len = 0;
- }
- }
-
- if (wid_caps & AC_WCAP_IN_AMP) {
- snd_iprintf(buffer, " Amp-In caps: ");
- print_amp_caps(buffer, codec, nid, HDA_INPUT);
- snd_iprintf(buffer, " Amp-In vals: ");
- if (wid_type == AC_WID_PIN ||
- (codec->single_adc_amp &&
- wid_type == AC_WID_AUD_IN))
- print_amp_vals(buffer, codec, nid, HDA_INPUT,
- wid_caps, 1);
- else
- print_amp_vals(buffer, codec, nid, HDA_INPUT,
- wid_caps, conn_len);
- }
- if (wid_caps & AC_WCAP_OUT_AMP) {
- snd_iprintf(buffer, " Amp-Out caps: ");
- print_amp_caps(buffer, codec, nid, HDA_OUTPUT);
- snd_iprintf(buffer, " Amp-Out vals: ");
- if (wid_type == AC_WID_PIN &&
- codec->pin_amp_workaround)
- print_amp_vals(buffer, codec, nid, HDA_OUTPUT,
- wid_caps, conn_len);
- else
- print_amp_vals(buffer, codec, nid, HDA_OUTPUT,
- wid_caps, 1);
- }
-
- switch (wid_type) {
- case AC_WID_PIN: {
- int supports_vref;
- print_pin_caps(buffer, codec, nid, &supports_vref);
- print_pin_ctls(buffer, codec, nid, supports_vref);
- break;
- }
- case AC_WID_VOL_KNB:
- print_vol_knob(buffer, codec, nid);
- break;
- case AC_WID_AUD_OUT:
- case AC_WID_AUD_IN:
- print_audio_io(buffer, codec, nid, wid_type);
- if (wid_caps & AC_WCAP_DIGITAL)
- print_digital_conv(buffer, codec, nid);
- if (wid_caps & AC_WCAP_FORMAT_OVRD) {
- snd_iprintf(buffer, " PCM:\n");
- print_pcm_caps(buffer, codec, nid);
- }
- break;
- }
-
- if (wid_caps & AC_WCAP_UNSOL_CAP)
- print_unsol_cap(buffer, codec, nid);
-
- if (wid_caps & AC_WCAP_POWER)
- print_power_state(buffer, codec, nid);
-
- if (wid_caps & AC_WCAP_DELAY)
- snd_iprintf(buffer, " Delay: %d samples\n",
- (wid_caps & AC_WCAP_DELAY) >>
- AC_WCAP_DELAY_SHIFT);
-
- if (wid_type == AC_WID_PIN && codec->dp_mst)
- print_device_list(buffer, codec, nid);
-
- if (wid_caps & AC_WCAP_CONN_LIST)
- print_conn_list(buffer, codec, nid, wid_type,
- conn, conn_len);
-
- if (wid_caps & AC_WCAP_PROC_WID)
- print_proc_caps(buffer, codec, nid);
-
- if (codec->proc_widget_hook)
- codec->proc_widget_hook(buffer, codec, nid);
-
- kfree(conn);
- }
- snd_hda_power_down(codec);
-}
-
-/*
- * create a proc read
- */
-int snd_hda_codec_proc_new(struct hda_codec *codec)
-{
- char name[32];
-
- snprintf(name, sizeof(name), "codec#%d", codec->core.addr);
- return snd_card_ro_proc_new(codec->card, name, codec, print_codec_info);
-}
-
diff --git a/sound/pci/hda/hda_sysfs.c b/sound/pci/hda/hda_sysfs.c
deleted file mode 100644
index 140e24bf4d7f..000000000000
--- a/sound/pci/hda/hda_sysfs.c
+++ /dev/null
@@ -1,792 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * sysfs interface for HD-audio codec
- *
- * Copyright (c) 2014 Takashi Iwai <tiwai@suse.de>
- *
- * split from hda_hwdep.c
- */
-
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/compat.h>
-#include <linux/mutex.h>
-#include <linux/ctype.h>
-#include <linux/string.h>
-#include <linux/export.h>
-#include <sound/core.h>
-#include <sound/hda_codec.h>
-#include "hda_local.h"
-#include <sound/hda_hwdep.h>
-#include <sound/minors.h>
-
-/* hint string pair */
-struct hda_hint {
- const char *key;
- const char *val; /* contained in the same alloc as key */
-};
-
-static ssize_t power_on_acct_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct hda_codec *codec = dev_get_drvdata(dev);
- snd_hda_update_power_acct(codec);
- return sysfs_emit(buf, "%u\n", jiffies_to_msecs(codec->power_on_acct));
-}
-
-static ssize_t power_off_acct_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct hda_codec *codec = dev_get_drvdata(dev);
- snd_hda_update_power_acct(codec);
- return sysfs_emit(buf, "%u\n", jiffies_to_msecs(codec->power_off_acct));
-}
-
-static DEVICE_ATTR_RO(power_on_acct);
-static DEVICE_ATTR_RO(power_off_acct);
-
-#define CODEC_INFO_SHOW(type, field) \
-static ssize_t type##_show(struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
-{ \
- struct hda_codec *codec = dev_get_drvdata(dev); \
- return sysfs_emit(buf, "0x%x\n", codec->field); \
-}
-
-#define CODEC_INFO_STR_SHOW(type, field) \
-static ssize_t type##_show(struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
-{ \
- struct hda_codec *codec = dev_get_drvdata(dev); \
- return sysfs_emit(buf, "%s\n", \
- codec->field ? codec->field : ""); \
-}
-
-CODEC_INFO_SHOW(vendor_id, core.vendor_id);
-CODEC_INFO_SHOW(subsystem_id, core.subsystem_id);
-CODEC_INFO_SHOW(revision_id, core.revision_id);
-CODEC_INFO_SHOW(afg, core.afg);
-CODEC_INFO_SHOW(mfg, core.mfg);
-CODEC_INFO_STR_SHOW(vendor_name, core.vendor_name);
-CODEC_INFO_STR_SHOW(chip_name, core.chip_name);
-CODEC_INFO_STR_SHOW(modelname, modelname);
-
-static ssize_t pin_configs_show(struct hda_codec *codec,
- struct snd_array *list,
- char *buf)
-{
- const struct hda_pincfg *pin;
- int i, len = 0;
- mutex_lock(&codec->user_mutex);
- snd_array_for_each(list, i, pin) {
- len += sysfs_emit_at(buf, len, "0x%02x 0x%08x\n",
- pin->nid, pin->cfg);
- }
- mutex_unlock(&codec->user_mutex);
- return len;
-}
-
-static ssize_t init_pin_configs_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct hda_codec *codec = dev_get_drvdata(dev);
- return pin_configs_show(codec, &codec->init_pins, buf);
-}
-
-static ssize_t driver_pin_configs_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct hda_codec *codec = dev_get_drvdata(dev);
- return pin_configs_show(codec, &codec->driver_pins, buf);
-}
-
-#ifdef CONFIG_SND_HDA_RECONFIG
-
-/*
- * sysfs interface
- */
-
-static int clear_codec(struct hda_codec *codec)
-{
- int err;
-
- err = snd_hda_codec_reset(codec);
- if (err < 0) {
- codec_err(codec, "The codec is being used, can't free.\n");
- return err;
- }
- snd_hda_sysfs_clear(codec);
- return 0;
-}
-
-static int reconfig_codec(struct hda_codec *codec)
-{
- int err;
-
- snd_hda_power_up(codec);
- codec_info(codec, "hda-codec: reconfiguring\n");
- err = snd_hda_codec_reset(codec);
- if (err < 0) {
- codec_err(codec,
- "The codec is being used, can't reconfigure.\n");
- goto error;
- }
- err = device_reprobe(hda_codec_dev(codec));
- if (err < 0)
- goto error;
- err = snd_card_register(codec->card);
- error:
- snd_hda_power_down(codec);
- return err;
-}
-
-/*
- * allocate a string at most len chars, and remove the trailing EOL
- */
-static char *kstrndup_noeol(const char *src, size_t len)
-{
- char *s = kstrndup(src, len, GFP_KERNEL);
- char *p;
- if (!s)
- return NULL;
- p = strchr(s, '\n');
- if (p)
- *p = 0;
- return s;
-}
-
-#define CODEC_INFO_STORE(type, field) \
-static ssize_t type##_store(struct device *dev, \
- struct device_attribute *attr, \
- const char *buf, size_t count) \
-{ \
- struct hda_codec *codec = dev_get_drvdata(dev); \
- unsigned long val; \
- int err = kstrtoul(buf, 0, &val); \
- if (err < 0) \
- return err; \
- codec->field = val; \
- return count; \
-}
-
-#define CODEC_INFO_STR_STORE(type, field) \
-static ssize_t type##_store(struct device *dev, \
- struct device_attribute *attr, \
- const char *buf, size_t count) \
-{ \
- struct hda_codec *codec = dev_get_drvdata(dev); \
- char *s = kstrndup_noeol(buf, 64); \
- if (!s) \
- return -ENOMEM; \
- kfree(codec->field); \
- codec->field = s; \
- return count; \
-}
-
-CODEC_INFO_STORE(vendor_id, core.vendor_id);
-CODEC_INFO_STORE(subsystem_id, core.subsystem_id);
-CODEC_INFO_STORE(revision_id, core.revision_id);
-CODEC_INFO_STR_STORE(vendor_name, core.vendor_name);
-CODEC_INFO_STR_STORE(chip_name, core.chip_name);
-CODEC_INFO_STR_STORE(modelname, modelname);
-
-#define CODEC_ACTION_STORE(type) \
-static ssize_t type##_store(struct device *dev, \
- struct device_attribute *attr, \
- const char *buf, size_t count) \
-{ \
- struct hda_codec *codec = dev_get_drvdata(dev); \
- int err = 0; \
- if (*buf) \
- err = type##_codec(codec); \
- return err < 0 ? err : count; \
-}
-
-CODEC_ACTION_STORE(reconfig);
-CODEC_ACTION_STORE(clear);
-
-static ssize_t init_verbs_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct hda_codec *codec = dev_get_drvdata(dev);
- const struct hda_verb *v;
- int i, len = 0;
- mutex_lock(&codec->user_mutex);
- snd_array_for_each(&codec->init_verbs, i, v) {
- len += sysfs_emit_at(buf, len, "0x%02x 0x%03x 0x%04x\n",
- v->nid, v->verb, v->param);
- }
- mutex_unlock(&codec->user_mutex);
- return len;
-}
-
-static int parse_init_verbs(struct hda_codec *codec, const char *buf)
-{
- struct hda_verb *v;
- int nid, verb, param;
-
- if (sscanf(buf, "%i %i %i", &nid, &verb, &param) != 3)
- return -EINVAL;
- if (!nid || !verb)
- return -EINVAL;
- mutex_lock(&codec->user_mutex);
- v = snd_array_new(&codec->init_verbs);
- if (!v) {
- mutex_unlock(&codec->user_mutex);
- return -ENOMEM;
- }
- v->nid = nid;
- v->verb = verb;
- v->param = param;
- mutex_unlock(&codec->user_mutex);
- return 0;
-}
-
-static ssize_t init_verbs_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct hda_codec *codec = dev_get_drvdata(dev);
- int err = parse_init_verbs(codec, buf);
- if (err < 0)
- return err;
- return count;
-}
-
-static ssize_t hints_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct hda_codec *codec = dev_get_drvdata(dev);
- const struct hda_hint *hint;
- int i, len = 0;
- mutex_lock(&codec->user_mutex);
- snd_array_for_each(&codec->hints, i, hint) {
- len += sysfs_emit_at(buf, len, "%s = %s\n",
- hint->key, hint->val);
- }
- mutex_unlock(&codec->user_mutex);
- return len;
-}
-
-static struct hda_hint *get_hint(struct hda_codec *codec, const char *key)
-{
- struct hda_hint *hint;
- int i;
-
- snd_array_for_each(&codec->hints, i, hint) {
- if (!strcmp(hint->key, key))
- return hint;
- }
- return NULL;
-}
-
-static void remove_trail_spaces(char *str)
-{
- char *p;
- if (!*str)
- return;
- p = str + strlen(str) - 1;
- for (; isspace(*p); p--) {
- *p = 0;
- if (p == str)
- return;
- }
-}
-
-#define MAX_HINTS 1024
-
-static int parse_hints(struct hda_codec *codec, const char *buf)
-{
- char *key, *val;
- struct hda_hint *hint;
- int err = 0;
-
- buf = skip_spaces(buf);
- if (!*buf || *buf == '#' || *buf == '\n')
- return 0;
- if (*buf == '=')
- return -EINVAL;
- key = kstrndup_noeol(buf, 1024);
- if (!key)
- return -ENOMEM;
- /* extract key and val */
- val = strchr(key, '=');
- if (!val) {
- kfree(key);
- return -EINVAL;
- }
- *val++ = 0;
- val = skip_spaces(val);
- remove_trail_spaces(key);
- remove_trail_spaces(val);
- mutex_lock(&codec->user_mutex);
- hint = get_hint(codec, key);
- if (hint) {
- /* replace */
- kfree(hint->key);
- hint->key = key;
- hint->val = val;
- goto unlock;
- }
- /* allocate a new hint entry */
- if (codec->hints.used >= MAX_HINTS)
- hint = NULL;
- else
- hint = snd_array_new(&codec->hints);
- if (hint) {
- hint->key = key;
- hint->val = val;
- } else {
- err = -ENOMEM;
- }
- unlock:
- mutex_unlock(&codec->user_mutex);
- if (err)
- kfree(key);
- return err;
-}
-
-static ssize_t hints_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct hda_codec *codec = dev_get_drvdata(dev);
- int err = parse_hints(codec, buf);
- if (err < 0)
- return err;
- return count;
-}
-
-static ssize_t user_pin_configs_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct hda_codec *codec = dev_get_drvdata(dev);
- return pin_configs_show(codec, &codec->user_pins, buf);
-}
-
-static int parse_user_pin_configs(struct hda_codec *codec, const char *buf)
-{
- int nid, cfg, err;
-
- if (sscanf(buf, "%i %i", &nid, &cfg) != 2)
- return -EINVAL;
- if (!nid)
- return -EINVAL;
- mutex_lock(&codec->user_mutex);
- err = snd_hda_add_pincfg(codec, &codec->user_pins, nid, cfg);
- mutex_unlock(&codec->user_mutex);
- return err;
-}
-
-static ssize_t user_pin_configs_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct hda_codec *codec = dev_get_drvdata(dev);
- int err = parse_user_pin_configs(codec, buf);
- if (err < 0)
- return err;
- return count;
-}
-
-/* sysfs attributes exposed only when CONFIG_SND_HDA_RECONFIG=y */
-static DEVICE_ATTR_RW(init_verbs);
-static DEVICE_ATTR_RW(hints);
-static DEVICE_ATTR_RW(user_pin_configs);
-static DEVICE_ATTR_WO(reconfig);
-static DEVICE_ATTR_WO(clear);
-
-/**
- * snd_hda_get_hint - Look for hint string
- * @codec: the HDA codec
- * @key: the hint key string
- *
- * Look for a hint key/value pair matching with the given key string
- * and returns the value string. If nothing found, returns NULL.
- */
-const char *snd_hda_get_hint(struct hda_codec *codec, const char *key)
-{
- struct hda_hint *hint = get_hint(codec, key);
- return hint ? hint->val : NULL;
-}
-EXPORT_SYMBOL_GPL(snd_hda_get_hint);
-
-/**
- * snd_hda_get_bool_hint - Get a boolean hint value
- * @codec: the HDA codec
- * @key: the hint key string
- *
- * Look for a hint key/value pair matching with the given key string
- * and returns a boolean value parsed from the value. If no matching
- * key is found, return a negative value.
- */
-int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key)
-{
- const char *p;
- int ret;
-
- mutex_lock(&codec->user_mutex);
- p = snd_hda_get_hint(codec, key);
- if (!p || !*p)
- ret = -ENOENT;
- else {
- switch (toupper(*p)) {
- case 'T': /* true */
- case 'Y': /* yes */
- case '1':
- ret = 1;
- break;
- default:
- ret = 0;
- break;
- }
- }
- mutex_unlock(&codec->user_mutex);
- return ret;
-}
-EXPORT_SYMBOL_GPL(snd_hda_get_bool_hint);
-
-/**
- * snd_hda_get_int_hint - Get an integer hint value
- * @codec: the HDA codec
- * @key: the hint key string
- * @valp: pointer to store a value
- *
- * Look for a hint key/value pair matching with the given key string
- * and stores the integer value to @valp. If no matching key is found,
- * return a negative error code. Otherwise it returns zero.
- */
-int snd_hda_get_int_hint(struct hda_codec *codec, const char *key, int *valp)
-{
- const char *p;
- unsigned long val;
- int ret;
-
- mutex_lock(&codec->user_mutex);
- p = snd_hda_get_hint(codec, key);
- if (!p)
- ret = -ENOENT;
- else if (kstrtoul(p, 0, &val))
- ret = -EINVAL;
- else {
- *valp = val;
- ret = 0;
- }
- mutex_unlock(&codec->user_mutex);
- return ret;
-}
-EXPORT_SYMBOL_GPL(snd_hda_get_int_hint);
-#endif /* CONFIG_SND_HDA_RECONFIG */
-
-/*
- * common sysfs attributes
- */
-#ifdef CONFIG_SND_HDA_RECONFIG
-#define RECONFIG_DEVICE_ATTR(name) DEVICE_ATTR_RW(name)
-#else
-#define RECONFIG_DEVICE_ATTR(name) DEVICE_ATTR_RO(name)
-#endif
-static RECONFIG_DEVICE_ATTR(vendor_id);
-static RECONFIG_DEVICE_ATTR(subsystem_id);
-static RECONFIG_DEVICE_ATTR(revision_id);
-static DEVICE_ATTR_RO(afg);
-static DEVICE_ATTR_RO(mfg);
-static RECONFIG_DEVICE_ATTR(vendor_name);
-static RECONFIG_DEVICE_ATTR(chip_name);
-static RECONFIG_DEVICE_ATTR(modelname);
-static DEVICE_ATTR_RO(init_pin_configs);
-static DEVICE_ATTR_RO(driver_pin_configs);
-
-
-#ifdef CONFIG_SND_HDA_PATCH_LOADER
-
-/* parser mode */
-enum {
- LINE_MODE_NONE,
- LINE_MODE_CODEC,
- LINE_MODE_MODEL,
- LINE_MODE_PINCFG,
- LINE_MODE_VERB,
- LINE_MODE_HINT,
- LINE_MODE_VENDOR_ID,
- LINE_MODE_SUBSYSTEM_ID,
- LINE_MODE_REVISION_ID,
- LINE_MODE_CHIP_NAME,
- NUM_LINE_MODES,
-};
-
-static inline int strmatch(const char *a, const char *b)
-{
- return strncasecmp(a, b, strlen(b)) == 0;
-}
-
-/* parse the contents after the line "[codec]"
- * accept only the line with three numbers, and assign the current codec
- */
-static void parse_codec_mode(char *buf, struct hda_bus *bus,
- struct hda_codec **codecp)
-{
- int vendorid, subid, caddr;
- struct hda_codec *codec;
-
- *codecp = NULL;
- if (sscanf(buf, "%i %i %i", &vendorid, &subid, &caddr) == 3) {
- list_for_each_codec(codec, bus) {
- if ((vendorid <= 0 || codec->core.vendor_id == vendorid) &&
- (subid <= 0 || codec->core.subsystem_id == subid) &&
- codec->core.addr == caddr) {
- *codecp = codec;
- break;
- }
- }
- }
-}
-
-/* parse the contents after the other command tags, [pincfg], [verb],
- * [vendor_id], [subsystem_id], [revision_id], [chip_name], [hint] and [model]
- * just pass to the sysfs helper (only when any codec was specified)
- */
-static void parse_pincfg_mode(char *buf, struct hda_bus *bus,
- struct hda_codec **codecp)
-{
- parse_user_pin_configs(*codecp, buf);
-}
-
-static void parse_verb_mode(char *buf, struct hda_bus *bus,
- struct hda_codec **codecp)
-{
- parse_init_verbs(*codecp, buf);
-}
-
-static void parse_hint_mode(char *buf, struct hda_bus *bus,
- struct hda_codec **codecp)
-{
- parse_hints(*codecp, buf);
-}
-
-static void parse_model_mode(char *buf, struct hda_bus *bus,
- struct hda_codec **codecp)
-{
- kfree((*codecp)->modelname);
- (*codecp)->modelname = kstrdup(buf, GFP_KERNEL);
-}
-
-static void parse_chip_name_mode(char *buf, struct hda_bus *bus,
- struct hda_codec **codecp)
-{
- snd_hda_codec_set_name(*codecp, buf);
-}
-
-#define DEFINE_PARSE_ID_MODE(name) \
-static void parse_##name##_mode(char *buf, struct hda_bus *bus, \
- struct hda_codec **codecp) \
-{ \
- unsigned long val; \
- if (!kstrtoul(buf, 0, &val)) \
- (*codecp)->core.name = val; \
-}
-
-DEFINE_PARSE_ID_MODE(vendor_id);
-DEFINE_PARSE_ID_MODE(subsystem_id);
-DEFINE_PARSE_ID_MODE(revision_id);
-
-
-struct hda_patch_item {
- const char *tag;
- const char *alias;
- void (*parser)(char *buf, struct hda_bus *bus, struct hda_codec **retc);
-};
-
-static const struct hda_patch_item patch_items[NUM_LINE_MODES] = {
- [LINE_MODE_CODEC] = {
- .tag = "[codec]",
- .parser = parse_codec_mode,
- },
- [LINE_MODE_MODEL] = {
- .tag = "[model]",
- .parser = parse_model_mode,
- },
- [LINE_MODE_VERB] = {
- .tag = "[verb]",
- .alias = "[init_verbs]",
- .parser = parse_verb_mode,
- },
- [LINE_MODE_PINCFG] = {
- .tag = "[pincfg]",
- .alias = "[user_pin_configs]",
- .parser = parse_pincfg_mode,
- },
- [LINE_MODE_HINT] = {
- .tag = "[hint]",
- .alias = "[hints]",
- .parser = parse_hint_mode
- },
- [LINE_MODE_VENDOR_ID] = {
- .tag = "[vendor_id]",
- .parser = parse_vendor_id_mode,
- },
- [LINE_MODE_SUBSYSTEM_ID] = {
- .tag = "[subsystem_id]",
- .parser = parse_subsystem_id_mode,
- },
- [LINE_MODE_REVISION_ID] = {
- .tag = "[revision_id]",
- .parser = parse_revision_id_mode,
- },
- [LINE_MODE_CHIP_NAME] = {
- .tag = "[chip_name]",
- .parser = parse_chip_name_mode,
- },
-};
-
-/* check the line starting with '[' -- change the parser mode accordingly */
-static int parse_line_mode(char *buf, struct hda_bus *bus)
-{
- int i;
- for (i = 0; i < ARRAY_SIZE(patch_items); i++) {
- if (!patch_items[i].tag)
- continue;
- if (strmatch(buf, patch_items[i].tag))
- return i;
- if (patch_items[i].alias && strmatch(buf, patch_items[i].alias))
- return i;
- }
- return LINE_MODE_NONE;
-}
-
-/* copy one line from the buffer in fw, and update the fields in fw
- * return zero if it reaches to the end of the buffer, or non-zero
- * if successfully copied a line
- *
- * the spaces at the beginning and the end of the line are stripped
- */
-static int get_line_from_fw(char *buf, int size, size_t *fw_size_p,
- const void **fw_data_p)
-{
- int len;
- size_t fw_size = *fw_size_p;
- const char *p = *fw_data_p;
-
- while (isspace(*p) && fw_size) {
- p++;
- fw_size--;
- }
- if (!fw_size)
- return 0;
-
- for (len = 0; len < fw_size; len++) {
- if (!*p)
- break;
- if (*p == '\n') {
- p++;
- len++;
- break;
- }
- if (len < size)
- *buf++ = *p++;
- }
- *buf = 0;
- *fw_size_p = fw_size - len;
- *fw_data_p = p;
- remove_trail_spaces(buf);
- return 1;
-}
-
-/**
- * snd_hda_load_patch - load a "patch" firmware file and parse it
- * @bus: HD-audio bus
- * @fw_size: the firmware byte size
- * @fw_buf: the firmware data
- */
-int snd_hda_load_patch(struct hda_bus *bus, size_t fw_size, const void *fw_buf)
-{
- char buf[128];
- struct hda_codec *codec;
- int line_mode;
-
- line_mode = LINE_MODE_NONE;
- codec = NULL;
- while (get_line_from_fw(buf, sizeof(buf) - 1, &fw_size, &fw_buf)) {
- if (!*buf || *buf == '#' || *buf == '\n')
- continue;
- if (*buf == '[')
- line_mode = parse_line_mode(buf, bus);
- else if (patch_items[line_mode].parser &&
- (codec || line_mode <= LINE_MODE_CODEC))
- patch_items[line_mode].parser(buf, bus, &codec);
- }
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_hda_load_patch);
-#endif /* CONFIG_SND_HDA_PATCH_LOADER */
-
-/*
- * sysfs entries
- */
-static struct attribute *hda_dev_attrs[] = {
- &dev_attr_vendor_id.attr,
- &dev_attr_subsystem_id.attr,
- &dev_attr_revision_id.attr,
- &dev_attr_afg.attr,
- &dev_attr_mfg.attr,
- &dev_attr_vendor_name.attr,
- &dev_attr_chip_name.attr,
- &dev_attr_modelname.attr,
- &dev_attr_init_pin_configs.attr,
- &dev_attr_driver_pin_configs.attr,
- &dev_attr_power_on_acct.attr,
- &dev_attr_power_off_acct.attr,
-#ifdef CONFIG_SND_HDA_RECONFIG
- &dev_attr_init_verbs.attr,
- &dev_attr_hints.attr,
- &dev_attr_user_pin_configs.attr,
- &dev_attr_reconfig.attr,
- &dev_attr_clear.attr,
-#endif
- NULL
-};
-
-static const struct attribute_group hda_dev_attr_group = {
- .attrs = hda_dev_attrs,
-};
-
-const struct attribute_group *snd_hda_dev_attr_groups[] = {
- &hda_dev_attr_group,
- NULL
-};
-
-void snd_hda_sysfs_init(struct hda_codec *codec)
-{
- mutex_init(&codec->user_mutex);
-#ifdef CONFIG_SND_HDA_RECONFIG
- snd_array_init(&codec->init_verbs, sizeof(struct hda_verb), 32);
- snd_array_init(&codec->hints, sizeof(struct hda_hint), 32);
- snd_array_init(&codec->user_pins, sizeof(struct hda_pincfg), 16);
-#endif
-}
-
-void snd_hda_sysfs_clear(struct hda_codec *codec)
-{
-#ifdef CONFIG_SND_HDA_RECONFIG
- struct hda_hint *hint;
- int i;
-
- /* clear init verbs */
- snd_array_free(&codec->init_verbs);
- /* clear hints */
- snd_array_for_each(&codec->hints, i, hint) {
- kfree(hint->key); /* we don't need to free hint->val */
- }
- snd_array_free(&codec->hints);
- snd_array_free(&codec->user_pins);
-#endif
-}
diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c
deleted file mode 100644
index 6ab338f37db5..000000000000
--- a/sound/pci/hda/hda_tegra.c
+++ /dev/null
@@ -1,652 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- *
- * Implementation of primary ALSA driver code base for NVIDIA Tegra HDA.
- */
-
-#include <linux/clk.h>
-#include <linux/clocksource.h>
-#include <linux/completion.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/mutex.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/reset.h>
-#include <linux/slab.h>
-#include <linux/time.h>
-#include <linux/string.h>
-#include <linux/pm_runtime.h>
-
-#include <sound/core.h>
-#include <sound/initval.h>
-
-#include <sound/hda_codec.h>
-#include "hda_controller.h"
-
-/* Defines for Nvidia Tegra HDA support */
-#define HDA_BAR0 0x8000
-
-#define HDA_CFG_CMD 0x1004
-#define HDA_CFG_BAR0 0x1010
-
-#define HDA_ENABLE_IO_SPACE (1 << 0)
-#define HDA_ENABLE_MEM_SPACE (1 << 1)
-#define HDA_ENABLE_BUS_MASTER (1 << 2)
-#define HDA_ENABLE_SERR (1 << 8)
-#define HDA_DISABLE_INTR (1 << 10)
-#define HDA_BAR0_INIT_PROGRAM 0xFFFFFFFF
-#define HDA_BAR0_FINAL_PROGRAM (1 << 14)
-
-/* IPFS */
-#define HDA_IPFS_CONFIG 0x180
-#define HDA_IPFS_EN_FPCI 0x1
-
-#define HDA_IPFS_FPCI_BAR0 0x80
-#define HDA_FPCI_BAR0_START 0x40
-
-#define HDA_IPFS_INTR_MASK 0x188
-#define HDA_IPFS_EN_INTR (1 << 16)
-
-/* FPCI */
-#define FPCI_DBG_CFG_2 0x10F4
-#define FPCI_GCAP_NSDO_SHIFT 18
-#define FPCI_GCAP_NSDO_MASK (0x3 << FPCI_GCAP_NSDO_SHIFT)
-
-/* max number of SDs */
-#define NUM_CAPTURE_SD 1
-#define NUM_PLAYBACK_SD 1
-
-/*
- * Tegra194 does not reflect correct number of SDO lines. Below macro
- * is used to update the GCAP register to workaround the issue.
- */
-#define TEGRA194_NUM_SDO_LINES 4
-
-struct hda_tegra_soc {
- bool has_hda2codec_2x_reset;
- bool has_hda2hdmi;
- bool has_hda2codec_2x;
- bool input_stream;
- bool always_on;
- bool requires_init;
-};
-
-struct hda_tegra {
- struct azx chip;
- struct device *dev;
- struct reset_control_bulk_data resets[3];
- struct clk_bulk_data clocks[3];
- unsigned int nresets;
- unsigned int nclocks;
- void __iomem *regs;
- struct work_struct probe_work;
- const struct hda_tegra_soc *soc;
-};
-
-#ifdef CONFIG_PM
-static int power_save = CONFIG_SND_HDA_POWER_SAVE_DEFAULT;
-module_param(power_save, bint, 0644);
-MODULE_PARM_DESC(power_save,
- "Automatic power-saving timeout (in seconds, 0 = disable).");
-#else
-#define power_save 0
-#endif
-
-static const struct hda_controller_ops hda_tegra_ops; /* nothing special */
-
-static void hda_tegra_init(struct hda_tegra *hda)
-{
- u32 v;
-
- /* Enable PCI access */
- v = readl(hda->regs + HDA_IPFS_CONFIG);
- v |= HDA_IPFS_EN_FPCI;
- writel(v, hda->regs + HDA_IPFS_CONFIG);
-
- /* Enable MEM/IO space and bus master */
- v = readl(hda->regs + HDA_CFG_CMD);
- v &= ~HDA_DISABLE_INTR;
- v |= HDA_ENABLE_MEM_SPACE | HDA_ENABLE_IO_SPACE |
- HDA_ENABLE_BUS_MASTER | HDA_ENABLE_SERR;
- writel(v, hda->regs + HDA_CFG_CMD);
-
- writel(HDA_BAR0_INIT_PROGRAM, hda->regs + HDA_CFG_BAR0);
- writel(HDA_BAR0_FINAL_PROGRAM, hda->regs + HDA_CFG_BAR0);
- writel(HDA_FPCI_BAR0_START, hda->regs + HDA_IPFS_FPCI_BAR0);
-
- v = readl(hda->regs + HDA_IPFS_INTR_MASK);
- v |= HDA_IPFS_EN_INTR;
- writel(v, hda->regs + HDA_IPFS_INTR_MASK);
-}
-
-/*
- * power management
- */
-static int hda_tegra_suspend(struct device *dev)
-{
- struct snd_card *card = dev_get_drvdata(dev);
- int rc;
-
- rc = pm_runtime_force_suspend(dev);
- if (rc < 0)
- return rc;
- snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
-
- return 0;
-}
-
-static int hda_tegra_resume(struct device *dev)
-{
- struct snd_card *card = dev_get_drvdata(dev);
- int rc;
-
- rc = pm_runtime_force_resume(dev);
- if (rc < 0)
- return rc;
- snd_power_change_state(card, SNDRV_CTL_POWER_D0);
-
- return 0;
-}
-
-static int hda_tegra_runtime_suspend(struct device *dev)
-{
- struct snd_card *card = dev_get_drvdata(dev);
- struct azx *chip = card->private_data;
- struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip);
-
- if (chip && chip->running) {
- /* enable controller wake up event */
- azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) |
- STATESTS_INT_MASK);
-
- azx_stop_chip(chip);
- azx_enter_link_reset(chip);
- }
- clk_bulk_disable_unprepare(hda->nclocks, hda->clocks);
-
- return 0;
-}
-
-static int hda_tegra_runtime_resume(struct device *dev)
-{
- struct snd_card *card = dev_get_drvdata(dev);
- struct azx *chip = card->private_data;
- struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip);
- int rc;
-
- if (!chip->running) {
- rc = reset_control_bulk_assert(hda->nresets, hda->resets);
- if (rc)
- return rc;
- }
-
- rc = clk_bulk_prepare_enable(hda->nclocks, hda->clocks);
- if (rc != 0)
- return rc;
- if (chip->running) {
- if (hda->soc->requires_init)
- hda_tegra_init(hda);
-
- azx_init_chip(chip, 1);
- /* disable controller wake up event*/
- azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) &
- ~STATESTS_INT_MASK);
- } else {
- usleep_range(10, 100);
-
- rc = reset_control_bulk_deassert(hda->nresets, hda->resets);
- if (rc)
- return rc;
- }
-
- return 0;
-}
-
-static const struct dev_pm_ops hda_tegra_pm = {
- SYSTEM_SLEEP_PM_OPS(hda_tegra_suspend, hda_tegra_resume)
- RUNTIME_PM_OPS(hda_tegra_runtime_suspend, hda_tegra_runtime_resume, NULL)
-};
-
-static int hda_tegra_dev_disconnect(struct snd_device *device)
-{
- struct azx *chip = device->device_data;
-
- chip->bus.shutdown = 1;
- return 0;
-}
-
-/*
- * destructor
- */
-static int hda_tegra_dev_free(struct snd_device *device)
-{
- struct azx *chip = device->device_data;
- struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip);
-
- cancel_work_sync(&hda->probe_work);
- if (azx_bus(chip)->chip_init) {
- azx_stop_all_streams(chip);
- azx_stop_chip(chip);
- }
-
- azx_free_stream_pages(chip);
- azx_free_streams(chip);
- snd_hdac_bus_exit(azx_bus(chip));
-
- return 0;
-}
-
-static int hda_tegra_init_chip(struct azx *chip, struct platform_device *pdev)
-{
- struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip);
- struct hdac_bus *bus = azx_bus(chip);
- struct resource *res;
-
- hda->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
- if (IS_ERR(hda->regs))
- return PTR_ERR(hda->regs);
-
- bus->remap_addr = hda->regs + HDA_BAR0;
- bus->addr = res->start + HDA_BAR0;
-
- if (hda->soc->requires_init)
- hda_tegra_init(hda);
-
- return 0;
-}
-
-static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev)
-{
- struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip);
- struct hdac_bus *bus = azx_bus(chip);
- struct snd_card *card = chip->card;
- int err;
- unsigned short gcap;
- int irq_id = platform_get_irq(pdev, 0);
- const char *sname, *drv_name = "tegra-hda";
- struct device_node *np = pdev->dev.of_node;
-
- if (irq_id < 0)
- return irq_id;
-
- err = hda_tegra_init_chip(chip, pdev);
- if (err)
- return err;
-
- err = devm_request_irq(chip->card->dev, irq_id, azx_interrupt,
- IRQF_SHARED, KBUILD_MODNAME, chip);
- if (err) {
- dev_err(chip->card->dev,
- "unable to request IRQ %d, disabling device\n",
- irq_id);
- return err;
- }
- bus->irq = irq_id;
- bus->dma_stop_delay = 100;
- card->sync_irq = bus->irq;
-
- /*
- * Tegra194 has 4 SDO lines and the STRIPE can be used to
- * indicate how many of the SDO lines the stream should be
- * striped. But GCAP register does not reflect the true
- * capability of HW. Below workaround helps to fix this.
- *
- * GCAP_NSDO is bits 19:18 in T_AZA_DBG_CFG_2,
- * 0 for 1 SDO, 1 for 2 SDO, 2 for 4 SDO lines.
- */
- if (of_device_is_compatible(np, "nvidia,tegra194-hda")) {
- u32 val;
-
- dev_info(card->dev, "Override SDO lines to %u\n",
- TEGRA194_NUM_SDO_LINES);
-
- val = readl(hda->regs + FPCI_DBG_CFG_2) & ~FPCI_GCAP_NSDO_MASK;
- val |= (TEGRA194_NUM_SDO_LINES >> 1) << FPCI_GCAP_NSDO_SHIFT;
- writel(val, hda->regs + FPCI_DBG_CFG_2);
- }
-
- gcap = azx_readw(chip, GCAP);
- dev_dbg(card->dev, "chipset global capabilities = 0x%x\n", gcap);
-
- chip->align_buffer_size = 1;
-
- /* read number of streams from GCAP register instead of using
- * hardcoded value
- */
- chip->capture_streams = (gcap >> 8) & 0x0f;
-
- /* The GCAP register on Tegra234 implies no Input Streams(ISS) support,
- * but the HW output stream descriptor programming should start with
- * offset 0x20*4 from base stream descriptor address. This will be a
- * problem while calculating the offset for output stream descriptor
- * which will be considering input stream also. So here output stream
- * starts with offset 0 which is wrong as HW register for output stream
- * offset starts with 4.
- */
- if (!hda->soc->input_stream)
- chip->capture_streams = 4;
-
- chip->playback_streams = (gcap >> 12) & 0x0f;
- if (!chip->playback_streams && !chip->capture_streams) {
- /* gcap didn't give any info, switching to old method */
- chip->playback_streams = NUM_PLAYBACK_SD;
- chip->capture_streams = NUM_CAPTURE_SD;
- }
- chip->capture_index_offset = 0;
- chip->playback_index_offset = chip->capture_streams;
- chip->num_streams = chip->playback_streams + chip->capture_streams;
-
- /* initialize streams */
- err = azx_init_streams(chip);
- if (err < 0) {
- dev_err(card->dev, "failed to initialize streams: %d\n", err);
- return err;
- }
-
- err = azx_alloc_stream_pages(chip);
- if (err < 0) {
- dev_err(card->dev, "failed to allocate stream pages: %d\n",
- err);
- return err;
- }
-
- /* initialize chip */
- azx_init_chip(chip, 1);
-
- /*
- * Playback (for 44.1K/48K, 2-channel, 16-bps) fails with
- * 4 SDO lines due to legacy design limitation. Following
- * is, from HD Audio Specification (Revision 1.0a), used to
- * control striping of the stream across multiple SDO lines
- * for sample rates <= 48K.
- *
- * { ((num_channels * bits_per_sample) / number of SDOs) >= 8 }
- *
- * Due to legacy design issue it is recommended that above
- * ratio must be greater than 8. Since number of SDO lines is
- * in powers of 2, next available ratio is 16 which can be
- * used as a limiting factor here.
- */
- if (of_device_is_compatible(np, "nvidia,tegra30-hda"))
- chip->bus.core.sdo_limit = 16;
-
- /* codec detection */
- if (!bus->codec_mask) {
- dev_err(card->dev, "no codecs found!\n");
- return -ENODEV;
- }
-
- /* driver name */
- strscpy(card->driver, drv_name);
- /* shortname for card */
- sname = of_get_property(np, "nvidia,model", NULL);
- if (!sname)
- sname = drv_name;
- if (strlen(sname) > sizeof(card->shortname))
- dev_info(card->dev, "truncating shortname for card\n");
- strscpy(card->shortname, sname);
-
- /* longname for card */
- snprintf(card->longname, sizeof(card->longname),
- "%s at 0x%lx irq %i",
- card->shortname, bus->addr, bus->irq);
-
- return 0;
-}
-
-/*
- * constructor
- */
-
-static void hda_tegra_probe_work(struct work_struct *work);
-
-static int hda_tegra_create(struct snd_card *card,
- unsigned int driver_caps,
- struct hda_tegra *hda)
-{
- static const struct snd_device_ops ops = {
- .dev_disconnect = hda_tegra_dev_disconnect,
- .dev_free = hda_tegra_dev_free,
- };
- struct azx *chip;
- int err;
-
- chip = &hda->chip;
-
- mutex_init(&chip->open_mutex);
- chip->card = card;
- chip->ops = &hda_tegra_ops;
- chip->driver_caps = driver_caps;
- chip->driver_type = driver_caps & 0xff;
- chip->dev_index = 0;
- INIT_LIST_HEAD(&chip->pcm_list);
-
- chip->codec_probe_mask = -1;
-
- chip->single_cmd = false;
- chip->snoop = true;
-
- INIT_WORK(&hda->probe_work, hda_tegra_probe_work);
-
- err = azx_bus_init(chip, NULL);
- if (err < 0)
- return err;
-
- chip->bus.core.sync_write = 0;
- chip->bus.core.needs_damn_long_delay = 1;
- chip->bus.core.aligned_mmio = 1;
-
- /*
- * HDA power domain and clocks are always on for Tegra264 and
- * the jack detection logic would work always, so no need of
- * jack polling mechanism running.
- */
- if (!hda->soc->always_on) {
- chip->jackpoll_interval = msecs_to_jiffies(5000);
- chip->bus.jackpoll_in_suspend = 1;
- }
-
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0) {
- dev_err(card->dev, "Error creating device\n");
- return err;
- }
-
- return 0;
-}
-
-static const struct hda_tegra_soc tegra30_data = {
- .has_hda2codec_2x_reset = true,
- .has_hda2hdmi = true,
- .has_hda2codec_2x = true,
- .input_stream = true,
- .always_on = false,
- .requires_init = true,
-};
-
-static const struct hda_tegra_soc tegra194_data = {
- .has_hda2codec_2x_reset = false,
- .has_hda2hdmi = true,
- .has_hda2codec_2x = true,
- .input_stream = true,
- .always_on = false,
- .requires_init = true,
-};
-
-static const struct hda_tegra_soc tegra234_data = {
- .has_hda2codec_2x_reset = true,
- .has_hda2hdmi = false,
- .has_hda2codec_2x = true,
- .input_stream = false,
- .always_on = false,
- .requires_init = true,
-};
-
-static const struct hda_tegra_soc tegra264_data = {
- .has_hda2codec_2x_reset = true,
- .has_hda2hdmi = false,
- .has_hda2codec_2x = false,
- .input_stream = false,
- .always_on = true,
- .requires_init = false,
-};
-
-static const struct of_device_id hda_tegra_match[] = {
- { .compatible = "nvidia,tegra30-hda", .data = &tegra30_data },
- { .compatible = "nvidia,tegra194-hda", .data = &tegra194_data },
- { .compatible = "nvidia,tegra234-hda", .data = &tegra234_data },
- { .compatible = "nvidia,tegra264-hda", .data = &tegra264_data },
- {},
-};
-MODULE_DEVICE_TABLE(of, hda_tegra_match);
-
-static int hda_tegra_probe(struct platform_device *pdev)
-{
- const unsigned int driver_flags = AZX_DCAPS_CORBRP_SELF_CLEAR |
- AZX_DCAPS_PM_RUNTIME |
- AZX_DCAPS_4K_BDLE_BOUNDARY;
- struct snd_card *card;
- struct azx *chip;
- struct hda_tegra *hda;
- int err;
-
- hda = devm_kzalloc(&pdev->dev, sizeof(*hda), GFP_KERNEL);
- if (!hda)
- return -ENOMEM;
- hda->dev = &pdev->dev;
- chip = &hda->chip;
-
- hda->soc = of_device_get_match_data(&pdev->dev);
-
- err = snd_card_new(&pdev->dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
- THIS_MODULE, 0, &card);
- if (err < 0) {
- dev_err(&pdev->dev, "Error creating card!\n");
- return err;
- }
-
- hda->resets[hda->nresets++].id = "hda";
-
- /*
- * "hda2hdmi" is not applicable for Tegra234. This is because the
- * codec is separate IP and not under display SOR partition now.
- */
- if (hda->soc->has_hda2hdmi)
- hda->resets[hda->nresets++].id = "hda2hdmi";
-
- /*
- * "hda2codec_2x" reset is not present on Tegra194. Though DT would
- * be updated to reflect this, but to have backward compatibility
- * below is necessary.
- */
- if (hda->soc->has_hda2codec_2x_reset)
- hda->resets[hda->nresets++].id = "hda2codec_2x";
-
- err = devm_reset_control_bulk_get_exclusive(&pdev->dev, hda->nresets,
- hda->resets);
- if (err)
- goto out_free;
-
- hda->clocks[hda->nclocks++].id = "hda";
- if (hda->soc->has_hda2hdmi)
- hda->clocks[hda->nclocks++].id = "hda2hdmi";
-
- if (hda->soc->has_hda2codec_2x)
- hda->clocks[hda->nclocks++].id = "hda2codec_2x";
-
- err = devm_clk_bulk_get(&pdev->dev, hda->nclocks, hda->clocks);
- if (err < 0)
- goto out_free;
-
- err = hda_tegra_create(card, driver_flags, hda);
- if (err < 0)
- goto out_free;
- card->private_data = chip;
-
- dev_set_drvdata(&pdev->dev, card);
-
- pm_runtime_enable(hda->dev);
- if (!azx_has_pm_runtime(chip))
- pm_runtime_forbid(hda->dev);
-
- schedule_work(&hda->probe_work);
-
- return 0;
-
-out_free:
- snd_card_free(card);
- return err;
-}
-
-static void hda_tegra_probe_work(struct work_struct *work)
-{
- struct hda_tegra *hda = container_of(work, struct hda_tegra, probe_work);
- struct azx *chip = &hda->chip;
- struct platform_device *pdev = to_platform_device(hda->dev);
- int err;
-
- pm_runtime_get_sync(hda->dev);
- err = hda_tegra_first_init(chip, pdev);
- if (err < 0)
- goto out_free;
-
- /* create codec instances */
- err = azx_probe_codecs(chip, 8);
- if (err < 0)
- goto out_free;
-
- err = azx_codec_configure(chip);
- if (err < 0)
- goto out_free;
-
- err = snd_card_register(chip->card);
- if (err < 0)
- goto out_free;
-
- chip->running = 1;
- snd_hda_set_power_save(&chip->bus, power_save * 1000);
-
- out_free:
- pm_runtime_put(hda->dev);
- return; /* no error return from async probe */
-}
-
-static void hda_tegra_remove(struct platform_device *pdev)
-{
- snd_card_free(dev_get_drvdata(&pdev->dev));
- pm_runtime_disable(&pdev->dev);
-}
-
-static void hda_tegra_shutdown(struct platform_device *pdev)
-{
- struct snd_card *card = dev_get_drvdata(&pdev->dev);
- struct azx *chip;
-
- if (!card)
- return;
- chip = card->private_data;
- if (chip && chip->running)
- azx_stop_chip(chip);
-}
-
-static struct platform_driver tegra_platform_hda = {
- .driver = {
- .name = "tegra-hda",
- .pm = pm_ptr(&hda_tegra_pm),
- .of_match_table = hda_tegra_match,
- },
- .probe = hda_tegra_probe,
- .remove = hda_tegra_remove,
- .shutdown = hda_tegra_shutdown,
-};
-module_platform_driver(tegra_platform_hda);
-
-MODULE_DESCRIPTION("Tegra HDA bus driver");
-MODULE_LICENSE("GPL v2");
diff --git a/sound/pci/hda/hp_x360_helper.c b/sound/pci/hda/hp_x360_helper.c
deleted file mode 100644
index 969542c57358..000000000000
--- a/sound/pci/hda/hp_x360_helper.c
+++ /dev/null
@@ -1,95 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Fixes for HP X360 laptops with top B&O speakers
- * to be included from codec driver
- */
-
-static void alc295_fixup_hp_top_speakers(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- static const struct hda_pintbl pincfgs[] = {
- { 0x17, 0x90170110 },
- { }
- };
- static const struct coef_fw alc295_hp_speakers_coefs[] = {
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0000), WRITE_COEF(0x28, 0x0000), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x003f), WRITE_COEF(0x28, 0x1000), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0004), WRITE_COEF(0x28, 0x0600), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x006a), WRITE_COEF(0x28, 0x0006), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x006c), WRITE_COEF(0x28, 0xc0c0), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0008), WRITE_COEF(0x28, 0xb000), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x002e), WRITE_COEF(0x28, 0x0800), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x006a), WRITE_COEF(0x28, 0x00c1), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x006c), WRITE_COEF(0x28, 0x0320), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0039), WRITE_COEF(0x28, 0x0000), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x003b), WRITE_COEF(0x28, 0xffff), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x003c), WRITE_COEF(0x28, 0xffd0), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x003a), WRITE_COEF(0x28, 0x1dfe), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0080), WRITE_COEF(0x28, 0x0880), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x003a), WRITE_COEF(0x28, 0x0dfe), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0018), WRITE_COEF(0x28, 0x0219), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x006a), WRITE_COEF(0x28, 0x005d), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x006c), WRITE_COEF(0x28, 0x9142), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00c0), WRITE_COEF(0x28, 0x01ce), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00c1), WRITE_COEF(0x28, 0xed0c), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00c2), WRITE_COEF(0x28, 0x1c00), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00c3), WRITE_COEF(0x28, 0x0000), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00c4), WRITE_COEF(0x28, 0x0200), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00c5), WRITE_COEF(0x28, 0x0000), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00c6), WRITE_COEF(0x28, 0x0399), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00c7), WRITE_COEF(0x28, 0x2330), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00c8), WRITE_COEF(0x28, 0x1e5d), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00c9), WRITE_COEF(0x28, 0x6eff), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00ca), WRITE_COEF(0x28, 0x01c0), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00cb), WRITE_COEF(0x28, 0xed0c), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00cc), WRITE_COEF(0x28, 0x1c00), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00cd), WRITE_COEF(0x28, 0x0000), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00ce), WRITE_COEF(0x28, 0x0200), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00cf), WRITE_COEF(0x28, 0x0000), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00d0), WRITE_COEF(0x28, 0x0399), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00d1), WRITE_COEF(0x28, 0x2330), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00d2), WRITE_COEF(0x28, 0x1e5d), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00d3), WRITE_COEF(0x28, 0x6eff), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0062), WRITE_COEF(0x28, 0x8000), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0063), WRITE_COEF(0x28, 0x5f5f), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0064), WRITE_COEF(0x28, 0x1000), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0065), WRITE_COEF(0x28, 0x0000), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0066), WRITE_COEF(0x28, 0x4004), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0067), WRITE_COEF(0x28, 0x0802), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0068), WRITE_COEF(0x28, 0x890f), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0069), WRITE_COEF(0x28, 0xe021), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0070), WRITE_COEF(0x28, 0x8012), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0071), WRITE_COEF(0x28, 0x3450), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0072), WRITE_COEF(0x28, 0x0123), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0073), WRITE_COEF(0x28, 0x4543), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0074), WRITE_COEF(0x28, 0x2100), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0075), WRITE_COEF(0x28, 0x4321), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0076), WRITE_COEF(0x28, 0x0000), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0050), WRITE_COEF(0x28, 0x8200), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x003a), WRITE_COEF(0x28, 0x1dfe), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0051), WRITE_COEF(0x28, 0x0707), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0052), WRITE_COEF(0x28, 0x4090), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x006a), WRITE_COEF(0x28, 0x0090), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x006c), WRITE_COEF(0x28, 0x721f), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0012), WRITE_COEF(0x28, 0xebeb), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x009e), WRITE_COEF(0x28, 0x0000), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0060), WRITE_COEF(0x28, 0x2213), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x006a), WRITE_COEF(0x28, 0x0006), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x006c), WRITE_COEF(0x28, 0x0000), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x003f), WRITE_COEF(0x28, 0x3000), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0004), WRITE_COEF(0x28, 0x0500), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0040), WRITE_COEF(0x28, 0x800c), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0046), WRITE_COEF(0x28, 0xc22e), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x004b), WRITE_COEF(0x28, 0x0000), WRITE_COEF(0x29, 0xb024),
- WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0050), WRITE_COEF(0x28, 0x82ec), WRITE_COEF(0x29, 0xb024),
- };
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- snd_hda_apply_pincfgs(codec, pincfgs);
- alc295_fixup_disable_dac3(codec, fix, action);
- break;
- case HDA_FIXUP_ACT_INIT:
- alc_process_coef_fw(codec, alc295_hp_speakers_coefs);
- break;
- }
-}
diff --git a/sound/pci/hda/ideapad_hotkey_led_helper.c b/sound/pci/hda/ideapad_hotkey_led_helper.c
deleted file mode 100644
index c10d97964d49..000000000000
--- a/sound/pci/hda/ideapad_hotkey_led_helper.c
+++ /dev/null
@@ -1,36 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Ideapad helper functions for Lenovo Ideapad LED control,
- * It should be included from codec driver.
- */
-
-#if IS_ENABLED(CONFIG_IDEAPAD_LAPTOP)
-
-#include <linux/acpi.h>
-#include <linux/leds.h>
-
-static bool is_ideapad(struct hda_codec *codec)
-{
- return (codec->core.subsystem_id >> 16 == 0x17aa) &&
- (acpi_dev_found("LHK2019") || acpi_dev_found("VPC2004"));
-}
-
-static void hda_fixup_ideapad_acpi(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- if (!is_ideapad(codec))
- return;
- snd_hda_gen_add_mute_led_cdev(codec, NULL);
- snd_hda_gen_add_micmute_led_cdev(codec, NULL);
- }
-}
-
-#else /* CONFIG_IDEAPAD_LAPTOP */
-
-static void hda_fixup_ideapad_acpi(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
-}
-
-#endif /* CONFIG_IDEAPAD_LAPTOP */
diff --git a/sound/pci/hda/ideapad_s740_helper.c b/sound/pci/hda/ideapad_s740_helper.c
deleted file mode 100644
index 564b9086e52d..000000000000
--- a/sound/pci/hda/ideapad_s740_helper.c
+++ /dev/null
@@ -1,492 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Fixes for Lenovo Ideapad S740, to be included from codec driver */
-
-static const struct hda_verb alc285_ideapad_s740_coefs[] = {
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x10 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0320 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x24 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0041 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x24 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0041 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x007f },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x007f },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x003c },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0011 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x003c },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0011 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x000c },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x000c },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x000f },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0042 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x000f },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0042 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0003 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0009 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0003 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0009 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x001c },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x004c },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x001c },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x004c },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x001d },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x004e },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x001d },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x004e },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x001b },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x001b },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0019 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0025 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0019 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0025 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0018 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0037 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0018 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0037 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0016 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0076 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0016 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0076 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0017 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0017 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0007 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0086 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0007 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0086 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x24 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0042 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x24 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0042 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x007f },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x007f },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x003c },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0011 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x003c },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0011 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x000c },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x002a },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x000c },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x002a },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x000f },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0046 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x000f },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0046 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0044 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0044 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0003 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0009 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0003 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0009 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x001c },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x004c },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x001c },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x004c },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x001b },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x001b },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0019 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0025 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0019 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0025 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0018 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0037 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0018 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0037 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0016 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0076 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0016 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0076 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0017 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0017 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0007 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0086 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0007 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0086 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
-{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
-{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-{}
-};
-
-static void alc285_fixup_ideapad_s740_coef(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- snd_hda_add_verbs(codec, alc285_ideapad_s740_coefs);
- break;
- }
-}
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
deleted file mode 100644
index 56354fe060a1..000000000000
--- a/sound/pci/hda/patch_analog.c
+++ /dev/null
@@ -1,1176 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * HD audio interface patch for AD1882, AD1884, AD1981HD, AD1983, AD1984,
- * AD1986A, AD1988
- *
- * Copyright (c) 2005-2007 Takashi Iwai <tiwai@suse.de>
- */
-
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-
-#include <sound/core.h>
-#include <sound/hda_codec.h>
-#include "hda_local.h"
-#include "hda_auto_parser.h"
-#include "hda_beep.h"
-#include "hda_jack.h"
-#include "hda_generic.h"
-
-
-struct ad198x_spec {
- struct hda_gen_spec gen;
-
- /* for auto parser */
- int smux_paths[4];
- unsigned int cur_smux;
- hda_nid_t eapd_nid;
-
- unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
- int num_smux_conns;
-};
-
-
-#ifdef CONFIG_SND_HDA_INPUT_BEEP
-/* additional beep mixers; the actual parameters are overwritten at build */
-static const struct snd_kcontrol_new ad_beep_mixer[] = {
- HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_OUTPUT),
- HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_OUTPUT),
- { } /* end */
-};
-
-#define set_beep_amp(spec, nid, idx, dir) \
- ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) /* mono */
-#else
-#define set_beep_amp(spec, nid, idx, dir) /* NOP */
-#endif
-
-#ifdef CONFIG_SND_HDA_INPUT_BEEP
-static int create_beep_ctls(struct hda_codec *codec)
-{
- struct ad198x_spec *spec = codec->spec;
- const struct snd_kcontrol_new *knew;
-
- if (!spec->beep_amp)
- return 0;
-
- for (knew = ad_beep_mixer ; knew->name; knew++) {
- int err;
- struct snd_kcontrol *kctl;
- kctl = snd_ctl_new1(knew, codec);
- if (!kctl)
- return -ENOMEM;
- kctl->private_value = spec->beep_amp;
- err = snd_hda_ctl_add(codec, 0, kctl);
- if (err < 0)
- return err;
- }
- return 0;
-}
-#else
-#define create_beep_ctls(codec) 0
-#endif
-
-static void ad198x_power_eapd_write(struct hda_codec *codec, hda_nid_t front,
- hda_nid_t hp)
-{
- if (snd_hda_query_pin_caps(codec, front) & AC_PINCAP_EAPD)
- snd_hda_codec_write(codec, front, 0, AC_VERB_SET_EAPD_BTLENABLE,
- !codec->inv_eapd ? 0x00 : 0x02);
- if (snd_hda_query_pin_caps(codec, hp) & AC_PINCAP_EAPD)
- snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_EAPD_BTLENABLE,
- !codec->inv_eapd ? 0x00 : 0x02);
-}
-
-static void ad198x_power_eapd(struct hda_codec *codec)
-{
- /* We currently only handle front, HP */
- switch (codec->core.vendor_id) {
- case 0x11d41882:
- case 0x11d4882a:
- case 0x11d41884:
- case 0x11d41984:
- case 0x11d41883:
- case 0x11d4184a:
- case 0x11d4194a:
- case 0x11d4194b:
- case 0x11d41988:
- case 0x11d4198b:
- case 0x11d4989a:
- case 0x11d4989b:
- ad198x_power_eapd_write(codec, 0x12, 0x11);
- break;
- case 0x11d41981:
- case 0x11d41983:
- ad198x_power_eapd_write(codec, 0x05, 0x06);
- break;
- case 0x11d41986:
- ad198x_power_eapd_write(codec, 0x1b, 0x1a);
- break;
- }
-}
-
-static int ad198x_suspend(struct hda_codec *codec)
-{
- snd_hda_shutup_pins(codec);
- ad198x_power_eapd(codec);
- return 0;
-}
-
-/* follow EAPD via vmaster hook */
-static void ad_vmaster_eapd_hook(void *private_data, int enabled)
-{
- struct hda_codec *codec = private_data;
- struct ad198x_spec *spec = codec->spec;
-
- if (!spec->eapd_nid)
- return;
- if (codec->inv_eapd)
- enabled = !enabled;
- snd_hda_codec_write_cache(codec, spec->eapd_nid, 0,
- AC_VERB_SET_EAPD_BTLENABLE,
- enabled ? 0x02 : 0x00);
-}
-
-/*
- * Automatic parse of I/O pins from the BIOS configuration
- */
-
-static int ad198x_auto_build_controls(struct hda_codec *codec)
-{
- int err;
-
- err = snd_hda_gen_build_controls(codec);
- if (err < 0)
- return err;
- err = create_beep_ctls(codec);
- if (err < 0)
- return err;
- return 0;
-}
-
-static const struct hda_codec_ops ad198x_auto_patch_ops = {
- .build_controls = ad198x_auto_build_controls,
- .build_pcms = snd_hda_gen_build_pcms,
- .init = snd_hda_gen_init,
- .free = snd_hda_gen_free,
- .unsol_event = snd_hda_jack_unsol_event,
- .check_power_status = snd_hda_gen_check_power_status,
- .suspend = ad198x_suspend,
-};
-
-
-static int ad198x_parse_auto_config(struct hda_codec *codec, bool indep_hp)
-{
- struct ad198x_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->gen.autocfg;
- int err;
-
- codec->spdif_status_reset = 1;
- codec->no_trigger_sense = 1;
- codec->no_sticky_stream = 1;
-
- spec->gen.indep_hp = indep_hp;
- if (!spec->gen.add_stereo_mix_input)
- spec->gen.add_stereo_mix_input = HDA_HINT_STEREO_MIX_AUTO;
-
- err = snd_hda_parse_pin_defcfg(codec, cfg, NULL, 0);
- if (err < 0)
- return err;
- err = snd_hda_gen_parse_auto_config(codec, cfg);
- if (err < 0)
- return err;
-
- return 0;
-}
-
-/*
- * AD1986A specific
- */
-
-static int alloc_ad_spec(struct hda_codec *codec)
-{
- struct ad198x_spec *spec;
-
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (!spec)
- return -ENOMEM;
- codec->spec = spec;
- snd_hda_gen_spec_init(&spec->gen);
- codec->patch_ops = ad198x_auto_patch_ops;
- return 0;
-}
-
-/*
- * AD1986A fixup codes
- */
-
-/* Lenovo N100 seems to report the reversed bit for HP jack-sensing */
-static void ad_fixup_inv_jack_detect(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct ad198x_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- codec->inv_jack_detect = 1;
- spec->gen.keep_eapd_on = 1;
- spec->gen.vmaster_mute.hook = ad_vmaster_eapd_hook;
- spec->eapd_nid = 0x1b;
- }
-}
-
-/* Toshiba Satellite L40 implements EAPD in a standard way unlike others */
-static void ad1986a_fixup_eapd(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct ad198x_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- codec->inv_eapd = 0;
- spec->gen.keep_eapd_on = 1;
- spec->eapd_nid = 0x1b;
- }
-}
-
-/* enable stereo-mix input for avoiding regression on KDE (bko#88251) */
-static void ad1986a_fixup_eapd_mix_in(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct ad198x_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- ad1986a_fixup_eapd(codec, fix, action);
- spec->gen.add_stereo_mix_input = HDA_HINT_STEREO_MIX_ENABLE;
- }
-}
-
-enum {
- AD1986A_FIXUP_INV_JACK_DETECT,
- AD1986A_FIXUP_ULTRA,
- AD1986A_FIXUP_SAMSUNG,
- AD1986A_FIXUP_3STACK,
- AD1986A_FIXUP_LAPTOP,
- AD1986A_FIXUP_LAPTOP_IMIC,
- AD1986A_FIXUP_EAPD,
- AD1986A_FIXUP_EAPD_MIX_IN,
- AD1986A_FIXUP_EASYNOTE,
-};
-
-static const struct hda_fixup ad1986a_fixups[] = {
- [AD1986A_FIXUP_INV_JACK_DETECT] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = ad_fixup_inv_jack_detect,
- },
- [AD1986A_FIXUP_ULTRA] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1b, 0x90170110 }, /* speaker */
- { 0x1d, 0x90a7013e }, /* int mic */
- {}
- },
- },
- [AD1986A_FIXUP_SAMSUNG] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1b, 0x90170110 }, /* speaker */
- { 0x1d, 0x90a7013e }, /* int mic */
- { 0x20, 0x411111f0 }, /* N/A */
- { 0x24, 0x411111f0 }, /* N/A */
- {}
- },
- },
- [AD1986A_FIXUP_3STACK] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1a, 0x02214021 }, /* headphone */
- { 0x1b, 0x01014011 }, /* front */
- { 0x1c, 0x01813030 }, /* line-in */
- { 0x1d, 0x01a19020 }, /* rear mic */
- { 0x1e, 0x411111f0 }, /* N/A */
- { 0x1f, 0x02a190f0 }, /* mic */
- { 0x20, 0x411111f0 }, /* N/A */
- {}
- },
- },
- [AD1986A_FIXUP_LAPTOP] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1a, 0x02214021 }, /* headphone */
- { 0x1b, 0x90170110 }, /* speaker */
- { 0x1c, 0x411111f0 }, /* N/A */
- { 0x1d, 0x411111f0 }, /* N/A */
- { 0x1e, 0x411111f0 }, /* N/A */
- { 0x1f, 0x02a191f0 }, /* mic */
- { 0x20, 0x411111f0 }, /* N/A */
- {}
- },
- },
- [AD1986A_FIXUP_LAPTOP_IMIC] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1d, 0x90a7013e }, /* int mic */
- {}
- },
- .chained_before = 1,
- .chain_id = AD1986A_FIXUP_LAPTOP,
- },
- [AD1986A_FIXUP_EAPD] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = ad1986a_fixup_eapd,
- },
- [AD1986A_FIXUP_EAPD_MIX_IN] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = ad1986a_fixup_eapd_mix_in,
- },
- [AD1986A_FIXUP_EASYNOTE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1a, 0x0421402f }, /* headphone */
- { 0x1b, 0x90170110 }, /* speaker */
- { 0x1c, 0x411111f0 }, /* N/A */
- { 0x1d, 0x90a70130 }, /* int mic */
- { 0x1e, 0x411111f0 }, /* N/A */
- { 0x1f, 0x04a19040 }, /* mic */
- { 0x20, 0x411111f0 }, /* N/A */
- { 0x21, 0x411111f0 }, /* N/A */
- { 0x22, 0x411111f0 }, /* N/A */
- { 0x23, 0x411111f0 }, /* N/A */
- { 0x24, 0x411111f0 }, /* N/A */
- { 0x25, 0x411111f0 }, /* N/A */
- {}
- },
- .chained = true,
- .chain_id = AD1986A_FIXUP_EAPD_MIX_IN,
- },
-};
-
-static const struct hda_quirk ad1986a_fixup_tbl[] = {
- SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_FIXUP_LAPTOP_IMIC),
- SND_PCI_QUIRK(0x1043, 0x1153, "ASUS M9V", AD1986A_FIXUP_LAPTOP_IMIC),
- SND_PCI_QUIRK(0x1043, 0x1443, "ASUS Z99He", AD1986A_FIXUP_EAPD),
- SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8JN", AD1986A_FIXUP_EAPD),
- SND_PCI_QUIRK_MASK(0x1043, 0xff00, 0x8100, "ASUS P5", AD1986A_FIXUP_3STACK),
- SND_PCI_QUIRK_MASK(0x1043, 0xff00, 0x8200, "ASUS M2", AD1986A_FIXUP_3STACK),
- SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_FIXUP_3STACK),
- SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba Satellite L40", AD1986A_FIXUP_EAPD),
- SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_FIXUP_LAPTOP),
- SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc000, "Samsung", AD1986A_FIXUP_SAMSUNG),
- SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_FIXUP_ULTRA),
- SND_PCI_QUIRK(0x1631, 0xc022, "PackardBell EasyNote MX65", AD1986A_FIXUP_EASYNOTE),
- SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_FIXUP_INV_JACK_DETECT),
- SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_FIXUP_3STACK),
- SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_FIXUP_3STACK),
- {}
-};
-
-static const struct hda_model_fixup ad1986a_fixup_models[] = {
- { .id = AD1986A_FIXUP_3STACK, .name = "3stack" },
- { .id = AD1986A_FIXUP_LAPTOP, .name = "laptop" },
- { .id = AD1986A_FIXUP_LAPTOP_IMIC, .name = "laptop-imic" },
- { .id = AD1986A_FIXUP_LAPTOP_IMIC, .name = "laptop-eapd" }, /* alias */
- { .id = AD1986A_FIXUP_EAPD, .name = "eapd" },
- {}
-};
-
-/*
- */
-static int patch_ad1986a(struct hda_codec *codec)
-{
- int err;
- struct ad198x_spec *spec;
- static const hda_nid_t preferred_pairs[] = {
- 0x1a, 0x03,
- 0x1b, 0x03,
- 0x1c, 0x04,
- 0x1d, 0x05,
- 0x1e, 0x03,
- 0
- };
-
- err = alloc_ad_spec(codec);
- if (err < 0)
- return err;
- spec = codec->spec;
-
- /* AD1986A has the inverted EAPD implementation */
- codec->inv_eapd = 1;
-
- spec->gen.mixer_nid = 0x07;
- spec->gen.beep_nid = 0x19;
- set_beep_amp(spec, 0x18, 0, HDA_OUTPUT);
-
- /* AD1986A has a hardware problem that it can't share a stream
- * with multiple output pins. The copy of front to surrounds
- * causes noisy or silent outputs at a certain timing, e.g.
- * changing the volume.
- * So, let's disable the shared stream.
- */
- spec->gen.multiout.no_share_stream = 1;
- /* give fixed DAC/pin pairs */
- spec->gen.preferred_dacs = preferred_pairs;
-
- /* AD1986A can't manage the dynamic pin on/off smoothly */
- spec->gen.auto_mute_via_amp = 1;
-
- snd_hda_pick_fixup(codec, ad1986a_fixup_models, ad1986a_fixup_tbl,
- ad1986a_fixups);
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
-
- err = ad198x_parse_auto_config(codec, false);
- if (err < 0) {
- snd_hda_gen_free(codec);
- return err;
- }
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
-
- return 0;
-}
-
-
-/*
- * AD1983 specific
- */
-
-/*
- * SPDIF mux control for AD1983 auto-parser
- */
-static int ad1983_auto_smux_enum_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ad198x_spec *spec = codec->spec;
- static const char * const texts2[] = { "PCM", "ADC" };
- static const char * const texts3[] = { "PCM", "ADC1", "ADC2" };
- int num_conns = spec->num_smux_conns;
-
- if (num_conns == 2)
- return snd_hda_enum_helper_info(kcontrol, uinfo, 2, texts2);
- else if (num_conns == 3)
- return snd_hda_enum_helper_info(kcontrol, uinfo, 3, texts3);
- else
- return -EINVAL;
-}
-
-static int ad1983_auto_smux_enum_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ad198x_spec *spec = codec->spec;
-
- ucontrol->value.enumerated.item[0] = spec->cur_smux;
- return 0;
-}
-
-static int ad1983_auto_smux_enum_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ad198x_spec *spec = codec->spec;
- unsigned int val = ucontrol->value.enumerated.item[0];
- hda_nid_t dig_out = spec->gen.multiout.dig_out_nid;
- int num_conns = spec->num_smux_conns;
-
- if (val >= num_conns)
- return -EINVAL;
- if (spec->cur_smux == val)
- return 0;
- spec->cur_smux = val;
- snd_hda_codec_write_cache(codec, dig_out, 0,
- AC_VERB_SET_CONNECT_SEL, val);
- return 1;
-}
-
-static const struct snd_kcontrol_new ad1983_auto_smux_mixer = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "IEC958 Playback Source",
- .info = ad1983_auto_smux_enum_info,
- .get = ad1983_auto_smux_enum_get,
- .put = ad1983_auto_smux_enum_put,
-};
-
-static int ad1983_add_spdif_mux_ctl(struct hda_codec *codec)
-{
- struct ad198x_spec *spec = codec->spec;
- hda_nid_t dig_out = spec->gen.multiout.dig_out_nid;
- int num_conns;
-
- if (!dig_out)
- return 0;
- num_conns = snd_hda_get_num_conns(codec, dig_out);
- if (num_conns != 2 && num_conns != 3)
- return 0;
- spec->num_smux_conns = num_conns;
- if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &ad1983_auto_smux_mixer))
- return -ENOMEM;
- return 0;
-}
-
-static int patch_ad1983(struct hda_codec *codec)
-{
- static const hda_nid_t conn_0c[] = { 0x08 };
- static const hda_nid_t conn_0d[] = { 0x09 };
- struct ad198x_spec *spec;
- int err;
-
- err = alloc_ad_spec(codec);
- if (err < 0)
- return err;
- spec = codec->spec;
-
- spec->gen.mixer_nid = 0x0e;
- spec->gen.beep_nid = 0x10;
- set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
-
- /* limit the loopback routes not to confuse the parser */
- snd_hda_override_conn_list(codec, 0x0c, ARRAY_SIZE(conn_0c), conn_0c);
- snd_hda_override_conn_list(codec, 0x0d, ARRAY_SIZE(conn_0d), conn_0d);
-
- err = ad198x_parse_auto_config(codec, false);
- if (err < 0)
- goto error;
- err = ad1983_add_spdif_mux_ctl(codec);
- if (err < 0)
- goto error;
- return 0;
-
- error:
- snd_hda_gen_free(codec);
- return err;
-}
-
-
-/*
- * AD1981 HD specific
- */
-
-static void ad1981_fixup_hp_eapd(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct ad198x_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->gen.vmaster_mute.hook = ad_vmaster_eapd_hook;
- spec->eapd_nid = 0x05;
- }
-}
-
-/* set the upper-limit for mixer amp to 0dB for avoiding the possible
- * damage by overloading
- */
-static void ad1981_fixup_amp_override(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_PRE_PROBE)
- snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT,
- (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
- (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
- (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
- (1 << AC_AMPCAP_MUTE_SHIFT));
-}
-
-enum {
- AD1981_FIXUP_AMP_OVERRIDE,
- AD1981_FIXUP_HP_EAPD,
-};
-
-static const struct hda_fixup ad1981_fixups[] = {
- [AD1981_FIXUP_AMP_OVERRIDE] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = ad1981_fixup_amp_override,
- },
- [AD1981_FIXUP_HP_EAPD] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = ad1981_fixup_hp_eapd,
- .chained = true,
- .chain_id = AD1981_FIXUP_AMP_OVERRIDE,
- },
-};
-
-static const struct hda_quirk ad1981_fixup_tbl[] = {
- SND_PCI_QUIRK_VENDOR(0x1014, "Lenovo", AD1981_FIXUP_AMP_OVERRIDE),
- SND_PCI_QUIRK_VENDOR(0x103c, "HP", AD1981_FIXUP_HP_EAPD),
- SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", AD1981_FIXUP_AMP_OVERRIDE),
- /* HP nx6320 (reversed SSID, H/W bug) */
- SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_FIXUP_HP_EAPD),
- {}
-};
-
-static int patch_ad1981(struct hda_codec *codec)
-{
- struct ad198x_spec *spec;
- int err;
-
- err = alloc_ad_spec(codec);
- if (err < 0)
- return -ENOMEM;
- spec = codec->spec;
-
- spec->gen.mixer_nid = 0x0e;
- spec->gen.beep_nid = 0x10;
- set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT);
-
- snd_hda_pick_fixup(codec, NULL, ad1981_fixup_tbl, ad1981_fixups);
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
-
- err = ad198x_parse_auto_config(codec, false);
- if (err < 0)
- goto error;
- err = ad1983_add_spdif_mux_ctl(codec);
- if (err < 0)
- goto error;
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
-
- return 0;
-
- error:
- snd_hda_gen_free(codec);
- return err;
-}
-
-
-/*
- * AD1988
- *
- * Output pins and routes
- *
- * Pin Mix Sel DAC (*)
- * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06
- * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06
- * port-C 0x15 (mute) <- 0x2c <- 0x31 <- 05/0a
- * port-D 0x12 (mute/hp) <- 0x29 <- 04
- * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a
- * port-F 0x16 (mute) <- 0x2a <- 06
- * port-G 0x24 (mute) <- 0x27 <- 05
- * port-H 0x25 (mute) <- 0x28 <- 0a
- * mono 0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06
- *
- * DAC0 = 03h, DAC1 = 04h, DAC2 = 05h, DAC3 = 06h, DAC4 = 0ah
- * (*) DAC2/3/4 are swapped to DAC3/4/2 on AD198A rev.2 due to a h/w bug.
- *
- * Input pins and routes
- *
- * pin boost mix input # / adc input #
- * port-A 0x11 -> 0x38 -> mix 2, ADC 0
- * port-B 0x14 -> 0x39 -> mix 0, ADC 1
- * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2
- * port-D 0x12 -> 0x3d -> mix 3, ADC 8
- * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4
- * port-F 0x16 -> 0x3b -> mix 5, ADC 3
- * port-G 0x24 -> N/A -> 33:1 - mix 1, 34:1 - mix 4, ADC 6
- * port-H 0x25 -> N/A -> 33:2 - mix 1, 34:2 - mix 4, ADC 7
- *
- *
- * DAC assignment
- * 6stack - front/surr/CLFE/side/opt DACs - 04/06/05/0a/03
- * 3stack - front/surr/CLFE/opt DACs - 04/05/0a/03
- *
- * Inputs of Analog Mix (0x20)
- * 0:Port-B (front mic)
- * 1:Port-C/G/H (line-in)
- * 2:Port-A
- * 3:Port-D (line-in/2)
- * 4:Port-E/G/H (mic-in)
- * 5:Port-F (mic2-in)
- * 6:CD
- * 7:Beep
- *
- * ADC selection
- * 0:Port-A
- * 1:Port-B (front mic-in)
- * 2:Port-C (line-in)
- * 3:Port-F (mic2-in)
- * 4:Port-E (mic-in)
- * 5:CD
- * 6:Port-G
- * 7:Port-H
- * 8:Port-D (line-in/2)
- * 9:Mix
- *
- * Proposed pin assignments by the datasheet
- *
- * 6-stack
- * Port-A front headphone
- * B front mic-in
- * C rear line-in
- * D rear front-out
- * E rear mic-in
- * F rear surround
- * G rear CLFE
- * H rear side
- *
- * 3-stack
- * Port-A front headphone
- * B front mic
- * C rear line-in/surround
- * D rear front-out
- * E rear mic-in/CLFE
- *
- * laptop
- * Port-A headphone
- * B mic-in
- * C docking station
- * D internal speaker (with EAPD)
- * E/F quad mic array
- */
-
-static int ad1988_auto_smux_enum_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ad198x_spec *spec = codec->spec;
- static const char * const texts[] = {
- "PCM", "ADC1", "ADC2", "ADC3",
- };
- int num_conns = spec->num_smux_conns;
-
- if (num_conns > 4)
- num_conns = 4;
- return snd_hda_enum_helper_info(kcontrol, uinfo, num_conns, texts);
-}
-
-static int ad1988_auto_smux_enum_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ad198x_spec *spec = codec->spec;
-
- ucontrol->value.enumerated.item[0] = spec->cur_smux;
- return 0;
-}
-
-static int ad1988_auto_smux_enum_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ad198x_spec *spec = codec->spec;
- unsigned int val = ucontrol->value.enumerated.item[0];
- struct nid_path *path;
- int num_conns = spec->num_smux_conns;
-
- if (val >= num_conns)
- return -EINVAL;
- if (spec->cur_smux == val)
- return 0;
-
- mutex_lock(&codec->control_mutex);
- path = snd_hda_get_path_from_idx(codec,
- spec->smux_paths[spec->cur_smux]);
- if (path)
- snd_hda_activate_path(codec, path, false, true);
- path = snd_hda_get_path_from_idx(codec, spec->smux_paths[val]);
- if (path)
- snd_hda_activate_path(codec, path, true, true);
- spec->cur_smux = val;
- mutex_unlock(&codec->control_mutex);
- return 1;
-}
-
-static const struct snd_kcontrol_new ad1988_auto_smux_mixer = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "IEC958 Playback Source",
- .info = ad1988_auto_smux_enum_info,
- .get = ad1988_auto_smux_enum_get,
- .put = ad1988_auto_smux_enum_put,
-};
-
-static int ad1988_auto_init(struct hda_codec *codec)
-{
- struct ad198x_spec *spec = codec->spec;
- int i, err;
-
- err = snd_hda_gen_init(codec);
- if (err < 0)
- return err;
- if (!spec->gen.autocfg.dig_outs)
- return 0;
-
- for (i = 0; i < 4; i++) {
- struct nid_path *path;
- path = snd_hda_get_path_from_idx(codec, spec->smux_paths[i]);
- if (path)
- snd_hda_activate_path(codec, path, path->active, false);
- }
-
- return 0;
-}
-
-static int ad1988_add_spdif_mux_ctl(struct hda_codec *codec)
-{
- struct ad198x_spec *spec = codec->spec;
- int i, num_conns;
- /* we create four static faked paths, since AD codecs have odd
- * widget connections regarding the SPDIF out source
- */
- static const struct nid_path fake_paths[4] = {
- {
- .depth = 3,
- .path = { 0x02, 0x1d, 0x1b },
- .idx = { 0, 0, 0 },
- .multi = { 0, 0, 0 },
- },
- {
- .depth = 4,
- .path = { 0x08, 0x0b, 0x1d, 0x1b },
- .idx = { 0, 0, 1, 0 },
- .multi = { 0, 1, 0, 0 },
- },
- {
- .depth = 4,
- .path = { 0x09, 0x0b, 0x1d, 0x1b },
- .idx = { 0, 1, 1, 0 },
- .multi = { 0, 1, 0, 0 },
- },
- {
- .depth = 4,
- .path = { 0x0f, 0x0b, 0x1d, 0x1b },
- .idx = { 0, 2, 1, 0 },
- .multi = { 0, 1, 0, 0 },
- },
- };
-
- /* SPDIF source mux appears to be present only on AD1988A */
- if (!spec->gen.autocfg.dig_outs ||
- get_wcaps_type(get_wcaps(codec, 0x1d)) != AC_WID_AUD_MIX)
- return 0;
-
- num_conns = snd_hda_get_num_conns(codec, 0x0b) + 1;
- if (num_conns != 3 && num_conns != 4)
- return 0;
- spec->num_smux_conns = num_conns;
-
- for (i = 0; i < num_conns; i++) {
- struct nid_path *path = snd_array_new(&spec->gen.paths);
- if (!path)
- return -ENOMEM;
- *path = fake_paths[i];
- if (!i)
- path->active = 1;
- spec->smux_paths[i] = snd_hda_get_path_idx(codec, path);
- }
-
- if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &ad1988_auto_smux_mixer))
- return -ENOMEM;
-
- codec->patch_ops.init = ad1988_auto_init;
-
- return 0;
-}
-
-/*
- */
-
-enum {
- AD1988_FIXUP_6STACK_DIG,
-};
-
-static const struct hda_fixup ad1988_fixups[] = {
- [AD1988_FIXUP_6STACK_DIG] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x11, 0x02214130 }, /* front-hp */
- { 0x12, 0x01014010 }, /* line-out */
- { 0x14, 0x02a19122 }, /* front-mic */
- { 0x15, 0x01813021 }, /* line-in */
- { 0x16, 0x01011012 }, /* line-out */
- { 0x17, 0x01a19020 }, /* mic */
- { 0x1b, 0x0145f1f0 }, /* SPDIF */
- { 0x24, 0x01016011 }, /* line-out */
- { 0x25, 0x01012013 }, /* line-out */
- { }
- }
- },
-};
-
-static const struct hda_model_fixup ad1988_fixup_models[] = {
- { .id = AD1988_FIXUP_6STACK_DIG, .name = "6stack-dig" },
- {}
-};
-
-static int patch_ad1988(struct hda_codec *codec)
-{
- struct ad198x_spec *spec;
- int err;
-
- err = alloc_ad_spec(codec);
- if (err < 0)
- return err;
- spec = codec->spec;
-
- spec->gen.mixer_nid = 0x20;
- spec->gen.mixer_merge_nid = 0x21;
- spec->gen.beep_nid = 0x10;
- set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
-
- snd_hda_pick_fixup(codec, ad1988_fixup_models, NULL, ad1988_fixups);
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
-
- err = ad198x_parse_auto_config(codec, true);
- if (err < 0)
- goto error;
- err = ad1988_add_spdif_mux_ctl(codec);
- if (err < 0)
- goto error;
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
-
- return 0;
-
- error:
- snd_hda_gen_free(codec);
- return err;
-}
-
-
-/*
- * AD1884 / AD1984
- *
- * port-B - front line/mic-in
- * port-E - aux in/out
- * port-F - aux in/out
- * port-C - rear line/mic-in
- * port-D - rear line/hp-out
- * port-A - front line/hp-out
- *
- * AD1984 = AD1884 + two digital mic-ins
- *
- * AD1883 / AD1884A / AD1984A / AD1984B
- *
- * port-B (0x14) - front mic-in
- * port-E (0x1c) - rear mic-in
- * port-F (0x16) - CD / ext out
- * port-C (0x15) - rear line-in
- * port-D (0x12) - rear line-out
- * port-A (0x11) - front hp-out
- *
- * AD1984A = AD1884A + digital-mic
- * AD1883 = equivalent with AD1984A
- * AD1984B = AD1984A + extra SPDIF-out
- */
-
-/* set the upper-limit for mixer amp to 0dB for avoiding the possible
- * damage by overloading
- */
-static void ad1884_fixup_amp_override(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_PRE_PROBE)
- snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
- (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
- (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
- (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
- (1 << AC_AMPCAP_MUTE_SHIFT));
-}
-
-/* toggle GPIO1 according to the mute state */
-static void ad1884_vmaster_hp_gpio_hook(void *private_data, int enabled)
-{
- struct hda_codec *codec = private_data;
- struct ad198x_spec *spec = codec->spec;
-
- if (spec->eapd_nid)
- ad_vmaster_eapd_hook(private_data, enabled);
- snd_hda_codec_write_cache(codec, 0x01, 0,
- AC_VERB_SET_GPIO_DATA,
- enabled ? 0x00 : 0x02);
-}
-
-static void ad1884_fixup_hp_eapd(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct ad198x_spec *spec = codec->spec;
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- spec->gen.vmaster_mute.hook = ad1884_vmaster_hp_gpio_hook;
- spec->gen.own_eapd_ctl = 1;
- snd_hda_codec_write_cache(codec, 0x01, 0,
- AC_VERB_SET_GPIO_MASK, 0x02);
- snd_hda_codec_write_cache(codec, 0x01, 0,
- AC_VERB_SET_GPIO_DIRECTION, 0x02);
- snd_hda_codec_write_cache(codec, 0x01, 0,
- AC_VERB_SET_GPIO_DATA, 0x02);
- break;
- case HDA_FIXUP_ACT_PROBE:
- if (spec->gen.autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
- spec->eapd_nid = spec->gen.autocfg.line_out_pins[0];
- else
- spec->eapd_nid = spec->gen.autocfg.speaker_pins[0];
- break;
- }
-}
-
-static void ad1884_fixup_thinkpad(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct ad198x_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->gen.keep_eapd_on = 1;
- spec->gen.vmaster_mute.hook = ad_vmaster_eapd_hook;
- spec->eapd_nid = 0x12;
- /* Analog PC Beeper - allow firmware/ACPI beeps */
- spec->beep_amp = HDA_COMPOSE_AMP_VAL(0x20, 3, 3, HDA_INPUT);
- spec->gen.beep_nid = 0; /* no digital beep */
- }
-}
-
-/* set magic COEFs for dmic */
-static const struct hda_verb ad1884_dmic_init_verbs[] = {
- {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
- {0x01, AC_VERB_SET_PROC_COEF, 0x08},
- {}
-};
-
-enum {
- AD1884_FIXUP_AMP_OVERRIDE,
- AD1884_FIXUP_HP_EAPD,
- AD1884_FIXUP_DMIC_COEF,
- AD1884_FIXUP_THINKPAD,
- AD1884_FIXUP_HP_TOUCHSMART,
-};
-
-static const struct hda_fixup ad1884_fixups[] = {
- [AD1884_FIXUP_AMP_OVERRIDE] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = ad1884_fixup_amp_override,
- },
- [AD1884_FIXUP_HP_EAPD] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = ad1884_fixup_hp_eapd,
- .chained = true,
- .chain_id = AD1884_FIXUP_AMP_OVERRIDE,
- },
- [AD1884_FIXUP_DMIC_COEF] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = ad1884_dmic_init_verbs,
- },
- [AD1884_FIXUP_THINKPAD] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = ad1884_fixup_thinkpad,
- .chained = true,
- .chain_id = AD1884_FIXUP_DMIC_COEF,
- },
- [AD1884_FIXUP_HP_TOUCHSMART] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = ad1884_dmic_init_verbs,
- .chained = true,
- .chain_id = AD1884_FIXUP_HP_EAPD,
- },
-};
-
-static const struct hda_quirk ad1884_fixup_tbl[] = {
- SND_PCI_QUIRK(0x103c, 0x2a82, "HP Touchsmart", AD1884_FIXUP_HP_TOUCHSMART),
- SND_PCI_QUIRK_VENDOR(0x103c, "HP", AD1884_FIXUP_HP_EAPD),
- SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1884_FIXUP_THINKPAD),
- {}
-};
-
-
-static int patch_ad1884(struct hda_codec *codec)
-{
- struct ad198x_spec *spec;
- int err;
-
- err = alloc_ad_spec(codec);
- if (err < 0)
- return err;
- spec = codec->spec;
-
- spec->gen.mixer_nid = 0x20;
- spec->gen.mixer_merge_nid = 0x21;
- spec->gen.beep_nid = 0x10;
- set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
-
- snd_hda_pick_fixup(codec, NULL, ad1884_fixup_tbl, ad1884_fixups);
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
-
- err = ad198x_parse_auto_config(codec, true);
- if (err < 0)
- goto error;
- err = ad1983_add_spdif_mux_ctl(codec);
- if (err < 0)
- goto error;
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
-
- return 0;
-
- error:
- snd_hda_gen_free(codec);
- return err;
-}
-
-/*
- * AD1882 / AD1882A
- *
- * port-A - front hp-out
- * port-B - front mic-in
- * port-C - rear line-in, shared surr-out (3stack)
- * port-D - rear line-out
- * port-E - rear mic-in, shared clfe-out (3stack)
- * port-F - rear surr-out (6stack)
- * port-G - rear clfe-out (6stack)
- */
-
-static int patch_ad1882(struct hda_codec *codec)
-{
- struct ad198x_spec *spec;
- int err;
-
- err = alloc_ad_spec(codec);
- if (err < 0)
- return err;
- spec = codec->spec;
-
- spec->gen.mixer_nid = 0x20;
- spec->gen.mixer_merge_nid = 0x21;
- spec->gen.beep_nid = 0x10;
- set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
- err = ad198x_parse_auto_config(codec, true);
- if (err < 0)
- goto error;
- err = ad1988_add_spdif_mux_ctl(codec);
- if (err < 0)
- goto error;
- return 0;
-
- error:
- snd_hda_gen_free(codec);
- return err;
-}
-
-
-/*
- * patch entries
- */
-static const struct hda_device_id snd_hda_id_analog[] = {
- HDA_CODEC_ENTRY(0x11d4184a, "AD1884A", patch_ad1884),
- HDA_CODEC_ENTRY(0x11d41882, "AD1882", patch_ad1882),
- HDA_CODEC_ENTRY(0x11d41883, "AD1883", patch_ad1884),
- HDA_CODEC_ENTRY(0x11d41884, "AD1884", patch_ad1884),
- HDA_CODEC_ENTRY(0x11d4194a, "AD1984A", patch_ad1884),
- HDA_CODEC_ENTRY(0x11d4194b, "AD1984B", patch_ad1884),
- HDA_CODEC_ENTRY(0x11d41981, "AD1981", patch_ad1981),
- HDA_CODEC_ENTRY(0x11d41983, "AD1983", patch_ad1983),
- HDA_CODEC_ENTRY(0x11d41984, "AD1984", patch_ad1884),
- HDA_CODEC_ENTRY(0x11d41986, "AD1986A", patch_ad1986a),
- HDA_CODEC_ENTRY(0x11d41988, "AD1988", patch_ad1988),
- HDA_CODEC_ENTRY(0x11d4198b, "AD1988B", patch_ad1988),
- HDA_CODEC_ENTRY(0x11d4882a, "AD1882A", patch_ad1882),
- HDA_CODEC_ENTRY(0x11d4989a, "AD1989A", patch_ad1988),
- HDA_CODEC_ENTRY(0x11d4989b, "AD1989B", patch_ad1988),
- {} /* terminator */
-};
-MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_analog);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Analog Devices HD-audio codec");
-
-static struct hda_codec_driver analog_driver = {
- .id = snd_hda_id_analog,
-};
-
-module_hda_codec_driver(analog_driver);
diff --git a/sound/pci/hda/patch_ca0110.c b/sound/pci/hda/patch_ca0110.c
deleted file mode 100644
index 1818ce67f761..000000000000
--- a/sound/pci/hda/patch_ca0110.c
+++ /dev/null
@@ -1,88 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * HD audio interface patch for Creative X-Fi CA0110-IBG chip
- *
- * Copyright (c) 2008 Takashi Iwai <tiwai@suse.de>
- */
-
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <sound/core.h>
-#include <sound/hda_codec.h>
-#include "hda_local.h"
-#include "hda_auto_parser.h"
-#include "hda_jack.h"
-#include "hda_generic.h"
-
-
-static const struct hda_codec_ops ca0110_patch_ops = {
- .build_controls = snd_hda_gen_build_controls,
- .build_pcms = snd_hda_gen_build_pcms,
- .init = snd_hda_gen_init,
- .free = snd_hda_gen_free,
- .unsol_event = snd_hda_jack_unsol_event,
-};
-
-static int ca0110_parse_auto_config(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec = codec->spec;
- int err;
-
- err = snd_hda_parse_pin_defcfg(codec, &spec->autocfg, NULL, 0);
- if (err < 0)
- return err;
- err = snd_hda_gen_parse_auto_config(codec, &spec->autocfg);
- if (err < 0)
- return err;
-
- return 0;
-}
-
-
-static int patch_ca0110(struct hda_codec *codec)
-{
- struct hda_gen_spec *spec;
- int err;
-
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (!spec)
- return -ENOMEM;
- snd_hda_gen_spec_init(spec);
- codec->spec = spec;
- codec->patch_ops = ca0110_patch_ops;
-
- spec->multi_cap_vol = 1;
- codec->bus->core.needs_damn_long_delay = 1;
-
- err = ca0110_parse_auto_config(codec);
- if (err < 0)
- goto error;
-
- return 0;
-
- error:
- snd_hda_gen_free(codec);
- return err;
-}
-
-
-/*
- * patch entries
- */
-static const struct hda_device_id snd_hda_id_ca0110[] = {
- HDA_CODEC_ENTRY(0x1102000a, "CA0110-IBG", patch_ca0110),
- HDA_CODEC_ENTRY(0x1102000b, "CA0110-IBG", patch_ca0110),
- HDA_CODEC_ENTRY(0x1102000d, "SB0880 X-Fi", patch_ca0110),
- {} /* terminator */
-};
-MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_ca0110);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Creative CA0110-IBG HD-audio codec");
-
-static struct hda_codec_driver ca0110_driver = {
- .id = snd_hda_id_ca0110,
-};
-
-module_hda_codec_driver(ca0110_driver);
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c
deleted file mode 100644
index d40197fb5fbd..000000000000
--- a/sound/pci/hda/patch_ca0132.c
+++ /dev/null
@@ -1,10123 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * HD audio interface patch for Creative CA0132 chip
- *
- * Copyright (c) 2011, Creative Technology Ltd.
- *
- * Based on patch_ca0110.c
- * Copyright (c) 2008 Takashi Iwai <tiwai@suse.de>
- */
-
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-#include <linux/module.h>
-#include <linux/firmware.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/io.h>
-#include <linux/pci.h>
-#include <asm/io.h>
-#include <sound/core.h>
-#include <sound/hda_codec.h>
-#include "hda_local.h"
-#include "hda_auto_parser.h"
-#include "hda_jack.h"
-
-#include "ca0132_regs.h"
-
-/* Enable this to see controls for tuning purpose. */
-/*#define ENABLE_TUNING_CONTROLS*/
-
-#ifdef ENABLE_TUNING_CONTROLS
-#include <sound/tlv.h>
-#endif
-
-#define FLOAT_ZERO 0x00000000
-#define FLOAT_ONE 0x3f800000
-#define FLOAT_TWO 0x40000000
-#define FLOAT_THREE 0x40400000
-#define FLOAT_FIVE 0x40a00000
-#define FLOAT_SIX 0x40c00000
-#define FLOAT_EIGHT 0x41000000
-#define FLOAT_MINUS_5 0xc0a00000
-
-#define UNSOL_TAG_DSP 0x16
-
-#define DSP_DMA_WRITE_BUFLEN_INIT (1UL<<18)
-#define DSP_DMA_WRITE_BUFLEN_OVLY (1UL<<15)
-
-#define DMA_TRANSFER_FRAME_SIZE_NWORDS 8
-#define DMA_TRANSFER_MAX_FRAME_SIZE_NWORDS 32
-#define DMA_OVERLAY_FRAME_SIZE_NWORDS 2
-
-#define MASTERCONTROL 0x80
-#define MASTERCONTROL_ALLOC_DMA_CHAN 10
-#define MASTERCONTROL_QUERY_SPEAKER_EQ_ADDRESS 60
-
-#define WIDGET_CHIP_CTRL 0x15
-#define WIDGET_DSP_CTRL 0x16
-
-#define MEM_CONNID_MICIN1 3
-#define MEM_CONNID_MICIN2 5
-#define MEM_CONNID_MICOUT1 12
-#define MEM_CONNID_MICOUT2 14
-#define MEM_CONNID_WUH 10
-#define MEM_CONNID_DSP 16
-#define MEM_CONNID_DMIC 100
-
-#define SCP_SET 0
-#define SCP_GET 1
-
-#define EFX_FILE "ctefx.bin"
-#define DESKTOP_EFX_FILE "ctefx-desktop.bin"
-#define R3DI_EFX_FILE "ctefx-r3di.bin"
-
-#ifdef CONFIG_SND_HDA_CODEC_CA0132_DSP
-MODULE_FIRMWARE(EFX_FILE);
-MODULE_FIRMWARE(DESKTOP_EFX_FILE);
-MODULE_FIRMWARE(R3DI_EFX_FILE);
-#endif
-
-static const char *const dirstr[2] = { "Playback", "Capture" };
-
-#define NUM_OF_OUTPUTS 2
-static const char *const out_type_str[2] = { "Speakers", "Headphone" };
-enum {
- SPEAKER_OUT,
- HEADPHONE_OUT,
-};
-
-enum {
- DIGITAL_MIC,
- LINE_MIC_IN
-};
-
-/* Strings for Input Source Enum Control */
-static const char *const in_src_str[3] = { "Microphone", "Line In", "Front Microphone" };
-#define IN_SRC_NUM_OF_INPUTS 3
-enum {
- REAR_MIC,
- REAR_LINE_IN,
- FRONT_MIC,
-};
-
-enum {
-#define VNODE_START_NID 0x80
- VNID_SPK = VNODE_START_NID, /* Speaker vnid */
- VNID_MIC,
- VNID_HP_SEL,
- VNID_AMIC1_SEL,
- VNID_HP_ASEL,
- VNID_AMIC1_ASEL,
- VNODE_END_NID,
-#define VNODES_COUNT (VNODE_END_NID - VNODE_START_NID)
-
-#define EFFECT_START_NID 0x90
-#define OUT_EFFECT_START_NID EFFECT_START_NID
- SURROUND = OUT_EFFECT_START_NID,
- CRYSTALIZER,
- DIALOG_PLUS,
- SMART_VOLUME,
- X_BASS,
- EQUALIZER,
- OUT_EFFECT_END_NID,
-#define OUT_EFFECTS_COUNT (OUT_EFFECT_END_NID - OUT_EFFECT_START_NID)
-
-#define IN_EFFECT_START_NID OUT_EFFECT_END_NID
- ECHO_CANCELLATION = IN_EFFECT_START_NID,
- VOICE_FOCUS,
- MIC_SVM,
- NOISE_REDUCTION,
- IN_EFFECT_END_NID,
-#define IN_EFFECTS_COUNT (IN_EFFECT_END_NID - IN_EFFECT_START_NID)
-
- VOICEFX = IN_EFFECT_END_NID,
- PLAY_ENHANCEMENT,
- CRYSTAL_VOICE,
- EFFECT_END_NID,
- OUTPUT_SOURCE_ENUM,
- INPUT_SOURCE_ENUM,
- XBASS_XOVER,
- EQ_PRESET_ENUM,
- SMART_VOLUME_ENUM,
- MIC_BOOST_ENUM,
- AE5_HEADPHONE_GAIN_ENUM,
- AE5_SOUND_FILTER_ENUM,
- ZXR_HEADPHONE_GAIN,
- SPEAKER_CHANNEL_CFG_ENUM,
- SPEAKER_FULL_RANGE_FRONT,
- SPEAKER_FULL_RANGE_REAR,
- BASS_REDIRECTION,
- BASS_REDIRECTION_XOVER,
-#define EFFECTS_COUNT (EFFECT_END_NID - EFFECT_START_NID)
-};
-
-/* Effects values size*/
-#define EFFECT_VALS_MAX_COUNT 12
-
-/*
- * Default values for the effect slider controls, they are in order of their
- * effect NID's. Surround, Crystalizer, Dialog Plus, Smart Volume, and then
- * X-bass.
- */
-static const unsigned int effect_slider_defaults[] = {67, 65, 50, 74, 50};
-/* Amount of effect level sliders for ca0132_alt controls. */
-#define EFFECT_LEVEL_SLIDERS 5
-
-/* Latency introduced by DSP blocks in milliseconds. */
-#define DSP_CAPTURE_INIT_LATENCY 0
-#define DSP_CRYSTAL_VOICE_LATENCY 124
-#define DSP_PLAYBACK_INIT_LATENCY 13
-#define DSP_PLAY_ENHANCEMENT_LATENCY 30
-#define DSP_SPEAKER_OUT_LATENCY 7
-
-struct ct_effect {
- char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
- hda_nid_t nid;
- int mid; /*effect module ID*/
- int reqs[EFFECT_VALS_MAX_COUNT]; /*effect module request*/
- int direct; /* 0:output; 1:input*/
- int params; /* number of default non-on/off params */
- /*effect default values, 1st is on/off. */
- unsigned int def_vals[EFFECT_VALS_MAX_COUNT];
-};
-
-#define EFX_DIR_OUT 0
-#define EFX_DIR_IN 1
-
-static const struct ct_effect ca0132_effects[EFFECTS_COUNT] = {
- { .name = "Surround",
- .nid = SURROUND,
- .mid = 0x96,
- .reqs = {0, 1},
- .direct = EFX_DIR_OUT,
- .params = 1,
- .def_vals = {0x3F800000, 0x3F2B851F}
- },
- { .name = "Crystalizer",
- .nid = CRYSTALIZER,
- .mid = 0x96,
- .reqs = {7, 8},
- .direct = EFX_DIR_OUT,
- .params = 1,
- .def_vals = {0x3F800000, 0x3F266666}
- },
- { .name = "Dialog Plus",
- .nid = DIALOG_PLUS,
- .mid = 0x96,
- .reqs = {2, 3},
- .direct = EFX_DIR_OUT,
- .params = 1,
- .def_vals = {0x00000000, 0x3F000000}
- },
- { .name = "Smart Volume",
- .nid = SMART_VOLUME,
- .mid = 0x96,
- .reqs = {4, 5, 6},
- .direct = EFX_DIR_OUT,
- .params = 2,
- .def_vals = {0x3F800000, 0x3F3D70A4, 0x00000000}
- },
- { .name = "X-Bass",
- .nid = X_BASS,
- .mid = 0x96,
- .reqs = {24, 23, 25},
- .direct = EFX_DIR_OUT,
- .params = 2,
- .def_vals = {0x3F800000, 0x42A00000, 0x3F000000}
- },
- { .name = "Equalizer",
- .nid = EQUALIZER,
- .mid = 0x96,
- .reqs = {9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20},
- .direct = EFX_DIR_OUT,
- .params = 11,
- .def_vals = {0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000}
- },
- { .name = "Echo Cancellation",
- .nid = ECHO_CANCELLATION,
- .mid = 0x95,
- .reqs = {0, 1, 2, 3},
- .direct = EFX_DIR_IN,
- .params = 3,
- .def_vals = {0x00000000, 0x3F3A9692, 0x00000000, 0x00000000}
- },
- { .name = "Voice Focus",
- .nid = VOICE_FOCUS,
- .mid = 0x95,
- .reqs = {6, 7, 8, 9},
- .direct = EFX_DIR_IN,
- .params = 3,
- .def_vals = {0x3F800000, 0x3D7DF3B6, 0x41F00000, 0x41F00000}
- },
- { .name = "Mic SVM",
- .nid = MIC_SVM,
- .mid = 0x95,
- .reqs = {44, 45},
- .direct = EFX_DIR_IN,
- .params = 1,
- .def_vals = {0x00000000, 0x3F3D70A4}
- },
- { .name = "Noise Reduction",
- .nid = NOISE_REDUCTION,
- .mid = 0x95,
- .reqs = {4, 5},
- .direct = EFX_DIR_IN,
- .params = 1,
- .def_vals = {0x3F800000, 0x3F000000}
- },
- { .name = "VoiceFX",
- .nid = VOICEFX,
- .mid = 0x95,
- .reqs = {10, 11, 12, 13, 14, 15, 16, 17, 18},
- .direct = EFX_DIR_IN,
- .params = 8,
- .def_vals = {0x00000000, 0x43C80000, 0x44AF0000, 0x44FA0000,
- 0x3F800000, 0x3F800000, 0x3F800000, 0x00000000,
- 0x00000000}
- }
-};
-
-/* Tuning controls */
-#ifdef ENABLE_TUNING_CONTROLS
-
-enum {
-#define TUNING_CTL_START_NID 0xC0
- WEDGE_ANGLE = TUNING_CTL_START_NID,
- SVM_LEVEL,
- EQUALIZER_BAND_0,
- EQUALIZER_BAND_1,
- EQUALIZER_BAND_2,
- EQUALIZER_BAND_3,
- EQUALIZER_BAND_4,
- EQUALIZER_BAND_5,
- EQUALIZER_BAND_6,
- EQUALIZER_BAND_7,
- EQUALIZER_BAND_8,
- EQUALIZER_BAND_9,
- TUNING_CTL_END_NID
-#define TUNING_CTLS_COUNT (TUNING_CTL_END_NID - TUNING_CTL_START_NID)
-};
-
-struct ct_tuning_ctl {
- char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
- hda_nid_t parent_nid;
- hda_nid_t nid;
- int mid; /*effect module ID*/
- int req; /*effect module request*/
- int direct; /* 0:output; 1:input*/
- unsigned int def_val;/*effect default values*/
-};
-
-static const struct ct_tuning_ctl ca0132_tuning_ctls[] = {
- { .name = "Wedge Angle",
- .parent_nid = VOICE_FOCUS,
- .nid = WEDGE_ANGLE,
- .mid = 0x95,
- .req = 8,
- .direct = EFX_DIR_IN,
- .def_val = 0x41F00000
- },
- { .name = "SVM Level",
- .parent_nid = MIC_SVM,
- .nid = SVM_LEVEL,
- .mid = 0x95,
- .req = 45,
- .direct = EFX_DIR_IN,
- .def_val = 0x3F3D70A4
- },
- { .name = "EQ Band0",
- .parent_nid = EQUALIZER,
- .nid = EQUALIZER_BAND_0,
- .mid = 0x96,
- .req = 11,
- .direct = EFX_DIR_OUT,
- .def_val = 0x00000000
- },
- { .name = "EQ Band1",
- .parent_nid = EQUALIZER,
- .nid = EQUALIZER_BAND_1,
- .mid = 0x96,
- .req = 12,
- .direct = EFX_DIR_OUT,
- .def_val = 0x00000000
- },
- { .name = "EQ Band2",
- .parent_nid = EQUALIZER,
- .nid = EQUALIZER_BAND_2,
- .mid = 0x96,
- .req = 13,
- .direct = EFX_DIR_OUT,
- .def_val = 0x00000000
- },
- { .name = "EQ Band3",
- .parent_nid = EQUALIZER,
- .nid = EQUALIZER_BAND_3,
- .mid = 0x96,
- .req = 14,
- .direct = EFX_DIR_OUT,
- .def_val = 0x00000000
- },
- { .name = "EQ Band4",
- .parent_nid = EQUALIZER,
- .nid = EQUALIZER_BAND_4,
- .mid = 0x96,
- .req = 15,
- .direct = EFX_DIR_OUT,
- .def_val = 0x00000000
- },
- { .name = "EQ Band5",
- .parent_nid = EQUALIZER,
- .nid = EQUALIZER_BAND_5,
- .mid = 0x96,
- .req = 16,
- .direct = EFX_DIR_OUT,
- .def_val = 0x00000000
- },
- { .name = "EQ Band6",
- .parent_nid = EQUALIZER,
- .nid = EQUALIZER_BAND_6,
- .mid = 0x96,
- .req = 17,
- .direct = EFX_DIR_OUT,
- .def_val = 0x00000000
- },
- { .name = "EQ Band7",
- .parent_nid = EQUALIZER,
- .nid = EQUALIZER_BAND_7,
- .mid = 0x96,
- .req = 18,
- .direct = EFX_DIR_OUT,
- .def_val = 0x00000000
- },
- { .name = "EQ Band8",
- .parent_nid = EQUALIZER,
- .nid = EQUALIZER_BAND_8,
- .mid = 0x96,
- .req = 19,
- .direct = EFX_DIR_OUT,
- .def_val = 0x00000000
- },
- { .name = "EQ Band9",
- .parent_nid = EQUALIZER,
- .nid = EQUALIZER_BAND_9,
- .mid = 0x96,
- .req = 20,
- .direct = EFX_DIR_OUT,
- .def_val = 0x00000000
- }
-};
-#endif
-
-/* Voice FX Presets */
-#define VOICEFX_MAX_PARAM_COUNT 9
-
-struct ct_voicefx {
- char *name;
- hda_nid_t nid;
- int mid;
- int reqs[VOICEFX_MAX_PARAM_COUNT]; /*effect module request*/
-};
-
-struct ct_voicefx_preset {
- char *name; /*preset name*/
- unsigned int vals[VOICEFX_MAX_PARAM_COUNT];
-};
-
-static const struct ct_voicefx ca0132_voicefx = {
- .name = "VoiceFX Capture Switch",
- .nid = VOICEFX,
- .mid = 0x95,
- .reqs = {10, 11, 12, 13, 14, 15, 16, 17, 18}
-};
-
-static const struct ct_voicefx_preset ca0132_voicefx_presets[] = {
- { .name = "Neutral",
- .vals = { 0x00000000, 0x43C80000, 0x44AF0000,
- 0x44FA0000, 0x3F800000, 0x3F800000,
- 0x3F800000, 0x00000000, 0x00000000 }
- },
- { .name = "Female2Male",
- .vals = { 0x3F800000, 0x43C80000, 0x44AF0000,
- 0x44FA0000, 0x3F19999A, 0x3F866666,
- 0x3F800000, 0x00000000, 0x00000000 }
- },
- { .name = "Male2Female",
- .vals = { 0x3F800000, 0x43C80000, 0x44AF0000,
- 0x450AC000, 0x4017AE14, 0x3F6B851F,
- 0x3F800000, 0x00000000, 0x00000000 }
- },
- { .name = "ScrappyKid",
- .vals = { 0x3F800000, 0x43C80000, 0x44AF0000,
- 0x44FA0000, 0x40400000, 0x3F28F5C3,
- 0x3F800000, 0x00000000, 0x00000000 }
- },
- { .name = "Elderly",
- .vals = { 0x3F800000, 0x44324000, 0x44BB8000,
- 0x44E10000, 0x3FB33333, 0x3FB9999A,
- 0x3F800000, 0x3E3A2E43, 0x00000000 }
- },
- { .name = "Orc",
- .vals = { 0x3F800000, 0x43EA0000, 0x44A52000,
- 0x45098000, 0x3F266666, 0x3FC00000,
- 0x3F800000, 0x00000000, 0x00000000 }
- },
- { .name = "Elf",
- .vals = { 0x3F800000, 0x43C70000, 0x44AE6000,
- 0x45193000, 0x3F8E147B, 0x3F75C28F,
- 0x3F800000, 0x00000000, 0x00000000 }
- },
- { .name = "Dwarf",
- .vals = { 0x3F800000, 0x43930000, 0x44BEE000,
- 0x45007000, 0x3F451EB8, 0x3F7851EC,
- 0x3F800000, 0x00000000, 0x00000000 }
- },
- { .name = "AlienBrute",
- .vals = { 0x3F800000, 0x43BFC5AC, 0x44B28FDF,
- 0x451F6000, 0x3F266666, 0x3FA7D945,
- 0x3F800000, 0x3CF5C28F, 0x00000000 }
- },
- { .name = "Robot",
- .vals = { 0x3F800000, 0x43C80000, 0x44AF0000,
- 0x44FA0000, 0x3FB2718B, 0x3F800000,
- 0xBC07010E, 0x00000000, 0x00000000 }
- },
- { .name = "Marine",
- .vals = { 0x3F800000, 0x43C20000, 0x44906000,
- 0x44E70000, 0x3F4CCCCD, 0x3F8A3D71,
- 0x3F0A3D71, 0x00000000, 0x00000000 }
- },
- { .name = "Emo",
- .vals = { 0x3F800000, 0x43C80000, 0x44AF0000,
- 0x44FA0000, 0x3F800000, 0x3F800000,
- 0x3E4CCCCD, 0x00000000, 0x00000000 }
- },
- { .name = "DeepVoice",
- .vals = { 0x3F800000, 0x43A9C5AC, 0x44AA4FDF,
- 0x44FFC000, 0x3EDBB56F, 0x3F99C4CA,
- 0x3F800000, 0x00000000, 0x00000000 }
- },
- { .name = "Munchkin",
- .vals = { 0x3F800000, 0x43C80000, 0x44AF0000,
- 0x44FA0000, 0x3F800000, 0x3F1A043C,
- 0x3F800000, 0x00000000, 0x00000000 }
- }
-};
-
-/* ca0132 EQ presets, taken from Windows Sound Blaster Z Driver */
-
-#define EQ_PRESET_MAX_PARAM_COUNT 11
-
-struct ct_eq {
- char *name;
- hda_nid_t nid;
- int mid;
- int reqs[EQ_PRESET_MAX_PARAM_COUNT]; /*effect module request*/
-};
-
-struct ct_eq_preset {
- char *name; /*preset name*/
- unsigned int vals[EQ_PRESET_MAX_PARAM_COUNT];
-};
-
-static const struct ct_eq ca0132_alt_eq_enum = {
- .name = "FX: Equalizer Preset Switch",
- .nid = EQ_PRESET_ENUM,
- .mid = 0x96,
- .reqs = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}
-};
-
-
-static const struct ct_eq_preset ca0132_alt_eq_presets[] = {
- { .name = "Flat",
- .vals = { 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000 }
- },
- { .name = "Acoustic",
- .vals = { 0x00000000, 0x00000000, 0x3F8CCCCD,
- 0x40000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x40000000,
- 0x40000000, 0x40000000 }
- },
- { .name = "Classical",
- .vals = { 0x00000000, 0x00000000, 0x40C00000,
- 0x40C00000, 0x40466666, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000,
- 0x40466666, 0x40466666 }
- },
- { .name = "Country",
- .vals = { 0x00000000, 0xBF99999A, 0x00000000,
- 0x3FA66666, 0x3FA66666, 0x3F8CCCCD,
- 0x00000000, 0x00000000, 0x40000000,
- 0x40466666, 0x40800000 }
- },
- { .name = "Dance",
- .vals = { 0x00000000, 0xBF99999A, 0x40000000,
- 0x40466666, 0x40866666, 0xBF99999A,
- 0xBF99999A, 0x00000000, 0x00000000,
- 0x40800000, 0x40800000 }
- },
- { .name = "Jazz",
- .vals = { 0x00000000, 0x00000000, 0x00000000,
- 0x3F8CCCCD, 0x40800000, 0x40800000,
- 0x40800000, 0x00000000, 0x3F8CCCCD,
- 0x40466666, 0x40466666 }
- },
- { .name = "New Age",
- .vals = { 0x00000000, 0x00000000, 0x40000000,
- 0x40000000, 0x00000000, 0x00000000,
- 0x00000000, 0x3F8CCCCD, 0x40000000,
- 0x40000000, 0x40000000 }
- },
- { .name = "Pop",
- .vals = { 0x00000000, 0xBFCCCCCD, 0x00000000,
- 0x40000000, 0x40000000, 0x00000000,
- 0xBF99999A, 0xBF99999A, 0x00000000,
- 0x40466666, 0x40C00000 }
- },
- { .name = "Rock",
- .vals = { 0x00000000, 0xBF99999A, 0xBF99999A,
- 0x3F8CCCCD, 0x40000000, 0xBF99999A,
- 0xBF99999A, 0x00000000, 0x00000000,
- 0x40800000, 0x40800000 }
- },
- { .name = "Vocal",
- .vals = { 0x00000000, 0xC0000000, 0xBF99999A,
- 0xBF99999A, 0x00000000, 0x40466666,
- 0x40800000, 0x40466666, 0x00000000,
- 0x00000000, 0x3F8CCCCD }
- }
-};
-
-/*
- * DSP reqs for handling full-range speakers/bass redirection. If a speaker is
- * set as not being full range, and bass redirection is enabled, all
- * frequencies below the crossover frequency are redirected to the LFE
- * channel. If the surround configuration has no LFE channel, this can't be
- * enabled. X-Bass must be disabled when using these.
- */
-enum speaker_range_reqs {
- SPEAKER_BASS_REDIRECT = 0x15,
- SPEAKER_BASS_REDIRECT_XOVER_FREQ = 0x16,
- /* Between 0x16-0x1a are the X-Bass reqs. */
- SPEAKER_FULL_RANGE_FRONT_L_R = 0x1a,
- SPEAKER_FULL_RANGE_CENTER_LFE = 0x1b,
- SPEAKER_FULL_RANGE_REAR_L_R = 0x1c,
- SPEAKER_FULL_RANGE_SURROUND_L_R = 0x1d,
- SPEAKER_BASS_REDIRECT_SUB_GAIN = 0x1e,
-};
-
-/*
- * Definitions for the DSP req's to handle speaker tuning. These all belong to
- * module ID 0x96, the output effects module.
- */
-enum speaker_tuning_reqs {
- /*
- * Currently, this value is always set to 0.0f. However, on Windows,
- * when selecting certain headphone profiles on the new Sound Blaster
- * connect software, the QUERY_SPEAKER_EQ_ADDRESS req on mid 0x80 is
- * sent. This gets the speaker EQ address area, which is then used to
- * send over (presumably) an equalizer profile for the specific
- * headphone setup. It is sent using the same method the DSP
- * firmware is uploaded with, which I believe is why the 'ctspeq.bin'
- * file exists in linux firmware tree but goes unused. It would also
- * explain why the QUERY_SPEAKER_EQ_ADDRESS req is defined but unused.
- * Once this profile is sent over, SPEAKER_TUNING_USE_SPEAKER_EQ is
- * set to 1.0f.
- */
- SPEAKER_TUNING_USE_SPEAKER_EQ = 0x1f,
- SPEAKER_TUNING_ENABLE_CENTER_EQ = 0x20,
- SPEAKER_TUNING_FRONT_LEFT_VOL_LEVEL = 0x21,
- SPEAKER_TUNING_FRONT_RIGHT_VOL_LEVEL = 0x22,
- SPEAKER_TUNING_CENTER_VOL_LEVEL = 0x23,
- SPEAKER_TUNING_LFE_VOL_LEVEL = 0x24,
- SPEAKER_TUNING_REAR_LEFT_VOL_LEVEL = 0x25,
- SPEAKER_TUNING_REAR_RIGHT_VOL_LEVEL = 0x26,
- SPEAKER_TUNING_SURROUND_LEFT_VOL_LEVEL = 0x27,
- SPEAKER_TUNING_SURROUND_RIGHT_VOL_LEVEL = 0x28,
- /*
- * Inversion is used when setting headphone virtualization to line
- * out. Not sure why this is, but it's the only place it's ever used.
- */
- SPEAKER_TUNING_FRONT_LEFT_INVERT = 0x29,
- SPEAKER_TUNING_FRONT_RIGHT_INVERT = 0x2a,
- SPEAKER_TUNING_CENTER_INVERT = 0x2b,
- SPEAKER_TUNING_LFE_INVERT = 0x2c,
- SPEAKER_TUNING_REAR_LEFT_INVERT = 0x2d,
- SPEAKER_TUNING_REAR_RIGHT_INVERT = 0x2e,
- SPEAKER_TUNING_SURROUND_LEFT_INVERT = 0x2f,
- SPEAKER_TUNING_SURROUND_RIGHT_INVERT = 0x30,
- /* Delay is used when setting surround speaker distance in Windows. */
- SPEAKER_TUNING_FRONT_LEFT_DELAY = 0x31,
- SPEAKER_TUNING_FRONT_RIGHT_DELAY = 0x32,
- SPEAKER_TUNING_CENTER_DELAY = 0x33,
- SPEAKER_TUNING_LFE_DELAY = 0x34,
- SPEAKER_TUNING_REAR_LEFT_DELAY = 0x35,
- SPEAKER_TUNING_REAR_RIGHT_DELAY = 0x36,
- SPEAKER_TUNING_SURROUND_LEFT_DELAY = 0x37,
- SPEAKER_TUNING_SURROUND_RIGHT_DELAY = 0x38,
- /* Of these two, only mute seems to ever be used. */
- SPEAKER_TUNING_MAIN_VOLUME = 0x39,
- SPEAKER_TUNING_MUTE = 0x3a,
-};
-
-/* Surround output channel count configuration structures. */
-#define SPEAKER_CHANNEL_CFG_COUNT 5
-enum {
- SPEAKER_CHANNELS_2_0,
- SPEAKER_CHANNELS_2_1,
- SPEAKER_CHANNELS_4_0,
- SPEAKER_CHANNELS_4_1,
- SPEAKER_CHANNELS_5_1,
-};
-
-struct ca0132_alt_speaker_channel_cfg {
- char *name;
- unsigned int val;
-};
-
-static const struct ca0132_alt_speaker_channel_cfg speaker_channel_cfgs[] = {
- { .name = "2.0",
- .val = FLOAT_ONE
- },
- { .name = "2.1",
- .val = FLOAT_TWO
- },
- { .name = "4.0",
- .val = FLOAT_FIVE
- },
- { .name = "4.1",
- .val = FLOAT_SIX
- },
- { .name = "5.1",
- .val = FLOAT_EIGHT
- }
-};
-
-/*
- * DSP volume setting structs. Req 1 is left volume, req 2 is right volume,
- * and I don't know what the third req is, but it's always zero. I assume it's
- * some sort of update or set command to tell the DSP there's new volume info.
- */
-#define DSP_VOL_OUT 0
-#define DSP_VOL_IN 1
-
-struct ct_dsp_volume_ctl {
- hda_nid_t vnid;
- int mid; /* module ID*/
- unsigned int reqs[3]; /* scp req ID */
-};
-
-static const struct ct_dsp_volume_ctl ca0132_alt_vol_ctls[] = {
- { .vnid = VNID_SPK,
- .mid = 0x32,
- .reqs = {3, 4, 2}
- },
- { .vnid = VNID_MIC,
- .mid = 0x37,
- .reqs = {2, 3, 1}
- }
-};
-
-/* Values for ca0113_mmio_command_set for selecting output. */
-#define AE_CA0113_OUT_SET_COMMANDS 6
-struct ae_ca0113_output_set {
- unsigned int group[AE_CA0113_OUT_SET_COMMANDS];
- unsigned int target[AE_CA0113_OUT_SET_COMMANDS];
- unsigned int vals[NUM_OF_OUTPUTS][AE_CA0113_OUT_SET_COMMANDS];
-};
-
-static const struct ae_ca0113_output_set ae5_ca0113_output_presets = {
- .group = { 0x30, 0x30, 0x48, 0x48, 0x48, 0x30 },
- .target = { 0x2e, 0x30, 0x0d, 0x17, 0x19, 0x32 },
- /* Speakers. */
- .vals = { { 0x00, 0x00, 0x40, 0x00, 0x00, 0x3f },
- /* Headphones. */
- { 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00 } },
-};
-
-static const struct ae_ca0113_output_set ae7_ca0113_output_presets = {
- .group = { 0x30, 0x30, 0x48, 0x48, 0x48, 0x30 },
- .target = { 0x2e, 0x30, 0x0d, 0x17, 0x19, 0x32 },
- /* Speakers. */
- .vals = { { 0x00, 0x00, 0x40, 0x00, 0x00, 0x3f },
- /* Headphones. */
- { 0x3f, 0x3f, 0x00, 0x00, 0x02, 0x00 } },
-};
-
-/* ae5 ca0113 command sequences to set headphone gain levels. */
-#define AE5_HEADPHONE_GAIN_PRESET_MAX_COMMANDS 4
-struct ae5_headphone_gain_set {
- char *name;
- unsigned int vals[AE5_HEADPHONE_GAIN_PRESET_MAX_COMMANDS];
-};
-
-static const struct ae5_headphone_gain_set ae5_headphone_gain_presets[] = {
- { .name = "Low (16-31",
- .vals = { 0xff, 0x2c, 0xf5, 0x32 }
- },
- { .name = "Medium (32-149",
- .vals = { 0x38, 0xa8, 0x3e, 0x4c }
- },
- { .name = "High (150-600",
- .vals = { 0xff, 0xff, 0xff, 0x7f }
- }
-};
-
-struct ae5_filter_set {
- char *name;
- unsigned int val;
-};
-
-static const struct ae5_filter_set ae5_filter_presets[] = {
- { .name = "Slow Roll Off",
- .val = 0xa0
- },
- { .name = "Minimum Phase",
- .val = 0xc0
- },
- { .name = "Fast Roll Off",
- .val = 0x80
- }
-};
-
-/*
- * Data structures for storing audio router remapping data. These are used to
- * remap a currently active streams ports.
- */
-struct chipio_stream_remap_data {
- unsigned int stream_id;
- unsigned int count;
-
- unsigned int offset[16];
- unsigned int value[16];
-};
-
-static const struct chipio_stream_remap_data stream_remap_data[] = {
- { .stream_id = 0x14,
- .count = 0x04,
- .offset = { 0x00, 0x04, 0x08, 0x0c },
- .value = { 0x0001f8c0, 0x0001f9c1, 0x0001fac6, 0x0001fbc7 },
- },
- { .stream_id = 0x0c,
- .count = 0x0c,
- .offset = { 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c,
- 0x20, 0x24, 0x28, 0x2c },
- .value = { 0x0001e0c0, 0x0001e1c1, 0x0001e4c2, 0x0001e5c3,
- 0x0001e2c4, 0x0001e3c5, 0x0001e8c6, 0x0001e9c7,
- 0x0001ecc8, 0x0001edc9, 0x0001eaca, 0x0001ebcb },
- },
- { .stream_id = 0x0c,
- .count = 0x08,
- .offset = { 0x08, 0x0c, 0x10, 0x14, 0x20, 0x24, 0x28, 0x2c },
- .value = { 0x000140c2, 0x000141c3, 0x000150c4, 0x000151c5,
- 0x000142c8, 0x000143c9, 0x000152ca, 0x000153cb },
- }
-};
-
-enum hda_cmd_vendor_io {
- /* for DspIO node */
- VENDOR_DSPIO_SCP_WRITE_DATA_LOW = 0x000,
- VENDOR_DSPIO_SCP_WRITE_DATA_HIGH = 0x100,
-
- VENDOR_DSPIO_STATUS = 0xF01,
- VENDOR_DSPIO_SCP_POST_READ_DATA = 0x702,
- VENDOR_DSPIO_SCP_READ_DATA = 0xF02,
- VENDOR_DSPIO_DSP_INIT = 0x703,
- VENDOR_DSPIO_SCP_POST_COUNT_QUERY = 0x704,
- VENDOR_DSPIO_SCP_READ_COUNT = 0xF04,
-
- /* for ChipIO node */
- VENDOR_CHIPIO_ADDRESS_LOW = 0x000,
- VENDOR_CHIPIO_ADDRESS_HIGH = 0x100,
- VENDOR_CHIPIO_STREAM_FORMAT = 0x200,
- VENDOR_CHIPIO_DATA_LOW = 0x300,
- VENDOR_CHIPIO_DATA_HIGH = 0x400,
-
- VENDOR_CHIPIO_8051_WRITE_DIRECT = 0x500,
- VENDOR_CHIPIO_8051_READ_DIRECT = 0xD00,
-
- VENDOR_CHIPIO_GET_PARAMETER = 0xF00,
- VENDOR_CHIPIO_STATUS = 0xF01,
- VENDOR_CHIPIO_HIC_POST_READ = 0x702,
- VENDOR_CHIPIO_HIC_READ_DATA = 0xF03,
-
- VENDOR_CHIPIO_8051_DATA_WRITE = 0x707,
- VENDOR_CHIPIO_8051_DATA_READ = 0xF07,
- VENDOR_CHIPIO_8051_PMEM_READ = 0xF08,
- VENDOR_CHIPIO_8051_IRAM_WRITE = 0x709,
- VENDOR_CHIPIO_8051_IRAM_READ = 0xF09,
-
- VENDOR_CHIPIO_CT_EXTENSIONS_ENABLE = 0x70A,
- VENDOR_CHIPIO_CT_EXTENSIONS_GET = 0xF0A,
-
- VENDOR_CHIPIO_PLL_PMU_WRITE = 0x70C,
- VENDOR_CHIPIO_PLL_PMU_READ = 0xF0C,
- VENDOR_CHIPIO_8051_ADDRESS_LOW = 0x70D,
- VENDOR_CHIPIO_8051_ADDRESS_HIGH = 0x70E,
- VENDOR_CHIPIO_FLAG_SET = 0x70F,
- VENDOR_CHIPIO_FLAGS_GET = 0xF0F,
- VENDOR_CHIPIO_PARAM_SET = 0x710,
- VENDOR_CHIPIO_PARAM_GET = 0xF10,
-
- VENDOR_CHIPIO_PORT_ALLOC_CONFIG_SET = 0x711,
- VENDOR_CHIPIO_PORT_ALLOC_SET = 0x712,
- VENDOR_CHIPIO_PORT_ALLOC_GET = 0xF12,
- VENDOR_CHIPIO_PORT_FREE_SET = 0x713,
-
- VENDOR_CHIPIO_PARAM_EX_ID_GET = 0xF17,
- VENDOR_CHIPIO_PARAM_EX_ID_SET = 0x717,
- VENDOR_CHIPIO_PARAM_EX_VALUE_GET = 0xF18,
- VENDOR_CHIPIO_PARAM_EX_VALUE_SET = 0x718,
-
- VENDOR_CHIPIO_DMIC_CTL_SET = 0x788,
- VENDOR_CHIPIO_DMIC_CTL_GET = 0xF88,
- VENDOR_CHIPIO_DMIC_PIN_SET = 0x789,
- VENDOR_CHIPIO_DMIC_PIN_GET = 0xF89,
- VENDOR_CHIPIO_DMIC_MCLK_SET = 0x78A,
- VENDOR_CHIPIO_DMIC_MCLK_GET = 0xF8A,
-
- VENDOR_CHIPIO_EAPD_SEL_SET = 0x78D
-};
-
-/*
- * Control flag IDs
- */
-enum control_flag_id {
- /* Connection manager stream setup is bypassed/enabled */
- CONTROL_FLAG_C_MGR = 0,
- /* DSP DMA is bypassed/enabled */
- CONTROL_FLAG_DMA = 1,
- /* 8051 'idle' mode is disabled/enabled */
- CONTROL_FLAG_IDLE_ENABLE = 2,
- /* Tracker for the SPDIF-in path is bypassed/enabled */
- CONTROL_FLAG_TRACKER = 3,
- /* DigitalOut to Spdif2Out connection is disabled/enabled */
- CONTROL_FLAG_SPDIF2OUT = 4,
- /* Digital Microphone is disabled/enabled */
- CONTROL_FLAG_DMIC = 5,
- /* ADC_B rate is 48 kHz/96 kHz */
- CONTROL_FLAG_ADC_B_96KHZ = 6,
- /* ADC_C rate is 48 kHz/96 kHz */
- CONTROL_FLAG_ADC_C_96KHZ = 7,
- /* DAC rate is 48 kHz/96 kHz (affects all DACs) */
- CONTROL_FLAG_DAC_96KHZ = 8,
- /* DSP rate is 48 kHz/96 kHz */
- CONTROL_FLAG_DSP_96KHZ = 9,
- /* SRC clock is 98 MHz/196 MHz (196 MHz forces rate to 96 KHz) */
- CONTROL_FLAG_SRC_CLOCK_196MHZ = 10,
- /* SRC rate is 48 kHz/96 kHz (48 kHz disabled when clock is 196 MHz) */
- CONTROL_FLAG_SRC_RATE_96KHZ = 11,
- /* Decode Loop (DSP->SRC->DSP) is disabled/enabled */
- CONTROL_FLAG_DECODE_LOOP = 12,
- /* De-emphasis filter on DAC-1 disabled/enabled */
- CONTROL_FLAG_DAC1_DEEMPHASIS = 13,
- /* De-emphasis filter on DAC-2 disabled/enabled */
- CONTROL_FLAG_DAC2_DEEMPHASIS = 14,
- /* De-emphasis filter on DAC-3 disabled/enabled */
- CONTROL_FLAG_DAC3_DEEMPHASIS = 15,
- /* High-pass filter on ADC_B disabled/enabled */
- CONTROL_FLAG_ADC_B_HIGH_PASS = 16,
- /* High-pass filter on ADC_C disabled/enabled */
- CONTROL_FLAG_ADC_C_HIGH_PASS = 17,
- /* Common mode on Port_A disabled/enabled */
- CONTROL_FLAG_PORT_A_COMMON_MODE = 18,
- /* Common mode on Port_D disabled/enabled */
- CONTROL_FLAG_PORT_D_COMMON_MODE = 19,
- /* Impedance for ramp generator on Port_A 16 Ohm/10K Ohm */
- CONTROL_FLAG_PORT_A_10KOHM_LOAD = 20,
- /* Impedance for ramp generator on Port_D, 16 Ohm/10K Ohm */
- CONTROL_FLAG_PORT_D_10KOHM_LOAD = 21,
- /* ASI rate is 48kHz/96kHz */
- CONTROL_FLAG_ASI_96KHZ = 22,
- /* DAC power settings able to control attached ports no/yes */
- CONTROL_FLAG_DACS_CONTROL_PORTS = 23,
- /* Clock Stop OK reporting is disabled/enabled */
- CONTROL_FLAG_CONTROL_STOP_OK_ENABLE = 24,
- /* Number of control flags */
- CONTROL_FLAGS_MAX = (CONTROL_FLAG_CONTROL_STOP_OK_ENABLE+1)
-};
-
-/*
- * Control parameter IDs
- */
-enum control_param_id {
- /* 0: None, 1: Mic1In*/
- CONTROL_PARAM_VIP_SOURCE = 1,
- /* 0: force HDA, 1: allow DSP if HDA Spdif1Out stream is idle */
- CONTROL_PARAM_SPDIF1_SOURCE = 2,
- /* Port A output stage gain setting to use when 16 Ohm output
- * impedance is selected*/
- CONTROL_PARAM_PORTA_160OHM_GAIN = 8,
- /* Port D output stage gain setting to use when 16 Ohm output
- * impedance is selected*/
- CONTROL_PARAM_PORTD_160OHM_GAIN = 10,
-
- /*
- * This control param name was found in the 8051 memory, and makes
- * sense given the fact the AE-5 uses it and has the ASI flag set.
- */
- CONTROL_PARAM_ASI = 23,
-
- /* Stream Control */
-
- /* Select stream with the given ID */
- CONTROL_PARAM_STREAM_ID = 24,
- /* Source connection point for the selected stream */
- CONTROL_PARAM_STREAM_SOURCE_CONN_POINT = 25,
- /* Destination connection point for the selected stream */
- CONTROL_PARAM_STREAM_DEST_CONN_POINT = 26,
- /* Number of audio channels in the selected stream */
- CONTROL_PARAM_STREAMS_CHANNELS = 27,
- /*Enable control for the selected stream */
- CONTROL_PARAM_STREAM_CONTROL = 28,
-
- /* Connection Point Control */
-
- /* Select connection point with the given ID */
- CONTROL_PARAM_CONN_POINT_ID = 29,
- /* Connection point sample rate */
- CONTROL_PARAM_CONN_POINT_SAMPLE_RATE = 30,
-
- /* Node Control */
-
- /* Select HDA node with the given ID */
- CONTROL_PARAM_NODE_ID = 31
-};
-
-/*
- * Dsp Io Status codes
- */
-enum hda_vendor_status_dspio {
- /* Success */
- VENDOR_STATUS_DSPIO_OK = 0x00,
- /* Busy, unable to accept new command, the host must retry */
- VENDOR_STATUS_DSPIO_BUSY = 0x01,
- /* SCP command queue is full */
- VENDOR_STATUS_DSPIO_SCP_COMMAND_QUEUE_FULL = 0x02,
- /* SCP response queue is empty */
- VENDOR_STATUS_DSPIO_SCP_RESPONSE_QUEUE_EMPTY = 0x03
-};
-
-/*
- * Chip Io Status codes
- */
-enum hda_vendor_status_chipio {
- /* Success */
- VENDOR_STATUS_CHIPIO_OK = 0x00,
- /* Busy, unable to accept new command, the host must retry */
- VENDOR_STATUS_CHIPIO_BUSY = 0x01
-};
-
-/*
- * CA0132 sample rate
- */
-enum ca0132_sample_rate {
- SR_6_000 = 0x00,
- SR_8_000 = 0x01,
- SR_9_600 = 0x02,
- SR_11_025 = 0x03,
- SR_16_000 = 0x04,
- SR_22_050 = 0x05,
- SR_24_000 = 0x06,
- SR_32_000 = 0x07,
- SR_44_100 = 0x08,
- SR_48_000 = 0x09,
- SR_88_200 = 0x0A,
- SR_96_000 = 0x0B,
- SR_144_000 = 0x0C,
- SR_176_400 = 0x0D,
- SR_192_000 = 0x0E,
- SR_384_000 = 0x0F,
-
- SR_COUNT = 0x10,
-
- SR_RATE_UNKNOWN = 0x1F
-};
-
-enum dsp_download_state {
- DSP_DOWNLOAD_FAILED = -1,
- DSP_DOWNLOAD_INIT = 0,
- DSP_DOWNLOADING = 1,
- DSP_DOWNLOADED = 2
-};
-
-/* retrieve parameters from hda format */
-#define get_hdafmt_chs(fmt) (fmt & 0xf)
-#define get_hdafmt_bits(fmt) ((fmt >> 4) & 0x7)
-#define get_hdafmt_rate(fmt) ((fmt >> 8) & 0x7f)
-#define get_hdafmt_type(fmt) ((fmt >> 15) & 0x1)
-
-/*
- * CA0132 specific
- */
-
-struct ca0132_spec {
- const struct snd_kcontrol_new *mixers[5];
- unsigned int num_mixers;
- const struct hda_verb *base_init_verbs;
- const struct hda_verb *base_exit_verbs;
- const struct hda_verb *chip_init_verbs;
- const struct hda_verb *desktop_init_verbs;
- struct hda_verb *spec_init_verbs;
- struct auto_pin_cfg autocfg;
-
- /* Nodes configurations */
- struct hda_multi_out multiout;
- hda_nid_t out_pins[AUTO_CFG_MAX_OUTS];
- hda_nid_t dacs[AUTO_CFG_MAX_OUTS];
- unsigned int num_outputs;
- hda_nid_t input_pins[AUTO_PIN_LAST];
- hda_nid_t adcs[AUTO_PIN_LAST];
- hda_nid_t dig_out;
- hda_nid_t dig_in;
- 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_front_hp; /* for desktop ca0132 codecs */
- hda_nid_t unsol_tag_amic1;
-
- /* chip access */
- struct mutex chipio_mutex; /* chip access mutex */
- u32 curr_chip_addx;
-
- /* DSP download related */
- enum dsp_download_state dsp_state;
- unsigned int dsp_stream_id;
- unsigned int wait_scp;
- unsigned int wait_scp_header;
- unsigned int wait_num_data;
- unsigned int scp_resp_header;
- unsigned int scp_resp_data[4];
- unsigned int scp_resp_count;
- bool startup_check_entered;
- bool dsp_reload;
-
- /* mixer and effects related */
- unsigned char dmic_ctl;
- int cur_out_type;
- int cur_mic_type;
- long vnode_lvol[VNODES_COUNT];
- long vnode_rvol[VNODES_COUNT];
- long vnode_lswitch[VNODES_COUNT];
- long vnode_rswitch[VNODES_COUNT];
- long effects_switch[EFFECTS_COUNT];
- long voicefx_val;
- long cur_mic_boost;
- /* ca0132_alt control related values */
- unsigned char in_enum_val;
- unsigned char out_enum_val;
- unsigned char channel_cfg_val;
- unsigned char speaker_range_val[2];
- unsigned char mic_boost_enum_val;
- unsigned char smart_volume_setting;
- unsigned char bass_redirection_val;
- long bass_redirect_xover_freq;
- long fx_ctl_val[EFFECT_LEVEL_SLIDERS];
- long xbass_xover_freq;
- long eq_preset_val;
- unsigned int tlv[4];
- struct hda_vmaster_mute_hook vmaster_mute;
- /* AE-5 Control values */
- unsigned char ae5_headphone_gain_val;
- unsigned char ae5_filter_val;
- /* ZxR Control Values */
- unsigned char zxr_gain_set;
-
- struct hda_codec *codec;
- struct delayed_work unsol_hp_work;
-
-#ifdef ENABLE_TUNING_CONTROLS
- long cur_ctl_vals[TUNING_CTLS_COUNT];
-#endif
- /*
- * The Recon3D, Sound Blaster Z, Sound Blaster ZxR, and Sound Blaster
- * AE-5 all use PCI region 2 to toggle GPIO and other currently unknown
- * things.
- */
- bool use_pci_mmio;
- void __iomem *mem_base;
-
- /*
- * Whether or not to use the alt functions like alt_select_out,
- * alt_select_in, etc. Only used on desktop codecs for now, because of
- * surround sound support.
- */
- bool use_alt_functions;
-
- /*
- * Whether or not to use alt controls: volume effect sliders, EQ
- * presets, smart volume presets, and new control names with FX prefix.
- * Renames PlayEnhancement and CrystalVoice too.
- */
- bool use_alt_controls;
-};
-
-/*
- * CA0132 quirks table
- */
-enum {
- QUIRK_ALIENWARE,
- QUIRK_ALIENWARE_M17XR4,
- QUIRK_SBZ,
- QUIRK_ZXR,
- QUIRK_ZXR_DBPRO,
- QUIRK_R3DI,
- QUIRK_R3D,
- QUIRK_AE5,
- QUIRK_AE7,
- QUIRK_NONE = HDA_FIXUP_ID_NOT_SET,
-};
-
-#ifdef CONFIG_PCI
-#define ca0132_quirk(spec) ((spec)->codec->fixup_id)
-#define ca0132_use_pci_mmio(spec) ((spec)->use_pci_mmio)
-#define ca0132_use_alt_functions(spec) ((spec)->use_alt_functions)
-#define ca0132_use_alt_controls(spec) ((spec)->use_alt_controls)
-#else
-#define ca0132_quirk(spec) ({ (void)(spec); QUIRK_NONE; })
-#define ca0132_use_alt_functions(spec) ({ (void)(spec); false; })
-#define ca0132_use_pci_mmio(spec) ({ (void)(spec); false; })
-#define ca0132_use_alt_controls(spec) ({ (void)(spec); false; })
-#endif
-
-static const struct hda_pintbl alienware_pincfgs[] = {
- { 0x0b, 0x90170110 }, /* Builtin Speaker */
- { 0x0c, 0x411111f0 }, /* N/A */
- { 0x0d, 0x411111f0 }, /* N/A */
- { 0x0e, 0x411111f0 }, /* N/A */
- { 0x0f, 0x0321101f }, /* HP */
- { 0x10, 0x411111f0 }, /* Headset? disabled for now */
- { 0x11, 0x03a11021 }, /* Mic */
- { 0x12, 0xd5a30140 }, /* Builtin Mic */
- { 0x13, 0x411111f0 }, /* N/A */
- { 0x18, 0x411111f0 }, /* N/A */
- {}
-};
-
-/* Sound Blaster Z pin configs taken from Windows Driver */
-static const struct hda_pintbl sbz_pincfgs[] = {
- { 0x0b, 0x01017010 }, /* Port G -- Lineout FRONT L/R */
- { 0x0c, 0x014510f0 }, /* SPDIF Out 1 */
- { 0x0d, 0x014510f0 }, /* Digital Out */
- { 0x0e, 0x01c510f0 }, /* SPDIF In */
- { 0x0f, 0x0221701f }, /* Port A -- BackPanel HP */
- { 0x10, 0x01017012 }, /* Port D -- Center/LFE or FP Hp */
- { 0x11, 0x01017014 }, /* Port B -- LineMicIn2 / Rear L/R */
- { 0x12, 0x01a170f0 }, /* Port C -- LineIn1 */
- { 0x13, 0x908700f0 }, /* What U Hear In*/
- { 0x18, 0x50d000f0 }, /* N/A */
- {}
-};
-
-/* Sound Blaster ZxR pin configs taken from Windows Driver */
-static const struct hda_pintbl zxr_pincfgs[] = {
- { 0x0b, 0x01047110 }, /* Port G -- Lineout FRONT L/R */
- { 0x0c, 0x414510f0 }, /* SPDIF Out 1 - Disabled*/
- { 0x0d, 0x014510f0 }, /* Digital Out */
- { 0x0e, 0x41c520f0 }, /* SPDIF In - Disabled*/
- { 0x0f, 0x0122711f }, /* Port A -- BackPanel HP */
- { 0x10, 0x01017111 }, /* Port D -- Center/LFE */
- { 0x11, 0x01017114 }, /* Port B -- LineMicIn2 / Rear L/R */
- { 0x12, 0x01a271f0 }, /* Port C -- LineIn1 */
- { 0x13, 0x908700f0 }, /* What U Hear In*/
- { 0x18, 0x50d000f0 }, /* N/A */
- {}
-};
-
-/* Recon3D pin configs taken from Windows Driver */
-static const struct hda_pintbl r3d_pincfgs[] = {
- { 0x0b, 0x01014110 }, /* Port G -- Lineout FRONT L/R */
- { 0x0c, 0x014510f0 }, /* SPDIF Out 1 */
- { 0x0d, 0x014510f0 }, /* Digital Out */
- { 0x0e, 0x01c520f0 }, /* SPDIF In */
- { 0x0f, 0x0221401f }, /* Port A -- BackPanel HP */
- { 0x10, 0x01016011 }, /* Port D -- Center/LFE or FP Hp */
- { 0x11, 0x01011014 }, /* Port B -- LineMicIn2 / Rear L/R */
- { 0x12, 0x02a090f0 }, /* Port C -- LineIn1 */
- { 0x13, 0x908700f0 }, /* What U Hear In*/
- { 0x18, 0x50d000f0 }, /* N/A */
- {}
-};
-
-/* Sound Blaster AE-5 pin configs taken from Windows Driver */
-static const struct hda_pintbl ae5_pincfgs[] = {
- { 0x0b, 0x01017010 }, /* Port G -- Lineout FRONT L/R */
- { 0x0c, 0x014510f0 }, /* SPDIF Out 1 */
- { 0x0d, 0x014510f0 }, /* Digital Out */
- { 0x0e, 0x01c510f0 }, /* SPDIF In */
- { 0x0f, 0x01017114 }, /* Port A -- Rear L/R. */
- { 0x10, 0x01017012 }, /* Port D -- Center/LFE or FP Hp */
- { 0x11, 0x012170ff }, /* Port B -- LineMicIn2 / Rear Headphone */
- { 0x12, 0x01a170f0 }, /* Port C -- LineIn1 */
- { 0x13, 0x908700f0 }, /* What U Hear In*/
- { 0x18, 0x50d000f0 }, /* N/A */
- {}
-};
-
-/* Recon3D integrated pin configs taken from Windows Driver */
-static const struct hda_pintbl r3di_pincfgs[] = {
- { 0x0b, 0x01014110 }, /* Port G -- Lineout FRONT L/R */
- { 0x0c, 0x014510f0 }, /* SPDIF Out 1 */
- { 0x0d, 0x014510f0 }, /* Digital Out */
- { 0x0e, 0x41c520f0 }, /* SPDIF In */
- { 0x0f, 0x0221401f }, /* Port A -- BackPanel HP */
- { 0x10, 0x01016011 }, /* Port D -- Center/LFE or FP Hp */
- { 0x11, 0x01011014 }, /* Port B -- LineMicIn2 / Rear L/R */
- { 0x12, 0x02a090f0 }, /* Port C -- LineIn1 */
- { 0x13, 0x908700f0 }, /* What U Hear In*/
- { 0x18, 0x500000f0 }, /* N/A */
- {}
-};
-
-static const struct hda_pintbl ae7_pincfgs[] = {
- { 0x0b, 0x01017010 },
- { 0x0c, 0x014510f0 },
- { 0x0d, 0x414510f0 },
- { 0x0e, 0x01c520f0 },
- { 0x0f, 0x01017114 },
- { 0x10, 0x01017011 },
- { 0x11, 0x018170ff },
- { 0x12, 0x01a170f0 },
- { 0x13, 0x908700f0 },
- { 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),
- SND_PCI_QUIRK(0x1028, 0x0688, "Alienware 17 2015", QUIRK_ALIENWARE),
- SND_PCI_QUIRK(0x1028, 0x0708, "Alienware 15 R2 2016", QUIRK_ALIENWARE),
- SND_PCI_QUIRK(0x1102, 0x0010, "Sound Blaster Z", QUIRK_SBZ),
- SND_PCI_QUIRK(0x1102, 0x0023, "Sound Blaster Z", QUIRK_SBZ),
- SND_PCI_QUIRK(0x1102, 0x0027, "Sound Blaster Z", QUIRK_SBZ),
- SND_PCI_QUIRK(0x1102, 0x0033, "Sound Blaster ZxR", QUIRK_SBZ),
- 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(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),
- SND_PCI_QUIRK(0x1102, 0x0013, "Recon3D", QUIRK_R3D),
- SND_PCI_QUIRK(0x1102, 0x0018, "Recon3D", QUIRK_R3D),
- SND_PCI_QUIRK(0x1102, 0x0051, "Sound Blaster AE-5", QUIRK_AE5),
- SND_PCI_QUIRK(0x1102, 0x0191, "Sound Blaster AE-5 Plus", QUIRK_AE5),
- SND_PCI_QUIRK(0x1102, 0x0081, "Sound Blaster AE-7", QUIRK_AE7),
- {}
-};
-
-static const struct hda_model_fixup ca0132_quirk_models[] = {
- { .id = QUIRK_ALIENWARE, .name = "alienware" },
- { .id = QUIRK_ALIENWARE_M17XR4, .name = "alienware-m17xr4" },
- { .id = QUIRK_SBZ, .name = "sbz" },
- { .id = QUIRK_ZXR, .name = "zxr" },
- { .id = QUIRK_ZXR_DBPRO, .name = "zxr-dbpro" },
- { .id = QUIRK_R3DI, .name = "r3di" },
- { .id = QUIRK_R3D, .name = "r3d" },
- { .id = QUIRK_AE5, .name = "ae5" },
- { .id = QUIRK_AE7, .name = "ae7" },
- {}
-};
-
-/* 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. */
-
- bool has_hda_gpio;
- char hda_gpio_pin;
- char hda_gpio_set;
-
- unsigned int mmio_gpio_count;
- char mmio_gpio_pin[MAX_QUIRK_MMIO_GPIO_SET_VALS];
- char mmio_gpio_set[MAX_QUIRK_MMIO_GPIO_SET_VALS];
-
- unsigned int scp_cmds_count;
- unsigned int scp_cmd_mid[MAX_QUIRK_SCP_SET_VALS];
- unsigned int scp_cmd_req[MAX_QUIRK_SCP_SET_VALS];
- unsigned int scp_cmd_val[MAX_QUIRK_SCP_SET_VALS];
-
- bool has_chipio_write;
- unsigned int chipio_write_addr;
- unsigned int chipio_write_data;
-};
-
-struct ca0132_alt_out_set_quirk_data {
- int quirk_id;
-
- bool has_headphone_gain;
- bool is_ae_series;
-
- struct ca0132_alt_out_set_info out_set_info[NUM_OF_OUTPUTS];
-};
-
-static const struct ca0132_alt_out_set_quirk_data quirk_out_set_data[] = {
- { .quirk_id = QUIRK_R3DI,
- .has_headphone_gain = false,
- .is_ae_series = false,
- .out_set_info = {
- /* Speakers. */
- { .dac2port = 0x24,
- .has_hda_gpio = true,
- .hda_gpio_pin = 2,
- .hda_gpio_set = 1,
- .mmio_gpio_count = 0,
- .scp_cmds_count = 0,
- .has_chipio_write = false,
- },
- /* Headphones. */
- { .dac2port = 0x21,
- .has_hda_gpio = true,
- .hda_gpio_pin = 2,
- .hda_gpio_set = 0,
- .mmio_gpio_count = 0,
- .scp_cmds_count = 0,
- .has_chipio_write = false,
- } },
- },
- { .quirk_id = QUIRK_R3D,
- .has_headphone_gain = false,
- .is_ae_series = false,
- .out_set_info = {
- /* Speakers. */
- { .dac2port = 0x24,
- .has_hda_gpio = false,
- .mmio_gpio_count = 1,
- .mmio_gpio_pin = { 1 },
- .mmio_gpio_set = { 1 },
- .scp_cmds_count = 0,
- .has_chipio_write = false,
- },
- /* Headphones. */
- { .dac2port = 0x21,
- .has_hda_gpio = false,
- .mmio_gpio_count = 1,
- .mmio_gpio_pin = { 1 },
- .mmio_gpio_set = { 0 },
- .scp_cmds_count = 0,
- .has_chipio_write = false,
- } },
- },
- { .quirk_id = QUIRK_SBZ,
- .has_headphone_gain = false,
- .is_ae_series = false,
- .out_set_info = {
- /* Speakers. */
- { .dac2port = 0x18,
- .has_hda_gpio = false,
- .mmio_gpio_count = 3,
- .mmio_gpio_pin = { 7, 4, 1 },
- .mmio_gpio_set = { 0, 1, 1 },
- .scp_cmds_count = 0,
- .has_chipio_write = false, },
- /* Headphones. */
- { .dac2port = 0x12,
- .has_hda_gpio = false,
- .mmio_gpio_count = 3,
- .mmio_gpio_pin = { 7, 4, 1 },
- .mmio_gpio_set = { 1, 1, 0 },
- .scp_cmds_count = 0,
- .has_chipio_write = false,
- } },
- },
- { .quirk_id = QUIRK_ZXR,
- .has_headphone_gain = true,
- .is_ae_series = false,
- .out_set_info = {
- /* Speakers. */
- { .dac2port = 0x24,
- .has_hda_gpio = false,
- .mmio_gpio_count = 3,
- .mmio_gpio_pin = { 2, 3, 5 },
- .mmio_gpio_set = { 1, 1, 0 },
- .scp_cmds_count = 0,
- .has_chipio_write = false,
- },
- /* Headphones. */
- { .dac2port = 0x21,
- .has_hda_gpio = false,
- .mmio_gpio_count = 3,
- .mmio_gpio_pin = { 2, 3, 5 },
- .mmio_gpio_set = { 0, 1, 1 },
- .scp_cmds_count = 0,
- .has_chipio_write = false,
- } },
- },
- { .quirk_id = QUIRK_AE5,
- .has_headphone_gain = true,
- .is_ae_series = true,
- .out_set_info = {
- /* Speakers. */
- { .dac2port = 0xa4,
- .has_hda_gpio = false,
- .mmio_gpio_count = 0,
- .scp_cmds_count = 2,
- .scp_cmd_mid = { 0x96, 0x96 },
- .scp_cmd_req = { SPEAKER_TUNING_FRONT_LEFT_INVERT,
- SPEAKER_TUNING_FRONT_RIGHT_INVERT },
- .scp_cmd_val = { FLOAT_ZERO, FLOAT_ZERO },
- .has_chipio_write = true,
- .chipio_write_addr = 0x0018b03c,
- .chipio_write_data = 0x00000012
- },
- /* Headphones. */
- { .dac2port = 0xa1,
- .has_hda_gpio = false,
- .mmio_gpio_count = 0,
- .scp_cmds_count = 2,
- .scp_cmd_mid = { 0x96, 0x96 },
- .scp_cmd_req = { SPEAKER_TUNING_FRONT_LEFT_INVERT,
- SPEAKER_TUNING_FRONT_RIGHT_INVERT },
- .scp_cmd_val = { FLOAT_ONE, FLOAT_ONE },
- .has_chipio_write = true,
- .chipio_write_addr = 0x0018b03c,
- .chipio_write_data = 0x00000012
- } },
- },
- { .quirk_id = QUIRK_AE7,
- .has_headphone_gain = true,
- .is_ae_series = true,
- .out_set_info = {
- /* Speakers. */
- { .dac2port = 0x58,
- .has_hda_gpio = false,
- .mmio_gpio_count = 1,
- .mmio_gpio_pin = { 0 },
- .mmio_gpio_set = { 1 },
- .scp_cmds_count = 2,
- .scp_cmd_mid = { 0x96, 0x96 },
- .scp_cmd_req = { SPEAKER_TUNING_FRONT_LEFT_INVERT,
- SPEAKER_TUNING_FRONT_RIGHT_INVERT },
- .scp_cmd_val = { FLOAT_ZERO, FLOAT_ZERO },
- .has_chipio_write = true,
- .chipio_write_addr = 0x0018b03c,
- .chipio_write_data = 0x00000000
- },
- /* Headphones. */
- { .dac2port = 0x58,
- .has_hda_gpio = false,
- .mmio_gpio_count = 1,
- .mmio_gpio_pin = { 0 },
- .mmio_gpio_set = { 1 },
- .scp_cmds_count = 2,
- .scp_cmd_mid = { 0x96, 0x96 },
- .scp_cmd_req = { SPEAKER_TUNING_FRONT_LEFT_INVERT,
- SPEAKER_TUNING_FRONT_RIGHT_INVERT },
- .scp_cmd_val = { FLOAT_ONE, FLOAT_ONE },
- .has_chipio_write = true,
- .chipio_write_addr = 0x0018b03c,
- .chipio_write_data = 0x00000010
- } },
- }
-};
-
-/*
- * CA0132 codec access
- */
-static unsigned int codec_send_command(struct hda_codec *codec, hda_nid_t nid,
- unsigned int verb, unsigned int parm, unsigned int *res)
-{
- unsigned int response;
- response = snd_hda_codec_read(codec, nid, 0, verb, parm);
- *res = response;
-
- return ((response == -1) ? -1 : 0);
-}
-
-static int codec_set_converter_format(struct hda_codec *codec, hda_nid_t nid,
- unsigned short converter_format, unsigned int *res)
-{
- return codec_send_command(codec, nid, VENDOR_CHIPIO_STREAM_FORMAT,
- converter_format & 0xffff, res);
-}
-
-static int codec_set_converter_stream_channel(struct hda_codec *codec,
- hda_nid_t nid, unsigned char stream,
- unsigned char channel, unsigned int *res)
-{
- unsigned char converter_stream_channel = 0;
-
- converter_stream_channel = (stream << 4) | (channel & 0x0f);
- return codec_send_command(codec, nid, AC_VERB_SET_CHANNEL_STREAMID,
- converter_stream_channel, res);
-}
-
-/* Chip access helper function */
-static int chipio_send(struct hda_codec *codec,
- unsigned int reg,
- unsigned int data)
-{
- unsigned int res;
- unsigned long timeout = jiffies + msecs_to_jiffies(1000);
-
- /* send bits of data specified by reg */
- do {
- res = snd_hda_codec_read(codec, WIDGET_CHIP_CTRL, 0,
- reg, data);
- if (res == VENDOR_STATUS_CHIPIO_OK)
- return 0;
- msleep(20);
- } while (time_before(jiffies, timeout));
-
- return -EIO;
-}
-
-/*
- * Write chip address through the vendor widget -- NOT protected by the Mutex!
- */
-static int chipio_write_address(struct hda_codec *codec,
- unsigned int chip_addx)
-{
- struct ca0132_spec *spec = codec->spec;
- int res;
-
- if (spec->curr_chip_addx == chip_addx)
- return 0;
-
- /* send low 16 bits of the address */
- res = chipio_send(codec, VENDOR_CHIPIO_ADDRESS_LOW,
- chip_addx & 0xffff);
-
- if (res != -EIO) {
- /* send high 16 bits of the address */
- res = chipio_send(codec, VENDOR_CHIPIO_ADDRESS_HIGH,
- chip_addx >> 16);
- }
-
- spec->curr_chip_addx = (res < 0) ? ~0U : chip_addx;
-
- return res;
-}
-
-/*
- * Write data through the vendor widget -- NOT protected by the Mutex!
- */
-static int chipio_write_data(struct hda_codec *codec, unsigned int data)
-{
- struct ca0132_spec *spec = codec->spec;
- int res;
-
- /* send low 16 bits of the data */
- res = chipio_send(codec, VENDOR_CHIPIO_DATA_LOW, data & 0xffff);
-
- if (res != -EIO) {
- /* send high 16 bits of the data */
- res = chipio_send(codec, VENDOR_CHIPIO_DATA_HIGH,
- data >> 16);
- }
-
- /*If no error encountered, automatically increment the address
- as per chip behaviour*/
- spec->curr_chip_addx = (res != -EIO) ?
- (spec->curr_chip_addx + 4) : ~0U;
- return res;
-}
-
-/*
- * Write multiple data through the vendor widget -- NOT protected by the Mutex!
- */
-static int chipio_write_data_multiple(struct hda_codec *codec,
- const u32 *data,
- unsigned int count)
-{
- int status = 0;
-
- if (data == NULL) {
- codec_dbg(codec, "chipio_write_data null ptr\n");
- return -EINVAL;
- }
-
- while ((count-- != 0) && (status == 0))
- status = chipio_write_data(codec, *data++);
-
- return status;
-}
-
-
-/*
- * Read data through the vendor widget -- NOT protected by the Mutex!
- */
-static int chipio_read_data(struct hda_codec *codec, unsigned int *data)
-{
- struct ca0132_spec *spec = codec->spec;
- int res;
-
- /* post read */
- res = chipio_send(codec, VENDOR_CHIPIO_HIC_POST_READ, 0);
-
- if (res != -EIO) {
- /* read status */
- res = chipio_send(codec, VENDOR_CHIPIO_STATUS, 0);
- }
-
- if (res != -EIO) {
- /* read data */
- *data = snd_hda_codec_read(codec, WIDGET_CHIP_CTRL, 0,
- VENDOR_CHIPIO_HIC_READ_DATA,
- 0);
- }
-
- /*If no error encountered, automatically increment the address
- as per chip behaviour*/
- spec->curr_chip_addx = (res != -EIO) ?
- (spec->curr_chip_addx + 4) : ~0U;
- return res;
-}
-
-/*
- * Write given value to the given address through the chip I/O widget.
- * protected by the Mutex
- */
-static int chipio_write(struct hda_codec *codec,
- unsigned int chip_addx, const unsigned int data)
-{
- struct ca0132_spec *spec = codec->spec;
- int err;
-
- mutex_lock(&spec->chipio_mutex);
-
- /* write the address, and if successful proceed to write data */
- err = chipio_write_address(codec, chip_addx);
- if (err < 0)
- goto exit;
-
- err = chipio_write_data(codec, data);
- if (err < 0)
- goto exit;
-
-exit:
- mutex_unlock(&spec->chipio_mutex);
- return err;
-}
-
-/*
- * Write given value to the given address through the chip I/O widget.
- * not protected by the Mutex
- */
-static int chipio_write_no_mutex(struct hda_codec *codec,
- unsigned int chip_addx, const unsigned int data)
-{
- int err;
-
-
- /* write the address, and if successful proceed to write data */
- err = chipio_write_address(codec, chip_addx);
- if (err < 0)
- goto exit;
-
- err = chipio_write_data(codec, data);
- if (err < 0)
- goto exit;
-
-exit:
- return err;
-}
-
-/*
- * Write multiple values to the given address through the chip I/O widget.
- * protected by the Mutex
- */
-static int chipio_write_multiple(struct hda_codec *codec,
- u32 chip_addx,
- const u32 *data,
- unsigned int count)
-{
- struct ca0132_spec *spec = codec->spec;
- int status;
-
- mutex_lock(&spec->chipio_mutex);
- status = chipio_write_address(codec, chip_addx);
- if (status < 0)
- goto error;
-
- status = chipio_write_data_multiple(codec, data, count);
-error:
- mutex_unlock(&spec->chipio_mutex);
-
- return status;
-}
-
-/*
- * Read the given address through the chip I/O widget
- * protected by the Mutex
- */
-static int chipio_read(struct hda_codec *codec,
- unsigned int chip_addx, unsigned int *data)
-{
- struct ca0132_spec *spec = codec->spec;
- int err;
-
- mutex_lock(&spec->chipio_mutex);
-
- /* write the address, and if successful proceed to write data */
- err = chipio_write_address(codec, chip_addx);
- if (err < 0)
- goto exit;
-
- err = chipio_read_data(codec, data);
- if (err < 0)
- goto exit;
-
-exit:
- mutex_unlock(&spec->chipio_mutex);
- return err;
-}
-
-/*
- * Set chip control flags through the chip I/O widget.
- */
-static void chipio_set_control_flag(struct hda_codec *codec,
- enum control_flag_id flag_id,
- bool flag_state)
-{
- unsigned int val;
- unsigned int flag_bit;
-
- flag_bit = (flag_state ? 1 : 0);
- val = (flag_bit << 7) | (flag_id);
- snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
- VENDOR_CHIPIO_FLAG_SET, val);
-}
-
-/*
- * Set chip parameters through the chip I/O widget.
- */
-static void chipio_set_control_param(struct hda_codec *codec,
- enum control_param_id param_id, int param_val)
-{
- struct ca0132_spec *spec = codec->spec;
- int val;
-
- if ((param_id < 32) && (param_val < 8)) {
- val = (param_val << 5) | (param_id);
- snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
- VENDOR_CHIPIO_PARAM_SET, val);
- } else {
- mutex_lock(&spec->chipio_mutex);
- if (chipio_send(codec, VENDOR_CHIPIO_STATUS, 0) == 0) {
- snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
- VENDOR_CHIPIO_PARAM_EX_ID_SET,
- param_id);
- snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
- VENDOR_CHIPIO_PARAM_EX_VALUE_SET,
- param_val);
- }
- mutex_unlock(&spec->chipio_mutex);
- }
-}
-
-/*
- * Set chip parameters through the chip I/O widget. NO MUTEX.
- */
-static void chipio_set_control_param_no_mutex(struct hda_codec *codec,
- enum control_param_id param_id, int param_val)
-{
- int val;
-
- if ((param_id < 32) && (param_val < 8)) {
- val = (param_val << 5) | (param_id);
- snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
- VENDOR_CHIPIO_PARAM_SET, val);
- } else {
- if (chipio_send(codec, VENDOR_CHIPIO_STATUS, 0) == 0) {
- snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
- VENDOR_CHIPIO_PARAM_EX_ID_SET,
- param_id);
- snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
- VENDOR_CHIPIO_PARAM_EX_VALUE_SET,
- param_val);
- }
- }
-}
-/*
- * Connect stream to a source point, and then connect
- * that source point to a destination point.
- */
-static void chipio_set_stream_source_dest(struct hda_codec *codec,
- int streamid, int source_point, int dest_point)
-{
- chipio_set_control_param_no_mutex(codec,
- CONTROL_PARAM_STREAM_ID, streamid);
- chipio_set_control_param_no_mutex(codec,
- CONTROL_PARAM_STREAM_SOURCE_CONN_POINT, source_point);
- chipio_set_control_param_no_mutex(codec,
- CONTROL_PARAM_STREAM_DEST_CONN_POINT, dest_point);
-}
-
-/*
- * Set number of channels in the selected stream.
- */
-static void chipio_set_stream_channels(struct hda_codec *codec,
- int streamid, unsigned int channels)
-{
- chipio_set_control_param_no_mutex(codec,
- CONTROL_PARAM_STREAM_ID, streamid);
- chipio_set_control_param_no_mutex(codec,
- CONTROL_PARAM_STREAMS_CHANNELS, channels);
-}
-
-/*
- * Enable/Disable audio stream.
- */
-static void chipio_set_stream_control(struct hda_codec *codec,
- int streamid, int enable)
-{
- chipio_set_control_param_no_mutex(codec,
- CONTROL_PARAM_STREAM_ID, streamid);
- chipio_set_control_param_no_mutex(codec,
- CONTROL_PARAM_STREAM_CONTROL, enable);
-}
-
-/*
- * Get ChipIO audio stream's status.
- */
-static void chipio_get_stream_control(struct hda_codec *codec,
- int streamid, unsigned int *enable)
-{
- chipio_set_control_param_no_mutex(codec,
- CONTROL_PARAM_STREAM_ID, streamid);
- *enable = snd_hda_codec_read(codec, WIDGET_CHIP_CTRL, 0,
- VENDOR_CHIPIO_PARAM_GET,
- CONTROL_PARAM_STREAM_CONTROL);
-}
-
-/*
- * Set sampling rate of the connection point. NO MUTEX.
- */
-static void chipio_set_conn_rate_no_mutex(struct hda_codec *codec,
- int connid, enum ca0132_sample_rate rate)
-{
- chipio_set_control_param_no_mutex(codec,
- CONTROL_PARAM_CONN_POINT_ID, connid);
- chipio_set_control_param_no_mutex(codec,
- CONTROL_PARAM_CONN_POINT_SAMPLE_RATE, rate);
-}
-
-/*
- * Set sampling rate of the connection point.
- */
-static void chipio_set_conn_rate(struct hda_codec *codec,
- int connid, enum ca0132_sample_rate rate)
-{
- chipio_set_control_param(codec, CONTROL_PARAM_CONN_POINT_ID, connid);
- chipio_set_control_param(codec, CONTROL_PARAM_CONN_POINT_SAMPLE_RATE,
- rate);
-}
-
-/*
- * Writes to the 8051's internal address space directly instead of indirectly,
- * giving access to the special function registers located at addresses
- * 0x80-0xFF.
- */
-static void chipio_8051_write_direct(struct hda_codec *codec,
- unsigned int addr, unsigned int data)
-{
- unsigned int verb;
-
- verb = VENDOR_CHIPIO_8051_WRITE_DIRECT | data;
- snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, verb, addr);
-}
-
-/*
- * Writes to the 8051's exram, which has 16-bits of address space.
- * Data at addresses 0x2000-0x7fff is mirrored to 0x8000-0xdfff.
- * Data at 0x8000-0xdfff can also be used as program memory for the 8051 by
- * setting the pmem bank selection SFR.
- * 0xe000-0xffff is always mapped as program memory, with only 0xf000-0xffff
- * being writable.
- */
-static void chipio_8051_set_address(struct hda_codec *codec, unsigned int addr)
-{
- unsigned int tmp;
-
- /* Lower 8-bits. */
- tmp = addr & 0xff;
- snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
- VENDOR_CHIPIO_8051_ADDRESS_LOW, tmp);
-
- /* Upper 8-bits. */
- tmp = (addr >> 8) & 0xff;
- snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
- VENDOR_CHIPIO_8051_ADDRESS_HIGH, tmp);
-}
-
-static void chipio_8051_set_data(struct hda_codec *codec, unsigned int data)
-{
- /* 8-bits of data. */
- snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
- VENDOR_CHIPIO_8051_DATA_WRITE, data & 0xff);
-}
-
-static unsigned int chipio_8051_get_data(struct hda_codec *codec)
-{
- return snd_hda_codec_read(codec, WIDGET_CHIP_CTRL, 0,
- VENDOR_CHIPIO_8051_DATA_READ, 0);
-}
-
-/* PLL_PMU writes share the lower address register of the 8051 exram writes. */
-static void chipio_8051_set_data_pll(struct hda_codec *codec, unsigned int data)
-{
- /* 8-bits of data. */
- snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
- VENDOR_CHIPIO_PLL_PMU_WRITE, data & 0xff);
-}
-
-static void chipio_8051_write_exram(struct hda_codec *codec,
- unsigned int addr, unsigned int data)
-{
- struct ca0132_spec *spec = codec->spec;
-
- mutex_lock(&spec->chipio_mutex);
-
- chipio_8051_set_address(codec, addr);
- chipio_8051_set_data(codec, data);
-
- mutex_unlock(&spec->chipio_mutex);
-}
-
-static void chipio_8051_write_exram_no_mutex(struct hda_codec *codec,
- unsigned int addr, unsigned int data)
-{
- chipio_8051_set_address(codec, addr);
- chipio_8051_set_data(codec, data);
-}
-
-/* Readback data from the 8051's exram. No mutex. */
-static void chipio_8051_read_exram(struct hda_codec *codec,
- unsigned int addr, unsigned int *data)
-{
- chipio_8051_set_address(codec, addr);
- *data = chipio_8051_get_data(codec);
-}
-
-static void chipio_8051_write_pll_pmu(struct hda_codec *codec,
- unsigned int addr, unsigned int data)
-{
- struct ca0132_spec *spec = codec->spec;
-
- mutex_lock(&spec->chipio_mutex);
-
- chipio_8051_set_address(codec, addr & 0xff);
- chipio_8051_set_data_pll(codec, data);
-
- mutex_unlock(&spec->chipio_mutex);
-}
-
-static void chipio_8051_write_pll_pmu_no_mutex(struct hda_codec *codec,
- unsigned int addr, unsigned int data)
-{
- chipio_8051_set_address(codec, addr & 0xff);
- chipio_8051_set_data_pll(codec, data);
-}
-
-/*
- * Enable clocks.
- */
-static void chipio_enable_clocks(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
-
- mutex_lock(&spec->chipio_mutex);
-
- chipio_8051_write_pll_pmu_no_mutex(codec, 0x00, 0xff);
- chipio_8051_write_pll_pmu_no_mutex(codec, 0x05, 0x0b);
- chipio_8051_write_pll_pmu_no_mutex(codec, 0x06, 0xff);
-
- mutex_unlock(&spec->chipio_mutex);
-}
-
-/*
- * CA0132 DSP IO stuffs
- */
-static int dspio_send(struct hda_codec *codec, unsigned int reg,
- unsigned int data)
-{
- int res;
- unsigned long timeout = jiffies + msecs_to_jiffies(1000);
-
- /* send bits of data specified by reg to dsp */
- do {
- res = snd_hda_codec_read(codec, WIDGET_DSP_CTRL, 0, reg, data);
- if ((res >= 0) && (res != VENDOR_STATUS_DSPIO_BUSY))
- return res;
- msleep(20);
- } while (time_before(jiffies, timeout));
-
- return -EIO;
-}
-
-/*
- * Wait for DSP to be ready for commands
- */
-static void dspio_write_wait(struct hda_codec *codec)
-{
- int status;
- unsigned long timeout = jiffies + msecs_to_jiffies(1000);
-
- do {
- status = snd_hda_codec_read(codec, WIDGET_DSP_CTRL, 0,
- VENDOR_DSPIO_STATUS, 0);
- if ((status == VENDOR_STATUS_DSPIO_OK) ||
- (status == VENDOR_STATUS_DSPIO_SCP_RESPONSE_QUEUE_EMPTY))
- break;
- msleep(1);
- } while (time_before(jiffies, timeout));
-}
-
-/*
- * Write SCP data to DSP
- */
-static int dspio_write(struct hda_codec *codec, unsigned int scp_data)
-{
- struct ca0132_spec *spec = codec->spec;
- int status;
-
- dspio_write_wait(codec);
-
- mutex_lock(&spec->chipio_mutex);
- status = dspio_send(codec, VENDOR_DSPIO_SCP_WRITE_DATA_LOW,
- scp_data & 0xffff);
- if (status < 0)
- goto error;
-
- status = dspio_send(codec, VENDOR_DSPIO_SCP_WRITE_DATA_HIGH,
- scp_data >> 16);
- if (status < 0)
- goto error;
-
- /* OK, now check if the write itself has executed*/
- status = snd_hda_codec_read(codec, WIDGET_DSP_CTRL, 0,
- VENDOR_DSPIO_STATUS, 0);
-error:
- mutex_unlock(&spec->chipio_mutex);
-
- return (status == VENDOR_STATUS_DSPIO_SCP_COMMAND_QUEUE_FULL) ?
- -EIO : 0;
-}
-
-/*
- * Write multiple SCP data to DSP
- */
-static int dspio_write_multiple(struct hda_codec *codec,
- unsigned int *buffer, unsigned int size)
-{
- int status = 0;
- unsigned int count;
-
- if (buffer == NULL)
- return -EINVAL;
-
- count = 0;
- while (count < size) {
- status = dspio_write(codec, *buffer++);
- if (status != 0)
- break;
- count++;
- }
-
- return status;
-}
-
-static int dspio_read(struct hda_codec *codec, unsigned int *data)
-{
- int status;
-
- status = dspio_send(codec, VENDOR_DSPIO_SCP_POST_READ_DATA, 0);
- if (status == -EIO)
- return status;
-
- status = dspio_send(codec, VENDOR_DSPIO_STATUS, 0);
- if (status == -EIO ||
- status == VENDOR_STATUS_DSPIO_SCP_RESPONSE_QUEUE_EMPTY)
- return -EIO;
-
- *data = snd_hda_codec_read(codec, WIDGET_DSP_CTRL, 0,
- VENDOR_DSPIO_SCP_READ_DATA, 0);
-
- return 0;
-}
-
-static int dspio_read_multiple(struct hda_codec *codec, unsigned int *buffer,
- unsigned int *buf_size, unsigned int size_count)
-{
- int status = 0;
- unsigned int size = *buf_size;
- unsigned int count;
- unsigned int skip_count;
- unsigned int dummy;
-
- if (buffer == NULL)
- return -1;
-
- count = 0;
- while (count < size && count < size_count) {
- status = dspio_read(codec, buffer++);
- if (status != 0)
- break;
- count++;
- }
-
- skip_count = count;
- if (status == 0) {
- while (skip_count < size) {
- status = dspio_read(codec, &dummy);
- if (status != 0)
- break;
- skip_count++;
- }
- }
- *buf_size = count;
-
- return status;
-}
-
-/*
- * Construct the SCP header using corresponding fields
- */
-static inline unsigned int
-make_scp_header(unsigned int target_id, unsigned int source_id,
- unsigned int get_flag, unsigned int req,
- unsigned int device_flag, unsigned int resp_flag,
- unsigned int error_flag, unsigned int data_size)
-{
- unsigned int header = 0;
-
- header = (data_size & 0x1f) << 27;
- header |= (error_flag & 0x01) << 26;
- header |= (resp_flag & 0x01) << 25;
- header |= (device_flag & 0x01) << 24;
- header |= (req & 0x7f) << 17;
- header |= (get_flag & 0x01) << 16;
- header |= (source_id & 0xff) << 8;
- header |= target_id & 0xff;
-
- return header;
-}
-
-/*
- * Extract corresponding fields from SCP header
- */
-static inline void
-extract_scp_header(unsigned int header,
- unsigned int *target_id, unsigned int *source_id,
- unsigned int *get_flag, unsigned int *req,
- unsigned int *device_flag, unsigned int *resp_flag,
- unsigned int *error_flag, unsigned int *data_size)
-{
- if (data_size)
- *data_size = (header >> 27) & 0x1f;
- if (error_flag)
- *error_flag = (header >> 26) & 0x01;
- if (resp_flag)
- *resp_flag = (header >> 25) & 0x01;
- if (device_flag)
- *device_flag = (header >> 24) & 0x01;
- if (req)
- *req = (header >> 17) & 0x7f;
- if (get_flag)
- *get_flag = (header >> 16) & 0x01;
- if (source_id)
- *source_id = (header >> 8) & 0xff;
- if (target_id)
- *target_id = header & 0xff;
-}
-
-#define SCP_MAX_DATA_WORDS (16)
-
-/* Structure to contain any SCP message */
-struct scp_msg {
- unsigned int hdr;
- unsigned int data[SCP_MAX_DATA_WORDS];
-};
-
-static void dspio_clear_response_queue(struct hda_codec *codec)
-{
- unsigned long timeout = jiffies + msecs_to_jiffies(1000);
- unsigned int dummy = 0;
- int status;
-
- /* clear all from the response queue */
- do {
- status = dspio_read(codec, &dummy);
- } while (status == 0 && time_before(jiffies, timeout));
-}
-
-static int dspio_get_response_data(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- unsigned int data = 0;
- unsigned int count;
-
- if (dspio_read(codec, &data) < 0)
- return -EIO;
-
- if ((data & 0x00ffffff) == spec->wait_scp_header) {
- spec->scp_resp_header = data;
- spec->scp_resp_count = data >> 27;
- count = spec->wait_num_data;
- dspio_read_multiple(codec, spec->scp_resp_data,
- &spec->scp_resp_count, count);
- return 0;
- }
-
- return -EIO;
-}
-
-/*
- * Send SCP message to DSP
- */
-static int dspio_send_scp_message(struct hda_codec *codec,
- unsigned char *send_buf,
- unsigned int send_buf_size,
- unsigned char *return_buf,
- unsigned int return_buf_size,
- unsigned int *bytes_returned)
-{
- struct ca0132_spec *spec = codec->spec;
- int status;
- unsigned int scp_send_size = 0;
- unsigned int total_size;
- bool waiting_for_resp = false;
- unsigned int header;
- struct scp_msg *ret_msg;
- unsigned int resp_src_id, resp_target_id;
- unsigned int data_size, src_id, target_id, get_flag, device_flag;
-
- if (bytes_returned)
- *bytes_returned = 0;
-
- /* get scp header from buffer */
- header = *((unsigned int *)send_buf);
- extract_scp_header(header, &target_id, &src_id, &get_flag, NULL,
- &device_flag, NULL, NULL, &data_size);
- scp_send_size = data_size + 1;
- total_size = (scp_send_size * 4);
-
- if (send_buf_size < total_size)
- return -EINVAL;
-
- if (get_flag || device_flag) {
- if (!return_buf || return_buf_size < 4 || !bytes_returned)
- return -EINVAL;
-
- spec->wait_scp_header = *((unsigned int *)send_buf);
-
- /* swap source id with target id */
- resp_target_id = src_id;
- resp_src_id = target_id;
- spec->wait_scp_header &= 0xffff0000;
- spec->wait_scp_header |= (resp_src_id << 8) | (resp_target_id);
- spec->wait_num_data = return_buf_size/sizeof(unsigned int) - 1;
- spec->wait_scp = 1;
- waiting_for_resp = true;
- }
-
- status = dspio_write_multiple(codec, (unsigned int *)send_buf,
- scp_send_size);
- if (status < 0) {
- spec->wait_scp = 0;
- return status;
- }
-
- if (waiting_for_resp) {
- unsigned long timeout = jiffies + msecs_to_jiffies(1000);
- memset(return_buf, 0, return_buf_size);
- do {
- msleep(20);
- } while (spec->wait_scp && time_before(jiffies, timeout));
- waiting_for_resp = false;
- if (!spec->wait_scp) {
- ret_msg = (struct scp_msg *)return_buf;
- memcpy(&ret_msg->hdr, &spec->scp_resp_header, 4);
- memcpy(&ret_msg->data, spec->scp_resp_data,
- spec->wait_num_data);
- *bytes_returned = (spec->scp_resp_count + 1) * 4;
- status = 0;
- } else {
- status = -EIO;
- }
- spec->wait_scp = 0;
- }
-
- return status;
-}
-
-/**
- * dspio_scp - Prepare and send the SCP message to DSP
- * @codec: the HDA codec
- * @mod_id: ID of the DSP module to send the command
- * @src_id: ID of the source
- * @req: ID of request to send to the DSP module
- * @dir: SET or GET
- * @data: pointer to the data to send with the request, request specific
- * @len: length of the data, in bytes
- * @reply: point to the buffer to hold data returned for a reply
- * @reply_len: length of the reply buffer returned from GET
- *
- * Returns zero or a negative error code.
- */
-static int dspio_scp(struct hda_codec *codec,
- int mod_id, int src_id, int req, int dir, const void *data,
- unsigned int len, void *reply, unsigned int *reply_len)
-{
- int status = 0;
- struct scp_msg scp_send, scp_reply;
- unsigned int ret_bytes, send_size, ret_size;
- unsigned int send_get_flag, reply_resp_flag, reply_error_flag;
- unsigned int reply_data_size;
-
- memset(&scp_send, 0, sizeof(scp_send));
- memset(&scp_reply, 0, sizeof(scp_reply));
-
- if ((len != 0 && data == NULL) || (len > SCP_MAX_DATA_WORDS))
- return -EINVAL;
-
- if (dir == SCP_GET && reply == NULL) {
- codec_dbg(codec, "dspio_scp get but has no buffer\n");
- return -EINVAL;
- }
-
- if (reply != NULL && (reply_len == NULL || (*reply_len == 0))) {
- codec_dbg(codec, "dspio_scp bad resp buf len parms\n");
- return -EINVAL;
- }
-
- scp_send.hdr = make_scp_header(mod_id, src_id, (dir == SCP_GET), req,
- 0, 0, 0, len/sizeof(unsigned int));
- if (data != NULL && len > 0) {
- len = min((unsigned int)(sizeof(scp_send.data)), len);
- memcpy(scp_send.data, data, len);
- }
-
- ret_bytes = 0;
- send_size = sizeof(unsigned int) + len;
- status = dspio_send_scp_message(codec, (unsigned char *)&scp_send,
- send_size, (unsigned char *)&scp_reply,
- sizeof(scp_reply), &ret_bytes);
-
- if (status < 0) {
- codec_dbg(codec, "dspio_scp: send scp msg failed\n");
- return status;
- }
-
- /* extract send and reply headers members */
- extract_scp_header(scp_send.hdr, NULL, NULL, &send_get_flag,
- NULL, NULL, NULL, NULL, NULL);
- extract_scp_header(scp_reply.hdr, NULL, NULL, NULL, NULL, NULL,
- &reply_resp_flag, &reply_error_flag,
- &reply_data_size);
-
- if (!send_get_flag)
- return 0;
-
- if (reply_resp_flag && !reply_error_flag) {
- ret_size = (ret_bytes - sizeof(scp_reply.hdr))
- / sizeof(unsigned int);
-
- if (*reply_len < ret_size*sizeof(unsigned int)) {
- codec_dbg(codec, "reply too long for buf\n");
- return -EINVAL;
- } else if (ret_size != reply_data_size) {
- codec_dbg(codec, "RetLen and HdrLen .NE.\n");
- return -EINVAL;
- } else if (!reply) {
- codec_dbg(codec, "NULL reply\n");
- return -EINVAL;
- } else {
- *reply_len = ret_size*sizeof(unsigned int);
- memcpy(reply, scp_reply.data, *reply_len);
- }
- } else {
- codec_dbg(codec, "reply ill-formed or errflag set\n");
- return -EIO;
- }
-
- return status;
-}
-
-/*
- * Set DSP parameters
- */
-static int dspio_set_param(struct hda_codec *codec, int mod_id,
- int src_id, int req, const void *data, unsigned int len)
-{
- return dspio_scp(codec, mod_id, src_id, req, SCP_SET, data, len, NULL,
- NULL);
-}
-
-static int dspio_set_uint_param(struct hda_codec *codec, int mod_id,
- int req, const unsigned int data)
-{
- return dspio_set_param(codec, mod_id, 0x20, req, &data,
- sizeof(unsigned int));
-}
-
-/*
- * Allocate a DSP DMA channel via an SCP message
- */
-static int dspio_alloc_dma_chan(struct hda_codec *codec, unsigned int *dma_chan)
-{
- int status = 0;
- unsigned int size = sizeof(*dma_chan);
-
- codec_dbg(codec, " dspio_alloc_dma_chan() -- begin\n");
- status = dspio_scp(codec, MASTERCONTROL, 0x20,
- MASTERCONTROL_ALLOC_DMA_CHAN, SCP_GET, NULL, 0,
- dma_chan, &size);
-
- if (status < 0) {
- codec_dbg(codec, "dspio_alloc_dma_chan: SCP Failed\n");
- return status;
- }
-
- if ((*dma_chan + 1) == 0) {
- codec_dbg(codec, "no free dma channels to allocate\n");
- return -EBUSY;
- }
-
- codec_dbg(codec, "dspio_alloc_dma_chan: chan=%d\n", *dma_chan);
- codec_dbg(codec, " dspio_alloc_dma_chan() -- complete\n");
-
- return status;
-}
-
-/*
- * Free a DSP DMA via an SCP message
- */
-static int dspio_free_dma_chan(struct hda_codec *codec, unsigned int dma_chan)
-{
- int status = 0;
- unsigned int dummy = 0;
-
- codec_dbg(codec, " dspio_free_dma_chan() -- begin\n");
- codec_dbg(codec, "dspio_free_dma_chan: chan=%d\n", dma_chan);
-
- status = dspio_scp(codec, MASTERCONTROL, 0x20,
- MASTERCONTROL_ALLOC_DMA_CHAN, SCP_SET, &dma_chan,
- sizeof(dma_chan), NULL, &dummy);
-
- if (status < 0) {
- codec_dbg(codec, "dspio_free_dma_chan: SCP Failed\n");
- return status;
- }
-
- codec_dbg(codec, " dspio_free_dma_chan() -- complete\n");
-
- return status;
-}
-
-/*
- * (Re)start the DSP
- */
-static int dsp_set_run_state(struct hda_codec *codec)
-{
- unsigned int dbg_ctrl_reg;
- unsigned int halt_state;
- int err;
-
- err = chipio_read(codec, DSP_DBGCNTL_INST_OFFSET, &dbg_ctrl_reg);
- if (err < 0)
- return err;
-
- halt_state = (dbg_ctrl_reg & DSP_DBGCNTL_STATE_MASK) >>
- DSP_DBGCNTL_STATE_LOBIT;
-
- if (halt_state != 0) {
- dbg_ctrl_reg &= ~((halt_state << DSP_DBGCNTL_SS_LOBIT) &
- DSP_DBGCNTL_SS_MASK);
- err = chipio_write(codec, DSP_DBGCNTL_INST_OFFSET,
- dbg_ctrl_reg);
- if (err < 0)
- return err;
-
- dbg_ctrl_reg |= (halt_state << DSP_DBGCNTL_EXEC_LOBIT) &
- DSP_DBGCNTL_EXEC_MASK;
- err = chipio_write(codec, DSP_DBGCNTL_INST_OFFSET,
- dbg_ctrl_reg);
- if (err < 0)
- return err;
- }
-
- return 0;
-}
-
-/*
- * Reset the DSP
- */
-static int dsp_reset(struct hda_codec *codec)
-{
- unsigned int res;
- int retry = 20;
-
- codec_dbg(codec, "dsp_reset\n");
- do {
- res = dspio_send(codec, VENDOR_DSPIO_DSP_INIT, 0);
- retry--;
- } while (res == -EIO && retry);
-
- if (!retry) {
- codec_dbg(codec, "dsp_reset timeout\n");
- return -EIO;
- }
-
- return 0;
-}
-
-/*
- * Convert chip address to DSP address
- */
-static unsigned int dsp_chip_to_dsp_addx(unsigned int chip_addx,
- bool *code, bool *yram)
-{
- *code = *yram = false;
-
- if (UC_RANGE(chip_addx, 1)) {
- *code = true;
- return UC_OFF(chip_addx);
- } else if (X_RANGE_ALL(chip_addx, 1)) {
- return X_OFF(chip_addx);
- } else if (Y_RANGE_ALL(chip_addx, 1)) {
- *yram = true;
- return Y_OFF(chip_addx);
- }
-
- return INVALID_CHIP_ADDRESS;
-}
-
-/*
- * Check if the DSP DMA is active
- */
-static bool dsp_is_dma_active(struct hda_codec *codec, unsigned int dma_chan)
-{
- unsigned int dma_chnlstart_reg;
-
- chipio_read(codec, DSPDMAC_CHNLSTART_INST_OFFSET, &dma_chnlstart_reg);
-
- return ((dma_chnlstart_reg & (1 <<
- (DSPDMAC_CHNLSTART_EN_LOBIT + dma_chan))) != 0);
-}
-
-static int dsp_dma_setup_common(struct hda_codec *codec,
- unsigned int chip_addx,
- unsigned int dma_chan,
- unsigned int port_map_mask,
- bool ovly)
-{
- int status = 0;
- unsigned int chnl_prop;
- unsigned int dsp_addx;
- unsigned int active;
- bool code, yram;
-
- codec_dbg(codec, "-- dsp_dma_setup_common() -- Begin ---------\n");
-
- if (dma_chan >= DSPDMAC_DMA_CFG_CHANNEL_COUNT) {
- codec_dbg(codec, "dma chan num invalid\n");
- return -EINVAL;
- }
-
- if (dsp_is_dma_active(codec, dma_chan)) {
- codec_dbg(codec, "dma already active\n");
- return -EBUSY;
- }
-
- dsp_addx = dsp_chip_to_dsp_addx(chip_addx, &code, &yram);
-
- if (dsp_addx == INVALID_CHIP_ADDRESS) {
- codec_dbg(codec, "invalid chip addr\n");
- return -ENXIO;
- }
-
- chnl_prop = DSPDMAC_CHNLPROP_AC_MASK;
- active = 0;
-
- codec_dbg(codec, " dsp_dma_setup_common() start reg pgm\n");
-
- if (ovly) {
- status = chipio_read(codec, DSPDMAC_CHNLPROP_INST_OFFSET,
- &chnl_prop);
-
- if (status < 0) {
- codec_dbg(codec, "read CHNLPROP Reg fail\n");
- return status;
- }
- codec_dbg(codec, "dsp_dma_setup_common() Read CHNLPROP\n");
- }
-
- if (!code)
- chnl_prop &= ~(1 << (DSPDMAC_CHNLPROP_MSPCE_LOBIT + dma_chan));
- else
- chnl_prop |= (1 << (DSPDMAC_CHNLPROP_MSPCE_LOBIT + dma_chan));
-
- chnl_prop &= ~(1 << (DSPDMAC_CHNLPROP_DCON_LOBIT + dma_chan));
-
- status = chipio_write(codec, DSPDMAC_CHNLPROP_INST_OFFSET, chnl_prop);
- if (status < 0) {
- codec_dbg(codec, "write CHNLPROP Reg fail\n");
- return status;
- }
- codec_dbg(codec, " dsp_dma_setup_common() Write CHNLPROP\n");
-
- if (ovly) {
- status = chipio_read(codec, DSPDMAC_ACTIVE_INST_OFFSET,
- &active);
-
- if (status < 0) {
- codec_dbg(codec, "read ACTIVE Reg fail\n");
- return status;
- }
- codec_dbg(codec, "dsp_dma_setup_common() Read ACTIVE\n");
- }
-
- active &= (~(1 << (DSPDMAC_ACTIVE_AAR_LOBIT + dma_chan))) &
- DSPDMAC_ACTIVE_AAR_MASK;
-
- status = chipio_write(codec, DSPDMAC_ACTIVE_INST_OFFSET, active);
- if (status < 0) {
- codec_dbg(codec, "write ACTIVE Reg fail\n");
- return status;
- }
-
- codec_dbg(codec, " dsp_dma_setup_common() Write ACTIVE\n");
-
- status = chipio_write(codec, DSPDMAC_AUDCHSEL_INST_OFFSET(dma_chan),
- port_map_mask);
- if (status < 0) {
- codec_dbg(codec, "write AUDCHSEL Reg fail\n");
- return status;
- }
- codec_dbg(codec, " dsp_dma_setup_common() Write AUDCHSEL\n");
-
- status = chipio_write(codec, DSPDMAC_IRQCNT_INST_OFFSET(dma_chan),
- DSPDMAC_IRQCNT_BICNT_MASK | DSPDMAC_IRQCNT_CICNT_MASK);
- if (status < 0) {
- codec_dbg(codec, "write IRQCNT Reg fail\n");
- return status;
- }
- codec_dbg(codec, " dsp_dma_setup_common() Write IRQCNT\n");
-
- codec_dbg(codec,
- "ChipA=0x%x,DspA=0x%x,dmaCh=%u, "
- "CHSEL=0x%x,CHPROP=0x%x,Active=0x%x\n",
- chip_addx, dsp_addx, dma_chan,
- port_map_mask, chnl_prop, active);
-
- codec_dbg(codec, "-- dsp_dma_setup_common() -- Complete ------\n");
-
- return 0;
-}
-
-/*
- * Setup the DSP DMA per-transfer-specific registers
- */
-static int dsp_dma_setup(struct hda_codec *codec,
- unsigned int chip_addx,
- unsigned int count,
- unsigned int dma_chan)
-{
- int status = 0;
- bool code, yram;
- unsigned int dsp_addx;
- unsigned int addr_field;
- unsigned int incr_field;
- unsigned int base_cnt;
- unsigned int cur_cnt;
- unsigned int dma_cfg = 0;
- unsigned int adr_ofs = 0;
- unsigned int xfr_cnt = 0;
- const unsigned int max_dma_count = 1 << (DSPDMAC_XFRCNT_BCNT_HIBIT -
- DSPDMAC_XFRCNT_BCNT_LOBIT + 1);
-
- codec_dbg(codec, "-- dsp_dma_setup() -- Begin ---------\n");
-
- if (count > max_dma_count) {
- codec_dbg(codec, "count too big\n");
- return -EINVAL;
- }
-
- dsp_addx = dsp_chip_to_dsp_addx(chip_addx, &code, &yram);
- if (dsp_addx == INVALID_CHIP_ADDRESS) {
- codec_dbg(codec, "invalid chip addr\n");
- return -ENXIO;
- }
-
- codec_dbg(codec, " dsp_dma_setup() start reg pgm\n");
-
- addr_field = dsp_addx << DSPDMAC_DMACFG_DBADR_LOBIT;
- incr_field = 0;
-
- if (!code) {
- addr_field <<= 1;
- if (yram)
- addr_field |= (1 << DSPDMAC_DMACFG_DBADR_LOBIT);
-
- incr_field = (1 << DSPDMAC_DMACFG_AINCR_LOBIT);
- }
-
- dma_cfg = addr_field + incr_field;
- status = chipio_write(codec, DSPDMAC_DMACFG_INST_OFFSET(dma_chan),
- dma_cfg);
- if (status < 0) {
- codec_dbg(codec, "write DMACFG Reg fail\n");
- return status;
- }
- codec_dbg(codec, " dsp_dma_setup() Write DMACFG\n");
-
- adr_ofs = (count - 1) << (DSPDMAC_DSPADROFS_BOFS_LOBIT +
- (code ? 0 : 1));
-
- status = chipio_write(codec, DSPDMAC_DSPADROFS_INST_OFFSET(dma_chan),
- adr_ofs);
- if (status < 0) {
- codec_dbg(codec, "write DSPADROFS Reg fail\n");
- return status;
- }
- codec_dbg(codec, " dsp_dma_setup() Write DSPADROFS\n");
-
- base_cnt = (count - 1) << DSPDMAC_XFRCNT_BCNT_LOBIT;
-
- cur_cnt = (count - 1) << DSPDMAC_XFRCNT_CCNT_LOBIT;
-
- xfr_cnt = base_cnt | cur_cnt;
-
- status = chipio_write(codec,
- DSPDMAC_XFRCNT_INST_OFFSET(dma_chan), xfr_cnt);
- if (status < 0) {
- codec_dbg(codec, "write XFRCNT Reg fail\n");
- return status;
- }
- codec_dbg(codec, " dsp_dma_setup() Write XFRCNT\n");
-
- codec_dbg(codec,
- "ChipA=0x%x, cnt=0x%x, DMACFG=0x%x, "
- "ADROFS=0x%x, XFRCNT=0x%x\n",
- chip_addx, count, dma_cfg, adr_ofs, xfr_cnt);
-
- codec_dbg(codec, "-- dsp_dma_setup() -- Complete ---------\n");
-
- return 0;
-}
-
-/*
- * Start the DSP DMA
- */
-static int dsp_dma_start(struct hda_codec *codec,
- unsigned int dma_chan, bool ovly)
-{
- unsigned int reg = 0;
- int status = 0;
-
- codec_dbg(codec, "-- dsp_dma_start() -- Begin ---------\n");
-
- if (ovly) {
- status = chipio_read(codec,
- DSPDMAC_CHNLSTART_INST_OFFSET, &reg);
-
- if (status < 0) {
- codec_dbg(codec, "read CHNLSTART reg fail\n");
- return status;
- }
- codec_dbg(codec, "-- dsp_dma_start() Read CHNLSTART\n");
-
- reg &= ~(DSPDMAC_CHNLSTART_EN_MASK |
- DSPDMAC_CHNLSTART_DIS_MASK);
- }
-
- status = chipio_write(codec, DSPDMAC_CHNLSTART_INST_OFFSET,
- reg | (1 << (dma_chan + DSPDMAC_CHNLSTART_EN_LOBIT)));
- if (status < 0) {
- codec_dbg(codec, "write CHNLSTART reg fail\n");
- return status;
- }
- codec_dbg(codec, "-- dsp_dma_start() -- Complete ---------\n");
-
- return status;
-}
-
-/*
- * Stop the DSP DMA
- */
-static int dsp_dma_stop(struct hda_codec *codec,
- unsigned int dma_chan, bool ovly)
-{
- unsigned int reg = 0;
- int status = 0;
-
- codec_dbg(codec, "-- dsp_dma_stop() -- Begin ---------\n");
-
- if (ovly) {
- status = chipio_read(codec,
- DSPDMAC_CHNLSTART_INST_OFFSET, &reg);
-
- if (status < 0) {
- codec_dbg(codec, "read CHNLSTART reg fail\n");
- return status;
- }
- codec_dbg(codec, "-- dsp_dma_stop() Read CHNLSTART\n");
- reg &= ~(DSPDMAC_CHNLSTART_EN_MASK |
- DSPDMAC_CHNLSTART_DIS_MASK);
- }
-
- status = chipio_write(codec, DSPDMAC_CHNLSTART_INST_OFFSET,
- reg | (1 << (dma_chan + DSPDMAC_CHNLSTART_DIS_LOBIT)));
- if (status < 0) {
- codec_dbg(codec, "write CHNLSTART reg fail\n");
- return status;
- }
- codec_dbg(codec, "-- dsp_dma_stop() -- Complete ---------\n");
-
- return status;
-}
-
-/**
- * dsp_allocate_router_ports - Allocate router ports
- *
- * @codec: the HDA codec
- * @num_chans: number of channels in the stream
- * @ports_per_channel: number of ports per channel
- * @start_device: start device
- * @port_map: pointer to the port list to hold the allocated ports
- *
- * Returns zero or a negative error code.
- */
-static int dsp_allocate_router_ports(struct hda_codec *codec,
- unsigned int num_chans,
- unsigned int ports_per_channel,
- unsigned int start_device,
- unsigned int *port_map)
-{
- int status = 0;
- int res;
- u8 val;
-
- status = chipio_send(codec, VENDOR_CHIPIO_STATUS, 0);
- if (status < 0)
- return status;
-
- val = start_device << 6;
- val |= (ports_per_channel - 1) << 4;
- val |= num_chans - 1;
-
- snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
- VENDOR_CHIPIO_PORT_ALLOC_CONFIG_SET,
- val);
-
- snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
- VENDOR_CHIPIO_PORT_ALLOC_SET,
- MEM_CONNID_DSP);
-
- status = chipio_send(codec, VENDOR_CHIPIO_STATUS, 0);
- if (status < 0)
- return status;
-
- res = snd_hda_codec_read(codec, WIDGET_CHIP_CTRL, 0,
- VENDOR_CHIPIO_PORT_ALLOC_GET, 0);
-
- *port_map = res;
-
- return (res < 0) ? res : 0;
-}
-
-/*
- * Free router ports
- */
-static int dsp_free_router_ports(struct hda_codec *codec)
-{
- int status = 0;
-
- status = chipio_send(codec, VENDOR_CHIPIO_STATUS, 0);
- if (status < 0)
- return status;
-
- snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
- VENDOR_CHIPIO_PORT_FREE_SET,
- MEM_CONNID_DSP);
-
- status = chipio_send(codec, VENDOR_CHIPIO_STATUS, 0);
-
- return status;
-}
-
-/*
- * Allocate DSP ports for the download stream
- */
-static int dsp_allocate_ports(struct hda_codec *codec,
- unsigned int num_chans,
- unsigned int rate_multi, unsigned int *port_map)
-{
- int status;
-
- codec_dbg(codec, " dsp_allocate_ports() -- begin\n");
-
- if ((rate_multi != 1) && (rate_multi != 2) && (rate_multi != 4)) {
- codec_dbg(codec, "bad rate multiple\n");
- return -EINVAL;
- }
-
- status = dsp_allocate_router_ports(codec, num_chans,
- rate_multi, 0, port_map);
-
- codec_dbg(codec, " dsp_allocate_ports() -- complete\n");
-
- return status;
-}
-
-static int dsp_allocate_ports_format(struct hda_codec *codec,
- const unsigned short fmt,
- unsigned int *port_map)
-{
- unsigned int num_chans;
-
- unsigned int sample_rate_div = ((get_hdafmt_rate(fmt) >> 0) & 3) + 1;
- unsigned int sample_rate_mul = ((get_hdafmt_rate(fmt) >> 3) & 3) + 1;
- unsigned int rate_multi = sample_rate_mul / sample_rate_div;
-
- if ((rate_multi != 1) && (rate_multi != 2) && (rate_multi != 4)) {
- codec_dbg(codec, "bad rate multiple\n");
- return -EINVAL;
- }
-
- num_chans = get_hdafmt_chs(fmt) + 1;
-
- return dsp_allocate_ports(codec, num_chans, rate_multi, port_map);
-}
-
-/*
- * free DSP ports
- */
-static int dsp_free_ports(struct hda_codec *codec)
-{
- int status;
-
- codec_dbg(codec, " dsp_free_ports() -- begin\n");
-
- status = dsp_free_router_ports(codec);
- if (status < 0) {
- codec_dbg(codec, "free router ports fail\n");
- return status;
- }
- codec_dbg(codec, " dsp_free_ports() -- complete\n");
-
- return status;
-}
-
-/*
- * HDA DMA engine stuffs for DSP code download
- */
-struct dma_engine {
- struct hda_codec *codec;
- unsigned short m_converter_format;
- struct snd_dma_buffer *dmab;
- unsigned int buf_size;
-};
-
-
-enum dma_state {
- DMA_STATE_STOP = 0,
- DMA_STATE_RUN = 1
-};
-
-static int dma_convert_to_hda_format(struct hda_codec *codec,
- unsigned int sample_rate,
- unsigned short channels,
- unsigned short *hda_format)
-{
- unsigned int format_val;
-
- format_val = snd_hdac_stream_format(channels, 32, sample_rate);
-
- if (hda_format)
- *hda_format = (unsigned short)format_val;
-
- return 0;
-}
-
-/*
- * Reset DMA for DSP download
- */
-static int dma_reset(struct dma_engine *dma)
-{
- struct hda_codec *codec = dma->codec;
- struct ca0132_spec *spec = codec->spec;
- int status;
-
- if (dma->dmab->area)
- snd_hda_codec_load_dsp_cleanup(codec, dma->dmab);
-
- status = snd_hda_codec_load_dsp_prepare(codec,
- dma->m_converter_format,
- dma->buf_size,
- dma->dmab);
- if (status < 0)
- return status;
- spec->dsp_stream_id = status;
- return 0;
-}
-
-static int dma_set_state(struct dma_engine *dma, enum dma_state state)
-{
- bool cmd;
-
- switch (state) {
- case DMA_STATE_STOP:
- cmd = false;
- break;
- case DMA_STATE_RUN:
- cmd = true;
- break;
- default:
- return 0;
- }
-
- snd_hda_codec_load_dsp_trigger(dma->codec, cmd);
- return 0;
-}
-
-static unsigned int dma_get_buffer_size(struct dma_engine *dma)
-{
- return dma->dmab->bytes;
-}
-
-static unsigned char *dma_get_buffer_addr(struct dma_engine *dma)
-{
- return dma->dmab->area;
-}
-
-static int dma_xfer(struct dma_engine *dma,
- const unsigned int *data,
- unsigned int count)
-{
- memcpy(dma->dmab->area, data, count);
- return 0;
-}
-
-static void dma_get_converter_format(
- struct dma_engine *dma,
- unsigned short *format)
-{
- if (format)
- *format = dma->m_converter_format;
-}
-
-static unsigned int dma_get_stream_id(struct dma_engine *dma)
-{
- struct ca0132_spec *spec = dma->codec->spec;
-
- return spec->dsp_stream_id;
-}
-
-struct dsp_image_seg {
- u32 magic;
- u32 chip_addr;
- u32 count;
- u32 data[];
-};
-
-static const u32 g_magic_value = 0x4c46584d;
-static const u32 g_chip_addr_magic_value = 0xFFFFFF01;
-
-static bool is_valid(const struct dsp_image_seg *p)
-{
- return p->magic == g_magic_value;
-}
-
-static bool is_hci_prog_list_seg(const struct dsp_image_seg *p)
-{
- return g_chip_addr_magic_value == p->chip_addr;
-}
-
-static bool is_last(const struct dsp_image_seg *p)
-{
- return p->count == 0;
-}
-
-static size_t dsp_sizeof(const struct dsp_image_seg *p)
-{
- return struct_size(p, data, p->count);
-}
-
-static const struct dsp_image_seg *get_next_seg_ptr(
- const struct dsp_image_seg *p)
-{
- return (struct dsp_image_seg *)((unsigned char *)(p) + dsp_sizeof(p));
-}
-
-/*
- * CA0132 chip DSP transfer stuffs. For DSP download.
- */
-#define INVALID_DMA_CHANNEL (~0U)
-
-/*
- * Program a list of address/data pairs via the ChipIO widget.
- * The segment data is in the format of successive pairs of words.
- * These are repeated as indicated by the segment's count field.
- */
-static int dspxfr_hci_write(struct hda_codec *codec,
- const struct dsp_image_seg *fls)
-{
- int status;
- const u32 *data;
- unsigned int count;
-
- if (fls == NULL || fls->chip_addr != g_chip_addr_magic_value) {
- codec_dbg(codec, "hci_write invalid params\n");
- return -EINVAL;
- }
-
- count = fls->count;
- data = (u32 *)(fls->data);
- while (count >= 2) {
- status = chipio_write(codec, data[0], data[1]);
- if (status < 0) {
- codec_dbg(codec, "hci_write chipio failed\n");
- return status;
- }
- count -= 2;
- data += 2;
- }
- return 0;
-}
-
-/**
- * dspxfr_one_seg - Write a block of data into DSP code or data RAM using pre-allocated DMA engine.
- *
- * @codec: the HDA codec
- * @fls: pointer to a fast load image
- * @reloc: Relocation address for loading single-segment overlays, or 0 for
- * no relocation
- * @dma_engine: pointer to DMA engine to be used for DSP download
- * @dma_chan: The number of DMA channels used for DSP download
- * @port_map_mask: port mapping
- * @ovly: TRUE if overlay format is required
- *
- * Returns zero or a negative error code.
- */
-static int dspxfr_one_seg(struct hda_codec *codec,
- const struct dsp_image_seg *fls,
- unsigned int reloc,
- struct dma_engine *dma_engine,
- unsigned int dma_chan,
- unsigned int port_map_mask,
- bool ovly)
-{
- int status = 0;
- bool comm_dma_setup_done = false;
- const unsigned int *data;
- unsigned int chip_addx;
- unsigned int words_to_write;
- unsigned int buffer_size_words;
- unsigned char *buffer_addx;
- unsigned short hda_format;
- unsigned int sample_rate_div;
- unsigned int sample_rate_mul;
- unsigned int num_chans;
- unsigned int hda_frame_size_words;
- unsigned int remainder_words;
- const u32 *data_remainder;
- u32 chip_addx_remainder;
- unsigned int run_size_words;
- const struct dsp_image_seg *hci_write = NULL;
- unsigned long timeout;
- bool dma_active;
-
- if (fls == NULL)
- return -EINVAL;
- if (is_hci_prog_list_seg(fls)) {
- hci_write = fls;
- fls = get_next_seg_ptr(fls);
- }
-
- if (hci_write && (!fls || is_last(fls))) {
- codec_dbg(codec, "hci_write\n");
- return dspxfr_hci_write(codec, hci_write);
- }
-
- if (fls == NULL || dma_engine == NULL || port_map_mask == 0) {
- codec_dbg(codec, "Invalid Params\n");
- return -EINVAL;
- }
-
- data = fls->data;
- chip_addx = fls->chip_addr;
- words_to_write = fls->count;
-
- if (!words_to_write)
- return hci_write ? dspxfr_hci_write(codec, hci_write) : 0;
- if (reloc)
- chip_addx = (chip_addx & (0xFFFF0000 << 2)) + (reloc << 2);
-
- if (!UC_RANGE(chip_addx, words_to_write) &&
- !X_RANGE_ALL(chip_addx, words_to_write) &&
- !Y_RANGE_ALL(chip_addx, words_to_write)) {
- codec_dbg(codec, "Invalid chip_addx Params\n");
- return -EINVAL;
- }
-
- buffer_size_words = (unsigned int)dma_get_buffer_size(dma_engine) /
- sizeof(u32);
-
- buffer_addx = dma_get_buffer_addr(dma_engine);
-
- if (buffer_addx == NULL) {
- codec_dbg(codec, "dma_engine buffer NULL\n");
- return -EINVAL;
- }
-
- dma_get_converter_format(dma_engine, &hda_format);
- sample_rate_div = ((get_hdafmt_rate(hda_format) >> 0) & 3) + 1;
- sample_rate_mul = ((get_hdafmt_rate(hda_format) >> 3) & 3) + 1;
- num_chans = get_hdafmt_chs(hda_format) + 1;
-
- hda_frame_size_words = ((sample_rate_div == 0) ? 0 :
- (num_chans * sample_rate_mul / sample_rate_div));
-
- if (hda_frame_size_words == 0) {
- codec_dbg(codec, "frmsz zero\n");
- return -EINVAL;
- }
-
- buffer_size_words = min(buffer_size_words,
- (unsigned int)(UC_RANGE(chip_addx, 1) ?
- 65536 : 32768));
- buffer_size_words -= buffer_size_words % hda_frame_size_words;
- codec_dbg(codec,
- "chpadr=0x%08x frmsz=%u nchan=%u "
- "rate_mul=%u div=%u bufsz=%u\n",
- chip_addx, hda_frame_size_words, num_chans,
- sample_rate_mul, sample_rate_div, buffer_size_words);
-
- if (buffer_size_words < hda_frame_size_words) {
- codec_dbg(codec, "dspxfr_one_seg:failed\n");
- return -EINVAL;
- }
-
- remainder_words = words_to_write % hda_frame_size_words;
- data_remainder = data;
- chip_addx_remainder = chip_addx;
-
- data += remainder_words;
- chip_addx += remainder_words*sizeof(u32);
- words_to_write -= remainder_words;
-
- while (words_to_write != 0) {
- run_size_words = min(buffer_size_words, words_to_write);
- codec_dbg(codec, "dspxfr (seg loop)cnt=%u rs=%u remainder=%u\n",
- words_to_write, run_size_words, remainder_words);
- dma_xfer(dma_engine, data, run_size_words*sizeof(u32));
- if (!comm_dma_setup_done) {
- status = dsp_dma_stop(codec, dma_chan, ovly);
- if (status < 0)
- return status;
- status = dsp_dma_setup_common(codec, chip_addx,
- dma_chan, port_map_mask, ovly);
- if (status < 0)
- return status;
- comm_dma_setup_done = true;
- }
-
- status = dsp_dma_setup(codec, chip_addx,
- run_size_words, dma_chan);
- if (status < 0)
- return status;
- status = dsp_dma_start(codec, dma_chan, ovly);
- if (status < 0)
- return status;
- if (!dsp_is_dma_active(codec, dma_chan)) {
- codec_dbg(codec, "dspxfr:DMA did not start\n");
- return -EIO;
- }
- status = dma_set_state(dma_engine, DMA_STATE_RUN);
- if (status < 0)
- return status;
- if (remainder_words != 0) {
- status = chipio_write_multiple(codec,
- chip_addx_remainder,
- data_remainder,
- remainder_words);
- if (status < 0)
- return status;
- remainder_words = 0;
- }
- if (hci_write) {
- status = dspxfr_hci_write(codec, hci_write);
- if (status < 0)
- return status;
- hci_write = NULL;
- }
-
- timeout = jiffies + msecs_to_jiffies(2000);
- do {
- dma_active = dsp_is_dma_active(codec, dma_chan);
- if (!dma_active)
- break;
- msleep(20);
- } while (time_before(jiffies, timeout));
- if (dma_active)
- break;
-
- codec_dbg(codec, "+++++ DMA complete\n");
- dma_set_state(dma_engine, DMA_STATE_STOP);
- status = dma_reset(dma_engine);
-
- if (status < 0)
- return status;
-
- data += run_size_words;
- chip_addx += run_size_words*sizeof(u32);
- words_to_write -= run_size_words;
- }
-
- if (remainder_words != 0) {
- status = chipio_write_multiple(codec, chip_addx_remainder,
- data_remainder, remainder_words);
- }
-
- return status;
-}
-
-/**
- * dspxfr_image - Write the entire DSP image of a DSP code/data overlay to DSP memories
- *
- * @codec: the HDA codec
- * @fls_data: pointer to a fast load image
- * @reloc: Relocation address for loading single-segment overlays, or 0 for
- * no relocation
- * @sample_rate: sampling rate of the stream used for DSP download
- * @channels: channels of the stream used for DSP download
- * @ovly: TRUE if overlay format is required
- *
- * Returns zero or a negative error code.
- */
-static int dspxfr_image(struct hda_codec *codec,
- const struct dsp_image_seg *fls_data,
- unsigned int reloc,
- unsigned int sample_rate,
- unsigned short channels,
- bool ovly)
-{
- struct ca0132_spec *spec = codec->spec;
- int status;
- unsigned short hda_format = 0;
- unsigned int response;
- unsigned char stream_id = 0;
- struct dma_engine *dma_engine;
- unsigned int dma_chan;
- unsigned int port_map_mask;
-
- if (fls_data == NULL)
- return -EINVAL;
-
- dma_engine = kzalloc(sizeof(*dma_engine), GFP_KERNEL);
- if (!dma_engine)
- return -ENOMEM;
-
- dma_engine->dmab = kzalloc(sizeof(*dma_engine->dmab), GFP_KERNEL);
- if (!dma_engine->dmab) {
- kfree(dma_engine);
- return -ENOMEM;
- }
-
- dma_engine->codec = codec;
- dma_convert_to_hda_format(codec, sample_rate, channels, &hda_format);
- dma_engine->m_converter_format = hda_format;
- dma_engine->buf_size = (ovly ? DSP_DMA_WRITE_BUFLEN_OVLY :
- DSP_DMA_WRITE_BUFLEN_INIT) * 2;
-
- dma_chan = ovly ? INVALID_DMA_CHANNEL : 0;
-
- status = codec_set_converter_format(codec, WIDGET_CHIP_CTRL,
- hda_format, &response);
-
- if (status < 0) {
- codec_dbg(codec, "set converter format fail\n");
- goto exit;
- }
-
- status = snd_hda_codec_load_dsp_prepare(codec,
- dma_engine->m_converter_format,
- dma_engine->buf_size,
- dma_engine->dmab);
- if (status < 0)
- goto exit;
- spec->dsp_stream_id = status;
-
- if (ovly) {
- status = dspio_alloc_dma_chan(codec, &dma_chan);
- if (status < 0) {
- codec_dbg(codec, "alloc dmachan fail\n");
- dma_chan = INVALID_DMA_CHANNEL;
- goto exit;
- }
- }
-
- port_map_mask = 0;
- status = dsp_allocate_ports_format(codec, hda_format,
- &port_map_mask);
- if (status < 0) {
- codec_dbg(codec, "alloc ports fail\n");
- goto exit;
- }
-
- stream_id = dma_get_stream_id(dma_engine);
- status = codec_set_converter_stream_channel(codec,
- WIDGET_CHIP_CTRL, stream_id, 0, &response);
- if (status < 0) {
- codec_dbg(codec, "set stream chan fail\n");
- goto exit;
- }
-
- while ((fls_data != NULL) && !is_last(fls_data)) {
- if (!is_valid(fls_data)) {
- codec_dbg(codec, "FLS check fail\n");
- status = -EINVAL;
- goto exit;
- }
- status = dspxfr_one_seg(codec, fls_data, reloc,
- dma_engine, dma_chan,
- port_map_mask, ovly);
- if (status < 0)
- break;
-
- if (is_hci_prog_list_seg(fls_data))
- fls_data = get_next_seg_ptr(fls_data);
-
- if ((fls_data != NULL) && !is_last(fls_data))
- fls_data = get_next_seg_ptr(fls_data);
- }
-
- if (port_map_mask != 0)
- status = dsp_free_ports(codec);
-
- if (status < 0)
- goto exit;
-
- status = codec_set_converter_stream_channel(codec,
- WIDGET_CHIP_CTRL, 0, 0, &response);
-
-exit:
- if (ovly && (dma_chan != INVALID_DMA_CHANNEL))
- dspio_free_dma_chan(codec, dma_chan);
-
- if (dma_engine->dmab->area)
- snd_hda_codec_load_dsp_cleanup(codec, dma_engine->dmab);
- kfree(dma_engine->dmab);
- kfree(dma_engine);
-
- return status;
-}
-
-/*
- * CA0132 DSP download stuffs.
- */
-static void dspload_post_setup(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- codec_dbg(codec, "---- dspload_post_setup ------\n");
- if (!ca0132_use_alt_functions(spec)) {
- /*set DSP speaker to 2.0 configuration*/
- chipio_write(codec, XRAM_XRAM_INST_OFFSET(0x18), 0x08080080);
- chipio_write(codec, XRAM_XRAM_INST_OFFSET(0x19), 0x3f800000);
-
- /*update write pointer*/
- chipio_write(codec, XRAM_XRAM_INST_OFFSET(0x29), 0x00000002);
- }
-}
-
-/**
- * dspload_image - Download DSP from a DSP Image Fast Load structure.
- *
- * @codec: the HDA codec
- * @fls: pointer to a fast load image
- * @ovly: TRUE if overlay format is required
- * @reloc: Relocation address for loading single-segment overlays, or 0 for
- * no relocation
- * @autostart: TRUE if DSP starts after loading; ignored if ovly is TRUE
- * @router_chans: number of audio router channels to be allocated (0 means use
- * internal defaults; max is 32)
- *
- * Download DSP from a DSP Image Fast Load structure. This structure is a
- * linear, non-constant sized element array of structures, each of which
- * contain the count of the data to be loaded, the data itself, and the
- * corresponding starting chip address of the starting data location.
- * Returns zero or a negative error code.
- */
-static int dspload_image(struct hda_codec *codec,
- const struct dsp_image_seg *fls,
- bool ovly,
- unsigned int reloc,
- bool autostart,
- int router_chans)
-{
- int status = 0;
- unsigned int sample_rate;
- unsigned short channels;
-
- codec_dbg(codec, "---- dspload_image begin ------\n");
- if (router_chans == 0) {
- if (!ovly)
- router_chans = DMA_TRANSFER_FRAME_SIZE_NWORDS;
- else
- router_chans = DMA_OVERLAY_FRAME_SIZE_NWORDS;
- }
-
- sample_rate = 48000;
- channels = (unsigned short)router_chans;
-
- while (channels > 16) {
- sample_rate *= 2;
- channels /= 2;
- }
-
- do {
- codec_dbg(codec, "Ready to program DMA\n");
- if (!ovly)
- status = dsp_reset(codec);
-
- if (status < 0)
- break;
-
- codec_dbg(codec, "dsp_reset() complete\n");
- status = dspxfr_image(codec, fls, reloc, sample_rate, channels,
- ovly);
-
- if (status < 0)
- break;
-
- codec_dbg(codec, "dspxfr_image() complete\n");
- if (autostart && !ovly) {
- dspload_post_setup(codec);
- status = dsp_set_run_state(codec);
- }
-
- codec_dbg(codec, "LOAD FINISHED\n");
- } while (0);
-
- return status;
-}
-
-#ifdef CONFIG_SND_HDA_CODEC_CA0132_DSP
-static bool dspload_is_loaded(struct hda_codec *codec)
-{
- unsigned int data = 0;
- int status = 0;
-
- status = chipio_read(codec, 0x40004, &data);
- if ((status < 0) || (data != 1))
- return false;
-
- return true;
-}
-#else
-#define dspload_is_loaded(codec) false
-#endif
-
-static bool dspload_wait_loaded(struct hda_codec *codec)
-{
- unsigned long timeout = jiffies + msecs_to_jiffies(2000);
-
- do {
- if (dspload_is_loaded(codec)) {
- codec_info(codec, "ca0132 DSP downloaded and running\n");
- return true;
- }
- msleep(20);
- } while (time_before(jiffies, timeout));
-
- codec_err(codec, "ca0132 failed to download DSP\n");
- return false;
-}
-
-/*
- * ca0113 related functions. The ca0113 acts as the HDA bus for the pci-e
- * based cards, and has a second mmio region, region2, that's used for special
- * commands.
- */
-
-/*
- * For cards with PCI-E region2 (Sound Blaster Z/ZxR, Recon3D, and AE-5)
- * the mmio address 0x320 is used to set GPIO pins. The format for the data
- * The first eight bits are just the number of the pin. So far, I've only seen
- * this number go to 7.
- * AE-5 note: The AE-5 seems to use pins 2 and 3 to somehow set the color value
- * of the on-card LED. It seems to use pin 2 for data, then toggles 3 to on and
- * then off to send that bit.
- */
-static void ca0113_mmio_gpio_set(struct hda_codec *codec, unsigned int gpio_pin,
- bool enable)
-{
- struct ca0132_spec *spec = codec->spec;
- unsigned short gpio_data;
-
- gpio_data = gpio_pin & 0xF;
- gpio_data |= ((enable << 8) & 0x100);
-
- writew(gpio_data, spec->mem_base + 0x320);
-}
-
-/*
- * Special pci region2 commands that are only used by the AE-5. They follow
- * a set format, and require reads at certain points to seemingly 'clear'
- * the response data. My first tests didn't do these reads, and would cause
- * the card to get locked up until the memory was read. These commands
- * seem to work with three distinct values that I've taken to calling group,
- * target-id, and value.
- */
-static void ca0113_mmio_command_set(struct hda_codec *codec, unsigned int group,
- unsigned int target, unsigned int value)
-{
- struct ca0132_spec *spec = codec->spec;
- unsigned int write_val;
-
- writel(0x0000007e, spec->mem_base + 0x210);
- readl(spec->mem_base + 0x210);
- writel(0x0000005a, spec->mem_base + 0x210);
- readl(spec->mem_base + 0x210);
- readl(spec->mem_base + 0x210);
-
- writel(0x00800005, spec->mem_base + 0x20c);
- writel(group, spec->mem_base + 0x804);
-
- writel(0x00800005, spec->mem_base + 0x20c);
- write_val = (target & 0xff);
- write_val |= (value << 8);
-
-
- writel(write_val, spec->mem_base + 0x204);
- /*
- * Need delay here or else it goes too fast and works inconsistently.
- */
- msleep(20);
-
- readl(spec->mem_base + 0x860);
- readl(spec->mem_base + 0x854);
- readl(spec->mem_base + 0x840);
-
- writel(0x00800004, spec->mem_base + 0x20c);
- writel(0x00000000, spec->mem_base + 0x210);
- readl(spec->mem_base + 0x210);
- readl(spec->mem_base + 0x210);
-}
-
-/*
- * This second type of command is used for setting the sound filter type.
- */
-static void ca0113_mmio_command_set_type2(struct hda_codec *codec,
- unsigned int group, unsigned int target, unsigned int value)
-{
- struct ca0132_spec *spec = codec->spec;
- unsigned int write_val;
-
- writel(0x0000007e, spec->mem_base + 0x210);
- readl(spec->mem_base + 0x210);
- writel(0x0000005a, spec->mem_base + 0x210);
- readl(spec->mem_base + 0x210);
- readl(spec->mem_base + 0x210);
-
- writel(0x00800003, spec->mem_base + 0x20c);
- writel(group, spec->mem_base + 0x804);
-
- writel(0x00800005, spec->mem_base + 0x20c);
- write_val = (target & 0xff);
- write_val |= (value << 8);
-
-
- writel(write_val, spec->mem_base + 0x204);
- msleep(20);
- readl(spec->mem_base + 0x860);
- readl(spec->mem_base + 0x854);
- readl(spec->mem_base + 0x840);
-
- writel(0x00800004, spec->mem_base + 0x20c);
- writel(0x00000000, spec->mem_base + 0x210);
- readl(spec->mem_base + 0x210);
- readl(spec->mem_base + 0x210);
-}
-
-/*
- * Setup GPIO for the other variants of Core3D.
- */
-
-/*
- * Sets up the GPIO pins so that they are discoverable. If this isn't done,
- * the card shows as having no GPIO pins.
- */
-static void ca0132_gpio_init(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
-
- switch (ca0132_quirk(spec)) {
- case QUIRK_SBZ:
- case QUIRK_AE5:
- case QUIRK_AE7:
- snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00);
- snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x53);
- snd_hda_codec_write(codec, 0x01, 0, 0x790, 0x23);
- break;
- case QUIRK_R3DI:
- snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00);
- snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x5B);
- break;
- default:
- break;
- }
-
-}
-
-/* Sets the GPIO for audio output. */
-static void ca0132_gpio_setup(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
-
- switch (ca0132_quirk(spec)) {
- case QUIRK_SBZ:
- snd_hda_codec_write(codec, 0x01, 0,
- AC_VERB_SET_GPIO_DIRECTION, 0x07);
- snd_hda_codec_write(codec, 0x01, 0,
- AC_VERB_SET_GPIO_MASK, 0x07);
- snd_hda_codec_write(codec, 0x01, 0,
- AC_VERB_SET_GPIO_DATA, 0x04);
- snd_hda_codec_write(codec, 0x01, 0,
- AC_VERB_SET_GPIO_DATA, 0x06);
- break;
- case QUIRK_R3DI:
- snd_hda_codec_write(codec, 0x01, 0,
- AC_VERB_SET_GPIO_DIRECTION, 0x1E);
- snd_hda_codec_write(codec, 0x01, 0,
- AC_VERB_SET_GPIO_MASK, 0x1F);
- snd_hda_codec_write(codec, 0x01, 0,
- AC_VERB_SET_GPIO_DATA, 0x0C);
- break;
- default:
- break;
- }
-}
-
-/*
- * GPIO control functions for the Recon3D integrated.
- */
-
-enum r3di_gpio_bit {
- /* Bit 1 - Switch between front/rear mic. 0 = rear, 1 = front */
- R3DI_MIC_SELECT_BIT = 1,
- /* Bit 2 - Switch between headphone/line out. 0 = Headphone, 1 = Line */
- R3DI_OUT_SELECT_BIT = 2,
- /*
- * I dunno what this actually does, but it stays on until the dsp
- * is downloaded.
- */
- R3DI_GPIO_DSP_DOWNLOADING = 3,
- /*
- * Same as above, no clue what it does, but it comes on after the dsp
- * is downloaded.
- */
- R3DI_GPIO_DSP_DOWNLOADED = 4
-};
-
-enum r3di_mic_select {
- /* Set GPIO bit 1 to 0 for rear mic */
- R3DI_REAR_MIC = 0,
- /* Set GPIO bit 1 to 1 for front microphone*/
- R3DI_FRONT_MIC = 1
-};
-
-enum r3di_out_select {
- /* Set GPIO bit 2 to 0 for headphone */
- R3DI_HEADPHONE_OUT = 0,
- /* Set GPIO bit 2 to 1 for speaker */
- R3DI_LINE_OUT = 1
-};
-enum r3di_dsp_status {
- /* Set GPIO bit 3 to 1 until DSP is downloaded */
- R3DI_DSP_DOWNLOADING = 0,
- /* Set GPIO bit 4 to 1 once DSP is downloaded */
- R3DI_DSP_DOWNLOADED = 1
-};
-
-
-static void r3di_gpio_mic_set(struct hda_codec *codec,
- enum r3di_mic_select cur_mic)
-{
- unsigned int cur_gpio;
-
- /* Get the current GPIO Data setup */
- cur_gpio = snd_hda_codec_read(codec, 0x01, 0, AC_VERB_GET_GPIO_DATA, 0);
-
- switch (cur_mic) {
- case R3DI_REAR_MIC:
- cur_gpio &= ~(1 << R3DI_MIC_SELECT_BIT);
- break;
- case R3DI_FRONT_MIC:
- cur_gpio |= (1 << R3DI_MIC_SELECT_BIT);
- break;
- }
- snd_hda_codec_write(codec, codec->core.afg, 0,
- AC_VERB_SET_GPIO_DATA, cur_gpio);
-}
-
-static void r3di_gpio_dsp_status_set(struct hda_codec *codec,
- enum r3di_dsp_status dsp_status)
-{
- unsigned int cur_gpio;
-
- /* Get the current GPIO Data setup */
- cur_gpio = snd_hda_codec_read(codec, 0x01, 0, AC_VERB_GET_GPIO_DATA, 0);
-
- switch (dsp_status) {
- case R3DI_DSP_DOWNLOADING:
- cur_gpio |= (1 << R3DI_GPIO_DSP_DOWNLOADING);
- snd_hda_codec_write(codec, codec->core.afg, 0,
- AC_VERB_SET_GPIO_DATA, cur_gpio);
- break;
- case R3DI_DSP_DOWNLOADED:
- /* Set DOWNLOADING bit to 0. */
- cur_gpio &= ~(1 << R3DI_GPIO_DSP_DOWNLOADING);
-
- snd_hda_codec_write(codec, codec->core.afg, 0,
- AC_VERB_SET_GPIO_DATA, cur_gpio);
-
- cur_gpio |= (1 << R3DI_GPIO_DSP_DOWNLOADED);
- break;
- }
-
- snd_hda_codec_write(codec, codec->core.afg, 0,
- AC_VERB_SET_GPIO_DATA, cur_gpio);
-}
-
-/*
- * PCM callbacks
- */
-static int ca0132_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- unsigned int stream_tag,
- unsigned int format,
- struct snd_pcm_substream *substream)
-{
- struct ca0132_spec *spec = codec->spec;
-
- snd_hda_codec_setup_stream(codec, spec->dacs[0], stream_tag, 0, format);
-
- return 0;
-}
-
-static int ca0132_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- struct ca0132_spec *spec = codec->spec;
-
- if (spec->dsp_state == DSP_DOWNLOADING)
- return 0;
-
- /*If Playback effects are on, allow stream some time to flush
- *effects tail*/
- if (spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID])
- msleep(50);
-
- snd_hda_codec_cleanup_stream(codec, spec->dacs[0]);
-
- return 0;
-}
-
-static unsigned int ca0132_playback_pcm_delay(struct hda_pcm_stream *info,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- struct ca0132_spec *spec = codec->spec;
- unsigned int latency = DSP_PLAYBACK_INIT_LATENCY;
- struct snd_pcm_runtime *runtime = substream->runtime;
-
- if (spec->dsp_state != DSP_DOWNLOADED)
- return 0;
-
- /* Add latency if playback enhancement and either effect is enabled. */
- if (spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID]) {
- if ((spec->effects_switch[SURROUND - EFFECT_START_NID]) ||
- (spec->effects_switch[DIALOG_PLUS - EFFECT_START_NID]))
- latency += DSP_PLAY_ENHANCEMENT_LATENCY;
- }
-
- /* Applying Speaker EQ adds latency as well. */
- if (spec->cur_out_type == SPEAKER_OUT)
- latency += DSP_SPEAKER_OUT_LATENCY;
-
- return (latency * runtime->rate) / 1000;
-}
-
-/*
- * Digital out
- */
-static int ca0132_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- struct ca0132_spec *spec = codec->spec;
- return snd_hda_multi_out_dig_open(codec, &spec->multiout);
-}
-
-static int ca0132_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- unsigned int stream_tag,
- unsigned int format,
- struct snd_pcm_substream *substream)
-{
- struct ca0132_spec *spec = codec->spec;
- return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
- stream_tag, format, substream);
-}
-
-static int ca0132_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- struct ca0132_spec *spec = codec->spec;
- return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
-}
-
-static int ca0132_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- struct ca0132_spec *spec = codec->spec;
- return snd_hda_multi_out_dig_close(codec, &spec->multiout);
-}
-
-/*
- * Analog capture
- */
-static int ca0132_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- unsigned int stream_tag,
- unsigned int format,
- struct snd_pcm_substream *substream)
-{
- snd_hda_codec_setup_stream(codec, hinfo->nid,
- stream_tag, 0, format);
-
- return 0;
-}
-
-static int ca0132_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- struct ca0132_spec *spec = codec->spec;
-
- if (spec->dsp_state == DSP_DOWNLOADING)
- return 0;
-
- snd_hda_codec_cleanup_stream(codec, hinfo->nid);
- return 0;
-}
-
-static unsigned int ca0132_capture_pcm_delay(struct hda_pcm_stream *info,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- struct ca0132_spec *spec = codec->spec;
- unsigned int latency = DSP_CAPTURE_INIT_LATENCY;
- struct snd_pcm_runtime *runtime = substream->runtime;
-
- if (spec->dsp_state != DSP_DOWNLOADED)
- return 0;
-
- if (spec->effects_switch[CRYSTAL_VOICE - EFFECT_START_NID])
- latency += DSP_CRYSTAL_VOICE_LATENCY;
-
- return (latency * runtime->rate) / 1000;
-}
-
-/*
- * Controls stuffs.
- */
-
-/*
- * Mixer controls helpers.
- */
-#define CA0132_CODEC_VOL_MONO(xname, nid, channel, dir) \
- { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
- .name = xname, \
- .subdevice = HDA_SUBDEV_AMP_FLAG, \
- .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
- SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
- SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \
- .info = ca0132_volume_info, \
- .get = ca0132_volume_get, \
- .put = ca0132_volume_put, \
- .tlv = { .c = ca0132_volume_tlv }, \
- .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, 0, dir) }
-
-/*
- * Creates a mixer control that uses defaults of HDA_CODEC_VOL except for the
- * volume put, which is used for setting the DSP volume. This was done because
- * the ca0132 functions were taking too much time and causing lag.
- */
-#define CA0132_ALT_CODEC_VOL_MONO(xname, nid, channel, dir) \
- { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
- .name = xname, \
- .subdevice = HDA_SUBDEV_AMP_FLAG, \
- .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
- SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
- SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \
- .info = snd_hda_mixer_amp_volume_info, \
- .get = snd_hda_mixer_amp_volume_get, \
- .put = ca0132_alt_volume_put, \
- .tlv = { .c = snd_hda_mixer_amp_tlv }, \
- .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, 0, dir) }
-
-#define CA0132_CODEC_MUTE_MONO(xname, nid, channel, dir) \
- { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
- .name = xname, \
- .subdevice = HDA_SUBDEV_AMP_FLAG, \
- .info = snd_hda_mixer_amp_switch_info, \
- .get = ca0132_switch_get, \
- .put = ca0132_switch_put, \
- .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, 0, dir) }
-
-/* stereo */
-#define CA0132_CODEC_VOL(xname, nid, dir) \
- CA0132_CODEC_VOL_MONO(xname, nid, 3, dir)
-#define CA0132_ALT_CODEC_VOL(xname, nid, dir) \
- CA0132_ALT_CODEC_VOL_MONO(xname, nid, 3, dir)
-#define CA0132_CODEC_MUTE(xname, nid, dir) \
- CA0132_CODEC_MUTE_MONO(xname, nid, 3, dir)
-
-/* lookup tables */
-/*
- * Lookup table with decibel values for the DSP. When volume is changed in
- * Windows, the DSP is also sent the dB value in floating point. In Windows,
- * these values have decimal points, probably because the Windows driver
- * actually uses floating point. We can't here, so I made a lookup table of
- * values -90 to 9. -90 is the lowest decibel value for both the ADC's and the
- * DAC's, and 9 is the maximum.
- */
-static const unsigned int float_vol_db_lookup[] = {
-0xC2B40000, 0xC2B20000, 0xC2B00000, 0xC2AE0000, 0xC2AC0000, 0xC2AA0000,
-0xC2A80000, 0xC2A60000, 0xC2A40000, 0xC2A20000, 0xC2A00000, 0xC29E0000,
-0xC29C0000, 0xC29A0000, 0xC2980000, 0xC2960000, 0xC2940000, 0xC2920000,
-0xC2900000, 0xC28E0000, 0xC28C0000, 0xC28A0000, 0xC2880000, 0xC2860000,
-0xC2840000, 0xC2820000, 0xC2800000, 0xC27C0000, 0xC2780000, 0xC2740000,
-0xC2700000, 0xC26C0000, 0xC2680000, 0xC2640000, 0xC2600000, 0xC25C0000,
-0xC2580000, 0xC2540000, 0xC2500000, 0xC24C0000, 0xC2480000, 0xC2440000,
-0xC2400000, 0xC23C0000, 0xC2380000, 0xC2340000, 0xC2300000, 0xC22C0000,
-0xC2280000, 0xC2240000, 0xC2200000, 0xC21C0000, 0xC2180000, 0xC2140000,
-0xC2100000, 0xC20C0000, 0xC2080000, 0xC2040000, 0xC2000000, 0xC1F80000,
-0xC1F00000, 0xC1E80000, 0xC1E00000, 0xC1D80000, 0xC1D00000, 0xC1C80000,
-0xC1C00000, 0xC1B80000, 0xC1B00000, 0xC1A80000, 0xC1A00000, 0xC1980000,
-0xC1900000, 0xC1880000, 0xC1800000, 0xC1700000, 0xC1600000, 0xC1500000,
-0xC1400000, 0xC1300000, 0xC1200000, 0xC1100000, 0xC1000000, 0xC0E00000,
-0xC0C00000, 0xC0A00000, 0xC0800000, 0xC0400000, 0xC0000000, 0xBF800000,
-0x00000000, 0x3F800000, 0x40000000, 0x40400000, 0x40800000, 0x40A00000,
-0x40C00000, 0x40E00000, 0x41000000, 0x41100000
-};
-
-/*
- * This table counts from float 0 to 1 in increments of .01, which is
- * useful for a few different sliders.
- */
-static const unsigned int float_zero_to_one_lookup[] = {
-0x00000000, 0x3C23D70A, 0x3CA3D70A, 0x3CF5C28F, 0x3D23D70A, 0x3D4CCCCD,
-0x3D75C28F, 0x3D8F5C29, 0x3DA3D70A, 0x3DB851EC, 0x3DCCCCCD, 0x3DE147AE,
-0x3DF5C28F, 0x3E051EB8, 0x3E0F5C29, 0x3E19999A, 0x3E23D70A, 0x3E2E147B,
-0x3E3851EC, 0x3E428F5C, 0x3E4CCCCD, 0x3E570A3D, 0x3E6147AE, 0x3E6B851F,
-0x3E75C28F, 0x3E800000, 0x3E851EB8, 0x3E8A3D71, 0x3E8F5C29, 0x3E947AE1,
-0x3E99999A, 0x3E9EB852, 0x3EA3D70A, 0x3EA8F5C3, 0x3EAE147B, 0x3EB33333,
-0x3EB851EC, 0x3EBD70A4, 0x3EC28F5C, 0x3EC7AE14, 0x3ECCCCCD, 0x3ED1EB85,
-0x3ED70A3D, 0x3EDC28F6, 0x3EE147AE, 0x3EE66666, 0x3EEB851F, 0x3EF0A3D7,
-0x3EF5C28F, 0x3EFAE148, 0x3F000000, 0x3F028F5C, 0x3F051EB8, 0x3F07AE14,
-0x3F0A3D71, 0x3F0CCCCD, 0x3F0F5C29, 0x3F11EB85, 0x3F147AE1, 0x3F170A3D,
-0x3F19999A, 0x3F1C28F6, 0x3F1EB852, 0x3F2147AE, 0x3F23D70A, 0x3F266666,
-0x3F28F5C3, 0x3F2B851F, 0x3F2E147B, 0x3F30A3D7, 0x3F333333, 0x3F35C28F,
-0x3F3851EC, 0x3F3AE148, 0x3F3D70A4, 0x3F400000, 0x3F428F5C, 0x3F451EB8,
-0x3F47AE14, 0x3F4A3D71, 0x3F4CCCCD, 0x3F4F5C29, 0x3F51EB85, 0x3F547AE1,
-0x3F570A3D, 0x3F59999A, 0x3F5C28F6, 0x3F5EB852, 0x3F6147AE, 0x3F63D70A,
-0x3F666666, 0x3F68F5C3, 0x3F6B851F, 0x3F6E147B, 0x3F70A3D7, 0x3F733333,
-0x3F75C28F, 0x3F7851EC, 0x3F7AE148, 0x3F7D70A4, 0x3F800000
-};
-
-/*
- * This table counts from float 10 to 1000, which is the range of the x-bass
- * crossover slider in Windows.
- */
-static const unsigned int float_xbass_xover_lookup[] = {
-0x41200000, 0x41A00000, 0x41F00000, 0x42200000, 0x42480000, 0x42700000,
-0x428C0000, 0x42A00000, 0x42B40000, 0x42C80000, 0x42DC0000, 0x42F00000,
-0x43020000, 0x430C0000, 0x43160000, 0x43200000, 0x432A0000, 0x43340000,
-0x433E0000, 0x43480000, 0x43520000, 0x435C0000, 0x43660000, 0x43700000,
-0x437A0000, 0x43820000, 0x43870000, 0x438C0000, 0x43910000, 0x43960000,
-0x439B0000, 0x43A00000, 0x43A50000, 0x43AA0000, 0x43AF0000, 0x43B40000,
-0x43B90000, 0x43BE0000, 0x43C30000, 0x43C80000, 0x43CD0000, 0x43D20000,
-0x43D70000, 0x43DC0000, 0x43E10000, 0x43E60000, 0x43EB0000, 0x43F00000,
-0x43F50000, 0x43FA0000, 0x43FF0000, 0x44020000, 0x44048000, 0x44070000,
-0x44098000, 0x440C0000, 0x440E8000, 0x44110000, 0x44138000, 0x44160000,
-0x44188000, 0x441B0000, 0x441D8000, 0x44200000, 0x44228000, 0x44250000,
-0x44278000, 0x442A0000, 0x442C8000, 0x442F0000, 0x44318000, 0x44340000,
-0x44368000, 0x44390000, 0x443B8000, 0x443E0000, 0x44408000, 0x44430000,
-0x44458000, 0x44480000, 0x444A8000, 0x444D0000, 0x444F8000, 0x44520000,
-0x44548000, 0x44570000, 0x44598000, 0x445C0000, 0x445E8000, 0x44610000,
-0x44638000, 0x44660000, 0x44688000, 0x446B0000, 0x446D8000, 0x44700000,
-0x44728000, 0x44750000, 0x44778000, 0x447A0000
-};
-
-/* The following are for tuning of products */
-#ifdef ENABLE_TUNING_CONTROLS
-
-static const unsigned int voice_focus_vals_lookup[] = {
-0x41A00000, 0x41A80000, 0x41B00000, 0x41B80000, 0x41C00000, 0x41C80000,
-0x41D00000, 0x41D80000, 0x41E00000, 0x41E80000, 0x41F00000, 0x41F80000,
-0x42000000, 0x42040000, 0x42080000, 0x420C0000, 0x42100000, 0x42140000,
-0x42180000, 0x421C0000, 0x42200000, 0x42240000, 0x42280000, 0x422C0000,
-0x42300000, 0x42340000, 0x42380000, 0x423C0000, 0x42400000, 0x42440000,
-0x42480000, 0x424C0000, 0x42500000, 0x42540000, 0x42580000, 0x425C0000,
-0x42600000, 0x42640000, 0x42680000, 0x426C0000, 0x42700000, 0x42740000,
-0x42780000, 0x427C0000, 0x42800000, 0x42820000, 0x42840000, 0x42860000,
-0x42880000, 0x428A0000, 0x428C0000, 0x428E0000, 0x42900000, 0x42920000,
-0x42940000, 0x42960000, 0x42980000, 0x429A0000, 0x429C0000, 0x429E0000,
-0x42A00000, 0x42A20000, 0x42A40000, 0x42A60000, 0x42A80000, 0x42AA0000,
-0x42AC0000, 0x42AE0000, 0x42B00000, 0x42B20000, 0x42B40000, 0x42B60000,
-0x42B80000, 0x42BA0000, 0x42BC0000, 0x42BE0000, 0x42C00000, 0x42C20000,
-0x42C40000, 0x42C60000, 0x42C80000, 0x42CA0000, 0x42CC0000, 0x42CE0000,
-0x42D00000, 0x42D20000, 0x42D40000, 0x42D60000, 0x42D80000, 0x42DA0000,
-0x42DC0000, 0x42DE0000, 0x42E00000, 0x42E20000, 0x42E40000, 0x42E60000,
-0x42E80000, 0x42EA0000, 0x42EC0000, 0x42EE0000, 0x42F00000, 0x42F20000,
-0x42F40000, 0x42F60000, 0x42F80000, 0x42FA0000, 0x42FC0000, 0x42FE0000,
-0x43000000, 0x43010000, 0x43020000, 0x43030000, 0x43040000, 0x43050000,
-0x43060000, 0x43070000, 0x43080000, 0x43090000, 0x430A0000, 0x430B0000,
-0x430C0000, 0x430D0000, 0x430E0000, 0x430F0000, 0x43100000, 0x43110000,
-0x43120000, 0x43130000, 0x43140000, 0x43150000, 0x43160000, 0x43170000,
-0x43180000, 0x43190000, 0x431A0000, 0x431B0000, 0x431C0000, 0x431D0000,
-0x431E0000, 0x431F0000, 0x43200000, 0x43210000, 0x43220000, 0x43230000,
-0x43240000, 0x43250000, 0x43260000, 0x43270000, 0x43280000, 0x43290000,
-0x432A0000, 0x432B0000, 0x432C0000, 0x432D0000, 0x432E0000, 0x432F0000,
-0x43300000, 0x43310000, 0x43320000, 0x43330000, 0x43340000
-};
-
-static const unsigned int mic_svm_vals_lookup[] = {
-0x00000000, 0x3C23D70A, 0x3CA3D70A, 0x3CF5C28F, 0x3D23D70A, 0x3D4CCCCD,
-0x3D75C28F, 0x3D8F5C29, 0x3DA3D70A, 0x3DB851EC, 0x3DCCCCCD, 0x3DE147AE,
-0x3DF5C28F, 0x3E051EB8, 0x3E0F5C29, 0x3E19999A, 0x3E23D70A, 0x3E2E147B,
-0x3E3851EC, 0x3E428F5C, 0x3E4CCCCD, 0x3E570A3D, 0x3E6147AE, 0x3E6B851F,
-0x3E75C28F, 0x3E800000, 0x3E851EB8, 0x3E8A3D71, 0x3E8F5C29, 0x3E947AE1,
-0x3E99999A, 0x3E9EB852, 0x3EA3D70A, 0x3EA8F5C3, 0x3EAE147B, 0x3EB33333,
-0x3EB851EC, 0x3EBD70A4, 0x3EC28F5C, 0x3EC7AE14, 0x3ECCCCCD, 0x3ED1EB85,
-0x3ED70A3D, 0x3EDC28F6, 0x3EE147AE, 0x3EE66666, 0x3EEB851F, 0x3EF0A3D7,
-0x3EF5C28F, 0x3EFAE148, 0x3F000000, 0x3F028F5C, 0x3F051EB8, 0x3F07AE14,
-0x3F0A3D71, 0x3F0CCCCD, 0x3F0F5C29, 0x3F11EB85, 0x3F147AE1, 0x3F170A3D,
-0x3F19999A, 0x3F1C28F6, 0x3F1EB852, 0x3F2147AE, 0x3F23D70A, 0x3F266666,
-0x3F28F5C3, 0x3F2B851F, 0x3F2E147B, 0x3F30A3D7, 0x3F333333, 0x3F35C28F,
-0x3F3851EC, 0x3F3AE148, 0x3F3D70A4, 0x3F400000, 0x3F428F5C, 0x3F451EB8,
-0x3F47AE14, 0x3F4A3D71, 0x3F4CCCCD, 0x3F4F5C29, 0x3F51EB85, 0x3F547AE1,
-0x3F570A3D, 0x3F59999A, 0x3F5C28F6, 0x3F5EB852, 0x3F6147AE, 0x3F63D70A,
-0x3F666666, 0x3F68F5C3, 0x3F6B851F, 0x3F6E147B, 0x3F70A3D7, 0x3F733333,
-0x3F75C28F, 0x3F7851EC, 0x3F7AE148, 0x3F7D70A4, 0x3F800000
-};
-
-static const unsigned int equalizer_vals_lookup[] = {
-0xC1C00000, 0xC1B80000, 0xC1B00000, 0xC1A80000, 0xC1A00000, 0xC1980000,
-0xC1900000, 0xC1880000, 0xC1800000, 0xC1700000, 0xC1600000, 0xC1500000,
-0xC1400000, 0xC1300000, 0xC1200000, 0xC1100000, 0xC1000000, 0xC0E00000,
-0xC0C00000, 0xC0A00000, 0xC0800000, 0xC0400000, 0xC0000000, 0xBF800000,
-0x00000000, 0x3F800000, 0x40000000, 0x40400000, 0x40800000, 0x40A00000,
-0x40C00000, 0x40E00000, 0x41000000, 0x41100000, 0x41200000, 0x41300000,
-0x41400000, 0x41500000, 0x41600000, 0x41700000, 0x41800000, 0x41880000,
-0x41900000, 0x41980000, 0x41A00000, 0x41A80000, 0x41B00000, 0x41B80000,
-0x41C00000
-};
-
-static int tuning_ctl_set(struct hda_codec *codec, hda_nid_t nid,
- const unsigned int *lookup, int idx)
-{
- int i = 0;
-
- for (i = 0; i < TUNING_CTLS_COUNT; i++)
- if (nid == ca0132_tuning_ctls[i].nid)
- goto found;
-
- return -EINVAL;
-found:
- snd_hda_power_up(codec);
- dspio_set_param(codec, ca0132_tuning_ctls[i].mid, 0x20,
- ca0132_tuning_ctls[i].req,
- &(lookup[idx]), sizeof(unsigned int));
- snd_hda_power_down(codec);
-
- return 1;
-}
-
-static int tuning_ctl_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ca0132_spec *spec = codec->spec;
- hda_nid_t nid = get_amp_nid(kcontrol);
- long *valp = ucontrol->value.integer.value;
- int idx = nid - TUNING_CTL_START_NID;
-
- *valp = spec->cur_ctl_vals[idx];
- return 0;
-}
-
-static int voice_focus_ctl_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- int chs = get_amp_channels(kcontrol);
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = chs == 3 ? 2 : 1;
- uinfo->value.integer.min = 20;
- uinfo->value.integer.max = 180;
- uinfo->value.integer.step = 1;
-
- return 0;
-}
-
-static int voice_focus_ctl_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ca0132_spec *spec = codec->spec;
- hda_nid_t nid = get_amp_nid(kcontrol);
- long *valp = ucontrol->value.integer.value;
- int idx;
-
- idx = nid - TUNING_CTL_START_NID;
- /* any change? */
- if (spec->cur_ctl_vals[idx] == *valp)
- return 0;
-
- spec->cur_ctl_vals[idx] = *valp;
-
- idx = *valp - 20;
- tuning_ctl_set(codec, nid, voice_focus_vals_lookup, idx);
-
- return 1;
-}
-
-static int mic_svm_ctl_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- int chs = get_amp_channels(kcontrol);
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = chs == 3 ? 2 : 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 100;
- uinfo->value.integer.step = 1;
-
- return 0;
-}
-
-static int mic_svm_ctl_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ca0132_spec *spec = codec->spec;
- hda_nid_t nid = get_amp_nid(kcontrol);
- long *valp = ucontrol->value.integer.value;
- int idx;
-
- idx = nid - TUNING_CTL_START_NID;
- /* any change? */
- if (spec->cur_ctl_vals[idx] == *valp)
- return 0;
-
- spec->cur_ctl_vals[idx] = *valp;
-
- idx = *valp;
- tuning_ctl_set(codec, nid, mic_svm_vals_lookup, idx);
-
- return 0;
-}
-
-static int equalizer_ctl_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- int chs = get_amp_channels(kcontrol);
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = chs == 3 ? 2 : 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 48;
- uinfo->value.integer.step = 1;
-
- return 0;
-}
-
-static int equalizer_ctl_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ca0132_spec *spec = codec->spec;
- hda_nid_t nid = get_amp_nid(kcontrol);
- long *valp = ucontrol->value.integer.value;
- int idx;
-
- idx = nid - TUNING_CTL_START_NID;
- /* any change? */
- if (spec->cur_ctl_vals[idx] == *valp)
- return 0;
-
- spec->cur_ctl_vals[idx] = *valp;
-
- idx = *valp;
- tuning_ctl_set(codec, nid, equalizer_vals_lookup, idx);
-
- return 1;
-}
-
-static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(voice_focus_db_scale, 2000, 100, 0);
-static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(eq_db_scale, -2400, 100, 0);
-
-static int add_tuning_control(struct hda_codec *codec,
- hda_nid_t pnid, hda_nid_t nid,
- const char *name, int dir)
-{
- char namestr[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
- int type = dir ? HDA_INPUT : HDA_OUTPUT;
- struct snd_kcontrol_new knew =
- HDA_CODEC_VOLUME_MONO(namestr, nid, 1, 0, type);
-
- knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
- SNDRV_CTL_ELEM_ACCESS_TLV_READ;
- knew.tlv.c = 0;
- knew.tlv.p = 0;
- switch (pnid) {
- case VOICE_FOCUS:
- knew.info = voice_focus_ctl_info;
- knew.get = tuning_ctl_get;
- knew.put = voice_focus_ctl_put;
- knew.tlv.p = voice_focus_db_scale;
- break;
- case MIC_SVM:
- knew.info = mic_svm_ctl_info;
- knew.get = tuning_ctl_get;
- knew.put = mic_svm_ctl_put;
- break;
- case EQUALIZER:
- knew.info = equalizer_ctl_info;
- knew.get = tuning_ctl_get;
- knew.put = equalizer_ctl_put;
- knew.tlv.p = eq_db_scale;
- break;
- default:
- return 0;
- }
- knew.private_value =
- HDA_COMPOSE_AMP_VAL(nid, 1, 0, type);
- sprintf(namestr, "%s %s Volume", name, dirstr[dir]);
- return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec));
-}
-
-static int add_tuning_ctls(struct hda_codec *codec)
-{
- int i;
- int err;
-
- for (i = 0; i < TUNING_CTLS_COUNT; i++) {
- err = add_tuning_control(codec,
- ca0132_tuning_ctls[i].parent_nid,
- ca0132_tuning_ctls[i].nid,
- ca0132_tuning_ctls[i].name,
- ca0132_tuning_ctls[i].direct);
- if (err < 0)
- return err;
- }
-
- return 0;
-}
-
-static void ca0132_init_tuning_defaults(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- int i;
-
- /* Wedge Angle defaults to 30. 10 below is 30 - 20. 20 is min. */
- spec->cur_ctl_vals[WEDGE_ANGLE - TUNING_CTL_START_NID] = 10;
- /* SVM level defaults to 0.74. */
- spec->cur_ctl_vals[SVM_LEVEL - TUNING_CTL_START_NID] = 74;
-
- /* EQ defaults to 0dB. */
- for (i = 2; i < TUNING_CTLS_COUNT; i++)
- spec->cur_ctl_vals[i] = 24;
-}
-#endif /*ENABLE_TUNING_CONTROLS*/
-
-/*
- * Select the active output.
- * If autodetect is enabled, output will be selected based on jack detection.
- * If jack inserted, headphone will be selected, else built-in speakers
- * If autodetect is disabled, output will be selected based on selection.
- */
-static int ca0132_select_out(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- unsigned int pin_ctl;
- int jack_present;
- int auto_jack;
- unsigned int tmp;
- int err;
-
- codec_dbg(codec, "ca0132_select_out\n");
-
- snd_hda_power_up_pm(codec);
-
- auto_jack = spec->vnode_lswitch[VNID_HP_ASEL - VNODE_START_NID];
-
- if (auto_jack)
- jack_present = snd_hda_jack_detect(codec, spec->unsol_tag_hp);
- else
- jack_present =
- spec->vnode_lswitch[VNID_HP_SEL - VNODE_START_NID];
-
- if (jack_present)
- spec->cur_out_type = HEADPHONE_OUT;
- else
- spec->cur_out_type = SPEAKER_OUT;
-
- if (spec->cur_out_type == SPEAKER_OUT) {
- codec_dbg(codec, "ca0132_select_out speaker\n");
- /*speaker out config*/
- tmp = FLOAT_ONE;
- err = dspio_set_uint_param(codec, 0x80, 0x04, tmp);
- if (err < 0)
- goto exit;
- /*enable speaker EQ*/
- tmp = FLOAT_ONE;
- err = dspio_set_uint_param(codec, 0x8f, 0x00, tmp);
- if (err < 0)
- goto exit;
-
- /* Setup EAPD */
- snd_hda_codec_write(codec, spec->out_pins[1], 0,
- VENDOR_CHIPIO_EAPD_SEL_SET, 0x02);
- snd_hda_codec_write(codec, spec->out_pins[0], 0,
- AC_VERB_SET_EAPD_BTLENABLE, 0x00);
- snd_hda_codec_write(codec, spec->out_pins[0], 0,
- VENDOR_CHIPIO_EAPD_SEL_SET, 0x00);
- snd_hda_codec_write(codec, spec->out_pins[0], 0,
- AC_VERB_SET_EAPD_BTLENABLE, 0x02);
-
- /* disable headphone node */
- pin_ctl = snd_hda_codec_read(codec, spec->out_pins[1], 0,
- AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
- snd_hda_set_pin_ctl(codec, spec->out_pins[1],
- pin_ctl & ~PIN_HP);
- /* enable speaker node */
- pin_ctl = snd_hda_codec_read(codec, spec->out_pins[0], 0,
- AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
- snd_hda_set_pin_ctl(codec, spec->out_pins[0],
- pin_ctl | PIN_OUT);
- } else {
- codec_dbg(codec, "ca0132_select_out hp\n");
- /*headphone out config*/
- tmp = FLOAT_ZERO;
- err = dspio_set_uint_param(codec, 0x80, 0x04, tmp);
- if (err < 0)
- goto exit;
- /*disable speaker EQ*/
- tmp = FLOAT_ZERO;
- err = dspio_set_uint_param(codec, 0x8f, 0x00, tmp);
- if (err < 0)
- goto exit;
-
- /* Setup EAPD */
- snd_hda_codec_write(codec, spec->out_pins[0], 0,
- VENDOR_CHIPIO_EAPD_SEL_SET, 0x00);
- snd_hda_codec_write(codec, spec->out_pins[0], 0,
- AC_VERB_SET_EAPD_BTLENABLE, 0x00);
- snd_hda_codec_write(codec, spec->out_pins[1], 0,
- VENDOR_CHIPIO_EAPD_SEL_SET, 0x02);
- snd_hda_codec_write(codec, spec->out_pins[0], 0,
- AC_VERB_SET_EAPD_BTLENABLE, 0x02);
-
- /* disable speaker*/
- pin_ctl = snd_hda_codec_read(codec, spec->out_pins[0], 0,
- AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
- snd_hda_set_pin_ctl(codec, spec->out_pins[0],
- pin_ctl & ~PIN_HP);
- /* enable headphone*/
- pin_ctl = snd_hda_codec_read(codec, spec->out_pins[1], 0,
- AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
- snd_hda_set_pin_ctl(codec, spec->out_pins[1],
- pin_ctl | PIN_HP);
- }
-
-exit:
- snd_hda_power_down_pm(codec);
-
- return err < 0 ? err : 0;
-}
-
-static int ae5_headphone_gain_set(struct hda_codec *codec, long val);
-static int zxr_headphone_gain_set(struct hda_codec *codec, long val);
-static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val);
-
-static void ae5_mmio_select_out(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- const struct ae_ca0113_output_set *out_cmds;
- unsigned int i;
-
- if (ca0132_quirk(spec) == QUIRK_AE5)
- out_cmds = &ae5_ca0113_output_presets;
- else
- out_cmds = &ae7_ca0113_output_presets;
-
- for (i = 0; i < AE_CA0113_OUT_SET_COMMANDS; i++)
- ca0113_mmio_command_set(codec, out_cmds->group[i],
- out_cmds->target[i],
- out_cmds->vals[spec->cur_out_type][i]);
-}
-
-static int ca0132_alt_set_full_range_speaker(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- int quirk = ca0132_quirk(spec);
- unsigned int tmp;
- int err;
-
- /* 2.0/4.0 setup has no LFE channel, so setting full-range does nothing. */
- if (spec->channel_cfg_val == SPEAKER_CHANNELS_4_0
- || spec->channel_cfg_val == SPEAKER_CHANNELS_2_0)
- return 0;
-
- /* Set front L/R full range. Zero for full-range, one for redirection. */
- tmp = spec->speaker_range_val[0] ? FLOAT_ZERO : FLOAT_ONE;
- err = dspio_set_uint_param(codec, 0x96,
- SPEAKER_FULL_RANGE_FRONT_L_R, tmp);
- if (err < 0)
- return err;
-
- /* When setting full-range rear, both rear and center/lfe are set. */
- tmp = spec->speaker_range_val[1] ? FLOAT_ZERO : FLOAT_ONE;
- err = dspio_set_uint_param(codec, 0x96,
- SPEAKER_FULL_RANGE_CENTER_LFE, tmp);
- if (err < 0)
- return err;
-
- err = dspio_set_uint_param(codec, 0x96,
- SPEAKER_FULL_RANGE_REAR_L_R, tmp);
- if (err < 0)
- return err;
-
- /*
- * Only the AE series cards set this value when setting full-range,
- * and it's always 1.0f.
- */
- if (quirk == QUIRK_AE5 || quirk == QUIRK_AE7) {
- err = dspio_set_uint_param(codec, 0x96,
- SPEAKER_FULL_RANGE_SURROUND_L_R, FLOAT_ONE);
- if (err < 0)
- return err;
- }
-
- return 0;
-}
-
-static int ca0132_alt_surround_set_bass_redirection(struct hda_codec *codec,
- bool val)
-{
- struct ca0132_spec *spec = codec->spec;
- unsigned int tmp;
- int err;
-
- if (val && spec->channel_cfg_val != SPEAKER_CHANNELS_4_0 &&
- spec->channel_cfg_val != SPEAKER_CHANNELS_2_0)
- tmp = FLOAT_ONE;
- else
- tmp = FLOAT_ZERO;
-
- err = dspio_set_uint_param(codec, 0x96, SPEAKER_BASS_REDIRECT, tmp);
- if (err < 0)
- return err;
-
- /* If it is enabled, make sure to set the crossover frequency. */
- if (tmp) {
- tmp = float_xbass_xover_lookup[spec->xbass_xover_freq];
- err = dspio_set_uint_param(codec, 0x96,
- SPEAKER_BASS_REDIRECT_XOVER_FREQ, tmp);
- if (err < 0)
- return err;
- }
-
- return 0;
-}
-
-/*
- * These are the commands needed to setup output on each of the different card
- * types.
- */
-static void ca0132_alt_select_out_get_quirk_data(struct hda_codec *codec,
- const struct ca0132_alt_out_set_quirk_data **quirk_data)
-{
- struct ca0132_spec *spec = codec->spec;
- int quirk = ca0132_quirk(spec);
- unsigned int i;
-
- *quirk_data = NULL;
- for (i = 0; i < ARRAY_SIZE(quirk_out_set_data); i++) {
- if (quirk_out_set_data[i].quirk_id == quirk) {
- *quirk_data = &quirk_out_set_data[i];
- return;
- }
- }
-}
-
-static int ca0132_alt_select_out_quirk_set(struct hda_codec *codec)
-{
- const struct ca0132_alt_out_set_quirk_data *quirk_data;
- const struct ca0132_alt_out_set_info *out_info;
- struct ca0132_spec *spec = codec->spec;
- unsigned int i, gpio_data;
- int err;
-
- ca0132_alt_select_out_get_quirk_data(codec, &quirk_data);
- if (!quirk_data)
- return 0;
-
- out_info = &quirk_data->out_set_info[spec->cur_out_type];
- if (quirk_data->is_ae_series)
- ae5_mmio_select_out(codec);
-
- if (out_info->has_hda_gpio) {
- gpio_data = snd_hda_codec_read(codec, codec->core.afg, 0,
- AC_VERB_GET_GPIO_DATA, 0);
-
- if (out_info->hda_gpio_set)
- gpio_data |= (1 << out_info->hda_gpio_pin);
- else
- gpio_data &= ~(1 << out_info->hda_gpio_pin);
-
- snd_hda_codec_write(codec, codec->core.afg, 0,
- AC_VERB_SET_GPIO_DATA, gpio_data);
- }
-
- if (out_info->mmio_gpio_count) {
- for (i = 0; i < out_info->mmio_gpio_count; i++) {
- ca0113_mmio_gpio_set(codec, out_info->mmio_gpio_pin[i],
- out_info->mmio_gpio_set[i]);
- }
- }
-
- if (out_info->scp_cmds_count) {
- for (i = 0; i < out_info->scp_cmds_count; i++) {
- err = dspio_set_uint_param(codec,
- out_info->scp_cmd_mid[i],
- out_info->scp_cmd_req[i],
- out_info->scp_cmd_val[i]);
- if (err < 0)
- return err;
- }
- }
-
- chipio_set_control_param(codec, 0x0d, out_info->dac2port);
-
- if (out_info->has_chipio_write) {
- chipio_write(codec, out_info->chipio_write_addr,
- out_info->chipio_write_data);
- }
-
- if (quirk_data->has_headphone_gain) {
- if (spec->cur_out_type != HEADPHONE_OUT) {
- if (quirk_data->is_ae_series)
- ae5_headphone_gain_set(codec, 2);
- else
- zxr_headphone_gain_set(codec, 0);
- } else {
- if (quirk_data->is_ae_series)
- ae5_headphone_gain_set(codec,
- spec->ae5_headphone_gain_val);
- else
- zxr_headphone_gain_set(codec,
- spec->zxr_gain_set);
- }
- }
-
- return 0;
-}
-
-static void ca0132_set_out_node_pincfg(struct hda_codec *codec, hda_nid_t nid,
- bool out_enable, bool hp_enable)
-{
- unsigned int pin_ctl;
-
- pin_ctl = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
-
- pin_ctl = hp_enable ? pin_ctl | PIN_HP_AMP : pin_ctl & ~PIN_HP_AMP;
- pin_ctl = out_enable ? pin_ctl | PIN_OUT : pin_ctl & ~PIN_OUT;
- snd_hda_set_pin_ctl(codec, nid, pin_ctl);
-}
-
-/*
- * This function behaves similarly to the ca0132_select_out funciton above,
- * except with a few differences. It adds the ability to select the current
- * output with an enumerated control "output source" if the auto detect
- * mute switch is set to off. If the auto detect mute switch is enabled, it
- * will detect either headphone or lineout(SPEAKER_OUT) from jack detection.
- * It also adds the ability to auto-detect the front headphone port.
- */
-static int ca0132_alt_select_out(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- unsigned int tmp, outfx_set;
- int jack_present;
- int auto_jack;
- int err;
- /* Default Headphone is rear headphone */
- hda_nid_t headphone_nid = spec->out_pins[1];
-
- codec_dbg(codec, "%s\n", __func__);
-
- snd_hda_power_up_pm(codec);
-
- auto_jack = spec->vnode_lswitch[VNID_HP_ASEL - VNODE_START_NID];
-
- /*
- * If headphone rear or front is plugged in, set to headphone.
- * If neither is plugged in, set to rear line out. Only if
- * hp/speaker auto detect is enabled.
- */
- if (auto_jack) {
- jack_present = snd_hda_jack_detect(codec, spec->unsol_tag_hp) ||
- snd_hda_jack_detect(codec, spec->unsol_tag_front_hp);
-
- if (jack_present)
- spec->cur_out_type = HEADPHONE_OUT;
- else
- spec->cur_out_type = SPEAKER_OUT;
- } else
- spec->cur_out_type = spec->out_enum_val;
-
- outfx_set = spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID];
-
- /* Begin DSP output switch, mute DSP volume. */
- err = dspio_set_uint_param(codec, 0x96, SPEAKER_TUNING_MUTE, FLOAT_ONE);
- if (err < 0)
- goto exit;
-
- if (ca0132_alt_select_out_quirk_set(codec) < 0)
- goto exit;
-
- switch (spec->cur_out_type) {
- case SPEAKER_OUT:
- codec_dbg(codec, "%s speaker\n", __func__);
-
- /* Enable EAPD */
- snd_hda_codec_write(codec, spec->out_pins[0], 0,
- AC_VERB_SET_EAPD_BTLENABLE, 0x01);
-
- /* Disable headphone node. */
- ca0132_set_out_node_pincfg(codec, spec->out_pins[1], 0, 0);
- /* Set front L-R to output. */
- ca0132_set_out_node_pincfg(codec, spec->out_pins[0], 1, 0);
- /* Set Center/LFE to output. */
- ca0132_set_out_node_pincfg(codec, spec->out_pins[2], 1, 0);
- /* Set rear surround to output. */
- ca0132_set_out_node_pincfg(codec, spec->out_pins[3], 1, 0);
-
- /*
- * Without PlayEnhancement being enabled, if we've got a 2.0
- * setup, set it to floating point eight to disable any DSP
- * processing effects.
- */
- if (!outfx_set && spec->channel_cfg_val == SPEAKER_CHANNELS_2_0)
- tmp = FLOAT_EIGHT;
- else
- tmp = speaker_channel_cfgs[spec->channel_cfg_val].val;
-
- err = dspio_set_uint_param(codec, 0x80, 0x04, tmp);
- if (err < 0)
- goto exit;
-
- break;
- case HEADPHONE_OUT:
- codec_dbg(codec, "%s hp\n", __func__);
- snd_hda_codec_write(codec, spec->out_pins[0], 0,
- AC_VERB_SET_EAPD_BTLENABLE, 0x00);
-
- /* Disable all speaker nodes. */
- ca0132_set_out_node_pincfg(codec, spec->out_pins[0], 0, 0);
- ca0132_set_out_node_pincfg(codec, spec->out_pins[2], 0, 0);
- ca0132_set_out_node_pincfg(codec, spec->out_pins[3], 0, 0);
-
- /* enable headphone, either front or rear */
- if (snd_hda_jack_detect(codec, spec->unsol_tag_front_hp))
- headphone_nid = spec->out_pins[2];
- else if (snd_hda_jack_detect(codec, spec->unsol_tag_hp))
- headphone_nid = spec->out_pins[1];
-
- ca0132_set_out_node_pincfg(codec, headphone_nid, 1, 1);
-
- if (outfx_set)
- err = dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_ONE);
- else
- err = dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_ZERO);
-
- if (err < 0)
- goto exit;
- break;
- }
- /*
- * If output effects are enabled, set the X-Bass effect value again to
- * make sure that it's properly enabled/disabled for speaker
- * configurations with an LFE channel.
- */
- if (outfx_set)
- ca0132_effects_set(codec, X_BASS,
- spec->effects_switch[X_BASS - EFFECT_START_NID]);
-
- /* Set speaker EQ bypass attenuation to 0. */
- err = dspio_set_uint_param(codec, 0x8f, 0x01, FLOAT_ZERO);
- if (err < 0)
- goto exit;
-
- /*
- * Although unused on all cards but the AE series, this is always set
- * to zero when setting the output.
- */
- err = dspio_set_uint_param(codec, 0x96,
- SPEAKER_TUNING_USE_SPEAKER_EQ, FLOAT_ZERO);
- if (err < 0)
- goto exit;
-
- if (spec->cur_out_type == SPEAKER_OUT)
- err = ca0132_alt_surround_set_bass_redirection(codec,
- spec->bass_redirection_val);
- else
- err = ca0132_alt_surround_set_bass_redirection(codec, 0);
-
- /* Unmute DSP now that we're done with output selection. */
- err = dspio_set_uint_param(codec, 0x96,
- SPEAKER_TUNING_MUTE, FLOAT_ZERO);
- if (err < 0)
- goto exit;
-
- if (spec->cur_out_type == SPEAKER_OUT) {
- err = ca0132_alt_set_full_range_speaker(codec);
- if (err < 0)
- goto exit;
- }
-
-exit:
- snd_hda_power_down_pm(codec);
-
- return err < 0 ? err : 0;
-}
-
-static void ca0132_unsol_hp_delayed(struct work_struct *work)
-{
- struct ca0132_spec *spec = container_of(
- to_delayed_work(work), struct ca0132_spec, unsol_hp_work);
- struct hda_jack_tbl *jack;
-
- if (ca0132_use_alt_functions(spec))
- ca0132_alt_select_out(spec->codec);
- else
- ca0132_select_out(spec->codec);
-
- 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);
- }
-}
-
-static void ca0132_set_dmic(struct hda_codec *codec, int enable);
-static int ca0132_mic_boost_set(struct hda_codec *codec, long val);
-static void resume_mic1(struct hda_codec *codec, unsigned int oldval);
-static int stop_mic1(struct hda_codec *codec);
-static int ca0132_cvoice_switch_set(struct hda_codec *codec);
-static int ca0132_alt_mic_boost_set(struct hda_codec *codec, long val);
-
-/*
- * Select the active VIP source
- */
-static int ca0132_set_vipsource(struct hda_codec *codec, int val)
-{
- struct ca0132_spec *spec = codec->spec;
- unsigned int tmp;
-
- if (spec->dsp_state != DSP_DOWNLOADED)
- return 0;
-
- /* if CrystalVoice if off, vipsource should be 0 */
- if (!spec->effects_switch[CRYSTAL_VOICE - EFFECT_START_NID] ||
- (val == 0)) {
- chipio_set_control_param(codec, CONTROL_PARAM_VIP_SOURCE, 0);
- chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000);
- chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000);
- if (spec->cur_mic_type == DIGITAL_MIC)
- tmp = FLOAT_TWO;
- else
- tmp = FLOAT_ONE;
- dspio_set_uint_param(codec, 0x80, 0x00, tmp);
- tmp = FLOAT_ZERO;
- dspio_set_uint_param(codec, 0x80, 0x05, tmp);
- } else {
- chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_16_000);
- chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_16_000);
- if (spec->cur_mic_type == DIGITAL_MIC)
- tmp = FLOAT_TWO;
- else
- tmp = FLOAT_ONE;
- dspio_set_uint_param(codec, 0x80, 0x00, tmp);
- tmp = FLOAT_ONE;
- dspio_set_uint_param(codec, 0x80, 0x05, tmp);
- msleep(20);
- chipio_set_control_param(codec, CONTROL_PARAM_VIP_SOURCE, val);
- }
-
- return 1;
-}
-
-static int ca0132_alt_set_vipsource(struct hda_codec *codec, int val)
-{
- struct ca0132_spec *spec = codec->spec;
- unsigned int tmp;
-
- if (spec->dsp_state != DSP_DOWNLOADED)
- return 0;
-
- codec_dbg(codec, "%s\n", __func__);
-
- chipio_set_stream_control(codec, 0x03, 0);
- chipio_set_stream_control(codec, 0x04, 0);
-
- /* if CrystalVoice is off, vipsource should be 0 */
- if (!spec->effects_switch[CRYSTAL_VOICE - EFFECT_START_NID] ||
- (val == 0) || spec->in_enum_val == REAR_LINE_IN) {
- codec_dbg(codec, "%s: off.", __func__);
- chipio_set_control_param(codec, CONTROL_PARAM_VIP_SOURCE, 0);
-
- tmp = FLOAT_ZERO;
- dspio_set_uint_param(codec, 0x80, 0x05, tmp);
-
- chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000);
- chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000);
- if (ca0132_quirk(spec) == QUIRK_R3DI)
- chipio_set_conn_rate(codec, 0x0F, SR_96_000);
-
-
- if (spec->in_enum_val == REAR_LINE_IN)
- tmp = FLOAT_ZERO;
- else {
- if (ca0132_quirk(spec) == QUIRK_SBZ)
- tmp = FLOAT_THREE;
- else
- tmp = FLOAT_ONE;
- }
-
- dspio_set_uint_param(codec, 0x80, 0x00, tmp);
-
- } else {
- codec_dbg(codec, "%s: on.", __func__);
- chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_16_000);
- chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_16_000);
- if (ca0132_quirk(spec) == QUIRK_R3DI)
- chipio_set_conn_rate(codec, 0x0F, SR_16_000);
-
- if (spec->effects_switch[VOICE_FOCUS - EFFECT_START_NID])
- tmp = FLOAT_TWO;
- else
- tmp = FLOAT_ONE;
- dspio_set_uint_param(codec, 0x80, 0x00, tmp);
-
- tmp = FLOAT_ONE;
- dspio_set_uint_param(codec, 0x80, 0x05, tmp);
-
- msleep(20);
- chipio_set_control_param(codec, CONTROL_PARAM_VIP_SOURCE, val);
- }
-
- chipio_set_stream_control(codec, 0x03, 1);
- chipio_set_stream_control(codec, 0x04, 1);
-
- return 1;
-}
-
-/*
- * Select the active microphone.
- * If autodetect is enabled, mic will be selected based on jack detection.
- * If jack inserted, ext.mic will be selected, else built-in mic
- * If autodetect is disabled, mic will be selected based on selection.
- */
-static int ca0132_select_mic(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- int jack_present;
- int auto_jack;
-
- codec_dbg(codec, "ca0132_select_mic\n");
-
- snd_hda_power_up_pm(codec);
-
- auto_jack = spec->vnode_lswitch[VNID_AMIC1_ASEL - VNODE_START_NID];
-
- if (auto_jack)
- jack_present = snd_hda_jack_detect(codec, spec->unsol_tag_amic1);
- else
- jack_present =
- spec->vnode_lswitch[VNID_AMIC1_SEL - VNODE_START_NID];
-
- if (jack_present)
- spec->cur_mic_type = LINE_MIC_IN;
- else
- spec->cur_mic_type = DIGITAL_MIC;
-
- if (spec->cur_mic_type == DIGITAL_MIC) {
- /* enable digital Mic */
- chipio_set_conn_rate(codec, MEM_CONNID_DMIC, SR_32_000);
- ca0132_set_dmic(codec, 1);
- ca0132_mic_boost_set(codec, 0);
- /* set voice focus */
- ca0132_effects_set(codec, VOICE_FOCUS,
- spec->effects_switch
- [VOICE_FOCUS - EFFECT_START_NID]);
- } else {
- /* disable digital Mic */
- chipio_set_conn_rate(codec, MEM_CONNID_DMIC, SR_96_000);
- ca0132_set_dmic(codec, 0);
- ca0132_mic_boost_set(codec, spec->cur_mic_boost);
- /* disable voice focus */
- ca0132_effects_set(codec, VOICE_FOCUS, 0);
- }
-
- snd_hda_power_down_pm(codec);
-
- return 0;
-}
-
-/*
- * Select the active input.
- * Mic detection isn't used, because it's kind of pointless on the SBZ.
- * The front mic has no jack-detection, so the only way to switch to it
- * is to do it manually in alsamixer.
- */
-static int ca0132_alt_select_in(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- unsigned int tmp;
-
- codec_dbg(codec, "%s\n", __func__);
-
- snd_hda_power_up_pm(codec);
-
- chipio_set_stream_control(codec, 0x03, 0);
- chipio_set_stream_control(codec, 0x04, 0);
-
- spec->cur_mic_type = spec->in_enum_val;
-
- switch (spec->cur_mic_type) {
- case REAR_MIC:
- switch (ca0132_quirk(spec)) {
- case QUIRK_SBZ:
- case QUIRK_R3D:
- ca0113_mmio_gpio_set(codec, 0, false);
- tmp = FLOAT_THREE;
- break;
- case QUIRK_ZXR:
- tmp = FLOAT_THREE;
- break;
- case QUIRK_R3DI:
- r3di_gpio_mic_set(codec, R3DI_REAR_MIC);
- tmp = FLOAT_ONE;
- break;
- case QUIRK_AE5:
- ca0113_mmio_command_set(codec, 0x30, 0x28, 0x00);
- tmp = FLOAT_THREE;
- break;
- case QUIRK_AE7:
- ca0113_mmio_command_set(codec, 0x30, 0x28, 0x00);
- tmp = FLOAT_THREE;
- chipio_set_conn_rate(codec, MEM_CONNID_MICIN2,
- SR_96_000);
- chipio_set_conn_rate(codec, MEM_CONNID_MICOUT2,
- SR_96_000);
- dspio_set_uint_param(codec, 0x80, 0x01, FLOAT_ZERO);
- break;
- default:
- tmp = FLOAT_ONE;
- break;
- }
-
- chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000);
- chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000);
- if (ca0132_quirk(spec) == QUIRK_R3DI)
- chipio_set_conn_rate(codec, 0x0F, SR_96_000);
-
- dspio_set_uint_param(codec, 0x80, 0x00, tmp);
-
- chipio_set_stream_control(codec, 0x03, 1);
- chipio_set_stream_control(codec, 0x04, 1);
- switch (ca0132_quirk(spec)) {
- case QUIRK_SBZ:
- chipio_write(codec, 0x18B098, 0x0000000C);
- chipio_write(codec, 0x18B09C, 0x0000000C);
- break;
- case QUIRK_ZXR:
- chipio_write(codec, 0x18B098, 0x0000000C);
- chipio_write(codec, 0x18B09C, 0x000000CC);
- break;
- case QUIRK_AE5:
- chipio_write(codec, 0x18B098, 0x0000000C);
- chipio_write(codec, 0x18B09C, 0x0000004C);
- break;
- default:
- break;
- }
- ca0132_alt_mic_boost_set(codec, spec->mic_boost_enum_val);
- break;
- case REAR_LINE_IN:
- ca0132_mic_boost_set(codec, 0);
- switch (ca0132_quirk(spec)) {
- case QUIRK_SBZ:
- case QUIRK_R3D:
- ca0113_mmio_gpio_set(codec, 0, false);
- break;
- case QUIRK_R3DI:
- r3di_gpio_mic_set(codec, R3DI_REAR_MIC);
- break;
- case QUIRK_AE5:
- ca0113_mmio_command_set(codec, 0x30, 0x28, 0x00);
- break;
- case QUIRK_AE7:
- ca0113_mmio_command_set(codec, 0x30, 0x28, 0x3f);
- chipio_set_conn_rate(codec, MEM_CONNID_MICIN2,
- SR_96_000);
- chipio_set_conn_rate(codec, MEM_CONNID_MICOUT2,
- SR_96_000);
- dspio_set_uint_param(codec, 0x80, 0x01, FLOAT_ZERO);
- break;
- default:
- break;
- }
-
- chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000);
- chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000);
- if (ca0132_quirk(spec) == QUIRK_R3DI)
- chipio_set_conn_rate(codec, 0x0F, SR_96_000);
-
- if (ca0132_quirk(spec) == QUIRK_AE7)
- tmp = FLOAT_THREE;
- else
- tmp = FLOAT_ZERO;
- dspio_set_uint_param(codec, 0x80, 0x00, tmp);
-
- switch (ca0132_quirk(spec)) {
- case QUIRK_SBZ:
- case QUIRK_AE5:
- chipio_write(codec, 0x18B098, 0x00000000);
- chipio_write(codec, 0x18B09C, 0x00000000);
- break;
- default:
- break;
- }
- chipio_set_stream_control(codec, 0x03, 1);
- chipio_set_stream_control(codec, 0x04, 1);
- break;
- case FRONT_MIC:
- switch (ca0132_quirk(spec)) {
- case QUIRK_SBZ:
- case QUIRK_R3D:
- ca0113_mmio_gpio_set(codec, 0, true);
- ca0113_mmio_gpio_set(codec, 5, false);
- tmp = FLOAT_THREE;
- break;
- case QUIRK_R3DI:
- r3di_gpio_mic_set(codec, R3DI_FRONT_MIC);
- tmp = FLOAT_ONE;
- break;
- case QUIRK_AE5:
- ca0113_mmio_command_set(codec, 0x30, 0x28, 0x3f);
- tmp = FLOAT_THREE;
- break;
- default:
- tmp = FLOAT_ONE;
- break;
- }
-
- chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000);
- chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000);
- if (ca0132_quirk(spec) == QUIRK_R3DI)
- chipio_set_conn_rate(codec, 0x0F, SR_96_000);
-
- dspio_set_uint_param(codec, 0x80, 0x00, tmp);
-
- chipio_set_stream_control(codec, 0x03, 1);
- chipio_set_stream_control(codec, 0x04, 1);
-
- switch (ca0132_quirk(spec)) {
- case QUIRK_SBZ:
- chipio_write(codec, 0x18B098, 0x0000000C);
- chipio_write(codec, 0x18B09C, 0x000000CC);
- break;
- case QUIRK_AE5:
- chipio_write(codec, 0x18B098, 0x0000000C);
- chipio_write(codec, 0x18B09C, 0x0000004C);
- break;
- default:
- break;
- }
- ca0132_alt_mic_boost_set(codec, spec->mic_boost_enum_val);
- break;
- }
- ca0132_cvoice_switch_set(codec);
-
- snd_hda_power_down_pm(codec);
- return 0;
-}
-
-/*
- * Check if VNODE settings take effect immediately.
- */
-static bool ca0132_is_vnode_effective(struct hda_codec *codec,
- hda_nid_t vnid,
- hda_nid_t *shared_nid)
-{
- struct ca0132_spec *spec = codec->spec;
- hda_nid_t nid;
-
- switch (vnid) {
- case VNID_SPK:
- nid = spec->shared_out_nid;
- break;
- case VNID_MIC:
- nid = spec->shared_mic_nid;
- break;
- default:
- return false;
- }
-
- if (shared_nid)
- *shared_nid = nid;
-
- return true;
-}
-
-/*
-* The following functions are control change helpers.
-* They return 0 if no changed. Return 1 if changed.
-*/
-static int ca0132_voicefx_set(struct hda_codec *codec, int enable)
-{
- struct ca0132_spec *spec = codec->spec;
- unsigned int tmp;
-
- /* based on CrystalVoice state to enable VoiceFX. */
- if (enable) {
- tmp = spec->effects_switch[CRYSTAL_VOICE - EFFECT_START_NID] ?
- FLOAT_ONE : FLOAT_ZERO;
- } else {
- tmp = FLOAT_ZERO;
- }
-
- dspio_set_uint_param(codec, ca0132_voicefx.mid,
- ca0132_voicefx.reqs[0], tmp);
-
- return 1;
-}
-
-/*
- * Set the effects parameters
- */
-static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val)
-{
- struct ca0132_spec *spec = codec->spec;
- unsigned int on, tmp, channel_cfg;
- int num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT;
- int err = 0;
- int idx = nid - EFFECT_START_NID;
-
- if ((idx < 0) || (idx >= num_fx))
- return 0; /* no changed */
-
- /* for out effect, qualify with PE */
- if ((nid >= OUT_EFFECT_START_NID) && (nid < OUT_EFFECT_END_NID)) {
- /* if PE if off, turn off out effects. */
- if (!spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID])
- val = 0;
- if (spec->cur_out_type == SPEAKER_OUT && nid == X_BASS) {
- channel_cfg = spec->channel_cfg_val;
- if (channel_cfg != SPEAKER_CHANNELS_2_0 &&
- channel_cfg != SPEAKER_CHANNELS_4_0)
- val = 0;
- }
- }
-
- /* for in effect, qualify with CrystalVoice */
- if ((nid >= IN_EFFECT_START_NID) && (nid < IN_EFFECT_END_NID)) {
- /* if CrystalVoice if off, turn off in effects. */
- if (!spec->effects_switch[CRYSTAL_VOICE - EFFECT_START_NID])
- val = 0;
-
- /* Voice Focus applies to 2-ch Mic, Digital Mic */
- if ((nid == VOICE_FOCUS) && (spec->cur_mic_type != DIGITAL_MIC))
- val = 0;
-
- /* If Voice Focus on SBZ, set to two channel. */
- if ((nid == VOICE_FOCUS) && ca0132_use_pci_mmio(spec)
- && (spec->cur_mic_type != REAR_LINE_IN)) {
- if (spec->effects_switch[CRYSTAL_VOICE -
- EFFECT_START_NID]) {
-
- if (spec->effects_switch[VOICE_FOCUS -
- EFFECT_START_NID]) {
- tmp = FLOAT_TWO;
- val = 1;
- } else
- tmp = FLOAT_ONE;
-
- dspio_set_uint_param(codec, 0x80, 0x00, tmp);
- }
- }
- /*
- * For SBZ noise reduction, there's an extra command
- * to module ID 0x47. No clue why.
- */
- if ((nid == NOISE_REDUCTION) && ca0132_use_pci_mmio(spec)
- && (spec->cur_mic_type != REAR_LINE_IN)) {
- if (spec->effects_switch[CRYSTAL_VOICE -
- EFFECT_START_NID]) {
- if (spec->effects_switch[NOISE_REDUCTION -
- EFFECT_START_NID])
- tmp = FLOAT_ONE;
- else
- tmp = FLOAT_ZERO;
- } else
- tmp = FLOAT_ZERO;
-
- dspio_set_uint_param(codec, 0x47, 0x00, tmp);
- }
-
- /* If rear line in disable effects. */
- if (ca0132_use_alt_functions(spec) &&
- spec->in_enum_val == REAR_LINE_IN)
- val = 0;
- }
-
- codec_dbg(codec, "ca0132_effect_set: nid=0x%x, val=%ld\n",
- nid, val);
-
- on = (val == 0) ? FLOAT_ZERO : FLOAT_ONE;
- err = dspio_set_uint_param(codec, ca0132_effects[idx].mid,
- ca0132_effects[idx].reqs[0], on);
-
- if (err < 0)
- return 0; /* no changed */
-
- return 1;
-}
-
-/*
- * Turn on/off Playback Enhancements
- */
-static int ca0132_pe_switch_set(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- hda_nid_t nid;
- int i, ret = 0;
-
- codec_dbg(codec, "ca0132_pe_switch_set: val=%ld\n",
- spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID]);
-
- if (ca0132_use_alt_functions(spec))
- ca0132_alt_select_out(codec);
-
- i = OUT_EFFECT_START_NID - EFFECT_START_NID;
- nid = OUT_EFFECT_START_NID;
- /* PE affects all out effects */
- for (; nid < OUT_EFFECT_END_NID; nid++, i++)
- ret |= ca0132_effects_set(codec, nid, spec->effects_switch[i]);
-
- return ret;
-}
-
-/* Check if Mic1 is streaming, if so, stop streaming */
-static int stop_mic1(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- unsigned int oldval = snd_hda_codec_read(codec, spec->adcs[0], 0,
- AC_VERB_GET_CONV, 0);
- if (oldval != 0)
- snd_hda_codec_write(codec, spec->adcs[0], 0,
- AC_VERB_SET_CHANNEL_STREAMID,
- 0);
- return oldval;
-}
-
-/* Resume Mic1 streaming if it was stopped. */
-static void resume_mic1(struct hda_codec *codec, unsigned int oldval)
-{
- struct ca0132_spec *spec = codec->spec;
- /* Restore the previous stream and channel */
- if (oldval != 0)
- snd_hda_codec_write(codec, spec->adcs[0], 0,
- AC_VERB_SET_CHANNEL_STREAMID,
- oldval);
-}
-
-/*
- * Turn on/off CrystalVoice
- */
-static int ca0132_cvoice_switch_set(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- hda_nid_t nid;
- int i, ret = 0;
- unsigned int oldval;
-
- codec_dbg(codec, "ca0132_cvoice_switch_set: val=%ld\n",
- spec->effects_switch[CRYSTAL_VOICE - EFFECT_START_NID]);
-
- i = IN_EFFECT_START_NID - EFFECT_START_NID;
- nid = IN_EFFECT_START_NID;
- /* CrystalVoice affects all in effects */
- for (; nid < IN_EFFECT_END_NID; nid++, i++)
- ret |= ca0132_effects_set(codec, nid, spec->effects_switch[i]);
-
- /* including VoiceFX */
- ret |= ca0132_voicefx_set(codec, (spec->voicefx_val ? 1 : 0));
-
- /* set correct vipsource */
- oldval = stop_mic1(codec);
- if (ca0132_use_alt_functions(spec))
- ret |= ca0132_alt_set_vipsource(codec, 1);
- else
- ret |= ca0132_set_vipsource(codec, 1);
- resume_mic1(codec, oldval);
- return ret;
-}
-
-static int ca0132_mic_boost_set(struct hda_codec *codec, long val)
-{
- struct ca0132_spec *spec = codec->spec;
- int ret = 0;
-
- if (val) /* on */
- ret = snd_hda_codec_amp_update(codec, spec->input_pins[0], 0,
- HDA_INPUT, 0, HDA_AMP_VOLMASK, 3);
- else /* off */
- ret = snd_hda_codec_amp_update(codec, spec->input_pins[0], 0,
- HDA_INPUT, 0, HDA_AMP_VOLMASK, 0);
-
- return ret;
-}
-
-static int ca0132_alt_mic_boost_set(struct hda_codec *codec, long val)
-{
- struct ca0132_spec *spec = codec->spec;
- int ret = 0;
-
- ret = snd_hda_codec_amp_update(codec, spec->input_pins[0], 0,
- HDA_INPUT, 0, HDA_AMP_VOLMASK, val);
- return ret;
-}
-
-static int ae5_headphone_gain_set(struct hda_codec *codec, long val)
-{
- unsigned int i;
-
- for (i = 0; i < 4; i++)
- ca0113_mmio_command_set(codec, 0x48, 0x11 + i,
- ae5_headphone_gain_presets[val].vals[i]);
- return 0;
-}
-
-/*
- * gpio pin 1 is a relay that switches on/off, apparently setting the headphone
- * amplifier to handle a 600 ohm load.
- */
-static int zxr_headphone_gain_set(struct hda_codec *codec, long val)
-{
- ca0113_mmio_gpio_set(codec, 1, val);
-
- return 0;
-}
-
-static int ca0132_vnode_switch_set(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = get_amp_nid(kcontrol);
- hda_nid_t shared_nid = 0;
- bool effective;
- int ret = 0;
- struct ca0132_spec *spec = codec->spec;
- int auto_jack;
-
- if (nid == VNID_HP_SEL) {
- auto_jack =
- spec->vnode_lswitch[VNID_HP_ASEL - VNODE_START_NID];
- if (!auto_jack) {
- if (ca0132_use_alt_functions(spec))
- ca0132_alt_select_out(codec);
- else
- ca0132_select_out(codec);
- }
- return 1;
- }
-
- if (nid == VNID_AMIC1_SEL) {
- auto_jack =
- spec->vnode_lswitch[VNID_AMIC1_ASEL - VNODE_START_NID];
- if (!auto_jack)
- ca0132_select_mic(codec);
- return 1;
- }
-
- if (nid == VNID_HP_ASEL) {
- if (ca0132_use_alt_functions(spec))
- ca0132_alt_select_out(codec);
- else
- ca0132_select_out(codec);
- return 1;
- }
-
- if (nid == VNID_AMIC1_ASEL) {
- ca0132_select_mic(codec);
- return 1;
- }
-
- /* if effective conditions, then update hw immediately. */
- effective = ca0132_is_vnode_effective(codec, nid, &shared_nid);
- if (effective) {
- int dir = get_amp_direction(kcontrol);
- int ch = get_amp_channels(kcontrol);
- unsigned long pval;
-
- mutex_lock(&codec->control_mutex);
- pval = kcontrol->private_value;
- kcontrol->private_value = HDA_COMPOSE_AMP_VAL(shared_nid, ch,
- 0, dir);
- ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
- kcontrol->private_value = pval;
- mutex_unlock(&codec->control_mutex);
- }
-
- return ret;
-}
-/* End of control change helpers. */
-
-static void ca0132_alt_bass_redirection_xover_set(struct hda_codec *codec,
- long idx)
-{
- snd_hda_power_up(codec);
-
- dspio_set_param(codec, 0x96, 0x20, SPEAKER_BASS_REDIRECT_XOVER_FREQ,
- &(float_xbass_xover_lookup[idx]), sizeof(unsigned int));
-
- snd_hda_power_down(codec);
-}
-
-/*
- * Below I've added controls to mess with the effect levels, I've only enabled
- * them on the Sound Blaster Z, but they would probably also work on the
- * Chromebook. I figured they were probably tuned specifically for it, and left
- * out for a reason.
- */
-
-/* Sets DSP effect level from the sliders above the controls */
-
-static int ca0132_alt_slider_ctl_set(struct hda_codec *codec, hda_nid_t nid,
- const unsigned int *lookup, int idx)
-{
- int i = 0;
- unsigned int y;
- /*
- * For X_BASS, req 2 is actually crossover freq instead of
- * effect level
- */
- if (nid == X_BASS)
- y = 2;
- else
- y = 1;
-
- snd_hda_power_up(codec);
- if (nid == XBASS_XOVER) {
- for (i = 0; i < OUT_EFFECTS_COUNT; i++)
- if (ca0132_effects[i].nid == X_BASS)
- break;
-
- dspio_set_param(codec, ca0132_effects[i].mid, 0x20,
- ca0132_effects[i].reqs[1],
- &(lookup[idx - 1]), sizeof(unsigned int));
- } else {
- /* Find the actual effect structure */
- for (i = 0; i < OUT_EFFECTS_COUNT; i++)
- if (nid == ca0132_effects[i].nid)
- break;
-
- dspio_set_param(codec, ca0132_effects[i].mid, 0x20,
- ca0132_effects[i].reqs[y],
- &(lookup[idx]), sizeof(unsigned int));
- }
-
- snd_hda_power_down(codec);
-
- return 0;
-}
-
-static int ca0132_alt_xbass_xover_slider_ctl_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ca0132_spec *spec = codec->spec;
- long *valp = ucontrol->value.integer.value;
- hda_nid_t nid = get_amp_nid(kcontrol);
-
- if (nid == BASS_REDIRECTION_XOVER)
- *valp = spec->bass_redirect_xover_freq;
- else
- *valp = spec->xbass_xover_freq;
-
- return 0;
-}
-
-static int ca0132_alt_slider_ctl_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ca0132_spec *spec = codec->spec;
- hda_nid_t nid = get_amp_nid(kcontrol);
- long *valp = ucontrol->value.integer.value;
- int idx = nid - OUT_EFFECT_START_NID;
-
- *valp = spec->fx_ctl_val[idx];
- return 0;
-}
-
-/*
- * The X-bass crossover starts at 10hz, so the min is 1. The
- * frequency is set in multiples of 10.
- */
-static int ca0132_alt_xbass_xover_slider_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = 1;
- uinfo->value.integer.min = 1;
- uinfo->value.integer.max = 100;
- uinfo->value.integer.step = 1;
-
- return 0;
-}
-
-static int ca0132_alt_effect_slider_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- int chs = get_amp_channels(kcontrol);
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = chs == 3 ? 2 : 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 100;
- uinfo->value.integer.step = 1;
-
- return 0;
-}
-
-static int ca0132_alt_xbass_xover_slider_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ca0132_spec *spec = codec->spec;
- hda_nid_t nid = get_amp_nid(kcontrol);
- long *valp = ucontrol->value.integer.value;
- long *cur_val;
- int idx;
-
- if (nid == BASS_REDIRECTION_XOVER)
- cur_val = &spec->bass_redirect_xover_freq;
- else
- cur_val = &spec->xbass_xover_freq;
-
- /* any change? */
- if (*cur_val == *valp)
- return 0;
-
- *cur_val = *valp;
-
- idx = *valp;
- if (nid == BASS_REDIRECTION_XOVER)
- ca0132_alt_bass_redirection_xover_set(codec, *cur_val);
- else
- ca0132_alt_slider_ctl_set(codec, nid, float_xbass_xover_lookup, idx);
-
- return 0;
-}
-
-static int ca0132_alt_effect_slider_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ca0132_spec *spec = codec->spec;
- hda_nid_t nid = get_amp_nid(kcontrol);
- long *valp = ucontrol->value.integer.value;
- int idx;
-
- idx = nid - EFFECT_START_NID;
- /* any change? */
- if (spec->fx_ctl_val[idx] == *valp)
- return 0;
-
- spec->fx_ctl_val[idx] = *valp;
-
- idx = *valp;
- ca0132_alt_slider_ctl_set(codec, nid, float_zero_to_one_lookup, idx);
-
- return 0;
-}
-
-
-/*
- * Mic Boost Enum for alternative ca0132 codecs. I didn't like that the original
- * only has off or full 30 dB, and didn't like making a volume slider that has
- * traditional 0-100 in alsamixer that goes in big steps. I like enum better.
- */
-#define MIC_BOOST_NUM_OF_STEPS 4
-#define MIC_BOOST_ENUM_MAX_STRLEN 10
-
-static int ca0132_alt_mic_boost_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- char *sfx = "dB";
- char namestr[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = MIC_BOOST_NUM_OF_STEPS;
- if (uinfo->value.enumerated.item >= MIC_BOOST_NUM_OF_STEPS)
- uinfo->value.enumerated.item = MIC_BOOST_NUM_OF_STEPS - 1;
- sprintf(namestr, "%d %s", (uinfo->value.enumerated.item * 10), sfx);
- strcpy(uinfo->value.enumerated.name, namestr);
- return 0;
-}
-
-static int ca0132_alt_mic_boost_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ca0132_spec *spec = codec->spec;
-
- ucontrol->value.enumerated.item[0] = spec->mic_boost_enum_val;
- return 0;
-}
-
-static int ca0132_alt_mic_boost_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ca0132_spec *spec = codec->spec;
- int sel = ucontrol->value.enumerated.item[0];
- unsigned int items = MIC_BOOST_NUM_OF_STEPS;
-
- if (sel >= items)
- return 0;
-
- codec_dbg(codec, "ca0132_alt_mic_boost: boost=%d\n",
- sel);
-
- spec->mic_boost_enum_val = sel;
-
- if (spec->in_enum_val != REAR_LINE_IN)
- ca0132_alt_mic_boost_set(codec, spec->mic_boost_enum_val);
-
- return 1;
-}
-
-/*
- * Sound BlasterX AE-5 Headphone Gain Controls.
- */
-#define AE5_HEADPHONE_GAIN_MAX 3
-static int ae5_headphone_gain_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- char *sfx = " Ohms)";
- char namestr[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = AE5_HEADPHONE_GAIN_MAX;
- if (uinfo->value.enumerated.item >= AE5_HEADPHONE_GAIN_MAX)
- uinfo->value.enumerated.item = AE5_HEADPHONE_GAIN_MAX - 1;
- sprintf(namestr, "%s %s",
- ae5_headphone_gain_presets[uinfo->value.enumerated.item].name,
- sfx);
- strcpy(uinfo->value.enumerated.name, namestr);
- return 0;
-}
-
-static int ae5_headphone_gain_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ca0132_spec *spec = codec->spec;
-
- ucontrol->value.enumerated.item[0] = spec->ae5_headphone_gain_val;
- return 0;
-}
-
-static int ae5_headphone_gain_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ca0132_spec *spec = codec->spec;
- int sel = ucontrol->value.enumerated.item[0];
- unsigned int items = AE5_HEADPHONE_GAIN_MAX;
-
- if (sel >= items)
- return 0;
-
- codec_dbg(codec, "ae5_headphone_gain: boost=%d\n",
- sel);
-
- spec->ae5_headphone_gain_val = sel;
-
- if (spec->out_enum_val == HEADPHONE_OUT)
- ae5_headphone_gain_set(codec, spec->ae5_headphone_gain_val);
-
- return 1;
-}
-
-/*
- * Sound BlasterX AE-5 sound filter enumerated control.
- */
-#define AE5_SOUND_FILTER_MAX 3
-
-static int ae5_sound_filter_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- char namestr[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = AE5_SOUND_FILTER_MAX;
- if (uinfo->value.enumerated.item >= AE5_SOUND_FILTER_MAX)
- uinfo->value.enumerated.item = AE5_SOUND_FILTER_MAX - 1;
- sprintf(namestr, "%s",
- ae5_filter_presets[uinfo->value.enumerated.item].name);
- strcpy(uinfo->value.enumerated.name, namestr);
- return 0;
-}
-
-static int ae5_sound_filter_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ca0132_spec *spec = codec->spec;
-
- ucontrol->value.enumerated.item[0] = spec->ae5_filter_val;
- return 0;
-}
-
-static int ae5_sound_filter_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ca0132_spec *spec = codec->spec;
- int sel = ucontrol->value.enumerated.item[0];
- unsigned int items = AE5_SOUND_FILTER_MAX;
-
- if (sel >= items)
- return 0;
-
- codec_dbg(codec, "ae5_sound_filter: %s\n",
- ae5_filter_presets[sel].name);
-
- spec->ae5_filter_val = sel;
-
- ca0113_mmio_command_set_type2(codec, 0x48, 0x07,
- ae5_filter_presets[sel].val);
-
- return 1;
-}
-
-/*
- * Input Select Control for alternative ca0132 codecs. This exists because
- * front microphone has no auto-detect, and we need a way to set the rear
- * as line-in
- */
-static int ca0132_alt_input_source_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = IN_SRC_NUM_OF_INPUTS;
- if (uinfo->value.enumerated.item >= IN_SRC_NUM_OF_INPUTS)
- uinfo->value.enumerated.item = IN_SRC_NUM_OF_INPUTS - 1;
- strcpy(uinfo->value.enumerated.name,
- in_src_str[uinfo->value.enumerated.item]);
- return 0;
-}
-
-static int ca0132_alt_input_source_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ca0132_spec *spec = codec->spec;
-
- ucontrol->value.enumerated.item[0] = spec->in_enum_val;
- return 0;
-}
-
-static int ca0132_alt_input_source_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ca0132_spec *spec = codec->spec;
- int sel = ucontrol->value.enumerated.item[0];
- unsigned int items = IN_SRC_NUM_OF_INPUTS;
-
- /*
- * The AE-7 has no front microphone, so limit items to 2: rear mic and
- * line-in.
- */
- if (ca0132_quirk(spec) == QUIRK_AE7)
- items = 2;
-
- if (sel >= items)
- return 0;
-
- codec_dbg(codec, "ca0132_alt_input_select: sel=%d, preset=%s\n",
- sel, in_src_str[sel]);
-
- spec->in_enum_val = sel;
-
- ca0132_alt_select_in(codec);
-
- return 1;
-}
-
-/* Sound Blaster Z Output Select Control */
-static int ca0132_alt_output_select_get_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = NUM_OF_OUTPUTS;
- if (uinfo->value.enumerated.item >= NUM_OF_OUTPUTS)
- uinfo->value.enumerated.item = NUM_OF_OUTPUTS - 1;
- strcpy(uinfo->value.enumerated.name,
- out_type_str[uinfo->value.enumerated.item]);
- return 0;
-}
-
-static int ca0132_alt_output_select_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ca0132_spec *spec = codec->spec;
-
- ucontrol->value.enumerated.item[0] = spec->out_enum_val;
- return 0;
-}
-
-static int ca0132_alt_output_select_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ca0132_spec *spec = codec->spec;
- int sel = ucontrol->value.enumerated.item[0];
- unsigned int items = NUM_OF_OUTPUTS;
- unsigned int auto_jack;
-
- if (sel >= items)
- return 0;
-
- codec_dbg(codec, "ca0132_alt_output_select: sel=%d, preset=%s\n",
- sel, out_type_str[sel]);
-
- spec->out_enum_val = sel;
-
- auto_jack = spec->vnode_lswitch[VNID_HP_ASEL - VNODE_START_NID];
-
- if (!auto_jack)
- ca0132_alt_select_out(codec);
-
- return 1;
-}
-
-/* Select surround output type: 2.1, 4.0, 4.1, or 5.1. */
-static int ca0132_alt_speaker_channel_cfg_get_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- unsigned int items = SPEAKER_CHANNEL_CFG_COUNT;
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = items;
- if (uinfo->value.enumerated.item >= items)
- uinfo->value.enumerated.item = items - 1;
- strcpy(uinfo->value.enumerated.name,
- speaker_channel_cfgs[uinfo->value.enumerated.item].name);
- return 0;
-}
-
-static int ca0132_alt_speaker_channel_cfg_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ca0132_spec *spec = codec->spec;
-
- ucontrol->value.enumerated.item[0] = spec->channel_cfg_val;
- return 0;
-}
-
-static int ca0132_alt_speaker_channel_cfg_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ca0132_spec *spec = codec->spec;
- int sel = ucontrol->value.enumerated.item[0];
- unsigned int items = SPEAKER_CHANNEL_CFG_COUNT;
-
- if (sel >= items)
- return 0;
-
- codec_dbg(codec, "ca0132_alt_speaker_channels: sel=%d, channels=%s\n",
- sel, speaker_channel_cfgs[sel].name);
-
- spec->channel_cfg_val = sel;
-
- if (spec->out_enum_val == SPEAKER_OUT)
- ca0132_alt_select_out(codec);
-
- return 1;
-}
-
-/*
- * Smart Volume output setting control. Three different settings, Normal,
- * which takes the value from the smart volume slider. The two others, loud
- * and night, disregard the slider value and have uneditable values.
- */
-#define NUM_OF_SVM_SETTINGS 3
-static const char *const out_svm_set_enum_str[3] = {"Normal", "Loud", "Night" };
-
-static int ca0132_alt_svm_setting_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = NUM_OF_SVM_SETTINGS;
- if (uinfo->value.enumerated.item >= NUM_OF_SVM_SETTINGS)
- uinfo->value.enumerated.item = NUM_OF_SVM_SETTINGS - 1;
- strcpy(uinfo->value.enumerated.name,
- out_svm_set_enum_str[uinfo->value.enumerated.item]);
- return 0;
-}
-
-static int ca0132_alt_svm_setting_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ca0132_spec *spec = codec->spec;
-
- ucontrol->value.enumerated.item[0] = spec->smart_volume_setting;
- return 0;
-}
-
-static int ca0132_alt_svm_setting_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ca0132_spec *spec = codec->spec;
- int sel = ucontrol->value.enumerated.item[0];
- unsigned int items = NUM_OF_SVM_SETTINGS;
- unsigned int idx = SMART_VOLUME - EFFECT_START_NID;
- unsigned int tmp;
-
- if (sel >= items)
- return 0;
-
- codec_dbg(codec, "ca0132_alt_svm_setting: sel=%d, preset=%s\n",
- sel, out_svm_set_enum_str[sel]);
-
- spec->smart_volume_setting = sel;
-
- switch (sel) {
- case 0:
- tmp = FLOAT_ZERO;
- break;
- case 1:
- tmp = FLOAT_ONE;
- break;
- case 2:
- tmp = FLOAT_TWO;
- break;
- default:
- tmp = FLOAT_ZERO;
- break;
- }
- /* Req 2 is the Smart Volume Setting req. */
- dspio_set_uint_param(codec, ca0132_effects[idx].mid,
- ca0132_effects[idx].reqs[2], tmp);
- return 1;
-}
-
-/* Sound Blaster Z EQ preset controls */
-static int ca0132_alt_eq_preset_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- unsigned int items = ARRAY_SIZE(ca0132_alt_eq_presets);
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = items;
- if (uinfo->value.enumerated.item >= items)
- uinfo->value.enumerated.item = items - 1;
- strcpy(uinfo->value.enumerated.name,
- ca0132_alt_eq_presets[uinfo->value.enumerated.item].name);
- return 0;
-}
-
-static int ca0132_alt_eq_preset_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ca0132_spec *spec = codec->spec;
-
- ucontrol->value.enumerated.item[0] = spec->eq_preset_val;
- return 0;
-}
-
-static int ca0132_alt_eq_preset_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ca0132_spec *spec = codec->spec;
- int i, err = 0;
- int sel = ucontrol->value.enumerated.item[0];
- unsigned int items = ARRAY_SIZE(ca0132_alt_eq_presets);
-
- if (sel >= items)
- return 0;
-
- codec_dbg(codec, "%s: sel=%d, preset=%s\n", __func__, sel,
- ca0132_alt_eq_presets[sel].name);
- /*
- * Idx 0 is default.
- * Default needs to qualify with CrystalVoice state.
- */
- for (i = 0; i < EQ_PRESET_MAX_PARAM_COUNT; i++) {
- err = dspio_set_uint_param(codec, ca0132_alt_eq_enum.mid,
- ca0132_alt_eq_enum.reqs[i],
- ca0132_alt_eq_presets[sel].vals[i]);
- if (err < 0)
- break;
- }
-
- if (err >= 0)
- spec->eq_preset_val = sel;
-
- return 1;
-}
-
-static int ca0132_voicefx_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- unsigned int items = ARRAY_SIZE(ca0132_voicefx_presets);
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = items;
- if (uinfo->value.enumerated.item >= items)
- uinfo->value.enumerated.item = items - 1;
- strcpy(uinfo->value.enumerated.name,
- ca0132_voicefx_presets[uinfo->value.enumerated.item].name);
- return 0;
-}
-
-static int ca0132_voicefx_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ca0132_spec *spec = codec->spec;
-
- ucontrol->value.enumerated.item[0] = spec->voicefx_val;
- return 0;
-}
-
-static int ca0132_voicefx_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ca0132_spec *spec = codec->spec;
- int i, err = 0;
- int sel = ucontrol->value.enumerated.item[0];
-
- if (sel >= ARRAY_SIZE(ca0132_voicefx_presets))
- return 0;
-
- codec_dbg(codec, "ca0132_voicefx_put: sel=%d, preset=%s\n",
- sel, ca0132_voicefx_presets[sel].name);
-
- /*
- * Idx 0 is default.
- * Default needs to qualify with CrystalVoice state.
- */
- for (i = 0; i < VOICEFX_MAX_PARAM_COUNT; i++) {
- err = dspio_set_uint_param(codec, ca0132_voicefx.mid,
- ca0132_voicefx.reqs[i],
- ca0132_voicefx_presets[sel].vals[i]);
- if (err < 0)
- break;
- }
-
- if (err >= 0) {
- spec->voicefx_val = sel;
- /* enable voice fx */
- ca0132_voicefx_set(codec, (sel ? 1 : 0));
- }
-
- return 1;
-}
-
-static int ca0132_switch_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ca0132_spec *spec = codec->spec;
- hda_nid_t nid = get_amp_nid(kcontrol);
- int ch = get_amp_channels(kcontrol);
- long *valp = ucontrol->value.integer.value;
-
- /* vnode */
- if ((nid >= VNODE_START_NID) && (nid < VNODE_END_NID)) {
- if (ch & 1) {
- *valp = spec->vnode_lswitch[nid - VNODE_START_NID];
- valp++;
- }
- if (ch & 2) {
- *valp = spec->vnode_rswitch[nid - VNODE_START_NID];
- valp++;
- }
- return 0;
- }
-
- /* effects, include PE and CrystalVoice */
- if ((nid >= EFFECT_START_NID) && (nid < EFFECT_END_NID)) {
- *valp = spec->effects_switch[nid - EFFECT_START_NID];
- return 0;
- }
-
- /* mic boost */
- if (nid == spec->input_pins[0]) {
- *valp = spec->cur_mic_boost;
- return 0;
- }
-
- if (nid == ZXR_HEADPHONE_GAIN) {
- *valp = spec->zxr_gain_set;
- return 0;
- }
-
- if (nid == SPEAKER_FULL_RANGE_FRONT || nid == SPEAKER_FULL_RANGE_REAR) {
- *valp = spec->speaker_range_val[nid - SPEAKER_FULL_RANGE_FRONT];
- return 0;
- }
-
- if (nid == BASS_REDIRECTION) {
- *valp = spec->bass_redirection_val;
- return 0;
- }
-
- return 0;
-}
-
-static int ca0132_switch_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ca0132_spec *spec = codec->spec;
- hda_nid_t nid = get_amp_nid(kcontrol);
- int ch = get_amp_channels(kcontrol);
- long *valp = ucontrol->value.integer.value;
- int changed = 1;
-
- codec_dbg(codec, "ca0132_switch_put: nid=0x%x, val=%ld\n",
- nid, *valp);
-
- snd_hda_power_up(codec);
- /* vnode */
- if ((nid >= VNODE_START_NID) && (nid < VNODE_END_NID)) {
- if (ch & 1) {
- spec->vnode_lswitch[nid - VNODE_START_NID] = *valp;
- valp++;
- }
- if (ch & 2) {
- spec->vnode_rswitch[nid - VNODE_START_NID] = *valp;
- valp++;
- }
- changed = ca0132_vnode_switch_set(kcontrol, ucontrol);
- goto exit;
- }
-
- /* PE */
- if (nid == PLAY_ENHANCEMENT) {
- spec->effects_switch[nid - EFFECT_START_NID] = *valp;
- changed = ca0132_pe_switch_set(codec);
- goto exit;
- }
-
- /* CrystalVoice */
- if (nid == CRYSTAL_VOICE) {
- spec->effects_switch[nid - EFFECT_START_NID] = *valp;
- changed = ca0132_cvoice_switch_set(codec);
- goto exit;
- }
-
- /* out and in effects */
- if (((nid >= OUT_EFFECT_START_NID) && (nid < OUT_EFFECT_END_NID)) ||
- ((nid >= IN_EFFECT_START_NID) && (nid < IN_EFFECT_END_NID))) {
- spec->effects_switch[nid - EFFECT_START_NID] = *valp;
- changed = ca0132_effects_set(codec, nid, *valp);
- goto exit;
- }
-
- /* mic boost */
- if (nid == spec->input_pins[0]) {
- spec->cur_mic_boost = *valp;
- if (ca0132_use_alt_functions(spec)) {
- if (spec->in_enum_val != REAR_LINE_IN)
- changed = ca0132_mic_boost_set(codec, *valp);
- } else {
- /* Mic boost does not apply to Digital Mic */
- if (spec->cur_mic_type != DIGITAL_MIC)
- changed = ca0132_mic_boost_set(codec, *valp);
- }
-
- goto exit;
- }
-
- if (nid == ZXR_HEADPHONE_GAIN) {
- spec->zxr_gain_set = *valp;
- if (spec->cur_out_type == HEADPHONE_OUT)
- changed = zxr_headphone_gain_set(codec, *valp);
- else
- changed = 0;
-
- goto exit;
- }
-
- if (nid == SPEAKER_FULL_RANGE_FRONT || nid == SPEAKER_FULL_RANGE_REAR) {
- spec->speaker_range_val[nid - SPEAKER_FULL_RANGE_FRONT] = *valp;
- if (spec->cur_out_type == SPEAKER_OUT)
- ca0132_alt_set_full_range_speaker(codec);
-
- changed = 0;
- }
-
- if (nid == BASS_REDIRECTION) {
- spec->bass_redirection_val = *valp;
- if (spec->cur_out_type == SPEAKER_OUT)
- ca0132_alt_surround_set_bass_redirection(codec, *valp);
-
- changed = 0;
- }
-
-exit:
- snd_hda_power_down(codec);
- return changed;
-}
-
-/*
- * Volume related
- */
-/*
- * Sets the internal DSP decibel level to match the DAC for output, and the
- * ADC for input. Currently only the SBZ sets dsp capture volume level, and
- * all alternative codecs set DSP playback volume.
- */
-static void ca0132_alt_dsp_volume_put(struct hda_codec *codec, hda_nid_t nid)
-{
- struct ca0132_spec *spec = codec->spec;
- unsigned int dsp_dir;
- unsigned int lookup_val;
-
- if (nid == VNID_SPK)
- dsp_dir = DSP_VOL_OUT;
- else
- dsp_dir = DSP_VOL_IN;
-
- lookup_val = spec->vnode_lvol[nid - VNODE_START_NID];
-
- dspio_set_uint_param(codec,
- ca0132_alt_vol_ctls[dsp_dir].mid,
- ca0132_alt_vol_ctls[dsp_dir].reqs[0],
- float_vol_db_lookup[lookup_val]);
-
- lookup_val = spec->vnode_rvol[nid - VNODE_START_NID];
-
- dspio_set_uint_param(codec,
- ca0132_alt_vol_ctls[dsp_dir].mid,
- ca0132_alt_vol_ctls[dsp_dir].reqs[1],
- float_vol_db_lookup[lookup_val]);
-
- dspio_set_uint_param(codec,
- ca0132_alt_vol_ctls[dsp_dir].mid,
- ca0132_alt_vol_ctls[dsp_dir].reqs[2], FLOAT_ZERO);
-}
-
-static int ca0132_volume_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ca0132_spec *spec = codec->spec;
- hda_nid_t nid = get_amp_nid(kcontrol);
- int ch = get_amp_channels(kcontrol);
- int dir = get_amp_direction(kcontrol);
- unsigned long pval;
- int err;
-
- switch (nid) {
- case VNID_SPK:
- /* follow shared_out info */
- nid = spec->shared_out_nid;
- mutex_lock(&codec->control_mutex);
- pval = kcontrol->private_value;
- kcontrol->private_value = HDA_COMPOSE_AMP_VAL(nid, ch, 0, dir);
- err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo);
- kcontrol->private_value = pval;
- mutex_unlock(&codec->control_mutex);
- break;
- case VNID_MIC:
- /* follow shared_mic info */
- nid = spec->shared_mic_nid;
- mutex_lock(&codec->control_mutex);
- pval = kcontrol->private_value;
- kcontrol->private_value = HDA_COMPOSE_AMP_VAL(nid, ch, 0, dir);
- err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo);
- kcontrol->private_value = pval;
- mutex_unlock(&codec->control_mutex);
- break;
- default:
- err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo);
- }
- return err;
-}
-
-static int ca0132_volume_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ca0132_spec *spec = codec->spec;
- hda_nid_t nid = get_amp_nid(kcontrol);
- int ch = get_amp_channels(kcontrol);
- long *valp = ucontrol->value.integer.value;
-
- /* store the left and right volume */
- if (ch & 1) {
- *valp = spec->vnode_lvol[nid - VNODE_START_NID];
- valp++;
- }
- if (ch & 2) {
- *valp = spec->vnode_rvol[nid - VNODE_START_NID];
- valp++;
- }
- return 0;
-}
-
-static int ca0132_volume_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ca0132_spec *spec = codec->spec;
- hda_nid_t nid = get_amp_nid(kcontrol);
- int ch = get_amp_channels(kcontrol);
- long *valp = ucontrol->value.integer.value;
- hda_nid_t shared_nid = 0;
- bool effective;
- int changed = 1;
-
- /* store the left and right volume */
- if (ch & 1) {
- spec->vnode_lvol[nid - VNODE_START_NID] = *valp;
- valp++;
- }
- if (ch & 2) {
- spec->vnode_rvol[nid - VNODE_START_NID] = *valp;
- valp++;
- }
-
- /* if effective conditions, then update hw immediately. */
- effective = ca0132_is_vnode_effective(codec, nid, &shared_nid);
- if (effective) {
- int dir = get_amp_direction(kcontrol);
- unsigned long pval;
-
- snd_hda_power_up(codec);
- mutex_lock(&codec->control_mutex);
- pval = kcontrol->private_value;
- kcontrol->private_value = HDA_COMPOSE_AMP_VAL(shared_nid, ch,
- 0, dir);
- changed = snd_hda_mixer_amp_volume_put(kcontrol, ucontrol);
- kcontrol->private_value = pval;
- mutex_unlock(&codec->control_mutex);
- snd_hda_power_down(codec);
- }
-
- return changed;
-}
-
-/*
- * This function is the same as the one above, because using an if statement
- * inside of the above volume control for the DSP volume would cause too much
- * lag. This is a lot more smooth.
- */
-static int ca0132_alt_volume_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ca0132_spec *spec = codec->spec;
- hda_nid_t nid = get_amp_nid(kcontrol);
- int ch = get_amp_channels(kcontrol);
- long *valp = ucontrol->value.integer.value;
- hda_nid_t vnid = 0;
- int changed;
-
- switch (nid) {
- case 0x02:
- vnid = VNID_SPK;
- break;
- case 0x07:
- vnid = VNID_MIC;
- break;
- }
-
- /* store the left and right volume */
- if (ch & 1) {
- spec->vnode_lvol[vnid - VNODE_START_NID] = *valp;
- valp++;
- }
- if (ch & 2) {
- spec->vnode_rvol[vnid - VNODE_START_NID] = *valp;
- valp++;
- }
-
- snd_hda_power_up(codec);
- ca0132_alt_dsp_volume_put(codec, vnid);
- mutex_lock(&codec->control_mutex);
- changed = snd_hda_mixer_amp_volume_put(kcontrol, ucontrol);
- mutex_unlock(&codec->control_mutex);
- snd_hda_power_down(codec);
-
- return changed;
-}
-
-static int ca0132_volume_tlv(struct snd_kcontrol *kcontrol, int op_flag,
- unsigned int size, unsigned int __user *tlv)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ca0132_spec *spec = codec->spec;
- hda_nid_t nid = get_amp_nid(kcontrol);
- int ch = get_amp_channels(kcontrol);
- int dir = get_amp_direction(kcontrol);
- unsigned long pval;
- int err;
-
- switch (nid) {
- case VNID_SPK:
- /* follow shared_out tlv */
- nid = spec->shared_out_nid;
- mutex_lock(&codec->control_mutex);
- pval = kcontrol->private_value;
- kcontrol->private_value = HDA_COMPOSE_AMP_VAL(nid, ch, 0, dir);
- err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv);
- kcontrol->private_value = pval;
- mutex_unlock(&codec->control_mutex);
- break;
- case VNID_MIC:
- /* follow shared_mic tlv */
- nid = spec->shared_mic_nid;
- mutex_lock(&codec->control_mutex);
- pval = kcontrol->private_value;
- kcontrol->private_value = HDA_COMPOSE_AMP_VAL(nid, ch, 0, dir);
- err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv);
- kcontrol->private_value = pval;
- mutex_unlock(&codec->control_mutex);
- break;
- default:
- err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv);
- }
- return err;
-}
-
-/* Add volume slider control for effect level */
-static int ca0132_alt_add_effect_slider(struct hda_codec *codec, hda_nid_t nid,
- const char *pfx, int dir)
-{
- char namestr[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
- int type = dir ? HDA_INPUT : HDA_OUTPUT;
- struct snd_kcontrol_new knew =
- HDA_CODEC_VOLUME_MONO(namestr, nid, 1, 0, type);
-
- sprintf(namestr, "FX: %s %s Volume", pfx, dirstr[dir]);
-
- knew.tlv.c = NULL;
-
- switch (nid) {
- case XBASS_XOVER:
- knew.info = ca0132_alt_xbass_xover_slider_info;
- knew.get = ca0132_alt_xbass_xover_slider_ctl_get;
- knew.put = ca0132_alt_xbass_xover_slider_put;
- break;
- default:
- knew.info = ca0132_alt_effect_slider_info;
- knew.get = ca0132_alt_slider_ctl_get;
- knew.put = ca0132_alt_effect_slider_put;
- knew.private_value =
- HDA_COMPOSE_AMP_VAL(nid, 1, 0, type);
- break;
- }
-
- return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec));
-}
-
-/*
- * Added FX: prefix for the alternative codecs, because otherwise the surround
- * effect would conflict with the Surround sound volume control. Also seems more
- * clear as to what the switches do. Left alone for others.
- */
-static int add_fx_switch(struct hda_codec *codec, hda_nid_t nid,
- const char *pfx, int dir)
-{
- struct ca0132_spec *spec = codec->spec;
- char namestr[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
- int type = dir ? HDA_INPUT : HDA_OUTPUT;
- struct snd_kcontrol_new knew =
- CA0132_CODEC_MUTE_MONO(namestr, nid, 1, type);
- /* If using alt_controls, add FX: prefix. But, don't add FX:
- * prefix to OutFX or InFX enable controls.
- */
- if (ca0132_use_alt_controls(spec) && (nid <= IN_EFFECT_END_NID))
- sprintf(namestr, "FX: %s %s Switch", pfx, dirstr[dir]);
- else
- sprintf(namestr, "%s %s Switch", pfx, dirstr[dir]);
-
- return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec));
-}
-
-static int add_voicefx(struct hda_codec *codec)
-{
- struct snd_kcontrol_new knew =
- HDA_CODEC_MUTE_MONO(ca0132_voicefx.name,
- VOICEFX, 1, 0, HDA_INPUT);
- knew.info = ca0132_voicefx_info;
- knew.get = ca0132_voicefx_get;
- knew.put = ca0132_voicefx_put;
- return snd_hda_ctl_add(codec, VOICEFX, snd_ctl_new1(&knew, codec));
-}
-
-/* Create the EQ Preset control */
-static int add_ca0132_alt_eq_presets(struct hda_codec *codec)
-{
- struct snd_kcontrol_new knew =
- HDA_CODEC_MUTE_MONO(ca0132_alt_eq_enum.name,
- EQ_PRESET_ENUM, 1, 0, HDA_OUTPUT);
- knew.info = ca0132_alt_eq_preset_info;
- knew.get = ca0132_alt_eq_preset_get;
- knew.put = ca0132_alt_eq_preset_put;
- return snd_hda_ctl_add(codec, EQ_PRESET_ENUM,
- snd_ctl_new1(&knew, codec));
-}
-
-/*
- * Add enumerated control for the three different settings of the smart volume
- * output effect. Normal just uses the slider value, and loud and night are
- * their own things that ignore that value.
- */
-static int ca0132_alt_add_svm_enum(struct hda_codec *codec)
-{
- struct snd_kcontrol_new knew =
- HDA_CODEC_MUTE_MONO("FX: Smart Volume Setting",
- SMART_VOLUME_ENUM, 1, 0, HDA_OUTPUT);
- knew.info = ca0132_alt_svm_setting_info;
- knew.get = ca0132_alt_svm_setting_get;
- knew.put = ca0132_alt_svm_setting_put;
- return snd_hda_ctl_add(codec, SMART_VOLUME_ENUM,
- snd_ctl_new1(&knew, codec));
-
-}
-
-/*
- * Create an Output Select enumerated control for codecs with surround
- * out capabilities.
- */
-static int ca0132_alt_add_output_enum(struct hda_codec *codec)
-{
- struct snd_kcontrol_new knew =
- HDA_CODEC_MUTE_MONO("Output Select",
- OUTPUT_SOURCE_ENUM, 1, 0, HDA_OUTPUT);
- knew.info = ca0132_alt_output_select_get_info;
- knew.get = ca0132_alt_output_select_get;
- knew.put = ca0132_alt_output_select_put;
- return snd_hda_ctl_add(codec, OUTPUT_SOURCE_ENUM,
- snd_ctl_new1(&knew, codec));
-}
-
-/*
- * Add a control for selecting channel count on speaker output. Setting this
- * allows the DSP to do bass redirection and channel upmixing on surround
- * configurations.
- */
-static int ca0132_alt_add_speaker_channel_cfg_enum(struct hda_codec *codec)
-{
- struct snd_kcontrol_new knew =
- HDA_CODEC_MUTE_MONO("Surround Channel Config",
- SPEAKER_CHANNEL_CFG_ENUM, 1, 0, HDA_OUTPUT);
- knew.info = ca0132_alt_speaker_channel_cfg_get_info;
- knew.get = ca0132_alt_speaker_channel_cfg_get;
- knew.put = ca0132_alt_speaker_channel_cfg_put;
- return snd_hda_ctl_add(codec, SPEAKER_CHANNEL_CFG_ENUM,
- snd_ctl_new1(&knew, codec));
-}
-
-/*
- * Full range front stereo and rear surround switches. When these are set to
- * full range, the lower frequencies from these channels are no longer
- * redirected to the LFE channel.
- */
-static int ca0132_alt_add_front_full_range_switch(struct hda_codec *codec)
-{
- struct snd_kcontrol_new knew =
- CA0132_CODEC_MUTE_MONO("Full-Range Front Speakers",
- SPEAKER_FULL_RANGE_FRONT, 1, HDA_OUTPUT);
-
- return snd_hda_ctl_add(codec, SPEAKER_FULL_RANGE_FRONT,
- snd_ctl_new1(&knew, codec));
-}
-
-static int ca0132_alt_add_rear_full_range_switch(struct hda_codec *codec)
-{
- struct snd_kcontrol_new knew =
- CA0132_CODEC_MUTE_MONO("Full-Range Rear Speakers",
- SPEAKER_FULL_RANGE_REAR, 1, HDA_OUTPUT);
-
- return snd_hda_ctl_add(codec, SPEAKER_FULL_RANGE_REAR,
- snd_ctl_new1(&knew, codec));
-}
-
-/*
- * Bass redirection redirects audio below the crossover frequency to the LFE
- * channel on speakers that are set as not being full-range. On configurations
- * without an LFE channel, it does nothing. Bass redirection seems to be the
- * replacement for X-Bass on configurations with an LFE channel.
- */
-static int ca0132_alt_add_bass_redirection_crossover(struct hda_codec *codec)
-{
- const char *namestr = "Bass Redirection Crossover";
- struct snd_kcontrol_new knew =
- HDA_CODEC_VOLUME_MONO(namestr, BASS_REDIRECTION_XOVER, 1, 0,
- HDA_OUTPUT);
-
- knew.tlv.c = NULL;
- knew.info = ca0132_alt_xbass_xover_slider_info;
- knew.get = ca0132_alt_xbass_xover_slider_ctl_get;
- knew.put = ca0132_alt_xbass_xover_slider_put;
-
- return snd_hda_ctl_add(codec, BASS_REDIRECTION_XOVER,
- snd_ctl_new1(&knew, codec));
-}
-
-static int ca0132_alt_add_bass_redirection_switch(struct hda_codec *codec)
-{
- const char *namestr = "Bass Redirection";
- struct snd_kcontrol_new knew =
- CA0132_CODEC_MUTE_MONO(namestr, BASS_REDIRECTION, 1,
- HDA_OUTPUT);
-
- return snd_hda_ctl_add(codec, BASS_REDIRECTION,
- snd_ctl_new1(&knew, codec));
-}
-
-/*
- * Create an Input Source enumerated control for the alternate ca0132 codecs
- * because the front microphone has no auto-detect, and Line-in has to be set
- * somehow.
- */
-static int ca0132_alt_add_input_enum(struct hda_codec *codec)
-{
- struct snd_kcontrol_new knew =
- HDA_CODEC_MUTE_MONO("Input Source",
- INPUT_SOURCE_ENUM, 1, 0, HDA_INPUT);
- knew.info = ca0132_alt_input_source_info;
- knew.get = ca0132_alt_input_source_get;
- knew.put = ca0132_alt_input_source_put;
- return snd_hda_ctl_add(codec, INPUT_SOURCE_ENUM,
- snd_ctl_new1(&knew, codec));
-}
-
-/*
- * Add mic boost enumerated control. Switches through 0dB to 30dB. This adds
- * more control than the original mic boost, which is either full 30dB or off.
- */
-static int ca0132_alt_add_mic_boost_enum(struct hda_codec *codec)
-{
- struct snd_kcontrol_new knew =
- HDA_CODEC_MUTE_MONO("Mic Boost Capture Switch",
- MIC_BOOST_ENUM, 1, 0, HDA_INPUT);
- knew.info = ca0132_alt_mic_boost_info;
- knew.get = ca0132_alt_mic_boost_get;
- knew.put = ca0132_alt_mic_boost_put;
- return snd_hda_ctl_add(codec, MIC_BOOST_ENUM,
- snd_ctl_new1(&knew, codec));
-
-}
-
-/*
- * Add headphone gain enumerated control for the AE-5. This switches between
- * three modes, low, medium, and high. When non-headphone outputs are selected,
- * it is automatically set to high. This is the same behavior as Windows.
- */
-static int ae5_add_headphone_gain_enum(struct hda_codec *codec)
-{
- struct snd_kcontrol_new knew =
- HDA_CODEC_MUTE_MONO("AE-5: Headphone Gain",
- AE5_HEADPHONE_GAIN_ENUM, 1, 0, HDA_OUTPUT);
- knew.info = ae5_headphone_gain_info;
- knew.get = ae5_headphone_gain_get;
- knew.put = ae5_headphone_gain_put;
- return snd_hda_ctl_add(codec, AE5_HEADPHONE_GAIN_ENUM,
- snd_ctl_new1(&knew, codec));
-}
-
-/*
- * Add sound filter enumerated control for the AE-5. This adds three different
- * settings: Slow Roll Off, Minimum Phase, and Fast Roll Off. From what I've
- * read into it, it changes the DAC's interpolation filter.
- */
-static int ae5_add_sound_filter_enum(struct hda_codec *codec)
-{
- struct snd_kcontrol_new knew =
- HDA_CODEC_MUTE_MONO("AE-5: Sound Filter",
- AE5_SOUND_FILTER_ENUM, 1, 0, HDA_OUTPUT);
- knew.info = ae5_sound_filter_info;
- knew.get = ae5_sound_filter_get;
- knew.put = ae5_sound_filter_put;
- return snd_hda_ctl_add(codec, AE5_SOUND_FILTER_ENUM,
- snd_ctl_new1(&knew, codec));
-}
-
-static int zxr_add_headphone_gain_switch(struct hda_codec *codec)
-{
- struct snd_kcontrol_new knew =
- CA0132_CODEC_MUTE_MONO("ZxR: 600 Ohm Gain",
- ZXR_HEADPHONE_GAIN, 1, HDA_OUTPUT);
-
- return snd_hda_ctl_add(codec, ZXR_HEADPHONE_GAIN,
- snd_ctl_new1(&knew, codec));
-}
-
-/*
- * Need to create follower controls for the alternate codecs that have surround
- * capabilities.
- */
-static const char * const ca0132_alt_follower_pfxs[] = {
- "Front", "Surround", "Center", "LFE", NULL,
-};
-
-/*
- * Also need special channel map, because the default one is incorrect.
- * I think this has to do with the pin for rear surround being 0x11,
- * and the center/lfe being 0x10. Usually the pin order is the opposite.
- */
-static const struct snd_pcm_chmap_elem ca0132_alt_chmaps[] = {
- { .channels = 2,
- .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } },
- { .channels = 4,
- .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,
- SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } },
- { .channels = 6,
- .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,
- SNDRV_CHMAP_FC, SNDRV_CHMAP_LFE,
- SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } },
- { }
-};
-
-/* Add the correct chmap for streams with 6 channels. */
-static void ca0132_alt_add_chmap_ctls(struct hda_codec *codec)
-{
- int err = 0;
- struct hda_pcm *pcm;
-
- list_for_each_entry(pcm, &codec->pcm_list_head, list) {
- struct hda_pcm_stream *hinfo =
- &pcm->stream[SNDRV_PCM_STREAM_PLAYBACK];
- struct snd_pcm_chmap *chmap;
- const struct snd_pcm_chmap_elem *elem;
-
- elem = ca0132_alt_chmaps;
- if (hinfo->channels_max == 6) {
- err = snd_pcm_add_chmap_ctls(pcm->pcm,
- SNDRV_PCM_STREAM_PLAYBACK,
- elem, hinfo->channels_max, 0, &chmap);
- if (err < 0)
- codec_dbg(codec, "snd_pcm_add_chmap_ctls failed!");
- }
- }
-}
-
-/*
- * When changing Node IDs for Mixer Controls below, make sure to update
- * Node IDs in ca0132_config() as well.
- */
-static const struct snd_kcontrol_new ca0132_mixer[] = {
- CA0132_CODEC_VOL("Master Playback Volume", VNID_SPK, HDA_OUTPUT),
- CA0132_CODEC_MUTE("Master Playback Switch", VNID_SPK, HDA_OUTPUT),
- CA0132_CODEC_VOL("Capture Volume", VNID_MIC, HDA_INPUT),
- CA0132_CODEC_MUTE("Capture Switch", VNID_MIC, HDA_INPUT),
- HDA_CODEC_VOLUME("Analog-Mic2 Capture Volume", 0x08, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Analog-Mic2 Capture Switch", 0x08, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("What U Hear Capture Volume", 0x0a, 0, HDA_INPUT),
- HDA_CODEC_MUTE("What U Hear Capture Switch", 0x0a, 0, HDA_INPUT),
- CA0132_CODEC_MUTE_MONO("Mic1-Boost (30dB) Capture Switch",
- 0x12, 1, HDA_INPUT),
- CA0132_CODEC_MUTE_MONO("HP/Speaker Playback Switch",
- VNID_HP_SEL, 1, HDA_OUTPUT),
- CA0132_CODEC_MUTE_MONO("AMic1/DMic Capture Switch",
- VNID_AMIC1_SEL, 1, HDA_INPUT),
- CA0132_CODEC_MUTE_MONO("HP/Speaker Auto Detect Playback Switch",
- VNID_HP_ASEL, 1, HDA_OUTPUT),
- CA0132_CODEC_MUTE_MONO("AMic1/DMic Auto Detect Capture Switch",
- VNID_AMIC1_ASEL, 1, HDA_INPUT),
- { } /* end */
-};
-
-/*
- * Desktop specific control mixer. Removes auto-detect for mic, and adds
- * surround controls. Also sets both the Front Playback and Capture Volume
- * controls to alt so they set the DSP's decibel level.
- */
-static const struct snd_kcontrol_new desktop_mixer[] = {
- CA0132_ALT_CODEC_VOL("Front Playback Volume", 0x02, HDA_OUTPUT),
- CA0132_CODEC_MUTE("Front Playback Switch", VNID_SPK, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x04, 0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Surround Playback Switch", 0x04, 0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x03, 1, 0, HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x03, 1, 0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x03, 2, 0, HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x03, 2, 0, HDA_OUTPUT),
- CA0132_ALT_CODEC_VOL("Capture Volume", 0x07, HDA_INPUT),
- CA0132_CODEC_MUTE("Capture Switch", VNID_MIC, HDA_INPUT),
- HDA_CODEC_VOLUME("What U Hear Capture Volume", 0x0a, 0, HDA_INPUT),
- HDA_CODEC_MUTE("What U Hear Capture Switch", 0x0a, 0, HDA_INPUT),
- CA0132_CODEC_MUTE_MONO("HP/Speaker Auto Detect Playback Switch",
- VNID_HP_ASEL, 1, HDA_OUTPUT),
- { } /* end */
-};
-
-/*
- * Same as the Sound Blaster Z, except doesn't use the alt volume for capture
- * because it doesn't set decibel levels for the DSP for capture.
- */
-static const struct snd_kcontrol_new r3di_mixer[] = {
- CA0132_ALT_CODEC_VOL("Front Playback Volume", 0x02, HDA_OUTPUT),
- CA0132_CODEC_MUTE("Front Playback Switch", VNID_SPK, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x04, 0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Surround Playback Switch", 0x04, 0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x03, 1, 0, HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x03, 1, 0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x03, 2, 0, HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x03, 2, 0, HDA_OUTPUT),
- CA0132_CODEC_VOL("Capture Volume", VNID_MIC, HDA_INPUT),
- CA0132_CODEC_MUTE("Capture Switch", VNID_MIC, HDA_INPUT),
- HDA_CODEC_VOLUME("What U Hear Capture Volume", 0x0a, 0, HDA_INPUT),
- HDA_CODEC_MUTE("What U Hear Capture Switch", 0x0a, 0, HDA_INPUT),
- CA0132_CODEC_MUTE_MONO("HP/Speaker Auto Detect Playback Switch",
- VNID_HP_ASEL, 1, HDA_OUTPUT),
- { } /* end */
-};
-
-static int ca0132_build_controls(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- int i, num_fx, num_sliders;
- int err = 0;
-
- /* Add Mixer controls */
- for (i = 0; i < spec->num_mixers; i++) {
- err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
- if (err < 0)
- return err;
- }
- /* Setup vmaster with surround followers for desktop ca0132 devices */
- if (ca0132_use_alt_functions(spec)) {
- snd_hda_set_vmaster_tlv(codec, spec->dacs[0], HDA_OUTPUT,
- spec->tlv);
- snd_hda_add_vmaster(codec, "Master Playback Volume",
- spec->tlv, ca0132_alt_follower_pfxs,
- "Playback Volume", 0);
- err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
- NULL, ca0132_alt_follower_pfxs,
- "Playback Switch",
- true, 0, &spec->vmaster_mute.sw_kctl);
- if (err < 0)
- return err;
- }
-
- /* Add in and out effects controls.
- * VoiceFX, PE and CrystalVoice are added separately.
- */
- num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT;
- for (i = 0; i < num_fx; i++) {
- /* Desktop cards break if Echo Cancellation is used. */
- if (ca0132_use_pci_mmio(spec)) {
- if (i == (ECHO_CANCELLATION - IN_EFFECT_START_NID +
- OUT_EFFECTS_COUNT))
- continue;
- }
-
- err = add_fx_switch(codec, ca0132_effects[i].nid,
- ca0132_effects[i].name,
- ca0132_effects[i].direct);
- if (err < 0)
- return err;
- }
- /*
- * If codec has use_alt_controls set to true, add effect level sliders,
- * EQ presets, and Smart Volume presets. Also, change names to add FX
- * prefix, and change PlayEnhancement and CrystalVoice to match.
- */
- if (ca0132_use_alt_controls(spec)) {
- err = ca0132_alt_add_svm_enum(codec);
- if (err < 0)
- return err;
-
- err = add_ca0132_alt_eq_presets(codec);
- if (err < 0)
- return err;
-
- err = add_fx_switch(codec, PLAY_ENHANCEMENT,
- "Enable OutFX", 0);
- if (err < 0)
- return err;
-
- err = add_fx_switch(codec, CRYSTAL_VOICE,
- "Enable InFX", 1);
- if (err < 0)
- return err;
-
- num_sliders = OUT_EFFECTS_COUNT - 1;
- for (i = 0; i < num_sliders; i++) {
- err = ca0132_alt_add_effect_slider(codec,
- ca0132_effects[i].nid,
- ca0132_effects[i].name,
- ca0132_effects[i].direct);
- if (err < 0)
- return err;
- }
-
- err = ca0132_alt_add_effect_slider(codec, XBASS_XOVER,
- "X-Bass Crossover", EFX_DIR_OUT);
-
- if (err < 0)
- return err;
- } else {
- err = add_fx_switch(codec, PLAY_ENHANCEMENT,
- "PlayEnhancement", 0);
- if (err < 0)
- return err;
-
- err = add_fx_switch(codec, CRYSTAL_VOICE,
- "CrystalVoice", 1);
- if (err < 0)
- return err;
- }
- err = add_voicefx(codec);
- if (err < 0)
- return err;
-
- /*
- * If the codec uses alt_functions, you need the enumerated controls
- * to select the new outputs and inputs, plus add the new mic boost
- * setting control.
- */
- if (ca0132_use_alt_functions(spec)) {
- err = ca0132_alt_add_output_enum(codec);
- if (err < 0)
- return err;
- err = ca0132_alt_add_speaker_channel_cfg_enum(codec);
- if (err < 0)
- return err;
- err = ca0132_alt_add_front_full_range_switch(codec);
- if (err < 0)
- return err;
- err = ca0132_alt_add_rear_full_range_switch(codec);
- if (err < 0)
- return err;
- err = ca0132_alt_add_bass_redirection_crossover(codec);
- if (err < 0)
- return err;
- err = ca0132_alt_add_bass_redirection_switch(codec);
- if (err < 0)
- return err;
- err = ca0132_alt_add_mic_boost_enum(codec);
- if (err < 0)
- return err;
- /*
- * ZxR only has microphone input, there is no front panel
- * header on the card, and aux-in is handled by the DBPro board.
- */
- if (ca0132_quirk(spec) != QUIRK_ZXR) {
- err = ca0132_alt_add_input_enum(codec);
- if (err < 0)
- return err;
- }
- }
-
- switch (ca0132_quirk(spec)) {
- case QUIRK_AE5:
- case QUIRK_AE7:
- err = ae5_add_headphone_gain_enum(codec);
- if (err < 0)
- return err;
- err = ae5_add_sound_filter_enum(codec);
- if (err < 0)
- return err;
- break;
- case QUIRK_ZXR:
- err = zxr_add_headphone_gain_switch(codec);
- if (err < 0)
- return err;
- break;
- default:
- break;
- }
-
-#ifdef ENABLE_TUNING_CONTROLS
- add_tuning_ctls(codec);
-#endif
-
- err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
- if (err < 0)
- return err;
-
- if (spec->dig_out) {
- err = snd_hda_create_spdif_out_ctls(codec, spec->dig_out,
- spec->dig_out);
- if (err < 0)
- return err;
- err = snd_hda_create_spdif_share_sw(codec, &spec->multiout);
- if (err < 0)
- return err;
- /* spec->multiout.share_spdif = 1; */
- }
-
- if (spec->dig_in) {
- err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in);
- if (err < 0)
- return err;
- }
-
- if (ca0132_use_alt_functions(spec))
- ca0132_alt_add_chmap_ctls(codec);
-
- return 0;
-}
-
-static int dbpro_build_controls(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- int err = 0;
-
- if (spec->dig_out) {
- err = snd_hda_create_spdif_out_ctls(codec, spec->dig_out,
- spec->dig_out);
- if (err < 0)
- return err;
- }
-
- if (spec->dig_in) {
- err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in);
- if (err < 0)
- return err;
- }
-
- return 0;
-}
-
-/*
- * PCM
- */
-static const struct hda_pcm_stream ca0132_pcm_analog_playback = {
- .substreams = 1,
- .channels_min = 2,
- .channels_max = 6,
- .ops = {
- .prepare = ca0132_playback_pcm_prepare,
- .cleanup = ca0132_playback_pcm_cleanup,
- .get_delay = ca0132_playback_pcm_delay,
- },
-};
-
-static const struct hda_pcm_stream ca0132_pcm_analog_capture = {
- .substreams = 1,
- .channels_min = 2,
- .channels_max = 2,
- .ops = {
- .prepare = ca0132_capture_pcm_prepare,
- .cleanup = ca0132_capture_pcm_cleanup,
- .get_delay = ca0132_capture_pcm_delay,
- },
-};
-
-static const struct hda_pcm_stream ca0132_pcm_digital_playback = {
- .substreams = 1,
- .channels_min = 2,
- .channels_max = 2,
- .ops = {
- .open = ca0132_dig_playback_pcm_open,
- .close = ca0132_dig_playback_pcm_close,
- .prepare = ca0132_dig_playback_pcm_prepare,
- .cleanup = ca0132_dig_playback_pcm_cleanup
- },
-};
-
-static const struct hda_pcm_stream ca0132_pcm_digital_capture = {
- .substreams = 1,
- .channels_min = 2,
- .channels_max = 2,
-};
-
-static int ca0132_build_pcms(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- struct hda_pcm *info;
-
- info = snd_hda_codec_pcm_new(codec, "CA0132 Analog");
- if (!info)
- return -ENOMEM;
- if (ca0132_use_alt_functions(spec)) {
- info->own_chmap = true;
- info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap
- = ca0132_alt_chmaps;
- }
- info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ca0132_pcm_analog_playback;
- info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->dacs[0];
- info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
- spec->multiout.max_channels;
- info->stream[SNDRV_PCM_STREAM_CAPTURE] = ca0132_pcm_analog_capture;
- info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = 1;
- info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[0];
-
- /* With the DSP enabled, desktops don't use this ADC. */
- if (!ca0132_use_alt_functions(spec)) {
- info = snd_hda_codec_pcm_new(codec, "CA0132 Analog Mic-In2");
- if (!info)
- return -ENOMEM;
- info->stream[SNDRV_PCM_STREAM_CAPTURE] =
- ca0132_pcm_analog_capture;
- info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = 1;
- info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[1];
- }
-
- info = snd_hda_codec_pcm_new(codec, "CA0132 What U Hear");
- if (!info)
- return -ENOMEM;
- info->stream[SNDRV_PCM_STREAM_CAPTURE] = ca0132_pcm_analog_capture;
- info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = 1;
- info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[2];
-
- if (!spec->dig_out && !spec->dig_in)
- return 0;
-
- info = snd_hda_codec_pcm_new(codec, "CA0132 Digital");
- if (!info)
- return -ENOMEM;
- info->pcm_type = HDA_PCM_TYPE_SPDIF;
- if (spec->dig_out) {
- info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
- ca0132_pcm_digital_playback;
- info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->dig_out;
- }
- if (spec->dig_in) {
- info->stream[SNDRV_PCM_STREAM_CAPTURE] =
- ca0132_pcm_digital_capture;
- info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in;
- }
-
- return 0;
-}
-
-static int dbpro_build_pcms(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- struct hda_pcm *info;
-
- info = snd_hda_codec_pcm_new(codec, "CA0132 Alt Analog");
- if (!info)
- return -ENOMEM;
- info->stream[SNDRV_PCM_STREAM_CAPTURE] = ca0132_pcm_analog_capture;
- info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = 1;
- info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[0];
-
-
- if (!spec->dig_out && !spec->dig_in)
- return 0;
-
- info = snd_hda_codec_pcm_new(codec, "CA0132 Digital");
- if (!info)
- return -ENOMEM;
- info->pcm_type = HDA_PCM_TYPE_SPDIF;
- if (spec->dig_out) {
- info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
- ca0132_pcm_digital_playback;
- info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->dig_out;
- }
- if (spec->dig_in) {
- info->stream[SNDRV_PCM_STREAM_CAPTURE] =
- ca0132_pcm_digital_capture;
- info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in;
- }
-
- return 0;
-}
-
-static void init_output(struct hda_codec *codec, hda_nid_t pin, hda_nid_t dac)
-{
- if (pin) {
- snd_hda_set_pin_ctl(codec, pin, PIN_HP);
- if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP)
- snd_hda_codec_write(codec, pin, 0,
- AC_VERB_SET_AMP_GAIN_MUTE,
- AMP_OUT_UNMUTE);
- }
- if (dac && (get_wcaps(codec, dac) & AC_WCAP_OUT_AMP))
- snd_hda_codec_write(codec, dac, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO);
-}
-
-static void init_input(struct hda_codec *codec, hda_nid_t pin, hda_nid_t adc)
-{
- if (pin) {
- snd_hda_set_pin_ctl(codec, pin, PIN_VREF80);
- if (get_wcaps(codec, pin) & AC_WCAP_IN_AMP)
- snd_hda_codec_write(codec, pin, 0,
- AC_VERB_SET_AMP_GAIN_MUTE,
- AMP_IN_UNMUTE(0));
- }
- if (adc && (get_wcaps(codec, adc) & AC_WCAP_IN_AMP)) {
- snd_hda_codec_write(codec, adc, 0, AC_VERB_SET_AMP_GAIN_MUTE,
- AMP_IN_UNMUTE(0));
-
- /* init to 0 dB and unmute. */
- snd_hda_codec_amp_stereo(codec, adc, HDA_INPUT, 0,
- HDA_AMP_VOLMASK, 0x5a);
- snd_hda_codec_amp_stereo(codec, adc, HDA_INPUT, 0,
- HDA_AMP_MUTE, 0);
- }
-}
-
-static void refresh_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir)
-{
- unsigned int caps;
-
- caps = snd_hda_param_read(codec, nid, dir == HDA_OUTPUT ?
- AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP);
- snd_hda_override_amp_caps(codec, nid, dir, caps);
-}
-
-/*
- * Switch between Digital built-in mic and analog mic.
- */
-static void ca0132_set_dmic(struct hda_codec *codec, int enable)
-{
- struct ca0132_spec *spec = codec->spec;
- unsigned int tmp;
- u8 val;
- unsigned int oldval;
-
- codec_dbg(codec, "ca0132_set_dmic: enable=%d\n", enable);
-
- oldval = stop_mic1(codec);
- ca0132_set_vipsource(codec, 0);
- if (enable) {
- /* set DMic input as 2-ch */
- tmp = FLOAT_TWO;
- dspio_set_uint_param(codec, 0x80, 0x00, tmp);
-
- val = spec->dmic_ctl;
- val |= 0x80;
- snd_hda_codec_write(codec, spec->input_pins[0], 0,
- VENDOR_CHIPIO_DMIC_CTL_SET, val);
-
- if (!(spec->dmic_ctl & 0x20))
- chipio_set_control_flag(codec, CONTROL_FLAG_DMIC, 1);
- } else {
- /* set AMic input as mono */
- tmp = FLOAT_ONE;
- dspio_set_uint_param(codec, 0x80, 0x00, tmp);
-
- val = spec->dmic_ctl;
- /* clear bit7 and bit5 to disable dmic */
- val &= 0x5f;
- snd_hda_codec_write(codec, spec->input_pins[0], 0,
- VENDOR_CHIPIO_DMIC_CTL_SET, val);
-
- if (!(spec->dmic_ctl & 0x20))
- chipio_set_control_flag(codec, CONTROL_FLAG_DMIC, 0);
- }
- ca0132_set_vipsource(codec, 1);
- resume_mic1(codec, oldval);
-}
-
-/*
- * Initialization for Digital Mic.
- */
-static void ca0132_init_dmic(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- u8 val;
-
- /* Setup Digital Mic here, but don't enable.
- * Enable based on jack detect.
- */
-
- /* MCLK uses MPIO1, set to enable.
- * Bit 2-0: MPIO select
- * Bit 3: set to disable
- * Bit 7-4: reserved
- */
- val = 0x01;
- snd_hda_codec_write(codec, spec->input_pins[0], 0,
- VENDOR_CHIPIO_DMIC_MCLK_SET, val);
-
- /* Data1 uses MPIO3. Data2 not use
- * Bit 2-0: Data1 MPIO select
- * Bit 3: set disable Data1
- * Bit 6-4: Data2 MPIO select
- * Bit 7: set disable Data2
- */
- val = 0x83;
- snd_hda_codec_write(codec, spec->input_pins[0], 0,
- VENDOR_CHIPIO_DMIC_PIN_SET, val);
-
- /* Use Ch-0 and Ch-1. Rate is 48K, mode 1. Disable DMic first.
- * Bit 3-0: Channel mask
- * Bit 4: set for 48KHz, clear for 32KHz
- * Bit 5: mode
- * Bit 6: set to select Data2, clear for Data1
- * Bit 7: set to enable DMic, clear for AMic
- */
- if (ca0132_quirk(spec) == QUIRK_ALIENWARE_M17XR4)
- val = 0x33;
- else
- val = 0x23;
- /* keep a copy of dmic ctl val for enable/disable dmic purpuse */
- spec->dmic_ctl = val;
- snd_hda_codec_write(codec, spec->input_pins[0], 0,
- VENDOR_CHIPIO_DMIC_CTL_SET, val);
-}
-
-/*
- * Initialization for Analog Mic 2
- */
-static void ca0132_init_analog_mic2(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
-
- mutex_lock(&spec->chipio_mutex);
-
- chipio_8051_write_exram_no_mutex(codec, 0x1920, 0x00);
- chipio_8051_write_exram_no_mutex(codec, 0x192d, 0x00);
-
- mutex_unlock(&spec->chipio_mutex);
-}
-
-static void ca0132_refresh_widget_caps(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- int i;
-
- codec_dbg(codec, "ca0132_refresh_widget_caps.\n");
- snd_hda_codec_update_widgets(codec);
-
- for (i = 0; i < spec->multiout.num_dacs; i++)
- refresh_amp_caps(codec, spec->dacs[i], HDA_OUTPUT);
-
- for (i = 0; i < spec->num_outputs; i++)
- refresh_amp_caps(codec, spec->out_pins[i], HDA_OUTPUT);
-
- for (i = 0; i < spec->num_inputs; i++) {
- refresh_amp_caps(codec, spec->adcs[i], HDA_INPUT);
- refresh_amp_caps(codec, spec->input_pins[i], HDA_INPUT);
- }
-}
-
-
-/* If there is an active channel for some reason, find it and free it. */
-static void ca0132_alt_free_active_dma_channels(struct hda_codec *codec)
-{
- unsigned int i, tmp;
- int status;
-
- /* Read active DSPDMAC channel register. */
- status = chipio_read(codec, DSPDMAC_CHNLSTART_MODULE_OFFSET, &tmp);
- if (status >= 0) {
- /* AND against 0xfff to get the active channel bits. */
- tmp = tmp & 0xfff;
-
- /* If there are no active channels, nothing to free. */
- if (!tmp)
- return;
- } else {
- codec_dbg(codec, "%s: Failed to read active DSP DMA channel register.\n",
- __func__);
- return;
- }
-
- /*
- * Check each DSP DMA channel for activity, and if the channel is
- * active, free it.
- */
- for (i = 0; i < DSPDMAC_DMA_CFG_CHANNEL_COUNT; i++) {
- if (dsp_is_dma_active(codec, i)) {
- status = dspio_free_dma_chan(codec, i);
- if (status < 0)
- codec_dbg(codec, "%s: Failed to free active DSP DMA channel %d.\n",
- __func__, i);
- }
- }
-}
-
-/*
- * In the case of CT_EXTENSIONS_ENABLE being set to 1, and the DSP being in
- * use, audio is no longer routed directly to the DAC/ADC from the HDA stream.
- * Instead, audio is now routed through the DSP's DMA controllers, which
- * the DSP is tasked with setting up itself. Through debugging, it seems the
- * cause of most of the no-audio on startup issues were due to improperly
- * configured DSP DMA channels.
- *
- * Normally, the DSP configures these the first time an HDA audio stream is
- * started post DSP firmware download. That is why creating a 'dummy' stream
- * worked in fixing the audio in some cases. This works most of the time, but
- * sometimes if a stream is started/stopped before the DSP can setup the DMA
- * configuration registers, it ends up in a broken state. Issues can also
- * arise if streams are started in an unusual order, i.e the audio output dma
- * channel being sandwiched between the mic1 and mic2 dma channels.
- *
- * The solution to this is to make sure that the DSP has no DMA channels
- * in use post DSP firmware download, and then to manually start each default
- * DSP stream that uses the DMA channels. These are 0x0c, the audio output
- * stream, 0x03, analog mic 1, and 0x04, analog mic 2.
- */
-static void ca0132_alt_start_dsp_audio_streams(struct hda_codec *codec)
-{
- static const unsigned int dsp_dma_stream_ids[] = { 0x0c, 0x03, 0x04 };
- struct ca0132_spec *spec = codec->spec;
- unsigned int i, tmp;
-
- /*
- * Check if any of the default streams are active, and if they are,
- * stop them.
- */
- mutex_lock(&spec->chipio_mutex);
-
- for (i = 0; i < ARRAY_SIZE(dsp_dma_stream_ids); i++) {
- chipio_get_stream_control(codec, dsp_dma_stream_ids[i], &tmp);
-
- if (tmp) {
- chipio_set_stream_control(codec,
- dsp_dma_stream_ids[i], 0);
- }
- }
-
- mutex_unlock(&spec->chipio_mutex);
-
- /*
- * If all DSP streams are inactive, there should be no active DSP DMA
- * channels. Check and make sure this is the case, and if it isn't,
- * free any active channels.
- */
- ca0132_alt_free_active_dma_channels(codec);
-
- mutex_lock(&spec->chipio_mutex);
-
- /* Make sure stream 0x0c is six channels. */
- chipio_set_stream_channels(codec, 0x0c, 6);
-
- for (i = 0; i < ARRAY_SIZE(dsp_dma_stream_ids); i++) {
- chipio_set_stream_control(codec,
- dsp_dma_stream_ids[i], 1);
-
- /* Give the DSP some time to setup the DMA channel. */
- msleep(75);
- }
-
- mutex_unlock(&spec->chipio_mutex);
-}
-
-/*
- * The region of ChipIO memory from 0x190000-0x1903fc is a sort of 'audio
- * router', where each entry represents a 48khz audio channel, with a format
- * of an 8-bit destination, an 8-bit source, and an unknown 2-bit number
- * value. The 2-bit number value is seemingly 0 if inactive, 1 if active,
- * and 3 if it's using Sample Rate Converter ports.
- * An example is:
- * 0x0001f8c0
- * In this case, f8 is the destination, and c0 is the source. The number value
- * is 1.
- * This region of memory is normally managed internally by the 8051, where
- * the region of exram memory from 0x1477-0x1575 has each byte represent an
- * entry within the 0x190000 range, and when a range of entries is in use, the
- * ending value is overwritten with 0xff.
- * 0x1578 in exram is a table of 0x25 entries, corresponding to the ChipIO
- * streamID's, where each entry is a starting 0x190000 port offset.
- * 0x159d in exram is the same as 0x1578, except it contains the ending port
- * offset for the corresponding streamID.
- *
- * On certain cards, such as the SBZ/ZxR/AE7, these are originally setup by
- * the 8051, then manually overwritten to remap the ports to work with the
- * new DACs.
- *
- * Currently known portID's:
- * 0x00-0x1f: HDA audio stream input/output ports.
- * 0x80-0xbf: Sample rate converter input/outputs. Only valid ports seem to
- * have the lower-nibble set to 0x1, 0x2, and 0x9.
- * 0xc0-0xdf: DSP DMA input/output ports. Dynamically assigned.
- * 0xe0-0xff: DAC/ADC audio input/output ports.
- *
- * Currently known streamID's:
- * 0x03: Mic1 ADC to DSP.
- * 0x04: Mic2 ADC to DSP.
- * 0x05: HDA node 0x02 audio stream to DSP.
- * 0x0f: DSP Mic exit to HDA node 0x07.
- * 0x0c: DSP processed audio to DACs.
- * 0x14: DAC0, front L/R.
- *
- * It is possible to route the HDA audio streams directly to the DAC and
- * bypass the DSP entirely, with the only downside being that since the DSP
- * does volume control, the only volume control you'll get is through PCM on
- * the PC side, in the same way volume is handled for optical out. This may be
- * useful for debugging.
- */
-static void chipio_remap_stream(struct hda_codec *codec,
- const struct chipio_stream_remap_data *remap_data)
-{
- unsigned int i, stream_offset;
-
- /* Get the starting port for the stream to be remapped. */
- chipio_8051_read_exram(codec, 0x1578 + remap_data->stream_id,
- &stream_offset);
-
- /*
- * Check if the stream's port value is 0xff, because the 8051 may not
- * have gotten around to setting up the stream yet. Wait until it's
- * setup to remap it's ports.
- */
- if (stream_offset == 0xff) {
- for (i = 0; i < 5; i++) {
- msleep(25);
-
- chipio_8051_read_exram(codec, 0x1578 + remap_data->stream_id,
- &stream_offset);
-
- if (stream_offset != 0xff)
- break;
- }
- }
-
- if (stream_offset == 0xff) {
- codec_info(codec, "%s: Stream 0x%02x ports aren't allocated, remap failed!\n",
- __func__, remap_data->stream_id);
- return;
- }
-
- /* Offset isn't in bytes, its in 32-bit words, so multiply it by 4. */
- stream_offset *= 0x04;
- stream_offset += 0x190000;
-
- for (i = 0; i < remap_data->count; i++) {
- chipio_write_no_mutex(codec,
- stream_offset + remap_data->offset[i],
- remap_data->value[i]);
- }
-
- /* Update stream map configuration. */
- chipio_write_no_mutex(codec, 0x19042c, 0x00000001);
-}
-
-/*
- * Default speaker tuning values setup for alternative codecs.
- */
-static const unsigned int sbz_default_delay_values[] = {
- /* Non-zero values are floating point 0.000198. */
- 0x394f9e38, 0x394f9e38, 0x00000000, 0x00000000, 0x00000000, 0x00000000
-};
-
-static const unsigned int zxr_default_delay_values[] = {
- /* Non-zero values are floating point 0.000220. */
- 0x00000000, 0x00000000, 0x3966afcd, 0x3966afcd, 0x3966afcd, 0x3966afcd
-};
-
-static const unsigned int ae5_default_delay_values[] = {
- /* Non-zero values are floating point 0.000100. */
- 0x00000000, 0x00000000, 0x38d1b717, 0x38d1b717, 0x38d1b717, 0x38d1b717
-};
-
-/*
- * If we never change these, probably only need them on initialization.
- */
-static void ca0132_alt_init_speaker_tuning(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- unsigned int i, tmp, start_req, end_req;
- const unsigned int *values;
-
- switch (ca0132_quirk(spec)) {
- case QUIRK_SBZ:
- values = sbz_default_delay_values;
- break;
- case QUIRK_ZXR:
- values = zxr_default_delay_values;
- break;
- case QUIRK_AE5:
- case QUIRK_AE7:
- values = ae5_default_delay_values;
- break;
- default:
- values = sbz_default_delay_values;
- break;
- }
-
- tmp = FLOAT_ZERO;
- dspio_set_uint_param(codec, 0x96, SPEAKER_TUNING_ENABLE_CENTER_EQ, tmp);
-
- start_req = SPEAKER_TUNING_FRONT_LEFT_VOL_LEVEL;
- end_req = SPEAKER_TUNING_REAR_RIGHT_VOL_LEVEL;
- for (i = start_req; i < end_req + 1; i++)
- dspio_set_uint_param(codec, 0x96, i, tmp);
-
- start_req = SPEAKER_TUNING_FRONT_LEFT_INVERT;
- end_req = SPEAKER_TUNING_REAR_RIGHT_INVERT;
- for (i = start_req; i < end_req + 1; i++)
- dspio_set_uint_param(codec, 0x96, i, tmp);
-
-
- for (i = 0; i < 6; i++)
- dspio_set_uint_param(codec, 0x96,
- SPEAKER_TUNING_FRONT_LEFT_DELAY + i, values[i]);
-}
-
-/*
- * Initialize mic for non-chromebook ca0132 implementations.
- */
-static void ca0132_alt_init_analog_mics(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- unsigned int tmp;
-
- /* Mic 1 Setup */
- chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000);
- chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000);
- if (ca0132_quirk(spec) == QUIRK_R3DI) {
- chipio_set_conn_rate(codec, 0x0F, SR_96_000);
- tmp = FLOAT_ONE;
- } else
- tmp = FLOAT_THREE;
- dspio_set_uint_param(codec, 0x80, 0x00, tmp);
-
- /* Mic 2 setup (not present on desktop cards) */
- chipio_set_conn_rate(codec, MEM_CONNID_MICIN2, SR_96_000);
- chipio_set_conn_rate(codec, MEM_CONNID_MICOUT2, SR_96_000);
- if (ca0132_quirk(spec) == QUIRK_R3DI)
- chipio_set_conn_rate(codec, 0x0F, SR_96_000);
- tmp = FLOAT_ZERO;
- dspio_set_uint_param(codec, 0x80, 0x01, tmp);
-}
-
-/*
- * Sets the source of stream 0x14 to connpointID 0x48, and the destination
- * connpointID to 0x91. If this isn't done, the destination is 0x71, and
- * you get no sound. I'm guessing this has to do with the Sound Blaster Z
- * having an updated DAC, which changes the destination to that DAC.
- */
-static void sbz_connect_streams(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
-
- mutex_lock(&spec->chipio_mutex);
-
- codec_dbg(codec, "Connect Streams entered, mutex locked and loaded.\n");
-
- /* This value is 0x43 for 96khz, and 0x83 for 192khz. */
- chipio_write_no_mutex(codec, 0x18a020, 0x00000043);
-
- /* Setup stream 0x14 with it's source and destination points */
- chipio_set_stream_source_dest(codec, 0x14, 0x48, 0x91);
- chipio_set_conn_rate_no_mutex(codec, 0x48, SR_96_000);
- chipio_set_conn_rate_no_mutex(codec, 0x91, SR_96_000);
- chipio_set_stream_channels(codec, 0x14, 2);
- chipio_set_stream_control(codec, 0x14, 1);
-
- codec_dbg(codec, "Connect Streams exited, mutex released.\n");
-
- mutex_unlock(&spec->chipio_mutex);
-}
-
-/*
- * Write data through ChipIO to setup proper stream destinations.
- * Not sure how it exactly works, but it seems to direct data
- * to different destinations. Example is f8 to c0, e0 to c0.
- * All I know is, if you don't set these, you get no sound.
- */
-static void sbz_chipio_startup_data(struct hda_codec *codec)
-{
- const struct chipio_stream_remap_data *dsp_out_remap_data;
- struct ca0132_spec *spec = codec->spec;
-
- mutex_lock(&spec->chipio_mutex);
- codec_dbg(codec, "Startup Data entered, mutex locked and loaded.\n");
-
- /* Remap DAC0's output ports. */
- chipio_remap_stream(codec, &stream_remap_data[0]);
-
- /* Remap DSP audio output stream ports. */
- switch (ca0132_quirk(spec)) {
- case QUIRK_SBZ:
- dsp_out_remap_data = &stream_remap_data[1];
- break;
-
- case QUIRK_ZXR:
- dsp_out_remap_data = &stream_remap_data[2];
- break;
-
- default:
- dsp_out_remap_data = NULL;
- break;
- }
-
- if (dsp_out_remap_data)
- chipio_remap_stream(codec, dsp_out_remap_data);
-
- codec_dbg(codec, "Startup Data exited, mutex released.\n");
- mutex_unlock(&spec->chipio_mutex);
-}
-
-static void ca0132_alt_dsp_initial_mic_setup(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- unsigned int tmp;
-
- chipio_set_stream_control(codec, 0x03, 0);
- chipio_set_stream_control(codec, 0x04, 0);
-
- chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000);
- chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000);
-
- tmp = FLOAT_THREE;
- dspio_set_uint_param(codec, 0x80, 0x00, tmp);
-
- chipio_set_stream_control(codec, 0x03, 1);
- chipio_set_stream_control(codec, 0x04, 1);
-
- switch (ca0132_quirk(spec)) {
- case QUIRK_SBZ:
- chipio_write(codec, 0x18b098, 0x0000000c);
- chipio_write(codec, 0x18b09C, 0x0000000c);
- break;
- case QUIRK_AE5:
- chipio_write(codec, 0x18b098, 0x0000000c);
- chipio_write(codec, 0x18b09c, 0x0000004c);
- break;
- default:
- break;
- }
-}
-
-static void ae5_post_dsp_register_set(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
-
- chipio_8051_write_direct(codec, 0x93, 0x10);
- chipio_8051_write_pll_pmu(codec, 0x44, 0xc2);
-
- writeb(0xff, spec->mem_base + 0x304);
- writeb(0xff, spec->mem_base + 0x304);
- writeb(0xff, spec->mem_base + 0x304);
- writeb(0xff, spec->mem_base + 0x304);
- writeb(0x00, spec->mem_base + 0x100);
- writeb(0xff, spec->mem_base + 0x304);
- writeb(0x00, spec->mem_base + 0x100);
- writeb(0xff, spec->mem_base + 0x304);
- writeb(0x00, spec->mem_base + 0x100);
- writeb(0xff, spec->mem_base + 0x304);
- writeb(0x00, spec->mem_base + 0x100);
- writeb(0xff, spec->mem_base + 0x304);
-
- ca0113_mmio_command_set(codec, 0x30, 0x2b, 0x3f);
- ca0113_mmio_command_set(codec, 0x30, 0x2d, 0x3f);
- ca0113_mmio_command_set(codec, 0x48, 0x07, 0x83);
-}
-
-static void ae5_post_dsp_param_setup(struct hda_codec *codec)
-{
- /*
- * Param3 in the 8051's memory is represented by the ascii string 'mch'
- * which seems to be 'multichannel'. This is also mentioned in the
- * AE-5's registry values in Windows.
- */
- chipio_set_control_param(codec, 3, 0);
- /*
- * I believe ASI is 'audio serial interface' and that it's used to
- * change colors on the external LED strip connected to the AE-5.
- */
- chipio_set_control_flag(codec, CONTROL_FLAG_ASI_96KHZ, 1);
-
- snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, 0x724, 0x83);
- chipio_set_control_param(codec, CONTROL_PARAM_ASI, 0);
-
- chipio_8051_write_exram(codec, 0xfa92, 0x22);
-}
-
-static void ae5_post_dsp_pll_setup(struct hda_codec *codec)
-{
- chipio_8051_write_pll_pmu(codec, 0x41, 0xc8);
- chipio_8051_write_pll_pmu(codec, 0x45, 0xcc);
- chipio_8051_write_pll_pmu(codec, 0x40, 0xcb);
- chipio_8051_write_pll_pmu(codec, 0x43, 0xc7);
- chipio_8051_write_pll_pmu(codec, 0x51, 0x8d);
-}
-
-static void ae5_post_dsp_stream_setup(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
-
- mutex_lock(&spec->chipio_mutex);
-
- snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, 0x725, 0x81);
-
- chipio_set_conn_rate_no_mutex(codec, 0x70, SR_96_000);
-
- chipio_set_stream_source_dest(codec, 0x5, 0x43, 0x0);
-
- chipio_set_stream_source_dest(codec, 0x18, 0x9, 0xd0);
- chipio_set_conn_rate_no_mutex(codec, 0xd0, SR_96_000);
- chipio_set_stream_channels(codec, 0x18, 6);
- chipio_set_stream_control(codec, 0x18, 1);
-
- chipio_set_control_param_no_mutex(codec, CONTROL_PARAM_ASI, 4);
-
- chipio_8051_write_pll_pmu_no_mutex(codec, 0x43, 0xc7);
-
- ca0113_mmio_command_set(codec, 0x48, 0x01, 0x80);
-
- mutex_unlock(&spec->chipio_mutex);
-}
-
-static void ae5_post_dsp_startup_data(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
-
- mutex_lock(&spec->chipio_mutex);
-
- chipio_write_no_mutex(codec, 0x189000, 0x0001f101);
- chipio_write_no_mutex(codec, 0x189004, 0x0001f101);
- chipio_write_no_mutex(codec, 0x189024, 0x00014004);
- chipio_write_no_mutex(codec, 0x189028, 0x0002000f);
-
- ca0113_mmio_command_set(codec, 0x48, 0x0a, 0x05);
- chipio_set_control_param_no_mutex(codec, CONTROL_PARAM_ASI, 7);
- ca0113_mmio_command_set(codec, 0x48, 0x0b, 0x12);
- ca0113_mmio_command_set(codec, 0x48, 0x04, 0x00);
- ca0113_mmio_command_set(codec, 0x48, 0x06, 0x48);
- ca0113_mmio_command_set(codec, 0x48, 0x0a, 0x05);
- ca0113_mmio_command_set(codec, 0x48, 0x07, 0x83);
- ca0113_mmio_command_set(codec, 0x48, 0x0f, 0x00);
- ca0113_mmio_command_set(codec, 0x48, 0x10, 0x00);
- ca0113_mmio_gpio_set(codec, 0, true);
- ca0113_mmio_gpio_set(codec, 1, true);
- ca0113_mmio_command_set(codec, 0x48, 0x07, 0x80);
-
- chipio_write_no_mutex(codec, 0x18b03c, 0x00000012);
-
- ca0113_mmio_command_set(codec, 0x48, 0x0f, 0x00);
- ca0113_mmio_command_set(codec, 0x48, 0x10, 0x00);
-
- mutex_unlock(&spec->chipio_mutex);
-}
-
-static void ae7_post_dsp_setup_ports(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
-
- mutex_lock(&spec->chipio_mutex);
-
- /* Seems to share the same port remapping as the SBZ. */
- chipio_remap_stream(codec, &stream_remap_data[1]);
-
- ca0113_mmio_command_set(codec, 0x30, 0x30, 0x00);
- ca0113_mmio_command_set(codec, 0x48, 0x0d, 0x40);
- ca0113_mmio_command_set(codec, 0x48, 0x17, 0x00);
- ca0113_mmio_command_set(codec, 0x48, 0x19, 0x00);
- ca0113_mmio_command_set(codec, 0x48, 0x11, 0xff);
- ca0113_mmio_command_set(codec, 0x48, 0x12, 0xff);
- ca0113_mmio_command_set(codec, 0x48, 0x13, 0xff);
- ca0113_mmio_command_set(codec, 0x48, 0x14, 0x7f);
-
- mutex_unlock(&spec->chipio_mutex);
-}
-
-static void ae7_post_dsp_asi_stream_setup(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
-
- mutex_lock(&spec->chipio_mutex);
-
- snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, 0x725, 0x81);
- ca0113_mmio_command_set(codec, 0x30, 0x2b, 0x00);
-
- chipio_set_conn_rate_no_mutex(codec, 0x70, SR_96_000);
-
- chipio_set_stream_source_dest(codec, 0x05, 0x43, 0x00);
- chipio_set_stream_source_dest(codec, 0x18, 0x09, 0xd0);
-
- chipio_set_conn_rate_no_mutex(codec, 0xd0, SR_96_000);
- chipio_set_stream_channels(codec, 0x18, 6);
- chipio_set_stream_control(codec, 0x18, 1);
-
- chipio_set_control_param_no_mutex(codec, CONTROL_PARAM_ASI, 4);
-
- mutex_unlock(&spec->chipio_mutex);
-}
-
-static void ae7_post_dsp_pll_setup(struct hda_codec *codec)
-{
- static const unsigned int addr[] = {
- 0x41, 0x45, 0x40, 0x43, 0x51
- };
- static const unsigned int data[] = {
- 0xc8, 0xcc, 0xcb, 0xc7, 0x8d
- };
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(addr); i++)
- chipio_8051_write_pll_pmu_no_mutex(codec, addr[i], data[i]);
-}
-
-static void ae7_post_dsp_asi_setup_ports(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- static const unsigned int target[] = {
- 0x0b, 0x04, 0x06, 0x0a, 0x0c, 0x11, 0x12, 0x13, 0x14
- };
- static const unsigned int data[] = {
- 0x12, 0x00, 0x48, 0x05, 0x5f, 0xff, 0xff, 0xff, 0x7f
- };
- unsigned int i;
-
- mutex_lock(&spec->chipio_mutex);
-
- chipio_8051_write_pll_pmu_no_mutex(codec, 0x43, 0xc7);
-
- chipio_write_no_mutex(codec, 0x189000, 0x0001f101);
- chipio_write_no_mutex(codec, 0x189004, 0x0001f101);
- chipio_write_no_mutex(codec, 0x189024, 0x00014004);
- chipio_write_no_mutex(codec, 0x189028, 0x0002000f);
-
- ae7_post_dsp_pll_setup(codec);
- chipio_set_control_param_no_mutex(codec, CONTROL_PARAM_ASI, 7);
-
- for (i = 0; i < ARRAY_SIZE(target); i++)
- ca0113_mmio_command_set(codec, 0x48, target[i], data[i]);
-
- ca0113_mmio_command_set_type2(codec, 0x48, 0x07, 0x83);
- ca0113_mmio_command_set(codec, 0x48, 0x0f, 0x00);
- ca0113_mmio_command_set(codec, 0x48, 0x10, 0x00);
-
- chipio_set_stream_source_dest(codec, 0x21, 0x64, 0x56);
- chipio_set_stream_channels(codec, 0x21, 2);
- chipio_set_conn_rate_no_mutex(codec, 0x56, SR_8_000);
-
- chipio_set_control_param_no_mutex(codec, CONTROL_PARAM_NODE_ID, 0x09);
- /*
- * In the 8051's memory, this param is referred to as 'n2sid', which I
- * believe is 'node to streamID'. It seems to be a way to assign a
- * stream to a given HDA node.
- */
- chipio_set_control_param_no_mutex(codec, 0x20, 0x21);
-
- chipio_write_no_mutex(codec, 0x18b038, 0x00000088);
-
- /*
- * Now, at this point on Windows, an actual stream is setup and
- * seemingly sends data to the HDA node 0x09, which is the digital
- * audio input node. This is left out here, because obviously I don't
- * know what data is being sent. Interestingly, the AE-5 seems to go
- * through the motions of getting here and never actually takes this
- * step, but the AE-7 does.
- */
-
- ca0113_mmio_gpio_set(codec, 0, 1);
- ca0113_mmio_gpio_set(codec, 1, 1);
-
- ca0113_mmio_command_set_type2(codec, 0x48, 0x07, 0x83);
- chipio_write_no_mutex(codec, 0x18b03c, 0x00000000);
- ca0113_mmio_command_set(codec, 0x48, 0x0f, 0x00);
- ca0113_mmio_command_set(codec, 0x48, 0x10, 0x00);
-
- chipio_set_stream_source_dest(codec, 0x05, 0x43, 0x00);
- chipio_set_stream_source_dest(codec, 0x18, 0x09, 0xd0);
-
- chipio_set_conn_rate_no_mutex(codec, 0xd0, SR_96_000);
- chipio_set_stream_channels(codec, 0x18, 6);
-
- /*
- * Runs again, this has been repeated a few times, but I'm just
- * following what the Windows driver does.
- */
- ae7_post_dsp_pll_setup(codec);
- chipio_set_control_param_no_mutex(codec, CONTROL_PARAM_ASI, 7);
-
- mutex_unlock(&spec->chipio_mutex);
-}
-
-/*
- * The Windows driver has commands that seem to setup ASI, which I believe to
- * be some sort of audio serial interface. My current speculation is that it's
- * related to communicating with the new DAC.
- */
-static void ae7_post_dsp_asi_setup(struct hda_codec *codec)
-{
- chipio_8051_write_direct(codec, 0x93, 0x10);
-
- chipio_8051_write_pll_pmu(codec, 0x44, 0xc2);
-
- ca0113_mmio_command_set_type2(codec, 0x48, 0x07, 0x83);
- ca0113_mmio_command_set(codec, 0x30, 0x2e, 0x3f);
-
- chipio_set_control_param(codec, 3, 3);
- chipio_set_control_flag(codec, CONTROL_FLAG_ASI_96KHZ, 1);
-
- snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, 0x724, 0x83);
- chipio_set_control_param(codec, CONTROL_PARAM_ASI, 0);
- snd_hda_codec_write(codec, 0x17, 0, 0x794, 0x00);
-
- chipio_8051_write_exram(codec, 0xfa92, 0x22);
-
- ae7_post_dsp_pll_setup(codec);
- ae7_post_dsp_asi_stream_setup(codec);
-
- chipio_8051_write_pll_pmu(codec, 0x43, 0xc7);
-
- ae7_post_dsp_asi_setup_ports(codec);
-}
-
-/*
- * Setup default parameters for DSP
- */
-static void ca0132_setup_defaults(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- unsigned int tmp;
- int num_fx;
- int idx, i;
-
- if (spec->dsp_state != DSP_DOWNLOADED)
- return;
-
- /* out, in effects + voicefx */
- num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT + 1;
- for (idx = 0; idx < num_fx; idx++) {
- for (i = 0; i <= ca0132_effects[idx].params; i++) {
- dspio_set_uint_param(codec, ca0132_effects[idx].mid,
- ca0132_effects[idx].reqs[i],
- ca0132_effects[idx].def_vals[i]);
- }
- }
-
- /*remove DSP headroom*/
- tmp = FLOAT_ZERO;
- dspio_set_uint_param(codec, 0x96, 0x3C, tmp);
-
- /*set speaker EQ bypass attenuation*/
- dspio_set_uint_param(codec, 0x8f, 0x01, tmp);
-
- /* set AMic1 and AMic2 as mono mic */
- tmp = FLOAT_ONE;
- dspio_set_uint_param(codec, 0x80, 0x00, tmp);
- dspio_set_uint_param(codec, 0x80, 0x01, tmp);
-
- /* set AMic1 as CrystalVoice input */
- tmp = FLOAT_ONE;
- dspio_set_uint_param(codec, 0x80, 0x05, tmp);
-
- /* set WUH source */
- tmp = FLOAT_TWO;
- dspio_set_uint_param(codec, 0x31, 0x00, tmp);
-}
-
-/*
- * Setup default parameters for Recon3D/Recon3Di DSP.
- */
-
-static void r3d_setup_defaults(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- unsigned int tmp;
- int num_fx;
- int idx, i;
-
- if (spec->dsp_state != DSP_DOWNLOADED)
- return;
-
- ca0132_alt_init_analog_mics(codec);
- ca0132_alt_start_dsp_audio_streams(codec);
-
- /*remove DSP headroom*/
- tmp = FLOAT_ZERO;
- dspio_set_uint_param(codec, 0x96, 0x3C, tmp);
-
- /* set WUH source */
- tmp = FLOAT_TWO;
- dspio_set_uint_param(codec, 0x31, 0x00, tmp);
- chipio_set_conn_rate(codec, MEM_CONNID_WUH, SR_48_000);
-
- /* Set speaker source? */
- dspio_set_uint_param(codec, 0x32, 0x00, tmp);
-
- if (ca0132_quirk(spec) == QUIRK_R3DI)
- r3di_gpio_dsp_status_set(codec, R3DI_DSP_DOWNLOADED);
-
- /* Disable mute on Center/LFE. */
- if (ca0132_quirk(spec) == QUIRK_R3D) {
- ca0113_mmio_gpio_set(codec, 2, false);
- ca0113_mmio_gpio_set(codec, 4, true);
- }
-
- /* Setup effect defaults */
- num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT + 1;
- for (idx = 0; idx < num_fx; idx++) {
- for (i = 0; i <= ca0132_effects[idx].params; i++) {
- dspio_set_uint_param(codec,
- ca0132_effects[idx].mid,
- ca0132_effects[idx].reqs[i],
- ca0132_effects[idx].def_vals[i]);
- }
- }
-}
-
-/*
- * Setup default parameters for the Sound Blaster Z DSP. A lot more going on
- * than the Chromebook setup.
- */
-static void sbz_setup_defaults(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- unsigned int tmp;
- int num_fx;
- int idx, i;
-
- if (spec->dsp_state != DSP_DOWNLOADED)
- return;
-
- ca0132_alt_init_analog_mics(codec);
- ca0132_alt_start_dsp_audio_streams(codec);
- sbz_connect_streams(codec);
- sbz_chipio_startup_data(codec);
-
- /*
- * Sets internal input loopback to off, used to have a switch to
- * enable input loopback, but turned out to be way too buggy.
- */
- tmp = FLOAT_ONE;
- dspio_set_uint_param(codec, 0x37, 0x08, tmp);
- dspio_set_uint_param(codec, 0x37, 0x10, tmp);
-
- /*remove DSP headroom*/
- tmp = FLOAT_ZERO;
- dspio_set_uint_param(codec, 0x96, 0x3C, tmp);
-
- /* set WUH source */
- tmp = FLOAT_TWO;
- dspio_set_uint_param(codec, 0x31, 0x00, tmp);
- chipio_set_conn_rate(codec, MEM_CONNID_WUH, SR_48_000);
-
- /* Set speaker source? */
- dspio_set_uint_param(codec, 0x32, 0x00, tmp);
-
- ca0132_alt_dsp_initial_mic_setup(codec);
-
- /* out, in effects + voicefx */
- num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT + 1;
- for (idx = 0; idx < num_fx; idx++) {
- for (i = 0; i <= ca0132_effects[idx].params; i++) {
- dspio_set_uint_param(codec,
- ca0132_effects[idx].mid,
- ca0132_effects[idx].reqs[i],
- ca0132_effects[idx].def_vals[i]);
- }
- }
-
- ca0132_alt_init_speaker_tuning(codec);
-}
-
-/*
- * Setup default parameters for the Sound BlasterX AE-5 DSP.
- */
-static void ae5_setup_defaults(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- unsigned int tmp;
- int num_fx;
- int idx, i;
-
- if (spec->dsp_state != DSP_DOWNLOADED)
- return;
-
- ca0132_alt_init_analog_mics(codec);
- ca0132_alt_start_dsp_audio_streams(codec);
-
- /* New, unknown SCP req's */
- tmp = FLOAT_ZERO;
- dspio_set_uint_param(codec, 0x96, 0x29, tmp);
- dspio_set_uint_param(codec, 0x96, 0x2a, tmp);
- dspio_set_uint_param(codec, 0x80, 0x0d, tmp);
- dspio_set_uint_param(codec, 0x80, 0x0e, tmp);
-
- ca0113_mmio_command_set(codec, 0x30, 0x2e, 0x3f);
- ca0113_mmio_gpio_set(codec, 0, false);
- ca0113_mmio_command_set(codec, 0x30, 0x28, 0x00);
-
- /* Internal loopback off */
- tmp = FLOAT_ONE;
- dspio_set_uint_param(codec, 0x37, 0x08, tmp);
- dspio_set_uint_param(codec, 0x37, 0x10, tmp);
-
- /*remove DSP headroom*/
- tmp = FLOAT_ZERO;
- dspio_set_uint_param(codec, 0x96, 0x3C, tmp);
-
- /* set WUH source */
- tmp = FLOAT_TWO;
- dspio_set_uint_param(codec, 0x31, 0x00, tmp);
- chipio_set_conn_rate(codec, MEM_CONNID_WUH, SR_48_000);
-
- /* Set speaker source? */
- dspio_set_uint_param(codec, 0x32, 0x00, tmp);
-
- ca0132_alt_dsp_initial_mic_setup(codec);
- ae5_post_dsp_register_set(codec);
- ae5_post_dsp_param_setup(codec);
- ae5_post_dsp_pll_setup(codec);
- ae5_post_dsp_stream_setup(codec);
- ae5_post_dsp_startup_data(codec);
-
- /* out, in effects + voicefx */
- num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT + 1;
- for (idx = 0; idx < num_fx; idx++) {
- for (i = 0; i <= ca0132_effects[idx].params; i++) {
- dspio_set_uint_param(codec,
- ca0132_effects[idx].mid,
- ca0132_effects[idx].reqs[i],
- ca0132_effects[idx].def_vals[i]);
- }
- }
-
- ca0132_alt_init_speaker_tuning(codec);
-}
-
-/*
- * Setup default parameters for the Sound Blaster AE-7 DSP.
- */
-static void ae7_setup_defaults(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- unsigned int tmp;
- int num_fx;
- int idx, i;
-
- if (spec->dsp_state != DSP_DOWNLOADED)
- return;
-
- ca0132_alt_init_analog_mics(codec);
- ca0132_alt_start_dsp_audio_streams(codec);
- ae7_post_dsp_setup_ports(codec);
-
- tmp = FLOAT_ZERO;
- dspio_set_uint_param(codec, 0x96,
- SPEAKER_TUNING_FRONT_LEFT_INVERT, tmp);
- dspio_set_uint_param(codec, 0x96,
- SPEAKER_TUNING_FRONT_RIGHT_INVERT, tmp);
-
- ca0113_mmio_command_set(codec, 0x30, 0x2e, 0x3f);
-
- /* New, unknown SCP req's */
- dspio_set_uint_param(codec, 0x80, 0x0d, tmp);
- dspio_set_uint_param(codec, 0x80, 0x0e, tmp);
-
- ca0113_mmio_gpio_set(codec, 0, false);
-
- /* Internal loopback off */
- tmp = FLOAT_ONE;
- dspio_set_uint_param(codec, 0x37, 0x08, tmp);
- dspio_set_uint_param(codec, 0x37, 0x10, tmp);
-
- /*remove DSP headroom*/
- tmp = FLOAT_ZERO;
- dspio_set_uint_param(codec, 0x96, 0x3C, tmp);
-
- /* set WUH source */
- tmp = FLOAT_TWO;
- dspio_set_uint_param(codec, 0x31, 0x00, tmp);
- chipio_set_conn_rate(codec, MEM_CONNID_WUH, SR_48_000);
-
- /* Set speaker source? */
- dspio_set_uint_param(codec, 0x32, 0x00, tmp);
- ca0113_mmio_command_set(codec, 0x30, 0x28, 0x00);
-
- /*
- * This is the second time we've called this, but this is seemingly
- * what Windows does.
- */
- ca0132_alt_init_analog_mics(codec);
-
- ae7_post_dsp_asi_setup(codec);
-
- /*
- * Not sure why, but these are both set to 1. They're only set to 0
- * upon shutdown.
- */
- ca0113_mmio_gpio_set(codec, 0, true);
- ca0113_mmio_gpio_set(codec, 1, true);
-
- /* Volume control related. */
- ca0113_mmio_command_set(codec, 0x48, 0x0f, 0x04);
- ca0113_mmio_command_set(codec, 0x48, 0x10, 0x04);
- ca0113_mmio_command_set_type2(codec, 0x48, 0x07, 0x80);
-
- /* out, in effects + voicefx */
- num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT + 1;
- for (idx = 0; idx < num_fx; idx++) {
- for (i = 0; i <= ca0132_effects[idx].params; i++) {
- dspio_set_uint_param(codec,
- ca0132_effects[idx].mid,
- ca0132_effects[idx].reqs[i],
- ca0132_effects[idx].def_vals[i]);
- }
- }
-
- ca0132_alt_init_speaker_tuning(codec);
-}
-
-/*
- * Initialization of flags in chip
- */
-static void ca0132_init_flags(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
-
- if (ca0132_use_alt_functions(spec)) {
- chipio_set_control_flag(codec, CONTROL_FLAG_DSP_96KHZ, 1);
- chipio_set_control_flag(codec, CONTROL_FLAG_DAC_96KHZ, 1);
- chipio_set_control_flag(codec, CONTROL_FLAG_ADC_B_96KHZ, 1);
- chipio_set_control_flag(codec, CONTROL_FLAG_ADC_C_96KHZ, 1);
- chipio_set_control_flag(codec, CONTROL_FLAG_SRC_RATE_96KHZ, 1);
- chipio_set_control_flag(codec, CONTROL_FLAG_IDLE_ENABLE, 0);
- chipio_set_control_flag(codec, CONTROL_FLAG_SPDIF2OUT, 0);
- chipio_set_control_flag(codec,
- CONTROL_FLAG_PORT_D_10KOHM_LOAD, 0);
- chipio_set_control_flag(codec,
- CONTROL_FLAG_PORT_A_10KOHM_LOAD, 1);
- } else {
- chipio_set_control_flag(codec, CONTROL_FLAG_IDLE_ENABLE, 0);
- chipio_set_control_flag(codec,
- CONTROL_FLAG_PORT_A_COMMON_MODE, 0);
- chipio_set_control_flag(codec,
- CONTROL_FLAG_PORT_D_COMMON_MODE, 0);
- chipio_set_control_flag(codec,
- CONTROL_FLAG_PORT_A_10KOHM_LOAD, 0);
- chipio_set_control_flag(codec,
- CONTROL_FLAG_PORT_D_10KOHM_LOAD, 0);
- chipio_set_control_flag(codec, CONTROL_FLAG_ADC_C_HIGH_PASS, 1);
- }
-}
-
-/*
- * Initialization of parameters in chip
- */
-static void ca0132_init_params(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
-
- if (ca0132_use_alt_functions(spec)) {
- chipio_set_conn_rate(codec, MEM_CONNID_WUH, SR_48_000);
- chipio_set_conn_rate(codec, 0x0B, SR_48_000);
- chipio_set_control_param(codec, CONTROL_PARAM_SPDIF1_SOURCE, 0);
- chipio_set_control_param(codec, 0, 0);
- chipio_set_control_param(codec, CONTROL_PARAM_VIP_SOURCE, 0);
- }
-
- chipio_set_control_param(codec, CONTROL_PARAM_PORTA_160OHM_GAIN, 6);
- chipio_set_control_param(codec, CONTROL_PARAM_PORTD_160OHM_GAIN, 6);
-}
-
-static void ca0132_set_dsp_msr(struct hda_codec *codec, bool is96k)
-{
- chipio_set_control_flag(codec, CONTROL_FLAG_DSP_96KHZ, is96k);
- chipio_set_control_flag(codec, CONTROL_FLAG_DAC_96KHZ, is96k);
- chipio_set_control_flag(codec, CONTROL_FLAG_SRC_RATE_96KHZ, is96k);
- chipio_set_control_flag(codec, CONTROL_FLAG_SRC_CLOCK_196MHZ, is96k);
- chipio_set_control_flag(codec, CONTROL_FLAG_ADC_B_96KHZ, is96k);
- chipio_set_control_flag(codec, CONTROL_FLAG_ADC_C_96KHZ, is96k);
-
- chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000);
- chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000);
- chipio_set_conn_rate(codec, MEM_CONNID_WUH, SR_48_000);
-}
-
-static bool ca0132_download_dsp_images(struct hda_codec *codec)
-{
- bool dsp_loaded = false;
- struct ca0132_spec *spec = codec->spec;
- const struct dsp_image_seg *dsp_os_image;
- const struct firmware *fw_entry = NULL;
- /*
- * Alternate firmwares for different variants. The Recon3Di apparently
- * can use the default firmware, but I'll leave the option in case
- * it needs it again.
- */
- switch (ca0132_quirk(spec)) {
- case QUIRK_SBZ:
- case QUIRK_R3D:
- case QUIRK_AE5:
- if (request_firmware(&fw_entry, DESKTOP_EFX_FILE,
- codec->card->dev) != 0)
- codec_dbg(codec, "Desktop firmware not found.");
- else
- codec_dbg(codec, "Desktop firmware selected.");
- break;
- case QUIRK_R3DI:
- if (request_firmware(&fw_entry, R3DI_EFX_FILE,
- codec->card->dev) != 0)
- codec_dbg(codec, "Recon3Di alt firmware not detected.");
- else
- codec_dbg(codec, "Recon3Di firmware selected.");
- break;
- default:
- break;
- }
- /*
- * Use default ctefx.bin if no alt firmware is detected, or if none
- * exists for your particular codec.
- */
- if (!fw_entry) {
- codec_dbg(codec, "Default firmware selected.");
- if (request_firmware(&fw_entry, EFX_FILE,
- codec->card->dev) != 0)
- return false;
- }
-
- dsp_os_image = (struct dsp_image_seg *)(fw_entry->data);
- if (dspload_image(codec, dsp_os_image, 0, 0, true, 0)) {
- codec_err(codec, "ca0132 DSP load image failed\n");
- goto exit_download;
- }
-
- dsp_loaded = dspload_wait_loaded(codec);
-
-exit_download:
- release_firmware(fw_entry);
-
- return dsp_loaded;
-}
-
-static void ca0132_download_dsp(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
-
-#ifndef CONFIG_SND_HDA_CODEC_CA0132_DSP
- return; /* NOP */
-#endif
-
- if (spec->dsp_state == DSP_DOWNLOAD_FAILED)
- return; /* don't retry failures */
-
- chipio_enable_clocks(codec);
- if (spec->dsp_state != DSP_DOWNLOADED) {
- spec->dsp_state = DSP_DOWNLOADING;
-
- if (!ca0132_download_dsp_images(codec))
- spec->dsp_state = DSP_DOWNLOAD_FAILED;
- else
- spec->dsp_state = DSP_DOWNLOADED;
- }
-
- /* For codecs using alt functions, this is already done earlier */
- if (spec->dsp_state == DSP_DOWNLOADED && !ca0132_use_alt_functions(spec))
- ca0132_set_dsp_msr(codec, true);
-}
-
-static void ca0132_process_dsp_response(struct hda_codec *codec,
- struct hda_jack_callback *callback)
-{
- struct ca0132_spec *spec = codec->spec;
-
- codec_dbg(codec, "ca0132_process_dsp_response\n");
- snd_hda_power_up_pm(codec);
- if (spec->wait_scp) {
- if (dspio_get_response_data(codec) >= 0)
- spec->wait_scp = 0;
- }
-
- dspio_clear_response_queue(codec);
- snd_hda_power_down_pm(codec);
-}
-
-static void hp_callback(struct hda_codec *codec, struct hda_jack_callback *cb)
-{
- struct ca0132_spec *spec = codec->spec;
- struct hda_jack_tbl *tbl;
-
- /* Delay enabling the HP amp, to let the mic-detection
- * state machine run.
- */
- tbl = snd_hda_jack_tbl_get(codec, cb->nid);
- if (tbl)
- tbl->block_report = 1;
- schedule_delayed_work(&spec->unsol_hp_work, msecs_to_jiffies(500));
-}
-
-static void amic_callback(struct hda_codec *codec, struct hda_jack_callback *cb)
-{
- struct ca0132_spec *spec = codec->spec;
-
- if (ca0132_use_alt_functions(spec))
- ca0132_alt_select_in(codec);
- else
- ca0132_select_mic(codec);
-}
-
-static void ca0132_setup_unsol(struct hda_codec *codec)
-{
- 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);
- /* Front headphone jack detection */
- if (ca0132_use_alt_functions(spec))
- snd_hda_jack_detect_enable_callback(codec,
- spec->unsol_tag_front_hp, hp_callback);
-}
-
-/*
- * Verbs tables.
- */
-
-/* Sends before DSP download. */
-static const struct hda_verb ca0132_base_init_verbs[] = {
- /*enable ct extension*/
- {0x15, VENDOR_CHIPIO_CT_EXTENSIONS_ENABLE, 0x1},
- {}
-};
-
-/* Send at exit. */
-static const struct hda_verb ca0132_base_exit_verbs[] = {
- /*set afg to D3*/
- {0x01, AC_VERB_SET_POWER_STATE, 0x03},
- /*disable ct extension*/
- {0x15, VENDOR_CHIPIO_CT_EXTENSIONS_ENABLE, 0},
- {}
-};
-
-/* Other verbs tables. Sends after DSP download. */
-
-static const struct hda_verb ca0132_init_verbs0[] = {
- /* chip init verbs */
- {0x15, 0x70D, 0xF0},
- {0x15, 0x70E, 0xFE},
- {0x15, 0x707, 0x75},
- {0x15, 0x707, 0xD3},
- {0x15, 0x707, 0x09},
- {0x15, 0x707, 0x53},
- {0x15, 0x707, 0xD4},
- {0x15, 0x707, 0xEF},
- {0x15, 0x707, 0x75},
- {0x15, 0x707, 0xD3},
- {0x15, 0x707, 0x09},
- {0x15, 0x707, 0x02},
- {0x15, 0x707, 0x37},
- {0x15, 0x707, 0x78},
- {0x15, 0x53C, 0xCE},
- {0x15, 0x575, 0xC9},
- {0x15, 0x53D, 0xCE},
- {0x15, 0x5B7, 0xC9},
- {0x15, 0x70D, 0xE8},
- {0x15, 0x70E, 0xFE},
- {0x15, 0x707, 0x02},
- {0x15, 0x707, 0x68},
- {0x15, 0x707, 0x62},
- {0x15, 0x53A, 0xCE},
- {0x15, 0x546, 0xC9},
- {0x15, 0x53B, 0xCE},
- {0x15, 0x5E8, 0xC9},
- {}
-};
-
-/* Extra init verbs for desktop cards. */
-static const struct hda_verb ca0132_init_verbs1[] = {
- {0x15, 0x70D, 0x20},
- {0x15, 0x70E, 0x19},
- {0x15, 0x707, 0x00},
- {0x15, 0x539, 0xCE},
- {0x15, 0x546, 0xC9},
- {0x15, 0x70D, 0xB7},
- {0x15, 0x70E, 0x09},
- {0x15, 0x707, 0x10},
- {0x15, 0x70D, 0xAF},
- {0x15, 0x70E, 0x09},
- {0x15, 0x707, 0x01},
- {0x15, 0x707, 0x05},
- {0x15, 0x70D, 0x73},
- {0x15, 0x70E, 0x09},
- {0x15, 0x707, 0x14},
- {0x15, 0x6FF, 0xC4},
- {}
-};
-
-static void ca0132_init_chip(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- int num_fx;
- int i;
- unsigned int on;
-
- mutex_init(&spec->chipio_mutex);
-
- /*
- * The Windows driver always does this upon startup, which seems to
- * clear out any previous configuration. This should help issues where
- * a boot into Windows prior to a boot into Linux breaks things. Also,
- * Windows always sends the reset twice.
- */
- if (ca0132_use_alt_functions(spec)) {
- chipio_set_control_flag(codec, CONTROL_FLAG_IDLE_ENABLE, 0);
- chipio_write_no_mutex(codec, 0x18b0a4, 0x000000c2);
-
- snd_hda_codec_write(codec, codec->core.afg, 0,
- AC_VERB_SET_CODEC_RESET, 0);
- snd_hda_codec_write(codec, codec->core.afg, 0,
- AC_VERB_SET_CODEC_RESET, 0);
- }
-
- spec->cur_out_type = SPEAKER_OUT;
- if (!ca0132_use_alt_functions(spec))
- spec->cur_mic_type = DIGITAL_MIC;
- else
- spec->cur_mic_type = REAR_MIC;
-
- spec->cur_mic_boost = 0;
-
- for (i = 0; i < VNODES_COUNT; i++) {
- spec->vnode_lvol[i] = 0x5a;
- spec->vnode_rvol[i] = 0x5a;
- spec->vnode_lswitch[i] = 0;
- spec->vnode_rswitch[i] = 0;
- }
-
- /*
- * Default states for effects are in ca0132_effects[].
- */
- num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT;
- for (i = 0; i < num_fx; i++) {
- on = (unsigned int)ca0132_effects[i].reqs[0];
- spec->effects_switch[i] = on ? 1 : 0;
- }
- /*
- * Sets defaults for the effect slider controls, only for alternative
- * ca0132 codecs. Also sets x-bass crossover frequency to 80hz.
- */
- if (ca0132_use_alt_controls(spec)) {
- /* Set speakers to default to full range. */
- spec->speaker_range_val[0] = 1;
- spec->speaker_range_val[1] = 1;
-
- spec->xbass_xover_freq = 8;
- for (i = 0; i < EFFECT_LEVEL_SLIDERS; i++)
- spec->fx_ctl_val[i] = effect_slider_defaults[i];
-
- spec->bass_redirect_xover_freq = 8;
- }
-
- spec->voicefx_val = 0;
- spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID] = 1;
- spec->effects_switch[CRYSTAL_VOICE - EFFECT_START_NID] = 0;
-
- /*
- * The ZxR doesn't have a front panel header, and it's line-in is on
- * the daughter board. So, there is no input enum control, and we need
- * to make sure that spec->in_enum_val is set properly.
- */
- if (ca0132_quirk(spec) == QUIRK_ZXR)
- spec->in_enum_val = REAR_MIC;
-
-#ifdef ENABLE_TUNING_CONTROLS
- ca0132_init_tuning_defaults(codec);
-#endif
-}
-
-/*
- * Recon3Di exit specific commands.
- */
-/* prevents popping noise on shutdown */
-static void r3di_gpio_shutdown(struct hda_codec *codec)
-{
- snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0x00);
-}
-
-/*
- * Sound Blaster Z exit specific commands.
- */
-static void sbz_region2_exit(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- unsigned int i;
-
- for (i = 0; i < 4; i++)
- writeb(0x0, spec->mem_base + 0x100);
- for (i = 0; i < 8; i++)
- writeb(0xb3, spec->mem_base + 0x304);
-
- ca0113_mmio_gpio_set(codec, 0, false);
- ca0113_mmio_gpio_set(codec, 1, false);
- ca0113_mmio_gpio_set(codec, 4, true);
- ca0113_mmio_gpio_set(codec, 5, false);
- ca0113_mmio_gpio_set(codec, 7, false);
-}
-
-static void sbz_set_pin_ctl_default(struct hda_codec *codec)
-{
- static const hda_nid_t pins[] = {0x0B, 0x0C, 0x0E, 0x12, 0x13};
- unsigned int i;
-
- snd_hda_codec_write(codec, 0x11, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40);
-
- for (i = 0; i < ARRAY_SIZE(pins); i++)
- snd_hda_codec_write(codec, pins[i], 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00);
-}
-
-static void ca0132_clear_unsolicited(struct hda_codec *codec)
-{
- static const hda_nid_t pins[] = {0x0B, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13};
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(pins); i++) {
- snd_hda_codec_write(codec, pins[i], 0,
- AC_VERB_SET_UNSOLICITED_ENABLE, 0x00);
- }
-}
-
-/* On shutdown, sends commands in sets of three */
-static void sbz_gpio_shutdown_commands(struct hda_codec *codec, int dir,
- int mask, int data)
-{
- if (dir >= 0)
- snd_hda_codec_write(codec, 0x01, 0,
- AC_VERB_SET_GPIO_DIRECTION, dir);
- if (mask >= 0)
- snd_hda_codec_write(codec, 0x01, 0,
- AC_VERB_SET_GPIO_MASK, mask);
-
- if (data >= 0)
- snd_hda_codec_write(codec, 0x01, 0,
- AC_VERB_SET_GPIO_DATA, data);
-}
-
-static void zxr_dbpro_power_state_shutdown(struct hda_codec *codec)
-{
- static const hda_nid_t pins[] = {0x05, 0x0c, 0x09, 0x0e, 0x08, 0x11, 0x01};
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(pins); i++)
- snd_hda_codec_write(codec, pins[i], 0,
- AC_VERB_SET_POWER_STATE, 0x03);
-}
-
-static void sbz_exit_chip(struct hda_codec *codec)
-{
- chipio_set_stream_control(codec, 0x03, 0);
- chipio_set_stream_control(codec, 0x04, 0);
-
- /* Mess with GPIO */
- sbz_gpio_shutdown_commands(codec, 0x07, 0x07, -1);
- sbz_gpio_shutdown_commands(codec, 0x07, 0x07, 0x05);
- sbz_gpio_shutdown_commands(codec, 0x07, 0x07, 0x01);
-
- chipio_set_stream_control(codec, 0x14, 0);
- chipio_set_stream_control(codec, 0x0C, 0);
-
- chipio_set_conn_rate(codec, 0x41, SR_192_000);
- chipio_set_conn_rate(codec, 0x91, SR_192_000);
-
- chipio_write(codec, 0x18a020, 0x00000083);
-
- sbz_gpio_shutdown_commands(codec, 0x07, 0x07, 0x03);
- sbz_gpio_shutdown_commands(codec, 0x07, 0x07, 0x07);
- sbz_gpio_shutdown_commands(codec, 0x07, 0x07, 0x06);
-
- chipio_set_stream_control(codec, 0x0C, 0);
-
- chipio_set_control_param(codec, 0x0D, 0x24);
-
- ca0132_clear_unsolicited(codec);
- sbz_set_pin_ctl_default(codec);
-
- snd_hda_codec_write(codec, 0x0B, 0,
- AC_VERB_SET_EAPD_BTLENABLE, 0x00);
-
- sbz_region2_exit(codec);
-}
-
-static void r3d_exit_chip(struct hda_codec *codec)
-{
- ca0132_clear_unsolicited(codec);
- snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00);
- snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x5b);
-}
-
-static void ae5_exit_chip(struct hda_codec *codec)
-{
- chipio_set_stream_control(codec, 0x03, 0);
- chipio_set_stream_control(codec, 0x04, 0);
-
- ca0113_mmio_command_set(codec, 0x30, 0x32, 0x3f);
- ca0113_mmio_command_set(codec, 0x48, 0x07, 0x83);
- ca0113_mmio_command_set(codec, 0x48, 0x07, 0x83);
- ca0113_mmio_command_set(codec, 0x30, 0x30, 0x00);
- ca0113_mmio_command_set(codec, 0x30, 0x2b, 0x00);
- ca0113_mmio_command_set(codec, 0x30, 0x2d, 0x00);
- ca0113_mmio_gpio_set(codec, 0, false);
- ca0113_mmio_gpio_set(codec, 1, false);
-
- snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00);
- snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x53);
-
- chipio_set_control_param(codec, CONTROL_PARAM_ASI, 0);
-
- chipio_set_stream_control(codec, 0x18, 0);
- chipio_set_stream_control(codec, 0x0c, 0);
-
- snd_hda_codec_write(codec, 0x01, 0, 0x724, 0x83);
-}
-
-static void ae7_exit_chip(struct hda_codec *codec)
-{
- chipio_set_stream_control(codec, 0x18, 0);
- chipio_set_stream_source_dest(codec, 0x21, 0xc8, 0xc8);
- chipio_set_stream_channels(codec, 0x21, 0);
- chipio_set_control_param(codec, CONTROL_PARAM_NODE_ID, 0x09);
- chipio_set_control_param(codec, 0x20, 0x01);
-
- chipio_set_control_param(codec, CONTROL_PARAM_ASI, 0);
-
- chipio_set_stream_control(codec, 0x18, 0);
- chipio_set_stream_control(codec, 0x0c, 0);
-
- ca0113_mmio_command_set(codec, 0x30, 0x2b, 0x00);
- snd_hda_codec_write(codec, 0x15, 0, 0x724, 0x83);
- ca0113_mmio_command_set_type2(codec, 0x48, 0x07, 0x83);
- ca0113_mmio_command_set(codec, 0x30, 0x30, 0x00);
- ca0113_mmio_command_set(codec, 0x30, 0x2e, 0x00);
- ca0113_mmio_gpio_set(codec, 0, false);
- ca0113_mmio_gpio_set(codec, 1, false);
- ca0113_mmio_command_set(codec, 0x30, 0x32, 0x3f);
-
- snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00);
- snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x53);
-}
-
-static void zxr_exit_chip(struct hda_codec *codec)
-{
- chipio_set_stream_control(codec, 0x03, 0);
- chipio_set_stream_control(codec, 0x04, 0);
- chipio_set_stream_control(codec, 0x14, 0);
- chipio_set_stream_control(codec, 0x0C, 0);
-
- chipio_set_conn_rate(codec, 0x41, SR_192_000);
- chipio_set_conn_rate(codec, 0x91, SR_192_000);
-
- chipio_write(codec, 0x18a020, 0x00000083);
-
- snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00);
- snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x53);
-
- ca0132_clear_unsolicited(codec);
- sbz_set_pin_ctl_default(codec);
- snd_hda_codec_write(codec, 0x0B, 0, AC_VERB_SET_EAPD_BTLENABLE, 0x00);
-
- ca0113_mmio_gpio_set(codec, 5, false);
- ca0113_mmio_gpio_set(codec, 2, false);
- ca0113_mmio_gpio_set(codec, 3, false);
- ca0113_mmio_gpio_set(codec, 0, false);
- ca0113_mmio_gpio_set(codec, 4, true);
- ca0113_mmio_gpio_set(codec, 0, true);
- ca0113_mmio_gpio_set(codec, 5, true);
- ca0113_mmio_gpio_set(codec, 2, false);
- ca0113_mmio_gpio_set(codec, 3, false);
-}
-
-static void ca0132_exit_chip(struct hda_codec *codec)
-{
- /* put any chip cleanup stuffs here. */
-
- if (dspload_is_loaded(codec))
- dsp_reset(codec);
-}
-
-/*
- * This fixes a problem that was hard to reproduce. Very rarely, I would
- * boot up, and there would be no sound, but the DSP indicated it had loaded
- * properly. I did a few memory dumps to see if anything was different, and
- * there were a few areas of memory uninitialized with a1a2a3a4. This function
- * checks if those areas are uninitialized, and if they are, it'll attempt to
- * reload the card 3 times. Usually it fixes by the second.
- */
-static void sbz_dsp_startup_check(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- unsigned int dsp_data_check[4];
- unsigned int cur_address = 0x390;
- unsigned int i;
- unsigned int failure = 0;
- unsigned int reload = 3;
-
- if (spec->startup_check_entered)
- return;
-
- spec->startup_check_entered = true;
-
- for (i = 0; i < 4; i++) {
- chipio_read(codec, cur_address, &dsp_data_check[i]);
- cur_address += 0x4;
- }
- for (i = 0; i < 4; i++) {
- if (dsp_data_check[i] == 0xa1a2a3a4)
- failure = 1;
- }
-
- codec_dbg(codec, "Startup Check: %d ", failure);
- if (failure)
- codec_info(codec, "DSP not initialized properly. Attempting to fix.");
- /*
- * While the failure condition is true, and we haven't reached our
- * three reload limit, continue trying to reload the driver and
- * fix the issue.
- */
- while (failure && (reload != 0)) {
- codec_info(codec, "Reloading... Tries left: %d", reload);
- sbz_exit_chip(codec);
- spec->dsp_state = DSP_DOWNLOAD_INIT;
- codec->patch_ops.init(codec);
- failure = 0;
- for (i = 0; i < 4; i++) {
- chipio_read(codec, cur_address, &dsp_data_check[i]);
- cur_address += 0x4;
- }
- for (i = 0; i < 4; i++) {
- if (dsp_data_check[i] == 0xa1a2a3a4)
- failure = 1;
- }
- reload--;
- }
-
- if (!failure && reload < 3)
- codec_info(codec, "DSP fixed.");
-
- if (!failure)
- return;
-
- codec_info(codec, "DSP failed to initialize properly. Either try a full shutdown or a suspend to clear the internal memory.");
-}
-
-/*
- * This is for the extra volume verbs 0x797 (left) and 0x798 (right). These add
- * extra precision for decibel values. If you had the dB value in floating point
- * you would take the value after the decimal point, multiply by 64, and divide
- * by 2. So for 8.59, it's (59 * 64) / 100. Useful if someone wanted to
- * implement fixed point or floating point dB volumes. For now, I'll set them
- * to 0 just incase a value has lingered from a boot into Windows.
- */
-static void ca0132_alt_vol_setup(struct hda_codec *codec)
-{
- snd_hda_codec_write(codec, 0x02, 0, 0x797, 0x00);
- snd_hda_codec_write(codec, 0x02, 0, 0x798, 0x00);
- snd_hda_codec_write(codec, 0x03, 0, 0x797, 0x00);
- snd_hda_codec_write(codec, 0x03, 0, 0x798, 0x00);
- snd_hda_codec_write(codec, 0x04, 0, 0x797, 0x00);
- snd_hda_codec_write(codec, 0x04, 0, 0x798, 0x00);
- snd_hda_codec_write(codec, 0x07, 0, 0x797, 0x00);
- snd_hda_codec_write(codec, 0x07, 0, 0x798, 0x00);
-}
-
-/*
- * Extra commands that don't really fit anywhere else.
- */
-static void sbz_pre_dsp_setup(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
-
- writel(0x00820680, spec->mem_base + 0x01C);
- writel(0x00820680, spec->mem_base + 0x01C);
-
- chipio_write(codec, 0x18b0a4, 0x000000c2);
-
- snd_hda_codec_write(codec, 0x11, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0x44);
-}
-
-static void r3d_pre_dsp_setup(struct hda_codec *codec)
-{
- chipio_write(codec, 0x18b0a4, 0x000000c2);
-
- chipio_8051_write_exram(codec, 0x1c1e, 0x5b);
-
- snd_hda_codec_write(codec, 0x11, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0x44);
-}
-
-static void r3di_pre_dsp_setup(struct hda_codec *codec)
-{
- chipio_write(codec, 0x18b0a4, 0x000000c2);
-
- chipio_8051_write_exram(codec, 0x1c1e, 0x5b);
- chipio_8051_write_exram(codec, 0x1920, 0x00);
- chipio_8051_write_exram(codec, 0x1921, 0x40);
-
- snd_hda_codec_write(codec, 0x11, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0x04);
-}
-
-/*
- * The ZxR seems to use alternative DAC's for the surround channels, which
- * require PLL PMU setup for the clock rate, I'm guessing. Without setting
- * this up, we get no audio out of the surround jacks.
- */
-static void zxr_pre_dsp_setup(struct hda_codec *codec)
-{
- static const unsigned int addr[] = { 0x43, 0x40, 0x41, 0x42, 0x45 };
- static const unsigned int data[] = { 0x08, 0x0c, 0x0b, 0x07, 0x0d };
- unsigned int i;
-
- chipio_write(codec, 0x189000, 0x0001f100);
- msleep(50);
- chipio_write(codec, 0x18900c, 0x0001f100);
- msleep(50);
-
- /*
- * This writes a RET instruction at the entry point of the function at
- * 0xfa92 in exram. This function seems to have something to do with
- * ASI. Might be some way to prevent the card from reconfiguring the
- * ASI stuff itself.
- */
- chipio_8051_write_exram(codec, 0xfa92, 0x22);
-
- chipio_8051_write_pll_pmu(codec, 0x51, 0x98);
-
- snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, 0x725, 0x82);
- chipio_set_control_param(codec, CONTROL_PARAM_ASI, 3);
-
- chipio_write(codec, 0x18902c, 0x00000000);
- msleep(50);
- chipio_write(codec, 0x18902c, 0x00000003);
- msleep(50);
-
- for (i = 0; i < ARRAY_SIZE(addr); i++)
- chipio_8051_write_pll_pmu(codec, addr[i], data[i]);
-}
-
-/*
- * These are sent before the DSP is downloaded. Not sure
- * what they do, or if they're necessary. Could possibly
- * be removed. Figure they're better to leave in.
- */
-static const unsigned int ca0113_mmio_init_address_sbz[] = {
- 0x400, 0x408, 0x40c, 0x01c, 0xc0c, 0xc00, 0xc04, 0xc0c, 0xc0c, 0xc0c,
- 0xc0c, 0xc08, 0xc08, 0xc08, 0xc08, 0xc08, 0xc04
-};
-
-static const unsigned int ca0113_mmio_init_data_sbz[] = {
- 0x00000030, 0x00000000, 0x00000003, 0x00000003, 0x00000003,
- 0x00000003, 0x000000c1, 0x000000f1, 0x00000001, 0x000000c7,
- 0x000000c1, 0x00000080
-};
-
-static const unsigned int ca0113_mmio_init_data_zxr[] = {
- 0x00000030, 0x00000000, 0x00000000, 0x00000003, 0x00000003,
- 0x00000003, 0x00000001, 0x000000f1, 0x00000001, 0x000000c7,
- 0x000000c1, 0x00000080
-};
-
-static const unsigned int ca0113_mmio_init_address_ae5[] = {
- 0x400, 0x42c, 0x46c, 0x4ac, 0x4ec, 0x43c, 0x47c, 0x4bc, 0x4fc, 0x408,
- 0x100, 0x410, 0x40c, 0x100, 0x100, 0x830, 0x86c, 0x800, 0x86c, 0x800,
- 0x804, 0x20c, 0x01c, 0xc0c, 0xc00, 0xc04, 0xc0c, 0xc0c, 0xc0c, 0xc0c,
- 0xc08, 0xc08, 0xc08, 0xc08, 0xc08, 0xc04, 0x01c
-};
-
-static const unsigned int ca0113_mmio_init_data_ae5[] = {
- 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001,
- 0x00000600, 0x00000014, 0x00000001, 0x0000060f, 0x0000070f,
- 0x00000aff, 0x00000000, 0x0000006b, 0x00000001, 0x0000006b,
- 0x00000057, 0x00800000, 0x00880680, 0x00000080, 0x00000030,
- 0x00000000, 0x00000000, 0x00000003, 0x00000003, 0x00000003,
- 0x00000001, 0x000000f1, 0x00000001, 0x000000c7, 0x000000c1,
- 0x00000080, 0x00880680
-};
-
-static void ca0132_mmio_init_sbz(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- unsigned int tmp[2], i, count, cur_addr;
- const unsigned int *addr, *data;
-
- addr = ca0113_mmio_init_address_sbz;
- for (i = 0; i < 3; i++)
- writel(0x00000000, spec->mem_base + addr[i]);
-
- cur_addr = i;
- switch (ca0132_quirk(spec)) {
- case QUIRK_ZXR:
- tmp[0] = 0x00880480;
- tmp[1] = 0x00000080;
- break;
- case QUIRK_SBZ:
- tmp[0] = 0x00820680;
- tmp[1] = 0x00000083;
- break;
- case QUIRK_R3D:
- tmp[0] = 0x00880680;
- tmp[1] = 0x00000083;
- break;
- default:
- tmp[0] = 0x00000000;
- tmp[1] = 0x00000000;
- break;
- }
-
- for (i = 0; i < 2; i++)
- writel(tmp[i], spec->mem_base + addr[cur_addr + i]);
-
- cur_addr += i;
-
- switch (ca0132_quirk(spec)) {
- case QUIRK_ZXR:
- count = ARRAY_SIZE(ca0113_mmio_init_data_zxr);
- data = ca0113_mmio_init_data_zxr;
- break;
- default:
- count = ARRAY_SIZE(ca0113_mmio_init_data_sbz);
- data = ca0113_mmio_init_data_sbz;
- break;
- }
-
- for (i = 0; i < count; i++)
- writel(data[i], spec->mem_base + addr[cur_addr + i]);
-}
-
-static void ca0132_mmio_init_ae5(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- const unsigned int *addr, *data;
- unsigned int i, count;
-
- addr = ca0113_mmio_init_address_ae5;
- data = ca0113_mmio_init_data_ae5;
- count = ARRAY_SIZE(ca0113_mmio_init_data_ae5);
-
- if (ca0132_quirk(spec) == QUIRK_AE7) {
- writel(0x00000680, spec->mem_base + 0x1c);
- writel(0x00880680, spec->mem_base + 0x1c);
- }
-
- for (i = 0; i < count; i++) {
- /*
- * AE-7 shares all writes with the AE-5, except that it writes
- * a different value to 0x20c.
- */
- if (i == 21 && ca0132_quirk(spec) == QUIRK_AE7) {
- writel(0x00800001, spec->mem_base + addr[i]);
- continue;
- }
-
- writel(data[i], spec->mem_base + addr[i]);
- }
-
- if (ca0132_quirk(spec) == QUIRK_AE5)
- writel(0x00880680, spec->mem_base + 0x1c);
-}
-
-static void ca0132_mmio_init(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
-
- switch (ca0132_quirk(spec)) {
- case QUIRK_R3D:
- case QUIRK_SBZ:
- case QUIRK_ZXR:
- ca0132_mmio_init_sbz(codec);
- break;
- case QUIRK_AE5:
- ca0132_mmio_init_ae5(codec);
- break;
- default:
- break;
- }
-}
-
-static const unsigned int ca0132_ae5_register_set_addresses[] = {
- 0x304, 0x304, 0x304, 0x304, 0x100, 0x304, 0x100, 0x304, 0x100, 0x304,
- 0x100, 0x304, 0x86c, 0x800, 0x86c, 0x800, 0x804
-};
-
-static const unsigned char ca0132_ae5_register_set_data[] = {
- 0x0f, 0x0e, 0x1f, 0x0c, 0x3f, 0x08, 0x7f, 0x00, 0xff, 0x00, 0x6b,
- 0x01, 0x6b, 0x57
-};
-
-/*
- * This function writes to some SFR's, does some region2 writes, and then
- * eventually resets the codec with the 0x7ff verb. Not quite sure why it does
- * what it does.
- */
-static void ae5_register_set(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- unsigned int count = ARRAY_SIZE(ca0132_ae5_register_set_addresses);
- const unsigned int *addr = ca0132_ae5_register_set_addresses;
- const unsigned char *data = ca0132_ae5_register_set_data;
- unsigned int i, cur_addr;
- unsigned char tmp[3];
-
- if (ca0132_quirk(spec) == QUIRK_AE7)
- chipio_8051_write_pll_pmu(codec, 0x41, 0xc8);
-
- chipio_8051_write_direct(codec, 0x93, 0x10);
- chipio_8051_write_pll_pmu(codec, 0x44, 0xc2);
-
- if (ca0132_quirk(spec) == QUIRK_AE7) {
- tmp[0] = 0x03;
- tmp[1] = 0x03;
- tmp[2] = 0x07;
- } else {
- tmp[0] = 0x0f;
- tmp[1] = 0x0f;
- tmp[2] = 0x0f;
- }
-
- for (i = cur_addr = 0; i < 3; i++, cur_addr++)
- writeb(tmp[i], spec->mem_base + addr[cur_addr]);
-
- /*
- * First writes are in single bytes, final are in 4 bytes. So, we use
- * writeb, then writel.
- */
- for (i = 0; cur_addr < 12; i++, cur_addr++)
- writeb(data[i], spec->mem_base + addr[cur_addr]);
-
- for (; cur_addr < count; i++, cur_addr++)
- writel(data[i], spec->mem_base + addr[cur_addr]);
-
- writel(0x00800001, spec->mem_base + 0x20c);
-
- if (ca0132_quirk(spec) == QUIRK_AE7) {
- ca0113_mmio_command_set_type2(codec, 0x48, 0x07, 0x83);
- ca0113_mmio_command_set(codec, 0x30, 0x2e, 0x3f);
- } else {
- ca0113_mmio_command_set(codec, 0x30, 0x2d, 0x3f);
- }
-
- chipio_8051_write_direct(codec, 0x90, 0x00);
- chipio_8051_write_direct(codec, 0x90, 0x10);
-
- if (ca0132_quirk(spec) == QUIRK_AE5)
- ca0113_mmio_command_set(codec, 0x48, 0x07, 0x83);
-}
-
-/*
- * Extra init functions for alternative ca0132 codecs. Done
- * here so they don't clutter up the main ca0132_init function
- * anymore than they have to.
- */
-static void ca0132_alt_init(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
-
- ca0132_alt_vol_setup(codec);
-
- switch (ca0132_quirk(spec)) {
- case QUIRK_SBZ:
- codec_dbg(codec, "SBZ alt_init");
- ca0132_gpio_init(codec);
- sbz_pre_dsp_setup(codec);
- snd_hda_sequence_write(codec, spec->chip_init_verbs);
- snd_hda_sequence_write(codec, spec->desktop_init_verbs);
- break;
- case QUIRK_R3DI:
- codec_dbg(codec, "R3DI alt_init");
- ca0132_gpio_init(codec);
- ca0132_gpio_setup(codec);
- r3di_gpio_dsp_status_set(codec, R3DI_DSP_DOWNLOADING);
- r3di_pre_dsp_setup(codec);
- snd_hda_sequence_write(codec, spec->chip_init_verbs);
- snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, 0x6FF, 0xC4);
- break;
- case QUIRK_R3D:
- r3d_pre_dsp_setup(codec);
- snd_hda_sequence_write(codec, spec->chip_init_verbs);
- snd_hda_sequence_write(codec, spec->desktop_init_verbs);
- break;
- case QUIRK_AE5:
- ca0132_gpio_init(codec);
- chipio_8051_write_pll_pmu(codec, 0x49, 0x88);
- chipio_write(codec, 0x18b030, 0x00000020);
- snd_hda_sequence_write(codec, spec->chip_init_verbs);
- snd_hda_sequence_write(codec, spec->desktop_init_verbs);
- ca0113_mmio_command_set(codec, 0x30, 0x32, 0x3f);
- break;
- case QUIRK_AE7:
- ca0132_gpio_init(codec);
- chipio_8051_write_pll_pmu(codec, 0x49, 0x88);
- snd_hda_sequence_write(codec, spec->chip_init_verbs);
- snd_hda_sequence_write(codec, spec->desktop_init_verbs);
- chipio_write(codec, 0x18b008, 0x000000f8);
- chipio_write(codec, 0x18b008, 0x000000f0);
- chipio_write(codec, 0x18b030, 0x00000020);
- ca0113_mmio_command_set(codec, 0x30, 0x32, 0x3f);
- break;
- case QUIRK_ZXR:
- chipio_8051_write_pll_pmu(codec, 0x49, 0x88);
- snd_hda_sequence_write(codec, spec->chip_init_verbs);
- snd_hda_sequence_write(codec, spec->desktop_init_verbs);
- zxr_pre_dsp_setup(codec);
- break;
- default:
- break;
- }
-}
-
-static int ca0132_init(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->autocfg;
- int i;
- bool dsp_loaded;
-
- /*
- * If the DSP is already downloaded, and init has been entered again,
- * there's only two reasons for it. One, the codec has awaken from a
- * suspended state, and in that case dspload_is_loaded will return
- * false, and the init will be ran again. The other reason it gets
- * re entered is on startup for some reason it triggers a suspend and
- * resume state. In this case, it will check if the DSP is downloaded,
- * and not run the init function again. For codecs using alt_functions,
- * it will check if the DSP is loaded properly.
- */
- if (spec->dsp_state == DSP_DOWNLOADED) {
- dsp_loaded = dspload_is_loaded(codec);
- if (!dsp_loaded) {
- spec->dsp_reload = true;
- spec->dsp_state = DSP_DOWNLOAD_INIT;
- } else {
- if (ca0132_quirk(spec) == QUIRK_SBZ)
- sbz_dsp_startup_check(codec);
- return 0;
- }
- }
-
- if (spec->dsp_state != DSP_DOWNLOAD_FAILED)
- spec->dsp_state = DSP_DOWNLOAD_INIT;
- spec->curr_chip_addx = INVALID_CHIP_ADDRESS;
-
- if (ca0132_use_pci_mmio(spec))
- ca0132_mmio_init(codec);
-
- snd_hda_power_up_pm(codec);
-
- if (ca0132_quirk(spec) == QUIRK_AE5 || ca0132_quirk(spec) == QUIRK_AE7)
- ae5_register_set(codec);
-
- ca0132_init_params(codec);
- ca0132_init_flags(codec);
-
- snd_hda_sequence_write(codec, spec->base_init_verbs);
-
- if (ca0132_use_alt_functions(spec))
- ca0132_alt_init(codec);
-
- ca0132_download_dsp(codec);
-
- ca0132_refresh_widget_caps(codec);
-
- switch (ca0132_quirk(spec)) {
- case QUIRK_R3DI:
- case QUIRK_R3D:
- r3d_setup_defaults(codec);
- break;
- case QUIRK_SBZ:
- case QUIRK_ZXR:
- sbz_setup_defaults(codec);
- break;
- case QUIRK_AE5:
- ae5_setup_defaults(codec);
- break;
- case QUIRK_AE7:
- ae7_setup_defaults(codec);
- break;
- default:
- ca0132_setup_defaults(codec);
- ca0132_init_analog_mic2(codec);
- ca0132_init_dmic(codec);
- break;
- }
-
- for (i = 0; i < spec->num_outputs; i++)
- init_output(codec, spec->out_pins[i], spec->dacs[0]);
-
- init_output(codec, cfg->dig_out_pins[0], spec->dig_out);
-
- for (i = 0; i < spec->num_inputs; i++)
- init_input(codec, spec->input_pins[i], spec->adcs[i]);
-
- init_input(codec, cfg->dig_in_pin, spec->dig_in);
-
- if (!ca0132_use_alt_functions(spec)) {
- snd_hda_sequence_write(codec, spec->chip_init_verbs);
- snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
- VENDOR_CHIPIO_PARAM_EX_ID_SET, 0x0D);
- snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
- VENDOR_CHIPIO_PARAM_EX_VALUE_SET, 0x20);
- }
-
- if (ca0132_quirk(spec) == QUIRK_SBZ)
- ca0132_gpio_setup(codec);
-
- snd_hda_sequence_write(codec, spec->spec_init_verbs);
- if (ca0132_use_alt_functions(spec)) {
- ca0132_alt_select_out(codec);
- ca0132_alt_select_in(codec);
- } else {
- ca0132_select_out(codec);
- ca0132_select_mic(codec);
- }
-
- snd_hda_jack_report_sync(codec);
-
- /*
- * Re set the PlayEnhancement switch on a resume event, because the
- * controls will not be reloaded.
- */
- if (spec->dsp_reload) {
- spec->dsp_reload = false;
- ca0132_pe_switch_set(codec);
- }
-
- snd_hda_power_down_pm(codec);
-
- return 0;
-}
-
-static int dbpro_init(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->autocfg;
- unsigned int i;
-
- init_output(codec, cfg->dig_out_pins[0], spec->dig_out);
- init_input(codec, cfg->dig_in_pin, spec->dig_in);
-
- for (i = 0; i < spec->num_inputs; i++)
- init_input(codec, spec->input_pins[i], spec->adcs[i]);
-
- return 0;
-}
-
-static void ca0132_free(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
-
- cancel_delayed_work_sync(&spec->unsol_hp_work);
- snd_hda_power_up(codec);
- switch (ca0132_quirk(spec)) {
- case QUIRK_SBZ:
- sbz_exit_chip(codec);
- break;
- case QUIRK_ZXR:
- zxr_exit_chip(codec);
- break;
- case QUIRK_R3D:
- r3d_exit_chip(codec);
- break;
- case QUIRK_AE5:
- ae5_exit_chip(codec);
- break;
- case QUIRK_AE7:
- ae7_exit_chip(codec);
- break;
- case QUIRK_R3DI:
- r3di_gpio_shutdown(codec);
- break;
- default:
- break;
- }
-
- snd_hda_sequence_write(codec, spec->base_exit_verbs);
- ca0132_exit_chip(codec);
-
- snd_hda_power_down(codec);
-#ifdef CONFIG_PCI
- if (spec->mem_base)
- pci_iounmap(codec->bus->pci, spec->mem_base);
-#endif
- kfree(spec->spec_init_verbs);
- kfree(codec->spec);
-}
-
-static void dbpro_free(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
-
- zxr_dbpro_power_state_shutdown(codec);
-
- kfree(spec->spec_init_verbs);
- kfree(codec->spec);
-}
-
-static int ca0132_suspend(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
-
- cancel_delayed_work_sync(&spec->unsol_hp_work);
- return 0;
-}
-
-static const struct hda_codec_ops ca0132_patch_ops = {
- .build_controls = ca0132_build_controls,
- .build_pcms = ca0132_build_pcms,
- .init = ca0132_init,
- .free = ca0132_free,
- .unsol_event = snd_hda_jack_unsol_event,
- .suspend = ca0132_suspend,
-};
-
-static const struct hda_codec_ops dbpro_patch_ops = {
- .build_controls = dbpro_build_controls,
- .build_pcms = dbpro_build_pcms,
- .init = dbpro_init,
- .free = dbpro_free,
-};
-
-static void ca0132_config(struct hda_codec *codec)
-{
- struct ca0132_spec *spec = codec->spec;
-
- spec->dacs[0] = 0x2;
- spec->dacs[1] = 0x3;
- spec->dacs[2] = 0x4;
-
- spec->multiout.dac_nids = spec->dacs;
- spec->multiout.num_dacs = 3;
-
- if (!ca0132_use_alt_functions(spec))
- spec->multiout.max_channels = 2;
- else
- spec->multiout.max_channels = 6;
-
- switch (ca0132_quirk(spec)) {
- case QUIRK_ALIENWARE:
- codec_dbg(codec, "%s: QUIRK_ALIENWARE applied.\n", __func__);
- snd_hda_apply_pincfgs(codec, alienware_pincfgs);
- break;
- case QUIRK_SBZ:
- codec_dbg(codec, "%s: QUIRK_SBZ applied.\n", __func__);
- snd_hda_apply_pincfgs(codec, sbz_pincfgs);
- break;
- case QUIRK_ZXR:
- codec_dbg(codec, "%s: QUIRK_ZXR applied.\n", __func__);
- snd_hda_apply_pincfgs(codec, zxr_pincfgs);
- break;
- case QUIRK_R3D:
- codec_dbg(codec, "%s: QUIRK_R3D applied.\n", __func__);
- snd_hda_apply_pincfgs(codec, r3d_pincfgs);
- break;
- case QUIRK_R3DI:
- codec_dbg(codec, "%s: QUIRK_R3DI applied.\n", __func__);
- snd_hda_apply_pincfgs(codec, r3di_pincfgs);
- break;
- case QUIRK_AE5:
- codec_dbg(codec, "%s: QUIRK_AE5 applied.\n", __func__);
- snd_hda_apply_pincfgs(codec, ae5_pincfgs);
- break;
- case QUIRK_AE7:
- codec_dbg(codec, "%s: QUIRK_AE7 applied.\n", __func__);
- snd_hda_apply_pincfgs(codec, ae7_pincfgs);
- break;
- default:
- break;
- }
-
- switch (ca0132_quirk(spec)) {
- case QUIRK_ALIENWARE:
- spec->num_outputs = 2;
- spec->out_pins[0] = 0x0b; /* speaker out */
- spec->out_pins[1] = 0x0f;
- spec->shared_out_nid = 0x2;
- spec->unsol_tag_hp = 0x0f;
-
- spec->adcs[0] = 0x7; /* digital mic / analog mic1 */
- spec->adcs[1] = 0x8; /* analog mic2 */
- spec->adcs[2] = 0xa; /* what u hear */
-
- 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 = 0x11;
- break;
- case QUIRK_SBZ:
- case QUIRK_R3D:
- spec->num_outputs = 2;
- spec->out_pins[0] = 0x0B; /* Line out */
- spec->out_pins[1] = 0x0F; /* Rear headphone out */
- spec->out_pins[2] = 0x10; /* Front Headphone / Center/LFE*/
- spec->out_pins[3] = 0x11; /* Rear surround */
- spec->shared_out_nid = 0x2;
- spec->unsol_tag_hp = spec->out_pins[1];
- spec->unsol_tag_front_hp = spec->out_pins[2];
-
- spec->adcs[0] = 0x7; /* Rear Mic / Line-in */
- spec->adcs[1] = 0x8; /* Front Mic, but only if no DSP */
- spec->adcs[2] = 0xa; /* what u hear */
-
- spec->num_inputs = 2;
- spec->input_pins[0] = 0x12; /* Rear Mic / Line-in */
- spec->input_pins[1] = 0x13; /* What U Hear */
- spec->shared_mic_nid = 0x7;
- spec->unsol_tag_amic1 = spec->input_pins[0];
-
- /* SPDIF I/O */
- spec->dig_out = 0x05;
- spec->multiout.dig_out_nid = spec->dig_out;
- spec->dig_in = 0x09;
- break;
- case QUIRK_ZXR:
- spec->num_outputs = 2;
- spec->out_pins[0] = 0x0B; /* Line out */
- spec->out_pins[1] = 0x0F; /* Rear headphone out */
- spec->out_pins[2] = 0x10; /* Center/LFE */
- spec->out_pins[3] = 0x11; /* Rear surround */
- spec->shared_out_nid = 0x2;
- spec->unsol_tag_hp = spec->out_pins[1];
- spec->unsol_tag_front_hp = spec->out_pins[2];
-
- spec->adcs[0] = 0x7; /* Rear Mic / Line-in */
- spec->adcs[1] = 0x8; /* Not connected, no front mic */
- spec->adcs[2] = 0xa; /* what u hear */
-
- spec->num_inputs = 2;
- spec->input_pins[0] = 0x12; /* Rear Mic / Line-in */
- spec->input_pins[1] = 0x13; /* What U Hear */
- spec->shared_mic_nid = 0x7;
- spec->unsol_tag_amic1 = spec->input_pins[0];
- break;
- case QUIRK_ZXR_DBPRO:
- spec->adcs[0] = 0x8; /* ZxR DBPro Aux In */
-
- spec->num_inputs = 1;
- spec->input_pins[0] = 0x11; /* RCA Line-in */
-
- spec->dig_out = 0x05;
- spec->multiout.dig_out_nid = spec->dig_out;
-
- spec->dig_in = 0x09;
- break;
- case QUIRK_AE5:
- case QUIRK_AE7:
- spec->num_outputs = 2;
- spec->out_pins[0] = 0x0B; /* Line out */
- spec->out_pins[1] = 0x11; /* Rear headphone out */
- spec->out_pins[2] = 0x10; /* Front Headphone / Center/LFE*/
- spec->out_pins[3] = 0x0F; /* Rear surround */
- spec->shared_out_nid = 0x2;
- spec->unsol_tag_hp = spec->out_pins[1];
- spec->unsol_tag_front_hp = spec->out_pins[2];
-
- spec->adcs[0] = 0x7; /* Rear Mic / Line-in */
- spec->adcs[1] = 0x8; /* Front Mic, but only if no DSP */
- spec->adcs[2] = 0xa; /* what u hear */
-
- spec->num_inputs = 2;
- spec->input_pins[0] = 0x12; /* Rear Mic / Line-in */
- spec->input_pins[1] = 0x13; /* What U Hear */
- spec->shared_mic_nid = 0x7;
- spec->unsol_tag_amic1 = spec->input_pins[0];
-
- /* SPDIF I/O */
- spec->dig_out = 0x05;
- spec->multiout.dig_out_nid = spec->dig_out;
- break;
- case QUIRK_R3DI:
- spec->num_outputs = 2;
- spec->out_pins[0] = 0x0B; /* Line out */
- spec->out_pins[1] = 0x0F; /* Rear headphone out */
- spec->out_pins[2] = 0x10; /* Front Headphone / Center/LFE*/
- spec->out_pins[3] = 0x11; /* Rear surround */
- spec->shared_out_nid = 0x2;
- spec->unsol_tag_hp = spec->out_pins[1];
- spec->unsol_tag_front_hp = spec->out_pins[2];
-
- spec->adcs[0] = 0x07; /* Rear Mic / Line-in */
- spec->adcs[1] = 0x08; /* Front Mic, but only if no DSP */
- spec->adcs[2] = 0x0a; /* what u hear */
-
- spec->num_inputs = 2;
- spec->input_pins[0] = 0x12; /* Rear Mic / Line-in */
- spec->input_pins[1] = 0x13; /* What U Hear */
- spec->shared_mic_nid = 0x7;
- spec->unsol_tag_amic1 = spec->input_pins[0];
-
- /* SPDIF I/O */
- spec->dig_out = 0x05;
- spec->multiout.dig_out_nid = spec->dig_out;
- break;
- default:
- spec->num_outputs = 2;
- spec->out_pins[0] = 0x0b; /* speaker out */
- spec->out_pins[1] = 0x10; /* headphone out */
- spec->shared_out_nid = 0x2;
- spec->unsol_tag_hp = spec->out_pins[1];
-
- spec->adcs[0] = 0x7; /* digital mic / analog mic1 */
- spec->adcs[1] = 0x8; /* analog mic2 */
- spec->adcs[2] = 0xa; /* what u hear */
-
- 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;
- spec->multiout.dig_out_nid = spec->dig_out;
- spec->dig_in = 0x09;
- break;
- }
-}
-
-static int ca0132_prepare_verbs(struct hda_codec *codec)
-{
-/* Verbs + terminator (an empty element) */
-#define NUM_SPEC_VERBS 2
- struct ca0132_spec *spec = codec->spec;
-
- spec->chip_init_verbs = ca0132_init_verbs0;
- /*
- * Since desktop cards use pci_mmio, this can be used to determine
- * whether or not to use these verbs instead of a separate bool.
- */
- if (ca0132_use_pci_mmio(spec))
- spec->desktop_init_verbs = ca0132_init_verbs1;
- spec->spec_init_verbs = kcalloc(NUM_SPEC_VERBS,
- sizeof(struct hda_verb),
- GFP_KERNEL);
- if (!spec->spec_init_verbs)
- return -ENOMEM;
-
- /* config EAPD */
- spec->spec_init_verbs[0].nid = 0x0b;
- spec->spec_init_verbs[0].param = 0x78D;
- spec->spec_init_verbs[0].verb = 0x00;
-
- /* Previously commented configuration */
- /*
- spec->spec_init_verbs[2].nid = 0x0b;
- spec->spec_init_verbs[2].param = AC_VERB_SET_EAPD_BTLENABLE;
- spec->spec_init_verbs[2].verb = 0x02;
-
- spec->spec_init_verbs[3].nid = 0x10;
- spec->spec_init_verbs[3].param = 0x78D;
- spec->spec_init_verbs[3].verb = 0x02;
-
- spec->spec_init_verbs[4].nid = 0x10;
- spec->spec_init_verbs[4].param = AC_VERB_SET_EAPD_BTLENABLE;
- spec->spec_init_verbs[4].verb = 0x02;
- */
-
- /* Terminator: spec->spec_init_verbs[NUM_SPEC_VERBS-1] */
- return 0;
-}
-
-/*
- * The Sound Blaster ZxR shares the same PCI subsystem ID as some regular
- * Sound Blaster Z cards. However, they have different HDA codec subsystem
- * ID's. So, we check for the ZxR's subsystem ID, as well as the DBPro
- * daughter boards ID.
- */
-static void sbz_detect_quirk(struct hda_codec *codec)
-{
- switch (codec->core.subsystem_id) {
- case 0x11020033:
- codec->fixup_id = QUIRK_ZXR;
- break;
- case 0x1102003f:
- codec->fixup_id = QUIRK_ZXR_DBPRO;
- break;
- default:
- codec->fixup_id = QUIRK_SBZ;
- break;
- }
-}
-
-static int patch_ca0132(struct hda_codec *codec)
-{
- struct ca0132_spec *spec;
- int err;
-
- codec_dbg(codec, "patch_ca0132\n");
-
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (!spec)
- return -ENOMEM;
- 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);
-
- if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO)
- codec->patch_ops = dbpro_patch_ops;
- else
- codec->patch_ops = ca0132_patch_ops;
-
- codec->pcm_format_first = 1;
- codec->no_sticky_stream = 1;
-
-
- spec->dsp_state = DSP_DOWNLOAD_INIT;
- spec->num_mixers = 1;
-
- /* Set which mixers each quirk uses. */
- switch (ca0132_quirk(spec)) {
- case QUIRK_SBZ:
- spec->mixers[0] = desktop_mixer;
- snd_hda_codec_set_name(codec, "Sound Blaster Z");
- break;
- case QUIRK_ZXR:
- spec->mixers[0] = desktop_mixer;
- snd_hda_codec_set_name(codec, "Sound Blaster ZxR");
- break;
- case QUIRK_ZXR_DBPRO:
- break;
- case QUIRK_R3D:
- spec->mixers[0] = desktop_mixer;
- snd_hda_codec_set_name(codec, "Recon3D");
- break;
- case QUIRK_R3DI:
- spec->mixers[0] = r3di_mixer;
- snd_hda_codec_set_name(codec, "Recon3Di");
- break;
- case QUIRK_AE5:
- spec->mixers[0] = desktop_mixer;
- snd_hda_codec_set_name(codec, "Sound BlasterX AE-5");
- break;
- case QUIRK_AE7:
- spec->mixers[0] = desktop_mixer;
- snd_hda_codec_set_name(codec, "Sound Blaster AE-7");
- break;
- default:
- spec->mixers[0] = ca0132_mixer;
- break;
- }
-
- /* Setup whether or not to use alt functions/controls/pci_mmio */
- switch (ca0132_quirk(spec)) {
- case QUIRK_SBZ:
- case QUIRK_R3D:
- case QUIRK_AE5:
- case QUIRK_AE7:
- case QUIRK_ZXR:
- spec->use_alt_controls = true;
- spec->use_alt_functions = true;
- spec->use_pci_mmio = true;
- break;
- case QUIRK_R3DI:
- spec->use_alt_controls = true;
- spec->use_alt_functions = true;
- spec->use_pci_mmio = false;
- break;
- default:
- spec->use_alt_controls = false;
- spec->use_alt_functions = false;
- spec->use_pci_mmio = false;
- break;
- }
-
-#ifdef CONFIG_PCI
- if (spec->use_pci_mmio) {
- spec->mem_base = pci_iomap(codec->bus->pci, 2, 0xC20);
- if (spec->mem_base == NULL) {
- codec_warn(codec, "pci_iomap failed! Setting quirk to QUIRK_NONE.");
- codec->fixup_id = QUIRK_NONE;
- }
- }
-#endif
-
- spec->base_init_verbs = ca0132_base_init_verbs;
- spec->base_exit_verbs = ca0132_base_exit_verbs;
-
- INIT_DELAYED_WORK(&spec->unsol_hp_work, ca0132_unsol_hp_delayed);
-
- ca0132_init_chip(codec);
-
- ca0132_config(codec);
-
- err = ca0132_prepare_verbs(codec);
- if (err < 0)
- goto error;
-
- err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
- if (err < 0)
- goto error;
-
- ca0132_setup_unsol(codec);
-
- return 0;
-
- error:
- ca0132_free(codec);
- return err;
-}
-
-/*
- * patch entries
- */
-static const struct hda_device_id snd_hda_id_ca0132[] = {
- HDA_CODEC_ENTRY(0x11020011, "CA0132", patch_ca0132),
- {} /* terminator */
-};
-MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_ca0132);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Creative Sound Core3D codec");
-
-static struct hda_codec_driver ca0132_driver = {
- .id = snd_hda_id_ca0132,
-};
-
-module_hda_codec_driver(ca0132_driver);
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c
deleted file mode 100644
index 06e046214a41..000000000000
--- a/sound/pci/hda/patch_cirrus.c
+++ /dev/null
@@ -1,1243 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * HD audio interface patch for Cirrus Logic CS420x chip
- *
- * Copyright (c) 2009 Takashi Iwai <tiwai@suse.de>
- */
-
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <sound/core.h>
-#include <linux/pci.h>
-#include <sound/tlv.h>
-#include <sound/hda_codec.h>
-#include "hda_local.h"
-#include "hda_auto_parser.h"
-#include "hda_jack.h"
-#include "hda_generic.h"
-
-/*
- */
-
-struct cs_spec {
- struct hda_gen_spec gen;
-
- unsigned int gpio_mask;
- unsigned int gpio_dir;
- unsigned int gpio_data;
- unsigned int gpio_eapd_hp; /* EAPD GPIO bit for headphones */
- unsigned int gpio_eapd_speaker; /* EAPD GPIO bit for speakers */
-
- /* CS421x */
- unsigned int spdif_detect:1;
- unsigned int spdif_present:1;
- unsigned int sense_b:1;
- hda_nid_t vendor_nid;
-
- /* for MBP SPDIF control */
- int (*spdif_sw_put)(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol);
-};
-
-/* available models with CS420x */
-enum {
- CS420X_MBP53,
- CS420X_MBP55,
- CS420X_IMAC27,
- CS420X_GPIO_13,
- CS420X_GPIO_23,
- CS420X_MBP101,
- CS420X_MBP81,
- CS420X_MBA42,
- CS420X_AUTO,
- /* aliases */
- CS420X_IMAC27_122 = CS420X_GPIO_23,
- CS420X_APPLE = CS420X_GPIO_13,
-};
-
-/* CS421x boards */
-enum {
- CS421X_CDB4210,
- CS421X_SENSE_B,
- CS421X_STUMPY,
-};
-
-/* Vendor-specific processing widget */
-#define CS420X_VENDOR_NID 0x11
-#define CS_DIG_OUT1_PIN_NID 0x10
-#define CS_DIG_OUT2_PIN_NID 0x15
-#define CS_DMIC1_PIN_NID 0x0e
-#define CS_DMIC2_PIN_NID 0x12
-
-/* coef indices */
-#define IDX_SPDIF_STAT 0x0000
-#define IDX_SPDIF_CTL 0x0001
-#define IDX_ADC_CFG 0x0002
-/* SZC bitmask, 4 modes below:
- * 0 = immediate,
- * 1 = digital immediate, analog zero-cross
- * 2 = digtail & analog soft-ramp
- * 3 = digital soft-ramp, analog zero-cross
- */
-#define CS_COEF_ADC_SZC_MASK (3 << 0)
-#define CS_COEF_ADC_MIC_SZC_MODE (3 << 0) /* SZC setup for mic */
-#define CS_COEF_ADC_LI_SZC_MODE (3 << 0) /* SZC setup for line-in */
-/* PGA mode: 0 = differential, 1 = signle-ended */
-#define CS_COEF_ADC_MIC_PGA_MODE (1 << 5) /* PGA setup for mic */
-#define CS_COEF_ADC_LI_PGA_MODE (1 << 6) /* PGA setup for line-in */
-#define IDX_DAC_CFG 0x0003
-/* SZC bitmask, 4 modes below:
- * 0 = Immediate
- * 1 = zero-cross
- * 2 = soft-ramp
- * 3 = soft-ramp on zero-cross
- */
-#define CS_COEF_DAC_HP_SZC_MODE (3 << 0) /* nid 0x02 */
-#define CS_COEF_DAC_LO_SZC_MODE (3 << 2) /* nid 0x03 */
-#define CS_COEF_DAC_SPK_SZC_MODE (3 << 4) /* nid 0x04 */
-
-#define IDX_BEEP_CFG 0x0004
-/* 0x0008 - test reg key */
-/* 0x0009 - 0x0014 -> 12 test regs */
-/* 0x0015 - visibility reg */
-
-/* Cirrus Logic CS4208 */
-#define CS4208_VENDOR_NID 0x24
-
-/*
- * Cirrus Logic CS4210
- *
- * 1 DAC => HP(sense) / Speakers,
- * 1 ADC <= LineIn(sense) / MicIn / DMicIn,
- * 1 SPDIF OUT => SPDIF Trasmitter(sense)
- */
-#define CS4210_DAC_NID 0x02
-#define CS4210_ADC_NID 0x03
-#define CS4210_VENDOR_NID 0x0B
-#define CS421X_DMIC_PIN_NID 0x09 /* Port E */
-#define CS421X_SPDIF_PIN_NID 0x0A /* Port H */
-
-#define CS421X_IDX_DEV_CFG 0x01
-#define CS421X_IDX_ADC_CFG 0x02
-#define CS421X_IDX_DAC_CFG 0x03
-#define CS421X_IDX_SPK_CTL 0x04
-
-/* Cirrus Logic CS4213 is like CS4210 but does not have SPDIF input/output */
-#define CS4213_VENDOR_NID 0x09
-
-
-static inline int cs_vendor_coef_get(struct hda_codec *codec, unsigned int idx)
-{
- struct cs_spec *spec = codec->spec;
-
- snd_hda_codec_write(codec, spec->vendor_nid, 0,
- AC_VERB_SET_COEF_INDEX, idx);
- return snd_hda_codec_read(codec, spec->vendor_nid, 0,
- AC_VERB_GET_PROC_COEF, 0);
-}
-
-static inline void cs_vendor_coef_set(struct hda_codec *codec, unsigned int idx,
- unsigned int coef)
-{
- struct cs_spec *spec = codec->spec;
-
- snd_hda_codec_write(codec, spec->vendor_nid, 0,
- AC_VERB_SET_COEF_INDEX, idx);
- snd_hda_codec_write(codec, spec->vendor_nid, 0,
- AC_VERB_SET_PROC_COEF, coef);
-}
-
-/*
- * auto-mute and auto-mic switching
- * CS421x auto-output redirecting
- * HP/SPK/SPDIF
- */
-
-static void cs_automute(struct hda_codec *codec)
-{
- struct cs_spec *spec = codec->spec;
-
- /* mute HPs if spdif jack (SENSE_B) is present */
- spec->gen.master_mute = !!(spec->spdif_present && spec->sense_b);
-
- snd_hda_gen_update_outputs(codec);
-
- if (spec->gpio_eapd_hp || spec->gpio_eapd_speaker) {
- if (spec->gen.automute_speaker)
- spec->gpio_data = spec->gen.hp_jack_present ?
- spec->gpio_eapd_hp : spec->gpio_eapd_speaker;
- else
- spec->gpio_data =
- spec->gpio_eapd_hp | spec->gpio_eapd_speaker;
- snd_hda_codec_write(codec, 0x01, 0,
- AC_VERB_SET_GPIO_DATA, spec->gpio_data);
- }
-}
-
-static bool is_active_pin(struct hda_codec *codec, hda_nid_t nid)
-{
- unsigned int val;
-
- val = snd_hda_codec_get_pincfg(codec, nid);
- return (get_defcfg_connect(val) != AC_JACK_PORT_NONE);
-}
-
-static void init_input_coef(struct hda_codec *codec)
-{
- struct cs_spec *spec = codec->spec;
- unsigned int coef;
-
- /* CS420x has multiple ADC, CS421x has single ADC */
- if (spec->vendor_nid == CS420X_VENDOR_NID) {
- coef = cs_vendor_coef_get(codec, IDX_BEEP_CFG);
- if (is_active_pin(codec, CS_DMIC2_PIN_NID))
- coef |= 1 << 4; /* DMIC2 2 chan on, GPIO1 off */
- if (is_active_pin(codec, CS_DMIC1_PIN_NID))
- coef |= 1 << 3; /* DMIC1 2 chan on, GPIO0 off
- * No effect if SPDIF_OUT2 is
- * selected in IDX_SPDIF_CTL.
- */
-
- cs_vendor_coef_set(codec, IDX_BEEP_CFG, coef);
- }
-}
-
-static const struct hda_verb cs_coef_init_verbs[] = {
- {0x11, AC_VERB_SET_PROC_STATE, 1},
- {0x11, AC_VERB_SET_COEF_INDEX, IDX_DAC_CFG},
- {0x11, AC_VERB_SET_PROC_COEF,
- (0x002a /* DAC1/2/3 SZCMode Soft Ramp */
- | 0x0040 /* Mute DACs on FIFO error */
- | 0x1000 /* Enable DACs High Pass Filter */
- | 0x0400 /* Disable Coefficient Auto increment */
- )},
- /* ADC1/2 - Digital and Analog Soft Ramp */
- {0x11, AC_VERB_SET_COEF_INDEX, IDX_ADC_CFG},
- {0x11, AC_VERB_SET_PROC_COEF, 0x000a},
- /* Beep */
- {0x11, AC_VERB_SET_COEF_INDEX, IDX_BEEP_CFG},
- {0x11, AC_VERB_SET_PROC_COEF, 0x0007}, /* Enable Beep thru DAC1/2/3 */
-
- {} /* terminator */
-};
-
-static const struct hda_verb cs4208_coef_init_verbs[] = {
- {0x01, AC_VERB_SET_POWER_STATE, 0x00}, /* AFG: D0 */
- {0x24, AC_VERB_SET_PROC_STATE, 0x01}, /* VPW: processing on */
- {0x24, AC_VERB_SET_COEF_INDEX, 0x0033},
- {0x24, AC_VERB_SET_PROC_COEF, 0x0001}, /* A1 ICS */
- {0x24, AC_VERB_SET_COEF_INDEX, 0x0034},
- {0x24, AC_VERB_SET_PROC_COEF, 0x1C01}, /* A1 Enable, A Thresh = 300mV */
- {} /* terminator */
-};
-
-/* Errata: CS4207 rev C0/C1/C2 Silicon
- *
- * http://www.cirrus.com/en/pubs/errata/ER880C3.pdf
- *
- * 6. At high temperature (TA > +85°C), the digital supply current (IVD)
- * may be excessive (up to an additional 200 μA), which is most easily
- * observed while the part is being held in reset (RESET# active low).
- *
- * Root Cause: At initial powerup of the device, the logic that drives
- * the clock and write enable to the S/PDIF SRC RAMs is not properly
- * initialized.
- * Certain random patterns will cause a steady leakage current in those
- * RAM cells. The issue will resolve once the SRCs are used (turned on).
- *
- * Workaround: The following verb sequence briefly turns on the S/PDIF SRC
- * blocks, which will alleviate the issue.
- */
-
-static const struct hda_verb cs_errata_init_verbs[] = {
- {0x01, AC_VERB_SET_POWER_STATE, 0x00}, /* AFG: D0 */
- {0x11, AC_VERB_SET_PROC_STATE, 0x01}, /* VPW: processing on */
-
- {0x11, AC_VERB_SET_COEF_INDEX, 0x0008},
- {0x11, AC_VERB_SET_PROC_COEF, 0x9999},
- {0x11, AC_VERB_SET_COEF_INDEX, 0x0017},
- {0x11, AC_VERB_SET_PROC_COEF, 0xa412},
- {0x11, AC_VERB_SET_COEF_INDEX, 0x0001},
- {0x11, AC_VERB_SET_PROC_COEF, 0x0009},
-
- {0x07, AC_VERB_SET_POWER_STATE, 0x00}, /* S/PDIF Rx: D0 */
- {0x08, AC_VERB_SET_POWER_STATE, 0x00}, /* S/PDIF Tx: D0 */
-
- {0x11, AC_VERB_SET_COEF_INDEX, 0x0017},
- {0x11, AC_VERB_SET_PROC_COEF, 0x2412},
- {0x11, AC_VERB_SET_COEF_INDEX, 0x0008},
- {0x11, AC_VERB_SET_PROC_COEF, 0x0000},
- {0x11, AC_VERB_SET_COEF_INDEX, 0x0001},
- {0x11, AC_VERB_SET_PROC_COEF, 0x0008},
- {0x11, AC_VERB_SET_PROC_STATE, 0x00},
- {} /* terminator */
-};
-
-/* SPDIF setup */
-static void init_digital_coef(struct hda_codec *codec)
-{
- unsigned int coef;
-
- coef = 0x0002; /* SRC_MUTE soft-mute on SPDIF (if no lock) */
- coef |= 0x0008; /* Replace with mute on error */
- if (is_active_pin(codec, CS_DIG_OUT2_PIN_NID))
- coef |= 0x4000; /* RX to TX1 or TX2 Loopthru / SPDIF2
- * SPDIF_OUT2 is shared with GPIO1 and
- * DMIC_SDA2.
- */
- cs_vendor_coef_set(codec, IDX_SPDIF_CTL, coef);
-}
-
-static int cs_init(struct hda_codec *codec)
-{
- struct cs_spec *spec = codec->spec;
-
- if (spec->vendor_nid == CS420X_VENDOR_NID) {
- /* init_verb sequence for C0/C1/C2 errata*/
- snd_hda_sequence_write(codec, cs_errata_init_verbs);
- snd_hda_sequence_write(codec, cs_coef_init_verbs);
- } else if (spec->vendor_nid == CS4208_VENDOR_NID) {
- snd_hda_sequence_write(codec, cs4208_coef_init_verbs);
- }
-
- snd_hda_gen_init(codec);
-
- if (spec->gpio_mask) {
- snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_MASK,
- spec->gpio_mask);
- snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DIRECTION,
- spec->gpio_dir);
- snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
- spec->gpio_data);
- }
-
- if (spec->vendor_nid == CS420X_VENDOR_NID) {
- init_input_coef(codec);
- init_digital_coef(codec);
- }
-
- return 0;
-}
-
-static int cs_build_controls(struct hda_codec *codec)
-{
- int err;
-
- err = snd_hda_gen_build_controls(codec);
- if (err < 0)
- return err;
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_BUILD);
- return 0;
-}
-
-#define cs_free snd_hda_gen_free
-
-static const struct hda_codec_ops cs_patch_ops = {
- .build_controls = cs_build_controls,
- .build_pcms = snd_hda_gen_build_pcms,
- .init = cs_init,
- .free = cs_free,
- .unsol_event = snd_hda_jack_unsol_event,
-};
-
-static int cs_parse_auto_config(struct hda_codec *codec)
-{
- struct cs_spec *spec = codec->spec;
- int err;
- int i;
-
- err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0);
- if (err < 0)
- return err;
-
- err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg);
- if (err < 0)
- return err;
-
- /* keep the ADCs powered up when it's dynamically switchable */
- if (spec->gen.dyn_adc_switch) {
- unsigned int done = 0;
-
- for (i = 0; i < spec->gen.input_mux.num_items; i++) {
- int idx = spec->gen.dyn_adc_idx[i];
-
- if (done & (1 << idx))
- continue;
- snd_hda_gen_fix_pin_power(codec,
- spec->gen.adc_nids[idx]);
- done |= 1 << idx;
- }
- }
-
- return 0;
-}
-
-static const struct hda_model_fixup cs420x_models[] = {
- { .id = CS420X_MBP53, .name = "mbp53" },
- { .id = CS420X_MBP55, .name = "mbp55" },
- { .id = CS420X_IMAC27, .name = "imac27" },
- { .id = CS420X_IMAC27_122, .name = "imac27_122" },
- { .id = CS420X_APPLE, .name = "apple" },
- { .id = CS420X_MBP101, .name = "mbp101" },
- { .id = CS420X_MBP81, .name = "mbp81" },
- { .id = CS420X_MBA42, .name = "mba42" },
- {}
-};
-
-static const struct hda_quirk cs420x_fixup_tbl[] = {
- SND_PCI_QUIRK(0x10de, 0x0ac0, "MacBookPro 5,3", CS420X_MBP53),
- SND_PCI_QUIRK(0x10de, 0x0d94, "MacBookAir 3,1(2)", CS420X_MBP55),
- SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55),
- SND_PCI_QUIRK(0x10de, 0xcb89, "MacBookPro 7,1", CS420X_MBP55),
- /* this conflicts with too many other models */
- /*SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27),*/
-
- /* codec SSID */
- SND_PCI_QUIRK(0x106b, 0x0600, "iMac 14,1", CS420X_IMAC27_122),
- SND_PCI_QUIRK(0x106b, 0x0900, "iMac 12,1", CS420X_IMAC27_122),
- SND_PCI_QUIRK(0x106b, 0x1c00, "MacBookPro 8,1", CS420X_MBP81),
- SND_PCI_QUIRK(0x106b, 0x2000, "iMac 12,2", CS420X_IMAC27_122),
- SND_PCI_QUIRK(0x106b, 0x2800, "MacBookPro 10,1", CS420X_MBP101),
- SND_PCI_QUIRK(0x106b, 0x5600, "MacBookAir 5,2", CS420X_MBP81),
- SND_PCI_QUIRK(0x106b, 0x5b00, "MacBookAir 4,2", CS420X_MBA42),
- SND_PCI_QUIRK_VENDOR(0x106b, "Apple", CS420X_APPLE),
- {} /* terminator */
-};
-
-static const struct hda_pintbl mbp53_pincfgs[] = {
- { 0x09, 0x012b4050 },
- { 0x0a, 0x90100141 },
- { 0x0b, 0x90100140 },
- { 0x0c, 0x018b3020 },
- { 0x0d, 0x90a00110 },
- { 0x0e, 0x400000f0 },
- { 0x0f, 0x01cbe030 },
- { 0x10, 0x014be060 },
- { 0x12, 0x400000f0 },
- { 0x15, 0x400000f0 },
- {} /* terminator */
-};
-
-static const struct hda_pintbl mbp55_pincfgs[] = {
- { 0x09, 0x012b4030 },
- { 0x0a, 0x90100121 },
- { 0x0b, 0x90100120 },
- { 0x0c, 0x400000f0 },
- { 0x0d, 0x90a00110 },
- { 0x0e, 0x400000f0 },
- { 0x0f, 0x400000f0 },
- { 0x10, 0x014be040 },
- { 0x12, 0x400000f0 },
- { 0x15, 0x400000f0 },
- {} /* terminator */
-};
-
-static const struct hda_pintbl imac27_pincfgs[] = {
- { 0x09, 0x012b4050 },
- { 0x0a, 0x90100140 },
- { 0x0b, 0x90100142 },
- { 0x0c, 0x018b3020 },
- { 0x0d, 0x90a00110 },
- { 0x0e, 0x400000f0 },
- { 0x0f, 0x01cbe030 },
- { 0x10, 0x014be060 },
- { 0x12, 0x01ab9070 },
- { 0x15, 0x400000f0 },
- {} /* terminator */
-};
-
-static const struct hda_pintbl mbp101_pincfgs[] = {
- { 0x0d, 0x40ab90f0 },
- { 0x0e, 0x90a600f0 },
- { 0x12, 0x50a600f0 },
- {} /* terminator */
-};
-
-static const struct hda_pintbl mba42_pincfgs[] = {
- { 0x09, 0x012b4030 }, /* HP */
- { 0x0a, 0x400000f0 },
- { 0x0b, 0x90100120 }, /* speaker */
- { 0x0c, 0x400000f0 },
- { 0x0d, 0x90a00110 }, /* mic */
- { 0x0e, 0x400000f0 },
- { 0x0f, 0x400000f0 },
- { 0x10, 0x400000f0 },
- { 0x12, 0x400000f0 },
- { 0x15, 0x400000f0 },
- {} /* terminator */
-};
-
-static const struct hda_pintbl mba6_pincfgs[] = {
- { 0x10, 0x032120f0 }, /* HP */
- { 0x11, 0x500000f0 },
- { 0x12, 0x90100010 }, /* Speaker */
- { 0x13, 0x500000f0 },
- { 0x14, 0x500000f0 },
- { 0x15, 0x770000f0 },
- { 0x16, 0x770000f0 },
- { 0x17, 0x430000f0 },
- { 0x18, 0x43ab9030 }, /* Mic */
- { 0x19, 0x770000f0 },
- { 0x1a, 0x770000f0 },
- { 0x1b, 0x770000f0 },
- { 0x1c, 0x90a00090 },
- { 0x1d, 0x500000f0 },
- { 0x1e, 0x500000f0 },
- { 0x1f, 0x500000f0 },
- { 0x20, 0x500000f0 },
- { 0x21, 0x430000f0 },
- { 0x22, 0x430000f0 },
- {} /* terminator */
-};
-
-static void cs420x_fixup_gpio_13(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- struct cs_spec *spec = codec->spec;
-
- spec->gpio_eapd_hp = 2; /* GPIO1 = headphones */
- spec->gpio_eapd_speaker = 8; /* GPIO3 = speakers */
- spec->gpio_mask = spec->gpio_dir =
- spec->gpio_eapd_hp | spec->gpio_eapd_speaker;
- }
-}
-
-static void cs420x_fixup_gpio_23(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- struct cs_spec *spec = codec->spec;
-
- spec->gpio_eapd_hp = 4; /* GPIO2 = headphones */
- spec->gpio_eapd_speaker = 8; /* GPIO3 = speakers */
- spec->gpio_mask = spec->gpio_dir =
- spec->gpio_eapd_hp | spec->gpio_eapd_speaker;
- }
-}
-
-static const struct hda_fixup cs420x_fixups[] = {
- [CS420X_MBP53] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = mbp53_pincfgs,
- .chained = true,
- .chain_id = CS420X_APPLE,
- },
- [CS420X_MBP55] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = mbp55_pincfgs,
- .chained = true,
- .chain_id = CS420X_GPIO_13,
- },
- [CS420X_IMAC27] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = imac27_pincfgs,
- .chained = true,
- .chain_id = CS420X_GPIO_13,
- },
- [CS420X_GPIO_13] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cs420x_fixup_gpio_13,
- },
- [CS420X_GPIO_23] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cs420x_fixup_gpio_23,
- },
- [CS420X_MBP101] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = mbp101_pincfgs,
- .chained = true,
- .chain_id = CS420X_GPIO_13,
- },
- [CS420X_MBP81] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- /* internal mic ADC2: right only, single ended */
- {0x11, AC_VERB_SET_COEF_INDEX, IDX_ADC_CFG},
- {0x11, AC_VERB_SET_PROC_COEF, 0x102a},
- {}
- },
- .chained = true,
- .chain_id = CS420X_GPIO_13,
- },
- [CS420X_MBA42] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = mba42_pincfgs,
- .chained = true,
- .chain_id = CS420X_GPIO_13,
- },
-};
-
-static struct cs_spec *cs_alloc_spec(struct hda_codec *codec, int vendor_nid)
-{
- struct cs_spec *spec;
-
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (!spec)
- return NULL;
- codec->spec = spec;
- spec->vendor_nid = vendor_nid;
- codec->power_save_node = 1;
- snd_hda_gen_spec_init(&spec->gen);
-
- return spec;
-}
-
-static int patch_cs420x(struct hda_codec *codec)
-{
- struct cs_spec *spec;
- int err;
-
- spec = cs_alloc_spec(codec, CS420X_VENDOR_NID);
- if (!spec)
- return -ENOMEM;
-
- codec->patch_ops = cs_patch_ops;
- spec->gen.automute_hook = cs_automute;
- codec->single_adc_amp = 1;
-
- snd_hda_pick_fixup(codec, cs420x_models, cs420x_fixup_tbl,
- cs420x_fixups);
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
-
- err = cs_parse_auto_config(codec);
- if (err < 0)
- goto error;
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
-
- return 0;
-
- error:
- cs_free(codec);
- return err;
-}
-
-/*
- * CS4208 support:
- * Its layout is no longer compatible with CS4206/CS4207
- */
-enum {
- CS4208_MAC_AUTO,
- CS4208_MBA6,
- CS4208_MBP11,
- CS4208_MACMINI,
- CS4208_GPIO0,
-};
-
-static const struct hda_model_fixup cs4208_models[] = {
- { .id = CS4208_GPIO0, .name = "gpio0" },
- { .id = CS4208_MBA6, .name = "mba6" },
- { .id = CS4208_MBP11, .name = "mbp11" },
- { .id = CS4208_MACMINI, .name = "macmini" },
- {}
-};
-
-static const struct hda_quirk cs4208_fixup_tbl[] = {
- SND_PCI_QUIRK_VENDOR(0x106b, "Apple", CS4208_MAC_AUTO),
- {} /* terminator */
-};
-
-/* codec SSID matching */
-static const struct hda_quirk cs4208_mac_fixup_tbl[] = {
- SND_PCI_QUIRK(0x106b, 0x5e00, "MacBookPro 11,2", CS4208_MBP11),
- SND_PCI_QUIRK(0x106b, 0x6c00, "MacMini 7,1", CS4208_MACMINI),
- SND_PCI_QUIRK(0x106b, 0x7100, "MacBookAir 6,1", CS4208_MBA6),
- SND_PCI_QUIRK(0x106b, 0x7200, "MacBookAir 6,2", CS4208_MBA6),
- SND_PCI_QUIRK(0x106b, 0x7b00, "MacBookPro 12,1", CS4208_MBP11),
- {} /* terminator */
-};
-
-static void cs4208_fixup_gpio0(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- struct cs_spec *spec = codec->spec;
-
- spec->gpio_eapd_hp = 0;
- spec->gpio_eapd_speaker = 1;
- spec->gpio_mask = spec->gpio_dir =
- spec->gpio_eapd_hp | spec->gpio_eapd_speaker;
- }
-}
-
-static const struct hda_fixup cs4208_fixups[];
-
-/* remap the fixup from codec SSID and apply it */
-static void cs4208_fixup_mac(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action != HDA_FIXUP_ACT_PRE_PROBE)
- return;
-
- codec->fixup_id = HDA_FIXUP_ID_NOT_SET;
- snd_hda_pick_fixup(codec, NULL, cs4208_mac_fixup_tbl, cs4208_fixups);
- if (codec->fixup_id == HDA_FIXUP_ID_NOT_SET)
- codec->fixup_id = CS4208_GPIO0; /* default fixup */
- snd_hda_apply_fixup(codec, action);
-}
-
-/* MacMini 7,1 has the inverted jack detection */
-static void cs4208_fixup_macmini(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- static const struct hda_pintbl pincfgs[] = {
- { 0x18, 0x00ab9150 }, /* mic (audio-in) jack: disable detect */
- { 0x21, 0x004be140 }, /* SPDIF: disable detect */
- { }
- };
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- /* HP pin (0x10) has an inverted detection */
- codec->inv_jack_detect = 1;
- /* disable the bogus Mic and SPDIF jack detections */
- snd_hda_apply_pincfgs(codec, pincfgs);
- }
-}
-
-static int cs4208_spdif_sw_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct cs_spec *spec = codec->spec;
- hda_nid_t pin = spec->gen.autocfg.dig_out_pins[0];
- int pinctl = ucontrol->value.integer.value[0] ? PIN_OUT : 0;
-
- snd_hda_set_pin_ctl_cache(codec, pin, pinctl);
- return spec->spdif_sw_put(kcontrol, ucontrol);
-}
-
-/* hook the SPDIF switch */
-static void cs4208_fixup_spdif_switch(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_BUILD) {
- struct cs_spec *spec = codec->spec;
- struct snd_kcontrol *kctl;
-
- if (!spec->gen.autocfg.dig_out_pins[0])
- return;
- kctl = snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch");
- if (!kctl)
- return;
- spec->spdif_sw_put = kctl->put;
- kctl->put = cs4208_spdif_sw_put;
- }
-}
-
-static const struct hda_fixup cs4208_fixups[] = {
- [CS4208_MBA6] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = mba6_pincfgs,
- .chained = true,
- .chain_id = CS4208_GPIO0,
- },
- [CS4208_MBP11] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cs4208_fixup_spdif_switch,
- .chained = true,
- .chain_id = CS4208_GPIO0,
- },
- [CS4208_MACMINI] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cs4208_fixup_macmini,
- .chained = true,
- .chain_id = CS4208_GPIO0,
- },
- [CS4208_GPIO0] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cs4208_fixup_gpio0,
- },
- [CS4208_MAC_AUTO] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cs4208_fixup_mac,
- },
-};
-
-/* correct the 0dB offset of input pins */
-static void cs4208_fix_amp_caps(struct hda_codec *codec, hda_nid_t adc)
-{
- unsigned int caps;
-
- caps = query_amp_caps(codec, adc, HDA_INPUT);
- caps &= ~(AC_AMPCAP_OFFSET);
- caps |= 0x02;
- snd_hda_override_amp_caps(codec, adc, HDA_INPUT, caps);
-}
-
-static int patch_cs4208(struct hda_codec *codec)
-{
- struct cs_spec *spec;
- int err;
-
- spec = cs_alloc_spec(codec, CS4208_VENDOR_NID);
- if (!spec)
- return -ENOMEM;
-
- codec->patch_ops = cs_patch_ops;
- spec->gen.automute_hook = cs_automute;
- /* exclude NID 0x10 (HP) from output volumes due to different steps */
- spec->gen.out_vol_mask = 1ULL << 0x10;
-
- snd_hda_pick_fixup(codec, cs4208_models, cs4208_fixup_tbl,
- cs4208_fixups);
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
-
- snd_hda_override_wcaps(codec, 0x18,
- get_wcaps(codec, 0x18) | AC_WCAP_STEREO);
- cs4208_fix_amp_caps(codec, 0x18);
- cs4208_fix_amp_caps(codec, 0x1b);
- cs4208_fix_amp_caps(codec, 0x1c);
-
- err = cs_parse_auto_config(codec);
- if (err < 0)
- goto error;
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
-
- return 0;
-
- error:
- cs_free(codec);
- return err;
-}
-
-/*
- * Cirrus Logic CS4210
- *
- * 1 DAC => HP(sense) / Speakers,
- * 1 ADC <= LineIn(sense) / MicIn / DMicIn,
- * 1 SPDIF OUT => SPDIF Trasmitter(sense)
- */
-
-/* CS4210 board names */
-static const struct hda_model_fixup cs421x_models[] = {
- { .id = CS421X_CDB4210, .name = "cdb4210" },
- { .id = CS421X_STUMPY, .name = "stumpy" },
- {}
-};
-
-static const struct hda_quirk cs421x_fixup_tbl[] = {
- /* Test Intel board + CDB2410 */
- SND_PCI_QUIRK(0x8086, 0x5001, "DP45SG/CDB4210", CS421X_CDB4210),
- {} /* terminator */
-};
-
-/* CS4210 board pinconfigs */
-/* Default CS4210 (CDB4210)*/
-static const struct hda_pintbl cdb4210_pincfgs[] = {
- { 0x05, 0x0321401f },
- { 0x06, 0x90170010 },
- { 0x07, 0x03813031 },
- { 0x08, 0xb7a70037 },
- { 0x09, 0xb7a6003e },
- { 0x0a, 0x034510f0 },
- {} /* terminator */
-};
-
-/* Stumpy ChromeBox */
-static const struct hda_pintbl stumpy_pincfgs[] = {
- { 0x05, 0x022120f0 },
- { 0x06, 0x901700f0 },
- { 0x07, 0x02a120f0 },
- { 0x08, 0x77a70037 },
- { 0x09, 0x77a6003e },
- { 0x0a, 0x434510f0 },
- {} /* terminator */
-};
-
-/* Setup GPIO/SENSE for each board (if used) */
-static void cs421x_fixup_sense_b(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct cs_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE)
- spec->sense_b = 1;
-}
-
-static const struct hda_fixup cs421x_fixups[] = {
- [CS421X_CDB4210] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = cdb4210_pincfgs,
- .chained = true,
- .chain_id = CS421X_SENSE_B,
- },
- [CS421X_SENSE_B] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cs421x_fixup_sense_b,
- },
- [CS421X_STUMPY] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = stumpy_pincfgs,
- },
-};
-
-static const struct hda_verb cs421x_coef_init_verbs[] = {
- {0x0B, AC_VERB_SET_PROC_STATE, 1},
- {0x0B, AC_VERB_SET_COEF_INDEX, CS421X_IDX_DEV_CFG},
- /*
- * Disable Coefficient Index Auto-Increment(DAI)=1,
- * PDREF=0
- */
- {0x0B, AC_VERB_SET_PROC_COEF, 0x0001 },
-
- {0x0B, AC_VERB_SET_COEF_INDEX, CS421X_IDX_ADC_CFG},
- /* ADC SZCMode = Digital Soft Ramp */
- {0x0B, AC_VERB_SET_PROC_COEF, 0x0002 },
-
- {0x0B, AC_VERB_SET_COEF_INDEX, CS421X_IDX_DAC_CFG},
- {0x0B, AC_VERB_SET_PROC_COEF,
- (0x0002 /* DAC SZCMode = Digital Soft Ramp */
- | 0x0004 /* Mute DAC on FIFO error */
- | 0x0008 /* Enable DAC High Pass Filter */
- )},
- {} /* terminator */
-};
-
-/* Errata: CS4210 rev A1 Silicon
- *
- * http://www.cirrus.com/en/pubs/errata/
- *
- * Description:
- * 1. Performance degredation is present in the ADC.
- * 2. Speaker output is not completely muted upon HP detect.
- * 3. Noise is present when clipping occurs on the amplified
- * speaker outputs.
- *
- * Workaround:
- * The following verb sequence written to the registers during
- * initialization will correct the issues listed above.
- */
-
-static const struct hda_verb cs421x_coef_init_verbs_A1_silicon_fixes[] = {
- {0x0B, AC_VERB_SET_PROC_STATE, 0x01}, /* VPW: processing on */
-
- {0x0B, AC_VERB_SET_COEF_INDEX, 0x0006},
- {0x0B, AC_VERB_SET_PROC_COEF, 0x9999}, /* Test mode: on */
-
- {0x0B, AC_VERB_SET_COEF_INDEX, 0x000A},
- {0x0B, AC_VERB_SET_PROC_COEF, 0x14CB}, /* Chop double */
-
- {0x0B, AC_VERB_SET_COEF_INDEX, 0x0011},
- {0x0B, AC_VERB_SET_PROC_COEF, 0xA2D0}, /* Increase ADC current */
-
- {0x0B, AC_VERB_SET_COEF_INDEX, 0x001A},
- {0x0B, AC_VERB_SET_PROC_COEF, 0x02A9}, /* Mute speaker */
-
- {0x0B, AC_VERB_SET_COEF_INDEX, 0x001B},
- {0x0B, AC_VERB_SET_PROC_COEF, 0X1006}, /* Remove noise */
-
- {} /* terminator */
-};
-
-/* Speaker Amp Gain is controlled by the vendor widget's coef 4 */
-static const DECLARE_TLV_DB_SCALE(cs421x_speaker_boost_db_scale, 900, 300, 0);
-
-static int cs421x_boost_vol_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 3;
- return 0;
-}
-
-static int cs421x_boost_vol_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-
- ucontrol->value.integer.value[0] =
- cs_vendor_coef_get(codec, CS421X_IDX_SPK_CTL) & 0x0003;
- return 0;
-}
-
-static int cs421x_boost_vol_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-
- unsigned int vol = ucontrol->value.integer.value[0];
- unsigned int coef =
- cs_vendor_coef_get(codec, CS421X_IDX_SPK_CTL);
- unsigned int original_coef = coef;
-
- coef &= ~0x0003;
- coef |= (vol & 0x0003);
- if (original_coef != coef) {
- cs_vendor_coef_set(codec, CS421X_IDX_SPK_CTL, coef);
- return 1;
- }
-
- return 0;
-}
-
-static const struct snd_kcontrol_new cs421x_speaker_boost_ctl = {
-
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
- SNDRV_CTL_ELEM_ACCESS_TLV_READ),
- .name = "Speaker Boost Playback Volume",
- .info = cs421x_boost_vol_info,
- .get = cs421x_boost_vol_get,
- .put = cs421x_boost_vol_put,
- .tlv = { .p = cs421x_speaker_boost_db_scale },
-};
-
-static void cs4210_pinmux_init(struct hda_codec *codec)
-{
- struct cs_spec *spec = codec->spec;
- unsigned int def_conf, coef;
-
- /* GPIO, DMIC_SCL, DMIC_SDA and SENSE_B are multiplexed */
- coef = cs_vendor_coef_get(codec, CS421X_IDX_DEV_CFG);
-
- if (spec->gpio_mask)
- coef |= 0x0008; /* B1,B2 are GPIOs */
- else
- coef &= ~0x0008;
-
- if (spec->sense_b)
- coef |= 0x0010; /* B2 is SENSE_B, not inverted */
- else
- coef &= ~0x0010;
-
- cs_vendor_coef_set(codec, CS421X_IDX_DEV_CFG, coef);
-
- if ((spec->gpio_mask || spec->sense_b) &&
- is_active_pin(codec, CS421X_DMIC_PIN_NID)) {
-
- /*
- * GPIO or SENSE_B forced - disconnect the DMIC pin.
- */
- def_conf = snd_hda_codec_get_pincfg(codec, CS421X_DMIC_PIN_NID);
- def_conf &= ~AC_DEFCFG_PORT_CONN;
- def_conf |= (AC_JACK_PORT_NONE << AC_DEFCFG_PORT_CONN_SHIFT);
- snd_hda_codec_set_pincfg(codec, CS421X_DMIC_PIN_NID, def_conf);
- }
-}
-
-static void cs4210_spdif_automute(struct hda_codec *codec,
- struct hda_jack_callback *tbl)
-{
- struct cs_spec *spec = codec->spec;
- bool spdif_present = false;
- hda_nid_t spdif_pin = spec->gen.autocfg.dig_out_pins[0];
-
- /* detect on spdif is specific to CS4210 */
- if (!spec->spdif_detect ||
- spec->vendor_nid != CS4210_VENDOR_NID)
- return;
-
- spdif_present = snd_hda_jack_detect(codec, spdif_pin);
- if (spdif_present == spec->spdif_present)
- return;
-
- spec->spdif_present = spdif_present;
- /* SPDIF TX on/off */
- snd_hda_set_pin_ctl(codec, spdif_pin, spdif_present ? PIN_OUT : 0);
-
- cs_automute(codec);
-}
-
-static void parse_cs421x_digital(struct hda_codec *codec)
-{
- struct cs_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->gen.autocfg;
- int i;
-
- for (i = 0; i < cfg->dig_outs; i++) {
- hda_nid_t nid = cfg->dig_out_pins[i];
-
- if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) {
- spec->spdif_detect = 1;
- snd_hda_jack_detect_enable_callback(codec, nid,
- cs4210_spdif_automute);
- }
- }
-}
-
-static int cs421x_init(struct hda_codec *codec)
-{
- struct cs_spec *spec = codec->spec;
-
- if (spec->vendor_nid == CS4210_VENDOR_NID) {
- snd_hda_sequence_write(codec, cs421x_coef_init_verbs);
- snd_hda_sequence_write(codec, cs421x_coef_init_verbs_A1_silicon_fixes);
- cs4210_pinmux_init(codec);
- }
-
- snd_hda_gen_init(codec);
-
- if (spec->gpio_mask) {
- snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_MASK,
- spec->gpio_mask);
- snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DIRECTION,
- spec->gpio_dir);
- snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
- spec->gpio_data);
- }
-
- init_input_coef(codec);
-
- cs4210_spdif_automute(codec, NULL);
-
- return 0;
-}
-
-static void fix_volume_caps(struct hda_codec *codec, hda_nid_t dac)
-{
- unsigned int caps;
-
- /* set the upper-limit for mixer amp to 0dB */
- caps = query_amp_caps(codec, dac, HDA_OUTPUT);
- caps &= ~(0x7f << AC_AMPCAP_NUM_STEPS_SHIFT);
- caps |= ((caps >> AC_AMPCAP_OFFSET_SHIFT) & 0x7f)
- << AC_AMPCAP_NUM_STEPS_SHIFT;
- snd_hda_override_amp_caps(codec, dac, HDA_OUTPUT, caps);
-}
-
-static int cs421x_parse_auto_config(struct hda_codec *codec)
-{
- struct cs_spec *spec = codec->spec;
- hda_nid_t dac = CS4210_DAC_NID;
- int err;
-
- fix_volume_caps(codec, dac);
-
- err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0);
- if (err < 0)
- return err;
-
- err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg);
- if (err < 0)
- return err;
-
- parse_cs421x_digital(codec);
-
- if (spec->gen.autocfg.speaker_outs &&
- spec->vendor_nid == CS4210_VENDOR_NID) {
- if (!snd_hda_gen_add_kctl(&spec->gen, NULL,
- &cs421x_speaker_boost_ctl))
- return -ENOMEM;
- }
-
- return 0;
-}
-
-/*
- * Manage PDREF, when transitioning to D3hot
- * (DAC,ADC) -> D3, PDREF=1, AFG->D3
- */
-static int cs421x_suspend(struct hda_codec *codec)
-{
- struct cs_spec *spec = codec->spec;
- unsigned int coef;
-
- snd_hda_shutup_pins(codec);
-
- snd_hda_codec_write(codec, CS4210_DAC_NID, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
- snd_hda_codec_write(codec, CS4210_ADC_NID, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
-
- if (spec->vendor_nid == CS4210_VENDOR_NID) {
- coef = cs_vendor_coef_get(codec, CS421X_IDX_DEV_CFG);
- coef |= 0x0004; /* PDREF */
- cs_vendor_coef_set(codec, CS421X_IDX_DEV_CFG, coef);
- }
-
- return 0;
-}
-
-static const struct hda_codec_ops cs421x_patch_ops = {
- .build_controls = snd_hda_gen_build_controls,
- .build_pcms = snd_hda_gen_build_pcms,
- .init = cs421x_init,
- .free = cs_free,
- .unsol_event = snd_hda_jack_unsol_event,
- .suspend = cs421x_suspend,
-};
-
-static int patch_cs4210(struct hda_codec *codec)
-{
- struct cs_spec *spec;
- int err;
-
- spec = cs_alloc_spec(codec, CS4210_VENDOR_NID);
- if (!spec)
- return -ENOMEM;
-
- codec->patch_ops = cs421x_patch_ops;
- spec->gen.automute_hook = cs_automute;
-
- snd_hda_pick_fixup(codec, cs421x_models, cs421x_fixup_tbl,
- cs421x_fixups);
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
-
- /*
- * Update the GPIO/DMIC/SENSE_B pinmux before the configuration
- * is auto-parsed. If GPIO or SENSE_B is forced, DMIC input
- * is disabled.
- */
- cs4210_pinmux_init(codec);
-
- err = cs421x_parse_auto_config(codec);
- if (err < 0)
- goto error;
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
-
- return 0;
-
- error:
- cs_free(codec);
- return err;
-}
-
-static int patch_cs4213(struct hda_codec *codec)
-{
- struct cs_spec *spec;
- int err;
-
- spec = cs_alloc_spec(codec, CS4213_VENDOR_NID);
- if (!spec)
- return -ENOMEM;
-
- codec->patch_ops = cs421x_patch_ops;
-
- err = cs421x_parse_auto_config(codec);
- if (err < 0)
- goto error;
-
- return 0;
-
- error:
- cs_free(codec);
- return err;
-}
-
-/*
- * patch entries
- */
-static const struct hda_device_id snd_hda_id_cirrus[] = {
- HDA_CODEC_ENTRY(0x10134206, "CS4206", patch_cs420x),
- HDA_CODEC_ENTRY(0x10134207, "CS4207", patch_cs420x),
- HDA_CODEC_ENTRY(0x10134208, "CS4208", patch_cs4208),
- HDA_CODEC_ENTRY(0x10134210, "CS4210", patch_cs4210),
- HDA_CODEC_ENTRY(0x10134213, "CS4213", patch_cs4213),
- {} /* terminator */
-};
-MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_cirrus);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Cirrus Logic HD-audio codec");
-
-static struct hda_codec_driver cirrus_driver = {
- .id = snd_hda_id_cirrus,
-};
-
-module_hda_codec_driver(cirrus_driver);
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
deleted file mode 100644
index fe946d407830..000000000000
--- a/sound/pci/hda/patch_cmedia.c
+++ /dev/null
@@ -1,396 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Universal Interface for Intel High Definition Audio Codec
- *
- * HD audio interface patch for C-Media CMI9880
- *
- * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
- */
-
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <sound/core.h>
-#include <sound/hda_codec.h>
-#include "hda_local.h"
-#include "hda_auto_parser.h"
-#include "hda_jack.h"
-#include "hda_generic.h"
-
-/* CM9825 Offset Definitions */
-
-#define CM9825_VERB_SET_HPF_1 0x781
-#define CM9825_VERB_SET_HPF_2 0x785
-#define CM9825_VERB_SET_PLL 0x7a0
-#define CM9825_VERB_SET_NEG 0x7a1
-#define CM9825_VERB_SET_ADCL 0x7a2
-#define CM9825_VERB_SET_DACL 0x7a3
-#define CM9825_VERB_SET_MBIAS 0x7a4
-#define CM9825_VERB_SET_VNEG 0x7a8
-#define CM9825_VERB_SET_D2S 0x7a9
-#define CM9825_VERB_SET_DACTRL 0x7aa
-#define CM9825_VERB_SET_PDNEG 0x7ac
-#define CM9825_VERB_SET_VDO 0x7ad
-#define CM9825_VERB_SET_CDALR 0x7b0
-#define CM9825_VERB_SET_MTCBA 0x7b1
-#define CM9825_VERB_SET_OTP 0x7b2
-#define CM9825_VERB_SET_OCP 0x7b3
-#define CM9825_VERB_SET_GAD 0x7b4
-#define CM9825_VERB_SET_TMOD 0x7b5
-#define CM9825_VERB_SET_SNR 0x7b6
-
-struct cmi_spec {
- struct hda_gen_spec gen;
- const struct hda_verb *chip_d0_verbs;
- const struct hda_verb *chip_d3_verbs;
- const struct hda_verb *chip_hp_present_verbs;
- const struct hda_verb *chip_hp_remove_verbs;
- struct hda_codec *codec;
- struct delayed_work unsol_hp_work;
- int quirk;
-};
-
-static const struct hda_verb cm9825_std_d3_verbs[] = {
- /* chip sleep verbs */
- {0x43, CM9825_VERB_SET_D2S, 0x62}, /* depop */
- {0x43, CM9825_VERB_SET_PLL, 0x01}, /* PLL set */
- {0x43, CM9825_VERB_SET_NEG, 0xc2}, /* NEG set */
- {0x43, CM9825_VERB_SET_ADCL, 0x00}, /* ADC */
- {0x43, CM9825_VERB_SET_DACL, 0x02}, /* DACL */
- {0x43, CM9825_VERB_SET_VNEG, 0x50}, /* VOL NEG */
- {0x43, CM9825_VERB_SET_MBIAS, 0x00}, /* MBIAS */
- {0x43, CM9825_VERB_SET_PDNEG, 0x04}, /* SEL OSC */
- {0x43, CM9825_VERB_SET_CDALR, 0xf6}, /* Class D */
- {0x43, CM9825_VERB_SET_OTP, 0xcd}, /* OTP set */
- {}
-};
-
-static const struct hda_verb cm9825_std_d0_verbs[] = {
- /* chip init verbs */
- {0x34, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, /* EAPD set */
- {0x43, CM9825_VERB_SET_SNR, 0x30}, /* SNR set */
- {0x43, CM9825_VERB_SET_PLL, 0x00}, /* PLL set */
- {0x43, CM9825_VERB_SET_ADCL, 0x00}, /* ADC */
- {0x43, CM9825_VERB_SET_DACL, 0x02}, /* DACL */
- {0x43, CM9825_VERB_SET_MBIAS, 0x00}, /* MBIAS */
- {0x43, CM9825_VERB_SET_VNEG, 0x56}, /* VOL NEG */
- {0x43, CM9825_VERB_SET_D2S, 0x62}, /* depop */
- {0x43, CM9825_VERB_SET_DACTRL, 0x00}, /* DACTRL set */
- {0x43, CM9825_VERB_SET_PDNEG, 0x0c}, /* SEL OSC */
- {0x43, CM9825_VERB_SET_VDO, 0x80}, /* VDO set */
- {0x43, CM9825_VERB_SET_CDALR, 0xf4}, /* Class D */
- {0x43, CM9825_VERB_SET_OTP, 0xcd}, /* OTP set */
- {0x43, CM9825_VERB_SET_MTCBA, 0x61}, /* SR set */
- {0x43, CM9825_VERB_SET_OCP, 0x33}, /* OTP set */
- {0x43, CM9825_VERB_SET_GAD, 0x07}, /* ADC -3db */
- {0x43, CM9825_VERB_SET_TMOD, 0x26}, /* Class D clk */
- {0x3C, AC_VERB_SET_AMP_GAIN_MUTE |
- AC_AMP_SET_OUTPUT | AC_AMP_SET_RIGHT, 0x2d}, /* Gain set */
- {0x3C, AC_VERB_SET_AMP_GAIN_MUTE |
- AC_AMP_SET_OUTPUT | AC_AMP_SET_LEFT, 0x2d}, /* Gain set */
- {0x43, CM9825_VERB_SET_HPF_1, 0x40}, /* HPF set */
- {0x43, CM9825_VERB_SET_HPF_2, 0x40}, /* HPF set */
- {}
-};
-
-static const struct hda_verb cm9825_hp_present_verbs[] = {
- {0x42, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00}, /* PIN off */
- {0x43, CM9825_VERB_SET_ADCL, 0x88}, /* ADC */
- {0x43, CM9825_VERB_SET_DACL, 0xaa}, /* DACL */
- {0x43, CM9825_VERB_SET_MBIAS, 0x10}, /* MBIAS */
- {0x43, CM9825_VERB_SET_D2S, 0xf2}, /* depop */
- {0x43, CM9825_VERB_SET_DACTRL, 0x00}, /* DACTRL set */
- {0x43, CM9825_VERB_SET_VDO, 0xc4}, /* VDO set */
- {}
-};
-
-static const struct hda_verb cm9825_hp_remove_verbs[] = {
- {0x43, CM9825_VERB_SET_ADCL, 0x00}, /* ADC */
- {0x43, CM9825_VERB_SET_DACL, 0x56}, /* DACL */
- {0x43, CM9825_VERB_SET_MBIAS, 0x00}, /* MBIAS */
- {0x43, CM9825_VERB_SET_D2S, 0x62}, /* depop */
- {0x43, CM9825_VERB_SET_DACTRL, 0xe0}, /* DACTRL set */
- {0x43, CM9825_VERB_SET_VDO, 0x80}, /* VDO set */
- {0x42, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, /* PIN on */
- {}
-};
-
-static void cm9825_unsol_hp_delayed(struct work_struct *work)
-{
- struct cmi_spec *spec =
- container_of(to_delayed_work(work), struct cmi_spec, unsol_hp_work);
- struct hda_jack_tbl *jack;
- hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
- bool hp_jack_plugin = false;
- int err = 0;
-
- hp_jack_plugin = snd_hda_jack_detect(spec->codec, hp_pin);
-
- codec_dbg(spec->codec, "hp_jack_plugin %d, hp_pin 0x%X\n",
- (int)hp_jack_plugin, hp_pin);
-
- if (!hp_jack_plugin) {
- err =
- snd_hda_codec_write(spec->codec, 0x42, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40);
- if (err)
- codec_dbg(spec->codec, "codec_write err %d\n", err);
-
- snd_hda_sequence_write(spec->codec, spec->chip_hp_remove_verbs);
- } else {
- snd_hda_sequence_write(spec->codec,
- spec->chip_hp_present_verbs);
- }
-
- jack = snd_hda_jack_tbl_get(spec->codec, hp_pin);
- if (jack) {
- jack->block_report = 0;
- snd_hda_jack_report_sync(spec->codec);
- }
-}
-
-static void hp_callback(struct hda_codec *codec, struct hda_jack_callback *cb)
-{
- struct cmi_spec *spec = codec->spec;
- struct hda_jack_tbl *tbl;
-
- /* Delay enabling the HP amp, to let the mic-detection
- * state machine run.
- */
-
- codec_dbg(spec->codec, "cb->nid 0x%X\n", cb->nid);
-
- tbl = snd_hda_jack_tbl_get(codec, cb->nid);
- if (tbl)
- tbl->block_report = 1;
- schedule_delayed_work(&spec->unsol_hp_work, msecs_to_jiffies(200));
-}
-
-static void cm9825_setup_unsol(struct hda_codec *codec)
-{
- struct cmi_spec *spec = codec->spec;
-
- hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
-
- snd_hda_jack_detect_enable_callback(codec, hp_pin, hp_callback);
-}
-
-static int cm9825_init(struct hda_codec *codec)
-{
- snd_hda_gen_init(codec);
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT);
-
- return 0;
-}
-
-static void cm9825_free(struct hda_codec *codec)
-{
- struct cmi_spec *spec = codec->spec;
-
- cancel_delayed_work_sync(&spec->unsol_hp_work);
- snd_hda_gen_free(codec);
-}
-
-static int cm9825_suspend(struct hda_codec *codec)
-{
- struct cmi_spec *spec = codec->spec;
-
- cancel_delayed_work_sync(&spec->unsol_hp_work);
-
- snd_hda_sequence_write(codec, spec->chip_d3_verbs);
-
- return 0;
-}
-
-static int cm9825_resume(struct hda_codec *codec)
-{
- struct cmi_spec *spec = codec->spec;
- hda_nid_t hp_pin = 0;
- bool hp_jack_plugin = false;
- int err;
-
- err =
- snd_hda_codec_write(spec->codec, 0x42, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00);
- if (err)
- codec_dbg(codec, "codec_write err %d\n", err);
-
- msleep(150); /* for depop noise */
-
- codec->patch_ops.init(codec);
-
- hp_pin = spec->gen.autocfg.hp_pins[0];
- hp_jack_plugin = snd_hda_jack_detect(spec->codec, hp_pin);
-
- codec_dbg(spec->codec, "hp_jack_plugin %d, hp_pin 0x%X\n",
- (int)hp_jack_plugin, hp_pin);
-
- if (!hp_jack_plugin) {
- err =
- snd_hda_codec_write(spec->codec, 0x42, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40);
-
- if (err)
- codec_dbg(codec, "codec_write err %d\n", err);
-
- snd_hda_sequence_write(codec, cm9825_hp_remove_verbs);
- }
-
- snd_hda_regmap_sync(codec);
- hda_call_check_power_status(codec, 0x01);
-
- return 0;
-}
-
-/*
- * stuff for auto-parser
- */
-static const struct hda_codec_ops cmi_auto_patch_ops = {
- .build_controls = snd_hda_gen_build_controls,
- .build_pcms = snd_hda_gen_build_pcms,
- .init = snd_hda_gen_init,
- .free = snd_hda_gen_free,
- .unsol_event = snd_hda_jack_unsol_event,
-};
-
-static int patch_cm9825(struct hda_codec *codec)
-{
- struct cmi_spec *spec;
- struct auto_pin_cfg *cfg;
- int err;
-
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
- return -ENOMEM;
-
- INIT_DELAYED_WORK(&spec->unsol_hp_work, cm9825_unsol_hp_delayed);
- codec->spec = spec;
- spec->codec = codec;
- codec->patch_ops = cmi_auto_patch_ops;
- codec->patch_ops.init = cm9825_init;
- codec->patch_ops.suspend = cm9825_suspend;
- codec->patch_ops.resume = cm9825_resume;
- codec->patch_ops.free = cm9825_free;
- codec->patch_ops.check_power_status = snd_hda_gen_check_power_status;
- cfg = &spec->gen.autocfg;
- snd_hda_gen_spec_init(&spec->gen);
- spec->chip_d0_verbs = cm9825_std_d0_verbs;
- spec->chip_d3_verbs = cm9825_std_d3_verbs;
- spec->chip_hp_present_verbs = cm9825_hp_present_verbs;
- spec->chip_hp_remove_verbs = cm9825_hp_remove_verbs;
-
- snd_hda_sequence_write(codec, spec->chip_d0_verbs);
-
- err = snd_hda_parse_pin_defcfg(codec, cfg, NULL, 0);
- if (err < 0)
- goto error;
- err = snd_hda_gen_parse_auto_config(codec, cfg);
- if (err < 0)
- goto error;
-
- cm9825_setup_unsol(codec);
-
- return 0;
-
- error:
- cm9825_free(codec);
-
- codec_info(codec, "Enter err %d\n", err);
-
- return err;
-}
-
-static int patch_cmi9880(struct hda_codec *codec)
-{
- struct cmi_spec *spec;
- struct auto_pin_cfg *cfg;
- int err;
-
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
- return -ENOMEM;
-
- codec->spec = spec;
- codec->patch_ops = cmi_auto_patch_ops;
- cfg = &spec->gen.autocfg;
- snd_hda_gen_spec_init(&spec->gen);
-
- err = snd_hda_parse_pin_defcfg(codec, cfg, NULL, 0);
- if (err < 0)
- goto error;
- err = snd_hda_gen_parse_auto_config(codec, cfg);
- if (err < 0)
- goto error;
-
- return 0;
-
- error:
- snd_hda_gen_free(codec);
- return err;
-}
-
-static int patch_cmi8888(struct hda_codec *codec)
-{
- struct cmi_spec *spec;
- struct auto_pin_cfg *cfg;
- int err;
-
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (!spec)
- return -ENOMEM;
-
- codec->spec = spec;
- codec->patch_ops = cmi_auto_patch_ops;
- cfg = &spec->gen.autocfg;
- snd_hda_gen_spec_init(&spec->gen);
-
- /* mask NID 0x10 from the playback volume selection;
- * it's a headphone boost volume handled manually below
- */
- spec->gen.out_vol_mask = (1ULL << 0x10);
-
- err = snd_hda_parse_pin_defcfg(codec, cfg, NULL, 0);
- if (err < 0)
- goto error;
- err = snd_hda_gen_parse_auto_config(codec, cfg);
- if (err < 0)
- goto error;
-
- if (get_defcfg_device(snd_hda_codec_get_pincfg(codec, 0x10)) ==
- AC_JACK_HP_OUT) {
- static const struct snd_kcontrol_new amp_kctl =
- HDA_CODEC_VOLUME("Headphone Amp Playback Volume",
- 0x10, 0, HDA_OUTPUT);
- if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &amp_kctl)) {
- err = -ENOMEM;
- goto error;
- }
- }
-
- return 0;
-
- error:
- snd_hda_gen_free(codec);
- return err;
-}
-
-/*
- * patch entries
- */
-static const struct hda_device_id snd_hda_id_cmedia[] = {
- HDA_CODEC_ENTRY(0x13f68888, "CMI8888", patch_cmi8888),
- HDA_CODEC_ENTRY(0x13f69880, "CMI9880", patch_cmi9880),
- HDA_CODEC_ENTRY(0x434d4980, "CMI9880", patch_cmi9880),
- HDA_CODEC_ENTRY(0x13f69825, "CM9825", patch_cm9825),
- {} /* terminator */
-};
-MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_cmedia);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("C-Media HD-audio codec");
-
-static struct hda_codec_driver cmedia_driver = {
- .id = snd_hda_id_cmedia,
-};
-
-module_hda_codec_driver(cmedia_driver);
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
deleted file mode 100644
index 34874039ad45..000000000000
--- a/sound/pci/hda/patch_conexant.c
+++ /dev/null
@@ -1,1331 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * HD audio interface patch for Conexant HDA audio codec
- *
- * Copyright (c) 2006 Pototskiy Akex <alex.pototskiy@gmail.com>
- * Takashi Iwai <tiwai@suse.de>
- * Tobin Davis <tdavis@dsl-only.net>
- */
-
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <sound/core.h>
-#include <sound/jack.h>
-
-#include <sound/hda_codec.h>
-#include "hda_local.h"
-#include "hda_auto_parser.h"
-#include "hda_beep.h"
-#include "hda_jack.h"
-#include "hda_generic.h"
-
-struct conexant_spec {
- struct hda_gen_spec gen;
-
- /* extra EAPD pins */
- unsigned int num_eapds;
- hda_nid_t eapds[4];
- bool dynamic_eapd;
- hda_nid_t mute_led_eapd;
-
- unsigned int parse_flags; /* flag for snd_hda_parse_pin_defcfg() */
-
- /* OPLC XO specific */
- bool recording;
- bool dc_enable;
- unsigned int dc_input_bias; /* offset into olpc_xo_dc_bias */
- struct nid_path *dc_mode_path;
-
- int mute_led_polarity;
- unsigned int gpio_led;
- unsigned int gpio_mute_led_mask;
- unsigned int gpio_mic_led_mask;
- bool is_cx8070_sn6140;
-};
-
-
-#ifdef CONFIG_SND_HDA_INPUT_BEEP
-/* additional beep mixers; private_value will be overwritten */
-static const struct snd_kcontrol_new cxt_beep_mixer[] = {
- HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0, 1, 0, HDA_OUTPUT),
- HDA_CODEC_MUTE_BEEP_MONO("Beep Playback Switch", 0, 1, 0, HDA_OUTPUT),
-};
-
-static int set_beep_amp(struct conexant_spec *spec, hda_nid_t nid,
- int idx, int dir)
-{
- struct snd_kcontrol_new *knew;
- unsigned int beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir);
- int i;
-
- spec->gen.beep_nid = nid;
- for (i = 0; i < ARRAY_SIZE(cxt_beep_mixer); i++) {
- knew = snd_hda_gen_add_kctl(&spec->gen, NULL,
- &cxt_beep_mixer[i]);
- if (!knew)
- return -ENOMEM;
- knew->private_value = beep_amp;
- }
- return 0;
-}
-
-static int cx_auto_parse_beep(struct hda_codec *codec)
-{
- struct conexant_spec *spec = codec->spec;
- hda_nid_t nid;
-
- for_each_hda_codec_node(nid, codec)
- if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_BEEP)
- return set_beep_amp(spec, nid, 0, HDA_OUTPUT);
- return 0;
-}
-#else
-#define cx_auto_parse_beep(codec) 0
-#endif
-
-/*
- * Automatic parser for CX20641 & co
- */
-
-/* parse EAPDs */
-static void cx_auto_parse_eapd(struct hda_codec *codec)
-{
- struct conexant_spec *spec = codec->spec;
- hda_nid_t nid;
-
- for_each_hda_codec_node(nid, codec) {
- if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
- continue;
- if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD))
- continue;
- spec->eapds[spec->num_eapds++] = nid;
- if (spec->num_eapds >= ARRAY_SIZE(spec->eapds))
- break;
- }
-
- /* NOTE: below is a wild guess; if we have more than two EAPDs,
- * it's a new chip, where EAPDs are supposed to be associated to
- * pins, and we can control EAPD per pin.
- * OTOH, if only one or two EAPDs are found, it's an old chip,
- * thus it might control over all pins.
- */
- if (spec->num_eapds > 2)
- spec->dynamic_eapd = 1;
-}
-
-static void cx_auto_turn_eapd(struct hda_codec *codec, int num_pins,
- const hda_nid_t *pins, bool on)
-{
- int i;
- for (i = 0; i < num_pins; i++) {
- if (snd_hda_query_pin_caps(codec, pins[i]) & AC_PINCAP_EAPD)
- snd_hda_codec_write(codec, pins[i], 0,
- AC_VERB_SET_EAPD_BTLENABLE,
- on ? 0x02 : 0);
- }
-}
-
-/* turn on/off EAPD according to Master switch */
-static void cx_auto_vmaster_hook(void *private_data, int enabled)
-{
- struct hda_codec *codec = private_data;
- struct conexant_spec *spec = codec->spec;
-
- cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, enabled);
-}
-
-/* turn on/off EAPD according to Master switch (inversely!) for mute LED */
-static int cx_auto_vmaster_mute_led(struct led_classdev *led_cdev,
- enum led_brightness brightness)
-{
- struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent);
- struct conexant_spec *spec = codec->spec;
-
- snd_hda_codec_write(codec, spec->mute_led_eapd, 0,
- AC_VERB_SET_EAPD_BTLENABLE,
- brightness ? 0x02 : 0x00);
- return 0;
-}
-
-static void cxt_init_gpio_led(struct hda_codec *codec)
-{
- struct conexant_spec *spec = codec->spec;
- unsigned int mask = spec->gpio_mute_led_mask | spec->gpio_mic_led_mask;
-
- if (mask) {
- snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_MASK,
- mask);
- snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DIRECTION,
- mask);
- snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
- spec->gpio_led);
- }
-}
-
-static void cx_fixup_headset_recog(struct hda_codec *codec)
-{
- unsigned int mic_present;
-
- /* fix some headset type recognize fail issue, such as EDIFIER headset */
- /* set micbias output current comparator threshold from 66% to 55%. */
- snd_hda_codec_write(codec, 0x1c, 0, 0x320, 0x010);
- /* set OFF voltage for DFET from -1.2V to -0.8V, set headset micbias register
- * value adjustment trim from 2.2K ohms to 2.0K ohms.
- */
- snd_hda_codec_write(codec, 0x1c, 0, 0x3b0, 0xe10);
- /* fix reboot headset type recognize fail issue */
- mic_present = snd_hda_codec_read(codec, 0x19, 0, AC_VERB_GET_PIN_SENSE, 0x0);
- if (mic_present & AC_PINSENSE_PRESENCE)
- /* enable headset mic VREF */
- snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24);
- else
- /* disable headset mic VREF */
- snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20);
-}
-
-static int cx_auto_init(struct hda_codec *codec)
-{
- struct conexant_spec *spec = codec->spec;
- snd_hda_gen_init(codec);
- if (!spec->dynamic_eapd)
- cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true);
-
- cxt_init_gpio_led(codec);
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT);
-
- if (spec->is_cx8070_sn6140)
- cx_fixup_headset_recog(codec);
-
- return 0;
-}
-
-static void cx_auto_shutdown(struct hda_codec *codec)
-{
- struct conexant_spec *spec = codec->spec;
-
- /* Turn the problematic codec into D3 to avoid spurious noises
- from the internal speaker during (and after) reboot */
- cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, false);
-}
-
-static void cx_auto_free(struct hda_codec *codec)
-{
- cx_auto_shutdown(codec);
- snd_hda_gen_free(codec);
-}
-
-static void cx_process_headset_plugin(struct hda_codec *codec)
-{
- unsigned int val;
- unsigned int count = 0;
-
- /* Wait headset detect done. */
- do {
- val = snd_hda_codec_read(codec, 0x1c, 0, 0xca0, 0x0);
- if (val & 0x080) {
- codec_dbg(codec, "headset type detect done!\n");
- break;
- }
- msleep(20);
- count++;
- } while (count < 3);
- val = snd_hda_codec_read(codec, 0x1c, 0, 0xcb0, 0x0);
- if (val & 0x800) {
- codec_dbg(codec, "headset plugin, type is CTIA\n");
- snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24);
- } else if (val & 0x400) {
- codec_dbg(codec, "headset plugin, type is OMTP\n");
- snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24);
- } else {
- codec_dbg(codec, "headphone plugin\n");
- }
-}
-
-static void cx_update_headset_mic_vref(struct hda_codec *codec, struct hda_jack_callback *event)
-{
- unsigned int mic_present;
-
- /* In cx8070 and sn6140, the node 16 can only be configured to headphone or disabled,
- * the node 19 can only be configured to microphone or disabled.
- * Check hp&mic tag to process headset plugin & plugout.
- */
- mic_present = snd_hda_codec_read(codec, 0x19, 0, AC_VERB_GET_PIN_SENSE, 0x0);
- if (!(mic_present & AC_PINSENSE_PRESENCE)) /* mic plugout */
- snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20);
- else
- cx_process_headset_plugin(codec);
-}
-
-static int cx_auto_suspend(struct hda_codec *codec)
-{
- cx_auto_shutdown(codec);
- return 0;
-}
-
-static const struct hda_codec_ops cx_auto_patch_ops = {
- .build_controls = snd_hda_gen_build_controls,
- .build_pcms = snd_hda_gen_build_pcms,
- .init = cx_auto_init,
- .free = cx_auto_free,
- .unsol_event = snd_hda_jack_unsol_event,
- .suspend = cx_auto_suspend,
- .check_power_status = snd_hda_gen_check_power_status,
-};
-
-/*
- * pin fix-up
- */
-enum {
- CXT_PINCFG_LENOVO_X200,
- CXT_PINCFG_LENOVO_TP410,
- CXT_PINCFG_LEMOTE_A1004,
- CXT_PINCFG_LEMOTE_A1205,
- CXT_PINCFG_COMPAQ_CQ60,
- CXT_FIXUP_STEREO_DMIC,
- CXT_PINCFG_LENOVO_NOTEBOOK,
- CXT_FIXUP_INC_MIC_BOOST,
- CXT_FIXUP_HEADPHONE_MIC_PIN,
- CXT_FIXUP_HEADPHONE_MIC,
- CXT_FIXUP_GPIO1,
- CXT_FIXUP_ASPIRE_DMIC,
- CXT_FIXUP_THINKPAD_ACPI,
- CXT_FIXUP_LENOVO_XPAD_ACPI,
- CXT_FIXUP_OLPC_XO,
- CXT_FIXUP_CAP_MIX_AMP,
- CXT_FIXUP_TOSHIBA_P105,
- CXT_FIXUP_HP_530,
- CXT_FIXUP_CAP_MIX_AMP_5047,
- CXT_FIXUP_MUTE_LED_EAPD,
- CXT_FIXUP_HP_DOCK,
- CXT_FIXUP_HP_SPECTRE,
- CXT_FIXUP_HP_GATE_MIC,
- CXT_FIXUP_MUTE_LED_GPIO,
- CXT_FIXUP_HP_ELITEONE_OUT_DIS,
- CXT_FIXUP_HP_ZBOOK_MUTE_LED,
- CXT_FIXUP_HEADSET_MIC,
- CXT_FIXUP_HP_MIC_NO_PRESENCE,
- CXT_PINCFG_SWS_JS201D,
- CXT_PINCFG_TOP_SPEAKER,
- CXT_FIXUP_HP_A_U,
-};
-
-/* for hda_fixup_thinkpad_acpi() */
-#include "thinkpad_helper.c"
-
-/* for hda_fixup_ideapad_acpi() */
-#include "ideapad_hotkey_led_helper.c"
-
-static void cxt_fixup_stereo_dmic(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct conexant_spec *spec = codec->spec;
- spec->gen.inv_dmic_split = 1;
-}
-
-/* fix widget control pin settings */
-static void cxt_fixup_update_pinctl(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_PROBE) {
- /* Unset OUT_EN for this Node pin, leaving only HP_EN.
- * This is the value stored in the codec register after
- * the correct initialization of the previous windows boot.
- */
- snd_hda_set_pin_ctl_cache(codec, 0x1d, AC_PINCTL_HP_EN);
- }
-}
-
-static void cxt5066_increase_mic_boost(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action != HDA_FIXUP_ACT_PRE_PROBE)
- return;
-
- snd_hda_override_amp_caps(codec, 0x17, HDA_OUTPUT,
- (0x3 << AC_AMPCAP_OFFSET_SHIFT) |
- (0x4 << AC_AMPCAP_NUM_STEPS_SHIFT) |
- (0x27 << AC_AMPCAP_STEP_SIZE_SHIFT) |
- (0 << AC_AMPCAP_MUTE_SHIFT));
-}
-
-static void cxt_update_headset_mode(struct hda_codec *codec)
-{
- /* The verbs used in this function were tested on a Conexant CX20751/2 codec. */
- int i;
- bool mic_mode = false;
- struct conexant_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->gen.autocfg;
-
- hda_nid_t mux_pin = spec->gen.imux_pins[spec->gen.cur_mux[0]];
-
- for (i = 0; i < cfg->num_inputs; i++)
- if (cfg->inputs[i].pin == mux_pin) {
- mic_mode = !!cfg->inputs[i].is_headphone_mic;
- break;
- }
-
- if (mic_mode) {
- snd_hda_codec_write_cache(codec, 0x1c, 0, 0x410, 0x7c); /* enable merged mode for analog int-mic */
- spec->gen.hp_jack_present = false;
- } else {
- snd_hda_codec_write_cache(codec, 0x1c, 0, 0x410, 0x54); /* disable merged mode for analog int-mic */
- spec->gen.hp_jack_present = snd_hda_jack_detect(codec, spec->gen.autocfg.hp_pins[0]);
- }
-
- snd_hda_gen_update_outputs(codec);
-}
-
-static void cxt_update_headset_mode_hook(struct hda_codec *codec,
- struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- cxt_update_headset_mode(codec);
-}
-
-static void cxt_fixup_headphone_mic(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct conexant_spec *spec = codec->spec;
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- spec->parse_flags |= HDA_PINCFG_HEADPHONE_MIC;
- snd_hdac_regmap_add_vendor_verb(&codec->core, 0x410);
- break;
- case HDA_FIXUP_ACT_PROBE:
- WARN_ON(spec->gen.cap_sync_hook);
- spec->gen.cap_sync_hook = cxt_update_headset_mode_hook;
- spec->gen.automute_hook = cxt_update_headset_mode;
- break;
- case HDA_FIXUP_ACT_INIT:
- cxt_update_headset_mode(codec);
- break;
- }
-}
-
-static void cxt_fixup_headset_mic(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct conexant_spec *spec = codec->spec;
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
- break;
- }
-}
-
-/* OPLC XO 1.5 fixup */
-
-/* OLPC XO-1.5 supports DC input mode (e.g. for use with analog sensors)
- * through the microphone jack.
- * When the user enables this through a mixer switch, both internal and
- * external microphones are disabled. Gain is fixed at 0dB. In this mode,
- * we also allow the bias to be configured through a separate mixer
- * control. */
-
-#define update_mic_pin(codec, nid, val) \
- snd_hda_codec_write_cache(codec, nid, 0, \
- AC_VERB_SET_PIN_WIDGET_CONTROL, val)
-
-static const struct hda_input_mux olpc_xo_dc_bias = {
- .num_items = 3,
- .items = {
- { "Off", PIN_IN },
- { "50%", PIN_VREF50 },
- { "80%", PIN_VREF80 },
- },
-};
-
-static void olpc_xo_update_mic_boost(struct hda_codec *codec)
-{
- struct conexant_spec *spec = codec->spec;
- int ch, val;
-
- for (ch = 0; ch < 2; ch++) {
- val = AC_AMP_SET_OUTPUT |
- (ch ? AC_AMP_SET_RIGHT : AC_AMP_SET_LEFT);
- if (!spec->dc_enable)
- val |= snd_hda_codec_amp_read(codec, 0x17, ch, HDA_OUTPUT, 0);
- snd_hda_codec_write(codec, 0x17, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, val);
- }
-}
-
-static void olpc_xo_update_mic_pins(struct hda_codec *codec)
-{
- struct conexant_spec *spec = codec->spec;
- int cur_input, val;
- struct nid_path *path;
-
- cur_input = spec->gen.input_paths[0][spec->gen.cur_mux[0]];
-
- /* Set up mic pins for port-B, C and F dynamically as the recording
- * LED is turned on/off by these pin controls
- */
- if (!spec->dc_enable) {
- /* disable DC bias path and pin for port F */
- update_mic_pin(codec, 0x1e, 0);
- snd_hda_activate_path(codec, spec->dc_mode_path, false, false);
-
- /* update port B (ext mic) and C (int mic) */
- /* OLPC defers mic widget control until when capture is
- * started because the microphone LED comes on as soon as
- * these settings are put in place. if we did this before
- * recording, it would give the false indication that
- * recording is happening when it is not.
- */
- update_mic_pin(codec, 0x1a, spec->recording ?
- snd_hda_codec_get_pin_target(codec, 0x1a) : 0);
- update_mic_pin(codec, 0x1b, spec->recording ?
- snd_hda_codec_get_pin_target(codec, 0x1b) : 0);
- /* enable normal mic path */
- path = snd_hda_get_path_from_idx(codec, cur_input);
- if (path)
- snd_hda_activate_path(codec, path, true, false);
- } else {
- /* disable normal mic path */
- path = snd_hda_get_path_from_idx(codec, cur_input);
- if (path)
- snd_hda_activate_path(codec, path, false, false);
-
- /* Even though port F is the DC input, the bias is controlled
- * on port B. We also leave that port as an active input (but
- * unselected) in DC mode just in case that is necessary to
- * make the bias setting take effect.
- */
- if (spec->recording)
- val = olpc_xo_dc_bias.items[spec->dc_input_bias].index;
- else
- val = 0;
- update_mic_pin(codec, 0x1a, val);
- update_mic_pin(codec, 0x1b, 0);
- /* enable DC bias path and pin */
- update_mic_pin(codec, 0x1e, spec->recording ? PIN_IN : 0);
- snd_hda_activate_path(codec, spec->dc_mode_path, true, false);
- }
-}
-
-/* mic_autoswitch hook */
-static void olpc_xo_automic(struct hda_codec *codec,
- struct hda_jack_callback *jack)
-{
- struct conexant_spec *spec = codec->spec;
-
- /* in DC mode, we don't handle automic */
- if (!spec->dc_enable)
- snd_hda_gen_mic_autoswitch(codec, jack);
- olpc_xo_update_mic_pins(codec);
- if (spec->dc_enable)
- olpc_xo_update_mic_boost(codec);
-}
-
-/* pcm_capture hook */
-static void olpc_xo_capture_hook(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream,
- int action)
-{
- struct conexant_spec *spec = codec->spec;
-
- /* toggle spec->recording flag and update mic pins accordingly
- * for turning on/off LED
- */
- switch (action) {
- case HDA_GEN_PCM_ACT_PREPARE:
- spec->recording = 1;
- olpc_xo_update_mic_pins(codec);
- break;
- case HDA_GEN_PCM_ACT_CLEANUP:
- spec->recording = 0;
- olpc_xo_update_mic_pins(codec);
- break;
- }
-}
-
-static int olpc_xo_dc_mode_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct conexant_spec *spec = codec->spec;
- ucontrol->value.integer.value[0] = spec->dc_enable;
- return 0;
-}
-
-static int olpc_xo_dc_mode_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct conexant_spec *spec = codec->spec;
- int dc_enable = !!ucontrol->value.integer.value[0];
-
- if (dc_enable == spec->dc_enable)
- return 0;
-
- spec->dc_enable = dc_enable;
- olpc_xo_update_mic_pins(codec);
- olpc_xo_update_mic_boost(codec);
- return 1;
-}
-
-static int olpc_xo_dc_bias_enum_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct conexant_spec *spec = codec->spec;
- ucontrol->value.enumerated.item[0] = spec->dc_input_bias;
- return 0;
-}
-
-static int olpc_xo_dc_bias_enum_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- return snd_hda_input_mux_info(&olpc_xo_dc_bias, uinfo);
-}
-
-static int olpc_xo_dc_bias_enum_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct conexant_spec *spec = codec->spec;
- const struct hda_input_mux *imux = &olpc_xo_dc_bias;
- unsigned int idx;
-
- idx = ucontrol->value.enumerated.item[0];
- if (idx >= imux->num_items)
- idx = imux->num_items - 1;
- if (spec->dc_input_bias == idx)
- return 0;
-
- spec->dc_input_bias = idx;
- if (spec->dc_enable)
- olpc_xo_update_mic_pins(codec);
- return 1;
-}
-
-static const struct snd_kcontrol_new olpc_xo_mixers[] = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "DC Mode Enable Switch",
- .info = snd_ctl_boolean_mono_info,
- .get = olpc_xo_dc_mode_get,
- .put = olpc_xo_dc_mode_put,
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "DC Input Bias Enum",
- .info = olpc_xo_dc_bias_enum_info,
- .get = olpc_xo_dc_bias_enum_get,
- .put = olpc_xo_dc_bias_enum_put,
- },
- {}
-};
-
-/* overriding mic boost put callback; update mic boost volume only when
- * DC mode is disabled
- */
-static int olpc_xo_mic_boost_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct conexant_spec *spec = codec->spec;
- int ret = snd_hda_mixer_amp_volume_put(kcontrol, ucontrol);
- if (ret > 0 && spec->dc_enable)
- olpc_xo_update_mic_boost(codec);
- return ret;
-}
-
-static void cxt_fixup_olpc_xo(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct conexant_spec *spec = codec->spec;
- struct snd_kcontrol_new *kctl;
- int i;
-
- if (action != HDA_FIXUP_ACT_PROBE)
- return;
-
- spec->gen.mic_autoswitch_hook = olpc_xo_automic;
- spec->gen.pcm_capture_hook = olpc_xo_capture_hook;
- spec->dc_mode_path = snd_hda_add_new_path(codec, 0x1e, 0x14, 0);
-
- snd_hda_add_new_ctls(codec, olpc_xo_mixers);
-
- /* OLPC's microphone port is DC coupled for use with external sensors,
- * therefore we use a 50% mic bias in order to center the input signal
- * with the DC input range of the codec.
- */
- snd_hda_codec_set_pin_target(codec, 0x1a, PIN_VREF50);
-
- /* override mic boost control */
- snd_array_for_each(&spec->gen.kctls, i, kctl) {
- if (!strcmp(kctl->name, "Mic Boost Volume")) {
- kctl->put = olpc_xo_mic_boost_put;
- break;
- }
- }
-}
-
-static void cxt_fixup_mute_led_eapd(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct conexant_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->mute_led_eapd = 0x1b;
- spec->dynamic_eapd = true;
- snd_hda_gen_add_mute_led_cdev(codec, cx_auto_vmaster_mute_led);
- }
-}
-
-/*
- * Fix max input level on mixer widget to 0dB
- * (originally it has 0x2b steps with 0dB offset 0x14)
- */
-static void cxt_fixup_cap_mix_amp(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- snd_hda_override_amp_caps(codec, 0x17, HDA_INPUT,
- (0x14 << AC_AMPCAP_OFFSET_SHIFT) |
- (0x14 << AC_AMPCAP_NUM_STEPS_SHIFT) |
- (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
- (1 << AC_AMPCAP_MUTE_SHIFT));
-}
-
-/*
- * Fix max input level on mixer widget to 0dB
- * (originally it has 0x1e steps with 0 dB offset 0x17)
- */
-static void cxt_fixup_cap_mix_amp_5047(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- snd_hda_override_amp_caps(codec, 0x10, HDA_INPUT,
- (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
- (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
- (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
- (1 << AC_AMPCAP_MUTE_SHIFT));
-}
-
-static void cxt_fixup_hp_gate_mic_jack(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- /* the mic pin (0x19) doesn't give an unsolicited event;
- * probe the mic pin together with the headphone pin (0x16)
- */
- if (action == HDA_FIXUP_ACT_PROBE)
- snd_hda_jack_set_gating_jack(codec, 0x19, 0x16);
-}
-
-/* update LED status via GPIO */
-static void cxt_update_gpio_led(struct hda_codec *codec, unsigned int mask,
- bool led_on)
-{
- struct conexant_spec *spec = codec->spec;
- unsigned int oldval = spec->gpio_led;
-
- if (spec->mute_led_polarity)
- led_on = !led_on;
-
- if (led_on)
- spec->gpio_led |= mask;
- else
- spec->gpio_led &= ~mask;
- codec_dbg(codec, "mask:%d enabled:%d gpio_led:%d\n",
- mask, led_on, spec->gpio_led);
- if (spec->gpio_led != oldval)
- snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
- spec->gpio_led);
-}
-
-/* turn on/off mute LED via GPIO per vmaster hook */
-static int cxt_gpio_mute_update(struct led_classdev *led_cdev,
- enum led_brightness brightness)
-{
- struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent);
- struct conexant_spec *spec = codec->spec;
-
- cxt_update_gpio_led(codec, spec->gpio_mute_led_mask, brightness);
- return 0;
-}
-
-/* turn on/off mic-mute LED via GPIO per capture hook */
-static int cxt_gpio_micmute_update(struct led_classdev *led_cdev,
- enum led_brightness brightness)
-{
- struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent);
- struct conexant_spec *spec = codec->spec;
-
- cxt_update_gpio_led(codec, spec->gpio_mic_led_mask, brightness);
- return 0;
-}
-
-static void cxt_setup_mute_led(struct hda_codec *codec,
- unsigned int mute, unsigned int mic_mute)
-{
- struct conexant_spec *spec = codec->spec;
-
- spec->gpio_led = 0;
- spec->mute_led_polarity = 0;
- if (mute) {
- snd_hda_gen_add_mute_led_cdev(codec, cxt_gpio_mute_update);
- spec->gpio_mute_led_mask = mute;
- }
- if (mic_mute) {
- snd_hda_gen_add_micmute_led_cdev(codec, cxt_gpio_micmute_update);
- spec->gpio_mic_led_mask = mic_mute;
- }
-}
-
-static void cxt_setup_gpio_unmute(struct hda_codec *codec,
- unsigned int gpio_mute_mask)
-{
- if (gpio_mute_mask) {
- // set gpio data to 0.
- snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0);
- snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_MASK, gpio_mute_mask);
- snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DIRECTION, gpio_mute_mask);
- snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_STICKY_MASK, 0);
- }
-}
-
-static void cxt_fixup_mute_led_gpio(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_PRE_PROBE)
- cxt_setup_mute_led(codec, 0x01, 0x02);
-}
-
-static void cxt_fixup_hp_zbook_mute_led(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_PRE_PROBE)
- cxt_setup_mute_led(codec, 0x10, 0x20);
-}
-
-static void cxt_fixup_hp_a_u(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- // Init vers in BIOS mute the spk/hp by set gpio high to avoid pop noise,
- // so need to unmute once by clearing the gpio data when runs into the system.
- if (action == HDA_FIXUP_ACT_INIT)
- cxt_setup_gpio_unmute(codec, 0x2);
-}
-
-/* ThinkPad X200 & co with cxt5051 */
-static const struct hda_pintbl cxt_pincfg_lenovo_x200[] = {
- { 0x16, 0x042140ff }, /* HP (seq# overridden) */
- { 0x17, 0x21a11000 }, /* dock-mic */
- { 0x19, 0x2121103f }, /* dock-HP */
- { 0x1c, 0x21440100 }, /* dock SPDIF out */
- {}
-};
-
-/* ThinkPad 410/420/510/520, X201 & co with cxt5066 */
-static const struct hda_pintbl cxt_pincfg_lenovo_tp410[] = {
- { 0x19, 0x042110ff }, /* HP (seq# overridden) */
- { 0x1a, 0x21a190f0 }, /* dock-mic */
- { 0x1c, 0x212140ff }, /* dock-HP */
- {}
-};
-
-/* Lemote A1004/A1205 with cxt5066 */
-static const struct hda_pintbl cxt_pincfg_lemote[] = {
- { 0x1a, 0x90a10020 }, /* Internal mic */
- { 0x1b, 0x03a11020 }, /* External mic */
- { 0x1d, 0x400101f0 }, /* Not used */
- { 0x1e, 0x40a701f0 }, /* Not used */
- { 0x20, 0x404501f0 }, /* Not used */
- { 0x22, 0x404401f0 }, /* Not used */
- { 0x23, 0x40a701f0 }, /* Not used */
- {}
-};
-
-/* SuoWoSi/South-holding JS201D with sn6140 */
-static const struct hda_pintbl cxt_pincfg_sws_js201d[] = {
- { 0x16, 0x03211040 }, /* hp out */
- { 0x17, 0x91170110 }, /* SPK/Class_D */
- { 0x18, 0x95a70130 }, /* Internal mic */
- { 0x19, 0x03a11020 }, /* Headset Mic */
- { 0x1a, 0x40f001f0 }, /* Not used */
- { 0x21, 0x40f001f0 }, /* Not used */
- {}
-};
-
-static const struct hda_fixup cxt_fixups[] = {
- [CXT_PINCFG_LENOVO_X200] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = cxt_pincfg_lenovo_x200,
- },
- [CXT_PINCFG_LENOVO_TP410] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = cxt_pincfg_lenovo_tp410,
- .chained = true,
- .chain_id = CXT_FIXUP_THINKPAD_ACPI,
- },
- [CXT_PINCFG_LEMOTE_A1004] = {
- .type = HDA_FIXUP_PINS,
- .chained = true,
- .chain_id = CXT_FIXUP_INC_MIC_BOOST,
- .v.pins = cxt_pincfg_lemote,
- },
- [CXT_PINCFG_LEMOTE_A1205] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = cxt_pincfg_lemote,
- },
- [CXT_PINCFG_COMPAQ_CQ60] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- /* 0x17 was falsely set up as a mic, it should 0x1d */
- { 0x17, 0x400001f0 },
- { 0x1d, 0x97a70120 },
- { }
- }
- },
- [CXT_FIXUP_STEREO_DMIC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cxt_fixup_stereo_dmic,
- },
- [CXT_PINCFG_LENOVO_NOTEBOOK] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1a, 0x05d71030 },
- { }
- },
- .chain_id = CXT_FIXUP_STEREO_DMIC,
- },
- [CXT_FIXUP_INC_MIC_BOOST] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cxt5066_increase_mic_boost,
- },
- [CXT_FIXUP_HEADPHONE_MIC_PIN] = {
- .type = HDA_FIXUP_PINS,
- .chained = true,
- .chain_id = CXT_FIXUP_HEADPHONE_MIC,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x18, 0x03a1913d }, /* use as headphone mic, without its own jack detect */
- { }
- }
- },
- [CXT_FIXUP_HEADPHONE_MIC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cxt_fixup_headphone_mic,
- },
- [CXT_FIXUP_GPIO1] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- { 0x01, AC_VERB_SET_GPIO_MASK, 0x01 },
- { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01 },
- { 0x01, AC_VERB_SET_GPIO_DATA, 0x01 },
- { }
- },
- },
- [CXT_FIXUP_ASPIRE_DMIC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cxt_fixup_stereo_dmic,
- .chained = true,
- .chain_id = CXT_FIXUP_GPIO1,
- },
- [CXT_FIXUP_THINKPAD_ACPI] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = hda_fixup_thinkpad_acpi,
- },
- [CXT_FIXUP_LENOVO_XPAD_ACPI] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = hda_fixup_ideapad_acpi,
- .chained = true,
- .chain_id = CXT_FIXUP_THINKPAD_ACPI,
- },
- [CXT_FIXUP_OLPC_XO] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cxt_fixup_olpc_xo,
- },
- [CXT_FIXUP_CAP_MIX_AMP] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cxt_fixup_cap_mix_amp,
- },
- [CXT_FIXUP_TOSHIBA_P105] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x10, 0x961701f0 }, /* speaker/hp */
- { 0x12, 0x02a1901e }, /* ext mic */
- { 0x14, 0x95a70110 }, /* int mic */
- {}
- },
- },
- [CXT_FIXUP_HP_530] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x12, 0x90a60160 }, /* int mic */
- {}
- },
- .chained = true,
- .chain_id = CXT_FIXUP_CAP_MIX_AMP,
- },
- [CXT_FIXUP_CAP_MIX_AMP_5047] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cxt_fixup_cap_mix_amp_5047,
- },
- [CXT_FIXUP_MUTE_LED_EAPD] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cxt_fixup_mute_led_eapd,
- },
- [CXT_FIXUP_HP_DOCK] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x16, 0x21011020 }, /* line-out */
- { 0x18, 0x2181103f }, /* line-in */
- { }
- },
- .chained = true,
- .chain_id = CXT_FIXUP_MUTE_LED_GPIO,
- },
- [CXT_FIXUP_HP_SPECTRE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- /* enable NID 0x1d for the speaker on top */
- { 0x1d, 0x91170111 },
- { }
- }
- },
- [CXT_FIXUP_HP_GATE_MIC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cxt_fixup_hp_gate_mic_jack,
- },
- [CXT_FIXUP_MUTE_LED_GPIO] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cxt_fixup_mute_led_gpio,
- },
- [CXT_FIXUP_HP_ELITEONE_OUT_DIS] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cxt_fixup_update_pinctl,
- },
- [CXT_FIXUP_HP_ZBOOK_MUTE_LED] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cxt_fixup_hp_zbook_mute_led,
- },
- [CXT_FIXUP_HEADSET_MIC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cxt_fixup_headset_mic,
- },
- [CXT_FIXUP_HP_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1a, 0x02a1113c },
- { }
- },
- .chained = true,
- .chain_id = CXT_FIXUP_HEADSET_MIC,
- },
- [CXT_PINCFG_SWS_JS201D] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = cxt_pincfg_sws_js201d,
- },
- [CXT_PINCFG_TOP_SPEAKER] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1d, 0x82170111 },
- { }
- },
- },
- [CXT_FIXUP_HP_A_U] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cxt_fixup_hp_a_u,
- },
-};
-
-static const struct hda_quirk cxt5045_fixups[] = {
- SND_PCI_QUIRK(0x103c, 0x30d5, "HP 530", CXT_FIXUP_HP_530),
- SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P105", CXT_FIXUP_TOSHIBA_P105),
- /* HP, Packard Bell, Fujitsu-Siemens & Lenovo laptops have
- * really bad sound over 0dB on NID 0x17.
- */
- SND_PCI_QUIRK_VENDOR(0x103c, "HP", CXT_FIXUP_CAP_MIX_AMP),
- SND_PCI_QUIRK_VENDOR(0x1631, "Packard Bell", CXT_FIXUP_CAP_MIX_AMP),
- SND_PCI_QUIRK_VENDOR(0x1734, "Fujitsu", CXT_FIXUP_CAP_MIX_AMP),
- SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", CXT_FIXUP_CAP_MIX_AMP),
- {}
-};
-
-static const struct hda_model_fixup cxt5045_fixup_models[] = {
- { .id = CXT_FIXUP_CAP_MIX_AMP, .name = "cap-mix-amp" },
- { .id = CXT_FIXUP_TOSHIBA_P105, .name = "toshiba-p105" },
- { .id = CXT_FIXUP_HP_530, .name = "hp-530" },
- {}
-};
-
-static const struct hda_quirk cxt5047_fixups[] = {
- /* HP laptops have really bad sound over 0 dB on NID 0x10.
- */
- SND_PCI_QUIRK_VENDOR(0x103c, "HP", CXT_FIXUP_CAP_MIX_AMP_5047),
- {}
-};
-
-static const struct hda_model_fixup cxt5047_fixup_models[] = {
- { .id = CXT_FIXUP_CAP_MIX_AMP_5047, .name = "cap-mix-amp" },
- {}
-};
-
-static const struct hda_quirk cxt5051_fixups[] = {
- SND_PCI_QUIRK(0x103c, 0x360b, "Compaq CQ60", CXT_PINCFG_COMPAQ_CQ60),
- SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT_PINCFG_LENOVO_X200),
- {}
-};
-
-static const struct hda_model_fixup cxt5051_fixup_models[] = {
- { .id = CXT_PINCFG_LENOVO_X200, .name = "lenovo-x200" },
- {}
-};
-
-static const struct hda_quirk cxt5066_fixups[] = {
- SND_PCI_QUIRK(0x1025, 0x0543, "Acer Aspire One 522", CXT_FIXUP_STEREO_DMIC),
- SND_PCI_QUIRK(0x1025, 0x054c, "Acer Aspire 3830TG", CXT_FIXUP_ASPIRE_DMIC),
- SND_PCI_QUIRK(0x1025, 0x054f, "Acer Aspire 4830T", CXT_FIXUP_ASPIRE_DMIC),
- SND_PCI_QUIRK(0x103c, 0x8079, "HP EliteBook 840 G3", CXT_FIXUP_HP_DOCK),
- SND_PCI_QUIRK(0x103c, 0x807C, "HP EliteBook 820 G3", CXT_FIXUP_HP_DOCK),
- SND_PCI_QUIRK(0x103c, 0x80FD, "HP ProBook 640 G2", CXT_FIXUP_HP_DOCK),
- SND_PCI_QUIRK(0x103c, 0x8115, "HP Z1 Gen3", CXT_FIXUP_HP_GATE_MIC),
- SND_PCI_QUIRK(0x103c, 0x814f, "HP ZBook 15u G3", CXT_FIXUP_MUTE_LED_GPIO),
- SND_PCI_QUIRK(0x103c, 0x8174, "HP Spectre x360", CXT_FIXUP_HP_SPECTRE),
- SND_PCI_QUIRK(0x103c, 0x822e, "HP ProBook 440 G4", CXT_FIXUP_MUTE_LED_GPIO),
- SND_PCI_QUIRK(0x103c, 0x8231, "HP ProBook 450 G4", CXT_FIXUP_MUTE_LED_GPIO),
- SND_PCI_QUIRK(0x103c, 0x828c, "HP EliteBook 840 G4", CXT_FIXUP_HP_DOCK),
- SND_PCI_QUIRK(0x103c, 0x8299, "HP 800 G3 SFF", CXT_FIXUP_HP_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x103c, 0x829a, "HP 800 G3 DM", CXT_FIXUP_HP_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x103c, 0x82b4, "HP ProDesk 600 G3", CXT_FIXUP_HP_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x103c, 0x836e, "HP ProBook 455 G5", CXT_FIXUP_MUTE_LED_GPIO),
- SND_PCI_QUIRK(0x103c, 0x837f, "HP ProBook 470 G5", CXT_FIXUP_MUTE_LED_GPIO),
- SND_PCI_QUIRK(0x103c, 0x83b2, "HP EliteBook 840 G5", CXT_FIXUP_HP_DOCK),
- SND_PCI_QUIRK(0x103c, 0x83b3, "HP EliteBook 830 G5", CXT_FIXUP_HP_DOCK),
- SND_PCI_QUIRK(0x103c, 0x83d3, "HP ProBook 640 G4", CXT_FIXUP_HP_DOCK),
- SND_PCI_QUIRK(0x103c, 0x83e5, "HP EliteOne 1000 G2", CXT_FIXUP_HP_ELITEONE_OUT_DIS),
- SND_PCI_QUIRK(0x103c, 0x8402, "HP ProBook 645 G4", CXT_FIXUP_MUTE_LED_GPIO),
- SND_PCI_QUIRK(0x103c, 0x8427, "HP ZBook Studio G5", CXT_FIXUP_HP_ZBOOK_MUTE_LED),
- SND_PCI_QUIRK(0x103c, 0x844f, "HP ZBook Studio G5", CXT_FIXUP_HP_ZBOOK_MUTE_LED),
- SND_PCI_QUIRK(0x103c, 0x8455, "HP Z2 G4", CXT_FIXUP_HP_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x103c, 0x8456, "HP Z2 G4 SFF", CXT_FIXUP_HP_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x103c, 0x8457, "HP Z2 G4 mini", CXT_FIXUP_HP_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x103c, 0x8458, "HP Z2 G4 mini premium", CXT_FIXUP_HP_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1043, 0x138d, "Asus", CXT_FIXUP_HEADPHONE_MIC_PIN),
- SND_PCI_QUIRK(0x14f1, 0x0252, "MBX-Z60MR100", CXT_FIXUP_HP_A_U),
- SND_PCI_QUIRK(0x14f1, 0x0265, "SWS JS201D", CXT_PINCFG_SWS_JS201D),
- SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT_FIXUP_OLPC_XO),
- SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410),
- SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo T410", CXT_PINCFG_LENOVO_TP410),
- SND_PCI_QUIRK(0x17aa, 0x215f, "Lenovo T510", CXT_PINCFG_LENOVO_TP410),
- SND_PCI_QUIRK(0x17aa, 0x21ce, "Lenovo T420", CXT_PINCFG_LENOVO_TP410),
- SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520", CXT_PINCFG_LENOVO_TP410),
- SND_PCI_QUIRK(0x17aa, 0x21d2, "Lenovo T420s", CXT_PINCFG_LENOVO_TP410),
- SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT_PINCFG_LENOVO_TP410),
- SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT_PINCFG_LENOVO_TP410),
- SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo IdeaPad Z560", CXT_FIXUP_MUTE_LED_EAPD),
- SND_PCI_QUIRK(0x17aa, 0x3905, "Lenovo G50-30", CXT_FIXUP_STEREO_DMIC),
- SND_PCI_QUIRK(0x17aa, 0x390b, "Lenovo G50-80", CXT_FIXUP_STEREO_DMIC),
- SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC),
- /* NOTE: we'd need to extend the quirk for 17aa:3977 as the same
- * PCI SSID is used on multiple Lenovo models
- */
- SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMIC),
- SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo G50-70", CXT_FIXUP_STEREO_DMIC),
- SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC),
- SND_PCI_QUIRK_VENDOR(0x17aa, "Thinkpad/Ideapad", CXT_FIXUP_LENOVO_XPAD_ACPI),
- SND_PCI_QUIRK(0x1c06, 0x2011, "Lemote A1004", CXT_PINCFG_LEMOTE_A1004),
- SND_PCI_QUIRK(0x1c06, 0x2012, "Lemote A1205", CXT_PINCFG_LEMOTE_A1205),
- HDA_CODEC_QUIRK(0x2782, 0x12c3, "Sirius Gen1", CXT_PINCFG_TOP_SPEAKER),
- HDA_CODEC_QUIRK(0x2782, 0x12c5, "Sirius Gen2", CXT_PINCFG_TOP_SPEAKER),
- {}
-};
-
-static const struct hda_model_fixup cxt5066_fixup_models[] = {
- { .id = CXT_FIXUP_STEREO_DMIC, .name = "stereo-dmic" },
- { .id = CXT_FIXUP_GPIO1, .name = "gpio1" },
- { .id = CXT_FIXUP_HEADPHONE_MIC_PIN, .name = "headphone-mic-pin" },
- { .id = CXT_PINCFG_LENOVO_TP410, .name = "tp410" },
- { .id = CXT_FIXUP_THINKPAD_ACPI, .name = "thinkpad" },
- { .id = CXT_FIXUP_LENOVO_XPAD_ACPI, .name = "thinkpad-ideapad" },
- { .id = CXT_PINCFG_LEMOTE_A1004, .name = "lemote-a1004" },
- { .id = CXT_PINCFG_LEMOTE_A1205, .name = "lemote-a1205" },
- { .id = CXT_FIXUP_OLPC_XO, .name = "olpc-xo" },
- { .id = CXT_FIXUP_MUTE_LED_EAPD, .name = "mute-led-eapd" },
- { .id = CXT_FIXUP_HP_DOCK, .name = "hp-dock" },
- { .id = CXT_FIXUP_MUTE_LED_GPIO, .name = "mute-led-gpio" },
- { .id = CXT_FIXUP_HP_ZBOOK_MUTE_LED, .name = "hp-zbook-mute-led" },
- { .id = CXT_FIXUP_HP_MIC_NO_PRESENCE, .name = "hp-mic-fix" },
- { .id = CXT_PINCFG_LENOVO_NOTEBOOK, .name = "lenovo-20149" },
- { .id = CXT_PINCFG_SWS_JS201D, .name = "sws-js201d" },
- { .id = CXT_PINCFG_TOP_SPEAKER, .name = "sirius-top-speaker" },
- { .id = CXT_FIXUP_HP_A_U, .name = "HP-U-support" },
- {}
-};
-
-/* add "fake" mute amp-caps to DACs on cx5051 so that mixer mute switches
- * can be created (bko#42825)
- */
-static void add_cx5051_fake_mutes(struct hda_codec *codec)
-{
- struct conexant_spec *spec = codec->spec;
- static const hda_nid_t out_nids[] = {
- 0x10, 0x11, 0
- };
- const hda_nid_t *p;
-
- for (p = out_nids; *p; p++)
- snd_hda_override_amp_caps(codec, *p, HDA_OUTPUT,
- AC_AMPCAP_MIN_MUTE |
- query_amp_caps(codec, *p, HDA_OUTPUT));
- spec->gen.dac_min_mute = true;
-}
-
-static int patch_conexant_auto(struct hda_codec *codec)
-{
- struct conexant_spec *spec;
- int err;
-
- codec_info(codec, "%s: BIOS auto-probing.\n", codec->core.chip_name);
-
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (!spec)
- return -ENOMEM;
- snd_hda_gen_spec_init(&spec->gen);
- codec->spec = spec;
- codec->patch_ops = cx_auto_patch_ops;
-
- /* init cx8070/sn6140 flag and reset headset_present_flag */
- switch (codec->core.vendor_id) {
- case 0x14f11f86:
- case 0x14f11f87:
- spec->is_cx8070_sn6140 = true;
- snd_hda_jack_detect_enable_callback(codec, 0x19, cx_update_headset_mic_vref);
- break;
- }
-
- cx_auto_parse_eapd(codec);
- spec->gen.own_eapd_ctl = 1;
-
- switch (codec->core.vendor_id) {
- case 0x14f15045:
- codec->single_adc_amp = 1;
- spec->gen.mixer_nid = 0x17;
- spec->gen.add_stereo_mix_input = HDA_HINT_STEREO_MIX_AUTO;
- snd_hda_pick_fixup(codec, cxt5045_fixup_models,
- cxt5045_fixups, cxt_fixups);
- break;
- case 0x14f15047:
- codec->pin_amp_workaround = 1;
- spec->gen.mixer_nid = 0x19;
- spec->gen.add_stereo_mix_input = HDA_HINT_STEREO_MIX_AUTO;
- snd_hda_pick_fixup(codec, cxt5047_fixup_models,
- cxt5047_fixups, cxt_fixups);
- break;
- case 0x14f15051:
- add_cx5051_fake_mutes(codec);
- codec->pin_amp_workaround = 1;
- snd_hda_pick_fixup(codec, cxt5051_fixup_models,
- cxt5051_fixups, cxt_fixups);
- break;
- case 0x14f15098:
- codec->pin_amp_workaround = 1;
- spec->gen.mixer_nid = 0x22;
- spec->gen.add_stereo_mix_input = HDA_HINT_STEREO_MIX_AUTO;
- snd_hda_pick_fixup(codec, cxt5066_fixup_models,
- cxt5066_fixups, cxt_fixups);
- break;
- case 0x14f150f2:
- codec->power_save_node = 1;
- fallthrough;
- default:
- codec->pin_amp_workaround = 1;
- snd_hda_pick_fixup(codec, cxt5066_fixup_models,
- cxt5066_fixups, cxt_fixups);
- break;
- }
-
- if (!spec->gen.vmaster_mute.hook && spec->dynamic_eapd)
- spec->gen.vmaster_mute.hook = cx_auto_vmaster_hook;
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
-
- err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL,
- spec->parse_flags);
- if (err < 0)
- goto error;
-
- err = cx_auto_parse_beep(codec);
- if (err < 0)
- goto error;
-
- err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg);
- if (err < 0)
- goto error;
-
- /* Some laptops with Conexant chips show stalls in S3 resume,
- * which falls into the single-cmd mode.
- * Better to make reset, then.
- */
- if (!codec->bus->core.sync_write) {
- codec_info(codec,
- "Enable sync_write for stable communication\n");
- codec->bus->core.sync_write = 1;
- codec->bus->allow_bus_reset = 1;
- }
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
-
- return 0;
-
- error:
- cx_auto_free(codec);
- return err;
-}
-
-/*
- */
-
-static const struct hda_device_id snd_hda_id_conexant[] = {
- HDA_CODEC_ENTRY(0x14f11f86, "CX8070", patch_conexant_auto),
- HDA_CODEC_ENTRY(0x14f11f87, "SN6140", patch_conexant_auto),
- HDA_CODEC_ENTRY(0x14f12008, "CX8200", patch_conexant_auto),
- HDA_CODEC_ENTRY(0x14f120d0, "CX11970", patch_conexant_auto),
- HDA_CODEC_ENTRY(0x14f120d1, "SN6180", patch_conexant_auto),
- HDA_CODEC_ENTRY(0x14f15045, "CX20549 (Venice)", patch_conexant_auto),
- HDA_CODEC_ENTRY(0x14f15047, "CX20551 (Waikiki)", patch_conexant_auto),
- HDA_CODEC_ENTRY(0x14f15051, "CX20561 (Hermosa)", patch_conexant_auto),
- HDA_CODEC_ENTRY(0x14f15066, "CX20582 (Pebble)", patch_conexant_auto),
- HDA_CODEC_ENTRY(0x14f15067, "CX20583 (Pebble HSF)", patch_conexant_auto),
- HDA_CODEC_ENTRY(0x14f15068, "CX20584", patch_conexant_auto),
- HDA_CODEC_ENTRY(0x14f15069, "CX20585", patch_conexant_auto),
- HDA_CODEC_ENTRY(0x14f1506c, "CX20588", patch_conexant_auto),
- HDA_CODEC_ENTRY(0x14f1506e, "CX20590", patch_conexant_auto),
- HDA_CODEC_ENTRY(0x14f15097, "CX20631", patch_conexant_auto),
- HDA_CODEC_ENTRY(0x14f15098, "CX20632", patch_conexant_auto),
- HDA_CODEC_ENTRY(0x14f150a1, "CX20641", patch_conexant_auto),
- HDA_CODEC_ENTRY(0x14f150a2, "CX20642", patch_conexant_auto),
- HDA_CODEC_ENTRY(0x14f150ab, "CX20651", patch_conexant_auto),
- HDA_CODEC_ENTRY(0x14f150ac, "CX20652", patch_conexant_auto),
- HDA_CODEC_ENTRY(0x14f150b8, "CX20664", patch_conexant_auto),
- HDA_CODEC_ENTRY(0x14f150b9, "CX20665", patch_conexant_auto),
- HDA_CODEC_ENTRY(0x14f150f1, "CX21722", patch_conexant_auto),
- HDA_CODEC_ENTRY(0x14f150f2, "CX20722", patch_conexant_auto),
- HDA_CODEC_ENTRY(0x14f150f3, "CX21724", patch_conexant_auto),
- HDA_CODEC_ENTRY(0x14f150f4, "CX20724", patch_conexant_auto),
- HDA_CODEC_ENTRY(0x14f1510f, "CX20751/2", patch_conexant_auto),
- HDA_CODEC_ENTRY(0x14f15110, "CX20751/2", patch_conexant_auto),
- HDA_CODEC_ENTRY(0x14f15111, "CX20753/4", patch_conexant_auto),
- HDA_CODEC_ENTRY(0x14f15113, "CX20755", patch_conexant_auto),
- HDA_CODEC_ENTRY(0x14f15114, "CX20756", patch_conexant_auto),
- HDA_CODEC_ENTRY(0x14f15115, "CX20757", patch_conexant_auto),
- HDA_CODEC_ENTRY(0x14f151d7, "CX20952", patch_conexant_auto),
- {} /* terminator */
-};
-MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_conexant);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Conexant HD-audio codec");
-
-static struct hda_codec_driver conexant_driver = {
- .id = snd_hda_id_conexant,
-};
-
-module_hda_codec_driver(conexant_driver);
diff --git a/sound/pci/hda/patch_cs8409-tables.c b/sound/pci/hda/patch_cs8409-tables.c
deleted file mode 100644
index 09240138e087..000000000000
--- a/sound/pci/hda/patch_cs8409-tables.c
+++ /dev/null
@@ -1,623 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * patch_cs8409-tables.c -- HD audio interface patch for Cirrus Logic CS8409 HDA bridge chip
- *
- * Copyright (C) 2021 Cirrus Logic, Inc. and
- * Cirrus Logic International Semiconductor Ltd.
- *
- * Author: Lucas Tanure <tanureal@opensource.cirrus.com>
- */
-
-#include "patch_cs8409.h"
-
-/******************************************************************************
- * CS42L42 Specific Data
- *
- ******************************************************************************/
-
-static const DECLARE_TLV_DB_SCALE(cs42l42_dac_db_scale, CS42L42_HP_VOL_REAL_MIN * 100, 100, 1);
-
-static const DECLARE_TLV_DB_SCALE(cs42l42_adc_db_scale, CS42L42_AMIC_VOL_REAL_MIN * 100, 100, 1);
-
-const struct snd_kcontrol_new cs42l42_dac_volume_mixer = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .index = 0,
- .subdevice = (HDA_SUBDEV_AMP_FLAG | HDA_SUBDEV_NID_FLAG),
- .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ),
- .info = cs42l42_volume_info,
- .get = cs42l42_volume_get,
- .put = cs42l42_volume_put,
- .tlv = { .p = cs42l42_dac_db_scale },
- .private_value = HDA_COMPOSE_AMP_VAL_OFS(CS8409_PIN_ASP1_TRANSMITTER_A, 3, CS8409_CODEC0,
- HDA_OUTPUT, CS42L42_VOL_DAC) | HDA_AMP_VAL_MIN_MUTE
-};
-
-const struct snd_kcontrol_new cs42l42_adc_volume_mixer = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .index = 0,
- .subdevice = (HDA_SUBDEV_AMP_FLAG | HDA_SUBDEV_NID_FLAG),
- .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ),
- .info = cs42l42_volume_info,
- .get = cs42l42_volume_get,
- .put = cs42l42_volume_put,
- .tlv = { .p = cs42l42_adc_db_scale },
- .private_value = HDA_COMPOSE_AMP_VAL_OFS(CS8409_PIN_ASP1_RECEIVER_A, 1, CS8409_CODEC0,
- HDA_INPUT, CS42L42_VOL_ADC) | HDA_AMP_VAL_MIN_MUTE
-};
-
-const struct hda_pcm_stream cs42l42_48k_pcm_analog_playback = {
- .rates = SNDRV_PCM_RATE_48000, /* fixed rate */
-};
-
-const struct hda_pcm_stream cs42l42_48k_pcm_analog_capture = {
- .rates = SNDRV_PCM_RATE_48000, /* fixed rate */
-};
-
-/******************************************************************************
- * BULLSEYE / WARLOCK / CYBORG Specific Arrays
- * CS8409/CS42L42
- ******************************************************************************/
-
-const struct hda_verb cs8409_cs42l42_init_verbs[] = {
- { CS8409_PIN_AFG, AC_VERB_SET_GPIO_WAKE_MASK, 0x0018 }, /* WAKE from GPIO 3,4 */
- { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_PROC_STATE, 0x0001 }, /* Enable VPW processing */
- { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_COEF_INDEX, 0x0002 }, /* Configure GPIO 6,7 */
- { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_PROC_COEF, 0x0080 }, /* I2C mode */
- { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_COEF_INDEX, 0x005b }, /* Set I2C bus speed */
- { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_PROC_COEF, 0x0200 }, /* 100kHz I2C_STO = 2 */
- {} /* terminator */
-};
-
-static const struct hda_pintbl cs8409_cs42l42_pincfgs[] = {
- { CS8409_PIN_ASP1_TRANSMITTER_A, 0x042120f0 }, /* ASP-1-TX */
- { CS8409_PIN_ASP1_RECEIVER_A, 0x04a12050 }, /* ASP-1-RX */
- { CS8409_PIN_ASP2_TRANSMITTER_A, 0x901000f0 }, /* ASP-2-TX */
- { CS8409_PIN_DMIC1_IN, 0x90a00090 }, /* DMIC-1 */
- {} /* terminator */
-};
-
-static const struct hda_pintbl cs8409_cs42l42_pincfgs_no_dmic[] = {
- { CS8409_PIN_ASP1_TRANSMITTER_A, 0x042120f0 }, /* ASP-1-TX */
- { CS8409_PIN_ASP1_RECEIVER_A, 0x04a12050 }, /* ASP-1-RX */
- { CS8409_PIN_ASP2_TRANSMITTER_A, 0x901000f0 }, /* ASP-2-TX */
- {} /* terminator */
-};
-
-/* Vendor specific HW configuration for CS42L42 */
-static const struct cs8409_i2c_param cs42l42_init_reg_seq[] = {
- { CS42L42_I2C_TIMEOUT, 0xB0 },
- { CS42L42_ADC_CTL, 0x00 },
- { 0x1D02, 0x06 },
- { CS42L42_ADC_VOLUME, 0x9F },
- { CS42L42_OSC_SWITCH, 0x01 },
- { CS42L42_MCLK_CTL, 0x02 },
- { CS42L42_SRC_CTL, 0x03 },
- { CS42L42_MCLK_SRC_SEL, 0x00 },
- { CS42L42_ASP_FRM_CFG, 0x13 },
- { CS42L42_FSYNC_P_LOWER, 0xFF },
- { CS42L42_FSYNC_P_UPPER, 0x00 },
- { CS42L42_ASP_CLK_CFG, 0x20 },
- { CS42L42_SPDIF_CLK_CFG, 0x0D },
- { CS42L42_ASP_RX_DAI0_CH1_AP_RES, 0x02 },
- { CS42L42_ASP_RX_DAI0_CH1_BIT_MSB, 0x00 },
- { CS42L42_ASP_RX_DAI0_CH1_BIT_LSB, 0x00 },
- { CS42L42_ASP_RX_DAI0_CH2_AP_RES, 0x02 },
- { CS42L42_ASP_RX_DAI0_CH2_BIT_MSB, 0x00 },
- { CS42L42_ASP_RX_DAI0_CH2_BIT_LSB, 0x20 },
- { CS42L42_ASP_RX_DAI0_CH3_AP_RES, 0x02 },
- { CS42L42_ASP_RX_DAI0_CH3_BIT_MSB, 0x00 },
- { CS42L42_ASP_RX_DAI0_CH3_BIT_LSB, 0x80 },
- { CS42L42_ASP_RX_DAI0_CH4_AP_RES, 0x02 },
- { CS42L42_ASP_RX_DAI0_CH4_BIT_MSB, 0x00 },
- { CS42L42_ASP_RX_DAI0_CH4_BIT_LSB, 0xA0 },
- { CS42L42_ASP_RX_DAI0_EN, 0x0C },
- { CS42L42_ASP_TX_CH_EN, 0x01 },
- { CS42L42_ASP_TX_CH_AP_RES, 0x02 },
- { CS42L42_ASP_TX_CH1_BIT_MSB, 0x00 },
- { CS42L42_ASP_TX_CH1_BIT_LSB, 0x00 },
- { CS42L42_ASP_TX_SZ_EN, 0x01 },
- { CS42L42_PWR_CTL1, 0x0A },
- { CS42L42_PWR_CTL2, 0x84 },
- { CS42L42_MIXER_CHA_VOL, 0x3F },
- { CS42L42_MIXER_CHB_VOL, 0x3F },
- { CS42L42_MIXER_ADC_VOL, 0x3f },
- { CS42L42_HP_CTL, 0x0D },
- { CS42L42_MIC_DET_CTL1, 0xB6 },
- { CS42L42_TIPSENSE_CTL, 0xC2 },
- { CS42L42_HS_CLAMP_DISABLE, 0x01 },
- { CS42L42_HS_SWITCH_CTL, 0xF3 },
- { CS42L42_PWR_CTL3, 0x20 },
- { CS42L42_RSENSE_CTL2, 0x00 },
- { CS42L42_RSENSE_CTL3, 0x00 },
- { CS42L42_TSENSE_CTL, 0x80 },
- { CS42L42_HS_BIAS_CTL, 0xC0 },
- { CS42L42_PWR_CTL1, 0x02, 10000 },
- { CS42L42_ADC_OVFL_INT_MASK, 0xff },
- { CS42L42_MIXER_INT_MASK, 0xff },
- { CS42L42_SRC_INT_MASK, 0xff },
- { CS42L42_ASP_RX_INT_MASK, 0xff },
- { CS42L42_ASP_TX_INT_MASK, 0xff },
- { CS42L42_CODEC_INT_MASK, 0xff },
- { CS42L42_SRCPL_INT_MASK, 0xff },
- { CS42L42_VPMON_INT_MASK, 0xff },
- { CS42L42_PLL_LOCK_INT_MASK, 0xff },
- { CS42L42_TSRS_PLUG_INT_MASK, 0xff },
- { CS42L42_DET_INT1_MASK, 0xff },
- { CS42L42_DET_INT2_MASK, 0xff },
-};
-
-/* Vendor specific hw configuration for CS8409 */
-const struct cs8409_cir_param cs8409_cs42l42_hw_cfg[] = {
- /* +PLL1/2_EN, +I2C_EN */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG1, 0xb008 },
- /* ASP1/2_EN=0, ASP1_STP=1 */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG2, 0x0002 },
- /* ASP1/2_BUS_IDLE=10, +GPIO_I2C */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG3, 0x0a80 },
- /* ASP1.A: TX.LAP=0, TX.LSZ=24 bits, TX.LCS=0 */
- { CS8409_PIN_VENDOR_WIDGET, ASP1_A_TX_CTRL1, 0x0800 },
- /* ASP1.A: TX.RAP=0, TX.RSZ=24 bits, TX.RCS=32 */
- { CS8409_PIN_VENDOR_WIDGET, ASP1_A_TX_CTRL2, 0x0820 },
- /* ASP2.A: TX.LAP=0, TX.LSZ=24 bits, TX.LCS=0 */
- { CS8409_PIN_VENDOR_WIDGET, ASP2_A_TX_CTRL1, 0x0800 },
- /* ASP2.A: TX.RAP=1, TX.RSZ=24 bits, TX.RCS=0 */
- { CS8409_PIN_VENDOR_WIDGET, ASP2_A_TX_CTRL2, 0x2800 },
- /* ASP1.A: RX.LAP=0, RX.LSZ=24 bits, RX.LCS=0 */
- { CS8409_PIN_VENDOR_WIDGET, ASP1_A_RX_CTRL1, 0x0800 },
- /* ASP1.A: RX.RAP=0, RX.RSZ=24 bits, RX.RCS=0 */
- { CS8409_PIN_VENDOR_WIDGET, ASP1_A_RX_CTRL2, 0x0800 },
- /* ASP1: LCHI = 00h */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP1_CLK_CTRL1, 0x8000 },
- /* ASP1: MC/SC_SRCSEL=PLL1, LCPR=FFh */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP1_CLK_CTRL2, 0x28ff },
- /* ASP1: MCEN=0, FSD=011, SCPOL_IN/OUT=0, SCDIV=1:4 */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP1_CLK_CTRL3, 0x0062 },
- /* ASP2: LCHI=1Fh */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP2_CLK_CTRL1, 0x801f },
- /* ASP2: MC/SC_SRCSEL=PLL1, LCPR=3Fh */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP2_CLK_CTRL2, 0x283f },
- /* ASP2: 5050=1, MCEN=0, FSD=010, SCPOL_IN/OUT=1, SCDIV=1:16 */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP2_CLK_CTRL3, 0x805c },
- /* DMIC1_MO=10b, DMIC1/2_SR=1 */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_DMIC_CFG, 0x0023 },
- /* ASP1/2_BEEP=0 */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_BEEP_CFG, 0x0000 },
- /* ASP1/2_EN=1, ASP1_STP=1 */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG2, 0x0062 },
- /* -PLL2_EN */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG1, 0x9008 },
- /* TX2.A: pre-scale att.=0 dB */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_PRE_SCALE_ATTN2, 0x0000 },
- /* ASP1/2_xxx_EN=1, ASP1/2_MCLK_EN=0, DMIC1_SCL_EN=1 */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_PAD_CFG_SLW_RATE_CTRL, 0xfc03 },
- /* test mode on */
- { CS8409_PIN_VENDOR_WIDGET, 0xc0, 0x9999 },
- /* GPIO hysteresis = 30 us */
- { CS8409_PIN_VENDOR_WIDGET, 0xc5, 0x0000 },
- /* test mode off */
- { CS8409_PIN_VENDOR_WIDGET, 0xc0, 0x0000 },
- {} /* Terminator */
-};
-
-const struct cs8409_cir_param cs8409_cs42l42_bullseye_atn[] = {
- /* EQ_SEL=1, EQ1/2_EN=0 */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_CTRL1, 0x4000 },
- /* +EQ_ACC */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0x4000 },
- /* +EQ2_EN */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_CTRL1, 0x4010 },
- /* EQ_DATA_HI=0x0647 */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0x0647 },
- /* +EQ_WRT, +EQ_ACC, EQ_ADR=0, EQ_DATA_LO=0x67 */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc0c7 },
- /* EQ_DATA_HI=0x0647 */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0x0647 },
- /* +EQ_WRT, +EQ_ACC, EQ_ADR=1, EQ_DATA_LO=0x67 */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc1c7 },
- /* EQ_DATA_HI=0xf370 */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0xf370 },
- /* +EQ_WRT, +EQ_ACC, EQ_ADR=2, EQ_DATA_LO=0x71 */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc271 },
- /* EQ_DATA_HI=0x1ef8 */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0x1ef8 },
- /* +EQ_WRT, +EQ_ACC, EQ_ADR=3, EQ_DATA_LO=0x48 */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc348 },
- /* EQ_DATA_HI=0xc110 */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0xc110 },
- /* +EQ_WRT, +EQ_ACC, EQ_ADR=4, EQ_DATA_LO=0x5a */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc45a },
- /* EQ_DATA_HI=0x1f29 */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0x1f29 },
- /* +EQ_WRT, +EQ_ACC, EQ_ADR=5, EQ_DATA_LO=0x74 */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc574 },
- /* EQ_DATA_HI=0x1d7a */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0x1d7a },
- /* +EQ_WRT, +EQ_ACC, EQ_ADR=6, EQ_DATA_LO=0x53 */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc653 },
- /* EQ_DATA_HI=0xc38c */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0xc38c },
- /* +EQ_WRT, +EQ_ACC, EQ_ADR=7, EQ_DATA_LO=0x14 */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc714 },
- /* EQ_DATA_HI=0x1ca3 */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0x1ca3 },
- /* +EQ_WRT, +EQ_ACC, EQ_ADR=8, EQ_DATA_LO=0xc7 */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc8c7 },
- /* EQ_DATA_HI=0xc38c */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W1, 0xc38c },
- /* +EQ_WRT, +EQ_ACC, EQ_ADR=9, EQ_DATA_LO=0x14 */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0xc914 },
- /* -EQ_ACC, -EQ_WRT */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_PFE_COEF_W2, 0x0000 },
- {} /* Terminator */
-};
-
-struct sub_codec cs8409_cs42l42_codec = {
- .addr = CS42L42_I2C_ADDR,
- .reset_gpio = CS8409_CS42L42_RESET,
- .irq_mask = CS8409_CS42L42_INT,
- .init_seq = cs42l42_init_reg_seq,
- .init_seq_num = ARRAY_SIZE(cs42l42_init_reg_seq),
- .hp_jack_in = 0,
- .mic_jack_in = 0,
- .paged = 1,
- .suspended = 1,
- .no_type_dect = 0,
-};
-
-/******************************************************************************
- * Dolphin Specific Arrays
- * CS8409/ 2 X CS42L42
- ******************************************************************************/
-
-const struct hda_verb dolphin_init_verbs[] = {
- { 0x01, AC_VERB_SET_GPIO_WAKE_MASK, DOLPHIN_WAKE }, /* WAKE from GPIO 0,4 */
- { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_PROC_STATE, 0x0001 }, /* Enable VPW processing */
- { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_COEF_INDEX, 0x0002 }, /* Configure GPIO 6,7 */
- { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_PROC_COEF, 0x0080 }, /* I2C mode */
- { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_COEF_INDEX, 0x005b }, /* Set I2C bus speed */
- { CS8409_PIN_VENDOR_WIDGET, AC_VERB_SET_PROC_COEF, 0x0200 }, /* 100kHz I2C_STO = 2 */
- {} /* terminator */
-};
-
-static const struct hda_pintbl dolphin_pincfgs[] = {
- { 0x24, 0x022210f0 }, /* ASP-1-TX-A */
- { 0x25, 0x010240f0 }, /* ASP-1-TX-B */
- { 0x34, 0x02a21050 }, /* ASP-1-RX */
- {} /* terminator */
-};
-
-/* Vendor specific HW configuration for CS42L42 */
-static const struct cs8409_i2c_param dolphin_c0_init_reg_seq[] = {
- { CS42L42_I2C_TIMEOUT, 0xB0 },
- { CS42L42_ADC_CTL, 0x00 },
- { 0x1D02, 0x06 },
- { CS42L42_ADC_VOLUME, 0x9F },
- { CS42L42_OSC_SWITCH, 0x01 },
- { CS42L42_MCLK_CTL, 0x02 },
- { CS42L42_SRC_CTL, 0x03 },
- { CS42L42_MCLK_SRC_SEL, 0x00 },
- { CS42L42_ASP_FRM_CFG, 0x13 },
- { CS42L42_FSYNC_P_LOWER, 0xFF },
- { CS42L42_FSYNC_P_UPPER, 0x00 },
- { CS42L42_ASP_CLK_CFG, 0x20 },
- { CS42L42_SPDIF_CLK_CFG, 0x0D },
- { CS42L42_ASP_RX_DAI0_CH1_AP_RES, 0x02 },
- { CS42L42_ASP_RX_DAI0_CH1_BIT_MSB, 0x00 },
- { CS42L42_ASP_RX_DAI0_CH1_BIT_LSB, 0x00 },
- { CS42L42_ASP_RX_DAI0_CH2_AP_RES, 0x02 },
- { CS42L42_ASP_RX_DAI0_CH2_BIT_MSB, 0x00 },
- { CS42L42_ASP_RX_DAI0_CH2_BIT_LSB, 0x20 },
- { CS42L42_ASP_RX_DAI0_EN, 0x0C },
- { CS42L42_ASP_TX_CH_EN, 0x01 },
- { CS42L42_ASP_TX_CH_AP_RES, 0x02 },
- { CS42L42_ASP_TX_CH1_BIT_MSB, 0x00 },
- { CS42L42_ASP_TX_CH1_BIT_LSB, 0x00 },
- { CS42L42_ASP_TX_SZ_EN, 0x01 },
- { CS42L42_PWR_CTL1, 0x0A },
- { CS42L42_PWR_CTL2, 0x84 },
- { CS42L42_HP_CTL, 0x0D },
- { CS42L42_MIXER_CHA_VOL, 0x3F },
- { CS42L42_MIXER_CHB_VOL, 0x3F },
- { CS42L42_MIXER_ADC_VOL, 0x3f },
- { CS42L42_MIC_DET_CTL1, 0xB6 },
- { CS42L42_TIPSENSE_CTL, 0xC2 },
- { CS42L42_HS_CLAMP_DISABLE, 0x01 },
- { CS42L42_HS_SWITCH_CTL, 0xF3 },
- { CS42L42_PWR_CTL3, 0x20 },
- { CS42L42_RSENSE_CTL2, 0x00 },
- { CS42L42_RSENSE_CTL3, 0x00 },
- { CS42L42_TSENSE_CTL, 0x80 },
- { CS42L42_HS_BIAS_CTL, 0xC0 },
- { CS42L42_PWR_CTL1, 0x02, 10000 },
- { CS42L42_ADC_OVFL_INT_MASK, 0xff },
- { CS42L42_MIXER_INT_MASK, 0xff },
- { CS42L42_SRC_INT_MASK, 0xff },
- { CS42L42_ASP_RX_INT_MASK, 0xff },
- { CS42L42_ASP_TX_INT_MASK, 0xff },
- { CS42L42_CODEC_INT_MASK, 0xff },
- { CS42L42_SRCPL_INT_MASK, 0xff },
- { CS42L42_VPMON_INT_MASK, 0xff },
- { CS42L42_PLL_LOCK_INT_MASK, 0xff },
- { CS42L42_TSRS_PLUG_INT_MASK, 0xff },
- { CS42L42_DET_INT1_MASK, 0xff },
- { CS42L42_DET_INT2_MASK, 0xff }
-};
-
-static const struct cs8409_i2c_param dolphin_c1_init_reg_seq[] = {
- { CS42L42_I2C_TIMEOUT, 0xB0 },
- { CS42L42_ADC_CTL, 0x00 },
- { 0x1D02, 0x06 },
- { CS42L42_ADC_VOLUME, 0x9F },
- { CS42L42_OSC_SWITCH, 0x01 },
- { CS42L42_MCLK_CTL, 0x02 },
- { CS42L42_SRC_CTL, 0x03 },
- { CS42L42_MCLK_SRC_SEL, 0x00 },
- { CS42L42_ASP_FRM_CFG, 0x13 },
- { CS42L42_FSYNC_P_LOWER, 0xFF },
- { CS42L42_FSYNC_P_UPPER, 0x00 },
- { CS42L42_ASP_CLK_CFG, 0x20 },
- { CS42L42_SPDIF_CLK_CFG, 0x0D },
- { CS42L42_ASP_RX_DAI0_CH1_AP_RES, 0x02 },
- { CS42L42_ASP_RX_DAI0_CH1_BIT_MSB, 0x00 },
- { CS42L42_ASP_RX_DAI0_CH1_BIT_LSB, 0x80 },
- { CS42L42_ASP_RX_DAI0_CH2_AP_RES, 0x02 },
- { CS42L42_ASP_RX_DAI0_CH2_BIT_MSB, 0x00 },
- { CS42L42_ASP_RX_DAI0_CH2_BIT_LSB, 0xA0 },
- { CS42L42_ASP_RX_DAI0_EN, 0x0C },
- { CS42L42_ASP_TX_CH_EN, 0x00 },
- { CS42L42_ASP_TX_CH_AP_RES, 0x02 },
- { CS42L42_ASP_TX_CH1_BIT_MSB, 0x00 },
- { CS42L42_ASP_TX_CH1_BIT_LSB, 0x00 },
- { CS42L42_ASP_TX_SZ_EN, 0x00 },
- { CS42L42_PWR_CTL1, 0x0E },
- { CS42L42_PWR_CTL2, 0x84 },
- { CS42L42_HP_CTL, 0x0D },
- { CS42L42_MIXER_CHA_VOL, 0x3F },
- { CS42L42_MIXER_CHB_VOL, 0x3F },
- { CS42L42_MIXER_ADC_VOL, 0x3f },
- { CS42L42_MIC_DET_CTL1, 0xB6 },
- { CS42L42_TIPSENSE_CTL, 0xC2 },
- { CS42L42_HS_CLAMP_DISABLE, 0x01 },
- { CS42L42_HS_SWITCH_CTL, 0xF3 },
- { CS42L42_PWR_CTL3, 0x20 },
- { CS42L42_RSENSE_CTL2, 0x00 },
- { CS42L42_RSENSE_CTL3, 0x00 },
- { CS42L42_TSENSE_CTL, 0x80 },
- { CS42L42_HS_BIAS_CTL, 0xC0 },
- { CS42L42_PWR_CTL1, 0x06, 10000 },
- { CS42L42_ADC_OVFL_INT_MASK, 0xff },
- { CS42L42_MIXER_INT_MASK, 0xff },
- { CS42L42_SRC_INT_MASK, 0xff },
- { CS42L42_ASP_RX_INT_MASK, 0xff },
- { CS42L42_ASP_TX_INT_MASK, 0xff },
- { CS42L42_CODEC_INT_MASK, 0xff },
- { CS42L42_SRCPL_INT_MASK, 0xff },
- { CS42L42_VPMON_INT_MASK, 0xff },
- { CS42L42_PLL_LOCK_INT_MASK, 0xff },
- { CS42L42_TSRS_PLUG_INT_MASK, 0xff },
- { CS42L42_DET_INT1_MASK, 0xff },
- { CS42L42_DET_INT2_MASK, 0xff }
-};
-
-/* Vendor specific hw configuration for CS8409 */
-const struct cs8409_cir_param dolphin_hw_cfg[] = {
- /* +PLL1/2_EN, +I2C_EN */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG1, 0xb008 },
- /* ASP1_EN=0, ASP1_STP=1 */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG2, 0x0002 },
- /* ASP1/2_BUS_IDLE=10, +GPIO_I2C */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG3, 0x0a80 },
- /* ASP1.A: TX.LAP=0, TX.LSZ=24 bits, TX.LCS=0 */
- { CS8409_PIN_VENDOR_WIDGET, ASP1_A_TX_CTRL1, 0x0800 },
- /* ASP1.A: TX.RAP=0, TX.RSZ=24 bits, TX.RCS=32 */
- { CS8409_PIN_VENDOR_WIDGET, ASP1_A_TX_CTRL2, 0x0820 },
- /* ASP1.B: TX.LAP=0, TX.LSZ=24 bits, TX.LCS=128 */
- { CS8409_PIN_VENDOR_WIDGET, ASP1_B_TX_CTRL1, 0x0880 },
- /* ASP1.B: TX.RAP=0, TX.RSZ=24 bits, TX.RCS=160 */
- { CS8409_PIN_VENDOR_WIDGET, ASP1_B_TX_CTRL2, 0x08a0 },
- /* ASP1.A: RX.LAP=0, RX.LSZ=24 bits, RX.LCS=0 */
- { CS8409_PIN_VENDOR_WIDGET, ASP1_A_RX_CTRL1, 0x0800 },
- /* ASP1.A: RX.RAP=0, RX.RSZ=24 bits, RX.RCS=0 */
- { CS8409_PIN_VENDOR_WIDGET, ASP1_A_RX_CTRL2, 0x0800 },
- /* ASP1: LCHI = 00h */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP1_CLK_CTRL1, 0x8000 },
- /* ASP1: MC/SC_SRCSEL=PLL1, LCPR=FFh */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP1_CLK_CTRL2, 0x28ff },
- /* ASP1: MCEN=0, FSD=011, SCPOL_IN/OUT=0, SCDIV=1:4 */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_ASP1_CLK_CTRL3, 0x0062 },
- /* ASP1/2_BEEP=0 */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_BEEP_CFG, 0x0000 },
- /* ASP1_EN=1, ASP1_STP=1 */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG2, 0x0022 },
- /* -PLL2_EN */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_DEV_CFG1, 0x9008 },
- /* ASP1_xxx_EN=1, ASP1_MCLK_EN=0 */
- { CS8409_PIN_VENDOR_WIDGET, CS8409_PAD_CFG_SLW_RATE_CTRL, 0x5400 },
- /* test mode on */
- { CS8409_PIN_VENDOR_WIDGET, 0xc0, 0x9999 },
- /* GPIO hysteresis = 30 us */
- { CS8409_PIN_VENDOR_WIDGET, 0xc5, 0x0000 },
- /* test mode off */
- { CS8409_PIN_VENDOR_WIDGET, 0xc0, 0x0000 },
- {} /* Terminator */
-};
-
-struct sub_codec dolphin_cs42l42_0 = {
- .addr = DOLPHIN_C0_I2C_ADDR,
- .reset_gpio = DOLPHIN_C0_RESET,
- .irq_mask = DOLPHIN_C0_INT,
- .init_seq = dolphin_c0_init_reg_seq,
- .init_seq_num = ARRAY_SIZE(dolphin_c0_init_reg_seq),
- .hp_jack_in = 0,
- .mic_jack_in = 0,
- .paged = 1,
- .suspended = 1,
- .no_type_dect = 0,
-};
-
-struct sub_codec dolphin_cs42l42_1 = {
- .addr = DOLPHIN_C1_I2C_ADDR,
- .reset_gpio = DOLPHIN_C1_RESET,
- .irq_mask = DOLPHIN_C1_INT,
- .init_seq = dolphin_c1_init_reg_seq,
- .init_seq_num = ARRAY_SIZE(dolphin_c1_init_reg_seq),
- .hp_jack_in = 0,
- .mic_jack_in = 0,
- .paged = 1,
- .suspended = 1,
- .no_type_dect = 1,
-};
-
-/******************************************************************************
- * CS8409 Patch Driver Structs
- * Arrays Used for all projects using CS8409
- ******************************************************************************/
-
-const struct hda_quirk cs8409_fixup_tbl[] = {
- SND_PCI_QUIRK(0x1028, 0x0A11, "Bullseye", CS8409_BULLSEYE),
- SND_PCI_QUIRK(0x1028, 0x0A12, "Bullseye", CS8409_BULLSEYE),
- SND_PCI_QUIRK(0x1028, 0x0A23, "Bullseye", CS8409_BULLSEYE),
- SND_PCI_QUIRK(0x1028, 0x0A24, "Bullseye", CS8409_BULLSEYE),
- SND_PCI_QUIRK(0x1028, 0x0A25, "Bullseye", CS8409_BULLSEYE),
- SND_PCI_QUIRK(0x1028, 0x0A29, "Bullseye", CS8409_BULLSEYE),
- SND_PCI_QUIRK(0x1028, 0x0A2A, "Bullseye", CS8409_BULLSEYE),
- SND_PCI_QUIRK(0x1028, 0x0A2B, "Bullseye", CS8409_BULLSEYE),
- SND_PCI_QUIRK(0x1028, 0x0A77, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0A78, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0A79, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0A7A, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0A7D, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0A7E, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0A7F, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0A80, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0AB0, "Warlock", CS8409_WARLOCK),
- SND_PCI_QUIRK(0x1028, 0x0AB2, "Warlock", CS8409_WARLOCK),
- SND_PCI_QUIRK(0x1028, 0x0AB1, "Warlock", CS8409_WARLOCK),
- SND_PCI_QUIRK(0x1028, 0x0AB3, "Warlock", CS8409_WARLOCK),
- SND_PCI_QUIRK(0x1028, 0x0AB4, "Warlock", CS8409_WARLOCK),
- SND_PCI_QUIRK(0x1028, 0x0AB5, "Warlock", CS8409_WARLOCK),
- SND_PCI_QUIRK(0x1028, 0x0ACF, "Dolphin", CS8409_DOLPHIN),
- SND_PCI_QUIRK(0x1028, 0x0AD0, "Dolphin", CS8409_DOLPHIN),
- SND_PCI_QUIRK(0x1028, 0x0AD1, "Dolphin", CS8409_DOLPHIN),
- SND_PCI_QUIRK(0x1028, 0x0AD2, "Dolphin", CS8409_DOLPHIN),
- SND_PCI_QUIRK(0x1028, 0x0AD3, "Dolphin", CS8409_DOLPHIN),
- SND_PCI_QUIRK(0x1028, 0x0AD9, "Warlock", CS8409_WARLOCK),
- SND_PCI_QUIRK(0x1028, 0x0ADA, "Warlock", CS8409_WARLOCK),
- SND_PCI_QUIRK(0x1028, 0x0ADB, "Warlock", CS8409_WARLOCK),
- SND_PCI_QUIRK(0x1028, 0x0ADC, "Warlock", CS8409_WARLOCK),
- SND_PCI_QUIRK(0x1028, 0x0ADF, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0AE0, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0AE1, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0AE2, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0AE9, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0AEA, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0AEB, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0AEC, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0AED, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0AEE, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0AEF, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0AF0, "Cyborg", CS8409_CYBORG),
- SND_PCI_QUIRK(0x1028, 0x0AF4, "Warlock", CS8409_WARLOCK),
- SND_PCI_QUIRK(0x1028, 0x0AF5, "Warlock", CS8409_WARLOCK),
- SND_PCI_QUIRK(0x1028, 0x0B92, "Warlock MLK", CS8409_WARLOCK_MLK),
- SND_PCI_QUIRK(0x1028, 0x0B93, "Warlock MLK Dual Mic", CS8409_WARLOCK_MLK_DUAL_MIC),
- SND_PCI_QUIRK(0x1028, 0x0B94, "Warlock MLK", CS8409_WARLOCK_MLK),
- SND_PCI_QUIRK(0x1028, 0x0B95, "Warlock MLK Dual Mic", CS8409_WARLOCK_MLK_DUAL_MIC),
- SND_PCI_QUIRK(0x1028, 0x0B96, "Warlock MLK", CS8409_WARLOCK_MLK),
- SND_PCI_QUIRK(0x1028, 0x0B97, "Warlock MLK Dual Mic", CS8409_WARLOCK_MLK_DUAL_MIC),
- SND_PCI_QUIRK(0x1028, 0x0BA5, "Odin", CS8409_ODIN),
- SND_PCI_QUIRK(0x1028, 0x0BA6, "Odin", CS8409_ODIN),
- SND_PCI_QUIRK(0x1028, 0x0BA8, "Odin", CS8409_ODIN),
- SND_PCI_QUIRK(0x1028, 0x0BAA, "Odin", CS8409_ODIN),
- SND_PCI_QUIRK(0x1028, 0x0BAE, "Odin", CS8409_ODIN),
- SND_PCI_QUIRK(0x1028, 0x0BB2, "Warlock MLK", CS8409_WARLOCK_MLK),
- SND_PCI_QUIRK(0x1028, 0x0BB3, "Warlock MLK", CS8409_WARLOCK_MLK),
- SND_PCI_QUIRK(0x1028, 0x0BB4, "Warlock MLK", CS8409_WARLOCK_MLK),
- SND_PCI_QUIRK(0x1028, 0x0BB5, "Warlock N3 15 TGL-U Nuvoton EC", CS8409_WARLOCK),
- SND_PCI_QUIRK(0x1028, 0x0BB6, "Warlock V3 15 TGL-U Nuvoton EC", CS8409_WARLOCK),
- SND_PCI_QUIRK(0x1028, 0x0BB8, "Warlock MLK", CS8409_WARLOCK_MLK),
- SND_PCI_QUIRK(0x1028, 0x0BB9, "Warlock MLK Dual Mic", CS8409_WARLOCK_MLK_DUAL_MIC),
- SND_PCI_QUIRK(0x1028, 0x0BBA, "Warlock MLK", CS8409_WARLOCK_MLK),
- SND_PCI_QUIRK(0x1028, 0x0BBB, "Warlock MLK Dual Mic", CS8409_WARLOCK_MLK_DUAL_MIC),
- SND_PCI_QUIRK(0x1028, 0x0BBC, "Warlock MLK", CS8409_WARLOCK_MLK),
- SND_PCI_QUIRK(0x1028, 0x0BBD, "Warlock MLK Dual Mic", CS8409_WARLOCK_MLK_DUAL_MIC),
- SND_PCI_QUIRK(0x1028, 0x0BD4, "Dolphin", CS8409_DOLPHIN),
- SND_PCI_QUIRK(0x1028, 0x0BD5, "Dolphin", CS8409_DOLPHIN),
- SND_PCI_QUIRK(0x1028, 0x0BD6, "Dolphin", CS8409_DOLPHIN),
- SND_PCI_QUIRK(0x1028, 0x0BD7, "Dolphin", CS8409_DOLPHIN),
- SND_PCI_QUIRK(0x1028, 0x0BD8, "Dolphin", CS8409_DOLPHIN),
- SND_PCI_QUIRK(0x1028, 0x0C43, "Dolphin", CS8409_DOLPHIN),
- SND_PCI_QUIRK(0x1028, 0x0C50, "Dolphin", CS8409_DOLPHIN),
- SND_PCI_QUIRK(0x1028, 0x0C51, "Dolphin", CS8409_DOLPHIN),
- SND_PCI_QUIRK(0x1028, 0x0C52, "Dolphin", CS8409_DOLPHIN),
- SND_PCI_QUIRK(0x1028, 0x0C73, "Dolphin", CS8409_DOLPHIN),
- SND_PCI_QUIRK(0x1028, 0x0C75, "Dolphin", CS8409_DOLPHIN),
- SND_PCI_QUIRK(0x1028, 0x0C7D, "Dolphin", CS8409_DOLPHIN),
- SND_PCI_QUIRK(0x1028, 0x0C7F, "Dolphin", CS8409_DOLPHIN),
- {} /* terminator */
-};
-
-/* Dell Inspiron models with cs8409/cs42l42 */
-const struct hda_model_fixup cs8409_models[] = {
- { .id = CS8409_BULLSEYE, .name = "bullseye" },
- { .id = CS8409_WARLOCK, .name = "warlock" },
- { .id = CS8409_WARLOCK_MLK, .name = "warlock mlk" },
- { .id = CS8409_WARLOCK_MLK_DUAL_MIC, .name = "warlock mlk dual mic" },
- { .id = CS8409_CYBORG, .name = "cyborg" },
- { .id = CS8409_DOLPHIN, .name = "dolphin" },
- { .id = CS8409_ODIN, .name = "odin" },
- {}
-};
-
-const struct hda_fixup cs8409_fixups[] = {
- [CS8409_BULLSEYE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = cs8409_cs42l42_pincfgs,
- .chained = true,
- .chain_id = CS8409_FIXUPS,
- },
- [CS8409_WARLOCK] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = cs8409_cs42l42_pincfgs,
- .chained = true,
- .chain_id = CS8409_FIXUPS,
- },
- [CS8409_WARLOCK_MLK] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = cs8409_cs42l42_pincfgs,
- .chained = true,
- .chain_id = CS8409_FIXUPS,
- },
- [CS8409_WARLOCK_MLK_DUAL_MIC] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = cs8409_cs42l42_pincfgs,
- .chained = true,
- .chain_id = CS8409_FIXUPS,
- },
- [CS8409_CYBORG] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = cs8409_cs42l42_pincfgs,
- .chained = true,
- .chain_id = CS8409_FIXUPS,
- },
- [CS8409_FIXUPS] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cs8409_cs42l42_fixups,
- },
- [CS8409_DOLPHIN] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = dolphin_pincfgs,
- .chained = true,
- .chain_id = CS8409_DOLPHIN_FIXUPS,
- },
- [CS8409_DOLPHIN_FIXUPS] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = dolphin_fixups,
- },
- [CS8409_ODIN] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = cs8409_cs42l42_pincfgs_no_dmic,
- .chained = true,
- .chain_id = CS8409_FIXUPS,
- },
-};
diff --git a/sound/pci/hda/patch_cs8409.c b/sound/pci/hda/patch_cs8409.c
deleted file mode 100644
index e50006757a2c..000000000000
--- a/sound/pci/hda/patch_cs8409.c
+++ /dev/null
@@ -1,1484 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * HD audio interface patch for Cirrus Logic CS8409 HDA bridge chip
- *
- * Copyright (C) 2021 Cirrus Logic, Inc. and
- * Cirrus Logic International Semiconductor Ltd.
- */
-
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <sound/core.h>
-#include <linux/mutex.h>
-#include <linux/iopoll.h>
-
-#include "patch_cs8409.h"
-
-/******************************************************************************
- * CS8409 Specific Functions
- ******************************************************************************/
-
-static int cs8409_parse_auto_config(struct hda_codec *codec)
-{
- struct cs8409_spec *spec = codec->spec;
- int err;
- int i;
-
- err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0);
- if (err < 0)
- return err;
-
- err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg);
- if (err < 0)
- return err;
-
- /* keep the ADCs powered up when it's dynamically switchable */
- if (spec->gen.dyn_adc_switch) {
- unsigned int done = 0;
-
- for (i = 0; i < spec->gen.input_mux.num_items; i++) {
- int idx = spec->gen.dyn_adc_idx[i];
-
- if (done & (1 << idx))
- continue;
- snd_hda_gen_fix_pin_power(codec, spec->gen.adc_nids[idx]);
- done |= 1 << idx;
- }
- }
-
- return 0;
-}
-
-static void cs8409_disable_i2c_clock_worker(struct work_struct *work);
-
-static struct cs8409_spec *cs8409_alloc_spec(struct hda_codec *codec)
-{
- struct cs8409_spec *spec;
-
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (!spec)
- return NULL;
- codec->spec = spec;
- spec->codec = codec;
- codec->power_save_node = 1;
- mutex_init(&spec->i2c_mux);
- INIT_DELAYED_WORK(&spec->i2c_clk_work, cs8409_disable_i2c_clock_worker);
- snd_hda_gen_spec_init(&spec->gen);
-
- return spec;
-}
-
-static inline int cs8409_vendor_coef_get(struct hda_codec *codec, unsigned int idx)
-{
- snd_hda_codec_write(codec, CS8409_PIN_VENDOR_WIDGET, 0, AC_VERB_SET_COEF_INDEX, idx);
- return snd_hda_codec_read(codec, CS8409_PIN_VENDOR_WIDGET, 0, AC_VERB_GET_PROC_COEF, 0);
-}
-
-static inline void cs8409_vendor_coef_set(struct hda_codec *codec, unsigned int idx,
- unsigned int coef)
-{
- snd_hda_codec_write(codec, CS8409_PIN_VENDOR_WIDGET, 0, AC_VERB_SET_COEF_INDEX, idx);
- snd_hda_codec_write(codec, CS8409_PIN_VENDOR_WIDGET, 0, AC_VERB_SET_PROC_COEF, coef);
-}
-
-/*
- * cs8409_enable_i2c_clock - Disable I2C clocks
- * @codec: the codec instance
- * Disable I2C clocks.
- * This must be called when the i2c mutex is unlocked.
- */
-static void cs8409_disable_i2c_clock(struct hda_codec *codec)
-{
- struct cs8409_spec *spec = codec->spec;
-
- mutex_lock(&spec->i2c_mux);
- if (spec->i2c_clck_enabled) {
- cs8409_vendor_coef_set(spec->codec, 0x0,
- cs8409_vendor_coef_get(spec->codec, 0x0) & 0xfffffff7);
- spec->i2c_clck_enabled = 0;
- }
- mutex_unlock(&spec->i2c_mux);
-}
-
-/*
- * cs8409_disable_i2c_clock_worker - Worker that disable the I2C Clock after 25ms without use
- */
-static void cs8409_disable_i2c_clock_worker(struct work_struct *work)
-{
- struct cs8409_spec *spec = container_of(work, struct cs8409_spec, i2c_clk_work.work);
-
- cs8409_disable_i2c_clock(spec->codec);
-}
-
-/*
- * cs8409_enable_i2c_clock - Enable I2C clocks
- * @codec: the codec instance
- * Enable I2C clocks.
- * This must be called when the i2c mutex is locked.
- */
-static void cs8409_enable_i2c_clock(struct hda_codec *codec)
-{
- struct cs8409_spec *spec = codec->spec;
-
- /* Cancel the disable timer, but do not wait for any running disable functions to finish.
- * If the disable timer runs out before cancel, the delayed work thread will be blocked,
- * waiting for the mutex to become unlocked. This mutex will be locked for the duration of
- * any i2c transaction, so the disable function will run to completion immediately
- * afterwards in the scenario. The next enable call will re-enable the clock, regardless.
- */
- cancel_delayed_work(&spec->i2c_clk_work);
-
- if (!spec->i2c_clck_enabled) {
- cs8409_vendor_coef_set(codec, 0x0, cs8409_vendor_coef_get(codec, 0x0) | 0x8);
- spec->i2c_clck_enabled = 1;
- }
- queue_delayed_work(system_power_efficient_wq, &spec->i2c_clk_work, msecs_to_jiffies(25));
-}
-
-/**
- * cs8409_i2c_wait_complete - Wait for I2C transaction
- * @codec: the codec instance
- *
- * Wait for I2C transaction to complete.
- * Return -ETIMEDOUT if transaction wait times out.
- */
-static int cs8409_i2c_wait_complete(struct hda_codec *codec)
-{
- unsigned int retval;
-
- return read_poll_timeout(cs8409_vendor_coef_get, retval, retval & 0x18,
- CS42L42_I2C_SLEEP_US, CS42L42_I2C_TIMEOUT_US, false, codec, CS8409_I2C_STS);
-}
-
-/**
- * cs8409_set_i2c_dev_addr - Set i2c address for transaction
- * @codec: the codec instance
- * @addr: I2C Address
- */
-static void cs8409_set_i2c_dev_addr(struct hda_codec *codec, unsigned int addr)
-{
- struct cs8409_spec *spec = codec->spec;
-
- if (spec->dev_addr != addr) {
- cs8409_vendor_coef_set(codec, CS8409_I2C_ADDR, addr);
- spec->dev_addr = addr;
- }
-}
-
-/**
- * cs8409_i2c_set_page - CS8409 I2C set page register.
- * @scodec: the codec instance
- * @i2c_reg: Page register
- *
- * Returns negative on error.
- */
-static int cs8409_i2c_set_page(struct sub_codec *scodec, unsigned int i2c_reg)
-{
- struct hda_codec *codec = scodec->codec;
-
- if (scodec->paged && (scodec->last_page != (i2c_reg >> 8))) {
- cs8409_vendor_coef_set(codec, CS8409_I2C_QWRITE, i2c_reg >> 8);
- if (cs8409_i2c_wait_complete(codec) < 0)
- return -EIO;
- scodec->last_page = i2c_reg >> 8;
- }
-
- return 0;
-}
-
-/**
- * cs8409_i2c_read - CS8409 I2C Read.
- * @scodec: the codec instance
- * @addr: Register to read
- *
- * Returns negative on error, otherwise returns read value in bits 0-7.
- */
-static int cs8409_i2c_read(struct sub_codec *scodec, unsigned int addr)
-{
- struct hda_codec *codec = scodec->codec;
- struct cs8409_spec *spec = codec->spec;
- unsigned int i2c_reg_data;
- unsigned int read_data;
-
- if (scodec->suspended)
- return -EPERM;
-
- mutex_lock(&spec->i2c_mux);
- cs8409_enable_i2c_clock(codec);
- cs8409_set_i2c_dev_addr(codec, scodec->addr);
-
- if (cs8409_i2c_set_page(scodec, addr))
- goto error;
-
- i2c_reg_data = (addr << 8) & 0x0ffff;
- cs8409_vendor_coef_set(codec, CS8409_I2C_QREAD, i2c_reg_data);
- if (cs8409_i2c_wait_complete(codec) < 0)
- goto error;
-
- /* Register in bits 15-8 and the data in 7-0 */
- read_data = cs8409_vendor_coef_get(codec, CS8409_I2C_QREAD);
-
- mutex_unlock(&spec->i2c_mux);
-
- return read_data & 0x0ff;
-
-error:
- mutex_unlock(&spec->i2c_mux);
- codec_err(codec, "%s() Failed 0x%02x : 0x%04x\n", __func__, scodec->addr, addr);
- return -EIO;
-}
-
-/**
- * cs8409_i2c_bulk_read - CS8409 I2C Read Sequence.
- * @scodec: the codec instance
- * @seq: Register Sequence to read
- * @count: Number of registeres to read
- *
- * Returns negative on error, values are read into value element of cs8409_i2c_param sequence.
- */
-static int cs8409_i2c_bulk_read(struct sub_codec *scodec, struct cs8409_i2c_param *seq, int count)
-{
- struct hda_codec *codec = scodec->codec;
- struct cs8409_spec *spec = codec->spec;
- unsigned int i2c_reg_data;
- int i;
-
- if (scodec->suspended)
- return -EPERM;
-
- mutex_lock(&spec->i2c_mux);
- cs8409_set_i2c_dev_addr(codec, scodec->addr);
-
- for (i = 0; i < count; i++) {
- cs8409_enable_i2c_clock(codec);
- if (cs8409_i2c_set_page(scodec, seq[i].addr))
- goto error;
-
- i2c_reg_data = (seq[i].addr << 8) & 0x0ffff;
- cs8409_vendor_coef_set(codec, CS8409_I2C_QREAD, i2c_reg_data);
-
- if (cs8409_i2c_wait_complete(codec) < 0)
- goto error;
-
- seq[i].value = cs8409_vendor_coef_get(codec, CS8409_I2C_QREAD) & 0xff;
- }
-
- mutex_unlock(&spec->i2c_mux);
-
- return 0;
-
-error:
- mutex_unlock(&spec->i2c_mux);
- codec_err(codec, "I2C Bulk Write Failed 0x%02x\n", scodec->addr);
- return -EIO;
-}
-
-/**
- * cs8409_i2c_write - CS8409 I2C Write.
- * @scodec: the codec instance
- * @addr: Register to write to
- * @value: Data to write
- *
- * Returns negative on error, otherwise returns 0.
- */
-static int cs8409_i2c_write(struct sub_codec *scodec, unsigned int addr, unsigned int value)
-{
- struct hda_codec *codec = scodec->codec;
- struct cs8409_spec *spec = codec->spec;
- unsigned int i2c_reg_data;
-
- if (scodec->suspended)
- return -EPERM;
-
- mutex_lock(&spec->i2c_mux);
-
- cs8409_enable_i2c_clock(codec);
- cs8409_set_i2c_dev_addr(codec, scodec->addr);
-
- if (cs8409_i2c_set_page(scodec, addr))
- goto error;
-
- i2c_reg_data = ((addr << 8) & 0x0ff00) | (value & 0x0ff);
- cs8409_vendor_coef_set(codec, CS8409_I2C_QWRITE, i2c_reg_data);
-
- if (cs8409_i2c_wait_complete(codec) < 0)
- goto error;
-
- mutex_unlock(&spec->i2c_mux);
- return 0;
-
-error:
- mutex_unlock(&spec->i2c_mux);
- codec_err(codec, "%s() Failed 0x%02x : 0x%04x\n", __func__, scodec->addr, addr);
- return -EIO;
-}
-
-/**
- * cs8409_i2c_bulk_write - CS8409 I2C Write Sequence.
- * @scodec: the codec instance
- * @seq: Register Sequence to write
- * @count: Number of registeres to write
- *
- * Returns negative on error.
- */
-static int cs8409_i2c_bulk_write(struct sub_codec *scodec, const struct cs8409_i2c_param *seq,
- int count)
-{
- struct hda_codec *codec = scodec->codec;
- struct cs8409_spec *spec = codec->spec;
- unsigned int i2c_reg_data;
- int i;
-
- if (scodec->suspended)
- return -EPERM;
-
- mutex_lock(&spec->i2c_mux);
- cs8409_set_i2c_dev_addr(codec, scodec->addr);
-
- for (i = 0; i < count; i++) {
- cs8409_enable_i2c_clock(codec);
- if (cs8409_i2c_set_page(scodec, seq[i].addr))
- goto error;
-
- i2c_reg_data = ((seq[i].addr << 8) & 0x0ff00) | (seq[i].value & 0x0ff);
- cs8409_vendor_coef_set(codec, CS8409_I2C_QWRITE, i2c_reg_data);
-
- if (cs8409_i2c_wait_complete(codec) < 0)
- goto error;
- /* Certain use cases may require a delay
- * after a write operation before proceeding.
- */
- if (seq[i].delay)
- fsleep(seq[i].delay);
- }
-
- mutex_unlock(&spec->i2c_mux);
-
- return 0;
-
-error:
- mutex_unlock(&spec->i2c_mux);
- codec_err(codec, "I2C Bulk Write Failed 0x%02x\n", scodec->addr);
- return -EIO;
-}
-
-static int cs8409_init(struct hda_codec *codec)
-{
- int ret = snd_hda_gen_init(codec);
-
- if (!ret)
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT);
-
- return ret;
-}
-
-static int cs8409_build_controls(struct hda_codec *codec)
-{
- int err;
-
- err = snd_hda_gen_build_controls(codec);
- if (err < 0)
- return err;
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_BUILD);
-
- return 0;
-}
-
-/* Enable/Disable Unsolicited Response */
-static void cs8409_enable_ur(struct hda_codec *codec, int flag)
-{
- struct cs8409_spec *spec = codec->spec;
- unsigned int ur_gpios = 0;
- int i;
-
- for (i = 0; i < spec->num_scodecs; i++)
- ur_gpios |= spec->scodecs[i]->irq_mask;
-
- snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK,
- flag ? ur_gpios : 0);
-
- snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_UNSOLICITED_ENABLE,
- flag ? AC_UNSOL_ENABLED : 0);
-}
-
-static void cs8409_fix_caps(struct hda_codec *codec, unsigned int nid)
-{
- int caps;
-
- /* CS8409 is simple HDA bridge and intended to be used with a remote
- * companion codec. Most of input/output PIN(s) have only basic
- * capabilities. Receive and Transmit NID(s) have only OUTC and INC
- * capabilities and no presence detect capable (PDC) and call to
- * snd_hda_gen_build_controls() will mark them as non detectable
- * phantom jacks. However, a companion codec may be
- * connected to these pins which supports jack detect
- * capabilities. We have to override pin capabilities,
- * otherwise they will not be created as input devices.
- */
- caps = snd_hdac_read_parm(&codec->core, nid, AC_PAR_PIN_CAP);
- if (caps >= 0)
- snd_hdac_override_parm(&codec->core, nid, AC_PAR_PIN_CAP,
- (caps | (AC_PINCAP_IMP_SENSE | AC_PINCAP_PRES_DETECT)));
-
- snd_hda_override_wcaps(codec, nid, (get_wcaps(codec, nid) | AC_WCAP_UNSOL_CAP));
-}
-
-static int cs8409_spk_sw_gpio_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct cs8409_spec *spec = codec->spec;
-
- ucontrol->value.integer.value[0] = !!(spec->gpio_data & spec->speaker_pdn_gpio);
- return 0;
-}
-
-static int cs8409_spk_sw_gpio_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct cs8409_spec *spec = codec->spec;
- unsigned int gpio_data;
-
- gpio_data = (spec->gpio_data & ~spec->speaker_pdn_gpio) |
- (ucontrol->value.integer.value[0] ? spec->speaker_pdn_gpio : 0);
- if (gpio_data == spec->gpio_data)
- return 0;
- spec->gpio_data = gpio_data;
- snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA, spec->gpio_data);
- return 1;
-}
-
-static const struct snd_kcontrol_new cs8409_spk_sw_ctrl = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .info = snd_ctl_boolean_mono_info,
- .get = cs8409_spk_sw_gpio_get,
- .put = cs8409_spk_sw_gpio_put,
-};
-
-/******************************************************************************
- * CS42L42 Specific Functions
- ******************************************************************************/
-
-int cs42l42_volume_info(struct snd_kcontrol *kctrl, struct snd_ctl_elem_info *uinfo)
-{
- unsigned int ofs = get_amp_offset(kctrl);
- u8 chs = get_amp_channels(kctrl);
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->value.integer.step = 1;
- uinfo->count = chs == 3 ? 2 : 1;
-
- switch (ofs) {
- case CS42L42_VOL_DAC:
- uinfo->value.integer.min = CS42L42_HP_VOL_REAL_MIN;
- uinfo->value.integer.max = CS42L42_HP_VOL_REAL_MAX;
- break;
- case CS42L42_VOL_ADC:
- uinfo->value.integer.min = CS42L42_AMIC_VOL_REAL_MIN;
- uinfo->value.integer.max = CS42L42_AMIC_VOL_REAL_MAX;
- break;
- default:
- break;
- }
-
- return 0;
-}
-
-int cs42l42_volume_get(struct snd_kcontrol *kctrl, struct snd_ctl_elem_value *uctrl)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kctrl);
- struct cs8409_spec *spec = codec->spec;
- struct sub_codec *cs42l42 = spec->scodecs[get_amp_index(kctrl)];
- int chs = get_amp_channels(kctrl);
- unsigned int ofs = get_amp_offset(kctrl);
- long *valp = uctrl->value.integer.value;
-
- switch (ofs) {
- case CS42L42_VOL_DAC:
- if (chs & BIT(0))
- *valp++ = cs42l42->vol[ofs];
- if (chs & BIT(1))
- *valp = cs42l42->vol[ofs+1];
- break;
- case CS42L42_VOL_ADC:
- if (chs & BIT(0))
- *valp = cs42l42->vol[ofs];
- break;
- default:
- break;
- }
-
- return 0;
-}
-
-static void cs42l42_mute(struct sub_codec *cs42l42, int vol_type,
- unsigned int chs, bool mute)
-{
- if (mute) {
- if (vol_type == CS42L42_VOL_DAC) {
- if (chs & BIT(0))
- cs8409_i2c_write(cs42l42, CS42L42_MIXER_CHA_VOL, 0x3f);
- if (chs & BIT(1))
- cs8409_i2c_write(cs42l42, CS42L42_MIXER_CHB_VOL, 0x3f);
- } else if (vol_type == CS42L42_VOL_ADC) {
- if (chs & BIT(0))
- cs8409_i2c_write(cs42l42, CS42L42_ADC_VOLUME, 0x9f);
- }
- } else {
- if (vol_type == CS42L42_VOL_DAC) {
- if (chs & BIT(0))
- cs8409_i2c_write(cs42l42, CS42L42_MIXER_CHA_VOL,
- -(cs42l42->vol[CS42L42_DAC_CH0_VOL_OFFSET])
- & CS42L42_MIXER_CH_VOL_MASK);
- if (chs & BIT(1))
- cs8409_i2c_write(cs42l42, CS42L42_MIXER_CHB_VOL,
- -(cs42l42->vol[CS42L42_DAC_CH1_VOL_OFFSET])
- & CS42L42_MIXER_CH_VOL_MASK);
- } else if (vol_type == CS42L42_VOL_ADC) {
- if (chs & BIT(0))
- cs8409_i2c_write(cs42l42, CS42L42_ADC_VOLUME,
- cs42l42->vol[CS42L42_ADC_VOL_OFFSET]
- & CS42L42_REG_AMIC_VOL_MASK);
- }
- }
-}
-
-int cs42l42_volume_put(struct snd_kcontrol *kctrl, struct snd_ctl_elem_value *uctrl)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kctrl);
- struct cs8409_spec *spec = codec->spec;
- struct sub_codec *cs42l42 = spec->scodecs[get_amp_index(kctrl)];
- int chs = get_amp_channels(kctrl);
- unsigned int ofs = get_amp_offset(kctrl);
- long *valp = uctrl->value.integer.value;
-
- switch (ofs) {
- case CS42L42_VOL_DAC:
- if (chs & BIT(0))
- cs42l42->vol[ofs] = *valp;
- if (chs & BIT(1)) {
- valp++;
- cs42l42->vol[ofs + 1] = *valp;
- }
- if (spec->playback_started)
- cs42l42_mute(cs42l42, CS42L42_VOL_DAC, chs, false);
- break;
- case CS42L42_VOL_ADC:
- if (chs & BIT(0))
- cs42l42->vol[ofs] = *valp;
- if (spec->capture_started)
- cs42l42_mute(cs42l42, CS42L42_VOL_ADC, chs, false);
- break;
- default:
- break;
- }
-
- return 0;
-}
-
-static void cs42l42_playback_pcm_hook(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream,
- int action)
-{
- struct cs8409_spec *spec = codec->spec;
- struct sub_codec *cs42l42;
- int i;
- bool mute;
-
- switch (action) {
- case HDA_GEN_PCM_ACT_PREPARE:
- mute = false;
- spec->playback_started = 1;
- break;
- case HDA_GEN_PCM_ACT_CLEANUP:
- mute = true;
- spec->playback_started = 0;
- break;
- default:
- return;
- }
-
- for (i = 0; i < spec->num_scodecs; i++) {
- cs42l42 = spec->scodecs[i];
- cs42l42_mute(cs42l42, CS42L42_VOL_DAC, 0x3, mute);
- }
-}
-
-static void cs42l42_capture_pcm_hook(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream,
- int action)
-{
- struct cs8409_spec *spec = codec->spec;
- struct sub_codec *cs42l42;
- int i;
- bool mute;
-
- switch (action) {
- case HDA_GEN_PCM_ACT_PREPARE:
- mute = false;
- spec->capture_started = 1;
- break;
- case HDA_GEN_PCM_ACT_CLEANUP:
- mute = true;
- spec->capture_started = 0;
- break;
- default:
- return;
- }
-
- for (i = 0; i < spec->num_scodecs; i++) {
- cs42l42 = spec->scodecs[i];
- cs42l42_mute(cs42l42, CS42L42_VOL_ADC, 0x3, mute);
- }
-}
-
-/* Configure CS42L42 slave codec for jack autodetect */
-static void cs42l42_enable_jack_detect(struct sub_codec *cs42l42)
-{
- cs8409_i2c_write(cs42l42, CS42L42_HSBIAS_SC_AUTOCTL, cs42l42->hsbias_hiz);
- /* Clear WAKE# */
- cs8409_i2c_write(cs42l42, CS42L42_WAKE_CTL, 0x00C1);
- /* Wait ~2.5ms */
- usleep_range(2500, 3000);
- /* Set mode WAKE# output follows the combination logic directly */
- cs8409_i2c_write(cs42l42, CS42L42_WAKE_CTL, 0x00C0);
- /* Clear interrupts status */
- cs8409_i2c_read(cs42l42, CS42L42_TSRS_PLUG_STATUS);
- /* Enable interrupt */
- cs8409_i2c_write(cs42l42, CS42L42_TSRS_PLUG_INT_MASK, 0xF3);
-}
-
-/* Enable and run CS42L42 slave codec jack auto detect */
-static void cs42l42_run_jack_detect(struct sub_codec *cs42l42)
-{
- /* Clear interrupts */
- cs8409_i2c_read(cs42l42, CS42L42_CODEC_STATUS);
- cs8409_i2c_read(cs42l42, CS42L42_DET_STATUS1);
- cs8409_i2c_write(cs42l42, CS42L42_TSRS_PLUG_INT_MASK, 0xFF);
- cs8409_i2c_read(cs42l42, CS42L42_TSRS_PLUG_STATUS);
-
- cs8409_i2c_write(cs42l42, CS42L42_PWR_CTL2, 0x87);
- cs8409_i2c_write(cs42l42, CS42L42_DAC_CTL2, 0x86);
- cs8409_i2c_write(cs42l42, CS42L42_MISC_DET_CTL, 0x07);
- cs8409_i2c_write(cs42l42, CS42L42_CODEC_INT_MASK, 0xFD);
- cs8409_i2c_write(cs42l42, CS42L42_HSDET_CTL2, 0x80);
- /* Wait ~20ms*/
- usleep_range(20000, 25000);
- cs8409_i2c_write(cs42l42, CS42L42_HSDET_CTL1, 0x77);
- cs8409_i2c_write(cs42l42, CS42L42_HSDET_CTL2, 0xc0);
-}
-
-static int cs42l42_manual_hs_det(struct sub_codec *cs42l42)
-{
- unsigned int hs_det_status;
- unsigned int hs_det_comp1;
- unsigned int hs_det_comp2;
- unsigned int hs_det_sw;
- unsigned int hs_type;
-
- /* Set hs detect to manual, active mode */
- cs8409_i2c_write(cs42l42, CS42L42_HSDET_CTL2,
- (1 << CS42L42_HSDET_CTRL_SHIFT) |
- (0 << CS42L42_HSDET_SET_SHIFT) |
- (0 << CS42L42_HSBIAS_REF_SHIFT) |
- (0 << CS42L42_HSDET_AUTO_TIME_SHIFT));
-
- /* Configure HS DET comparator reference levels. */
- cs8409_i2c_write(cs42l42, CS42L42_HSDET_CTL1,
- (CS42L42_HSDET_COMP1_LVL_VAL << CS42L42_HSDET_COMP1_LVL_SHIFT) |
- (CS42L42_HSDET_COMP2_LVL_VAL << CS42L42_HSDET_COMP2_LVL_SHIFT));
-
- /* Open the SW_HSB_HS3 switch and close SW_HSB_HS4 for a Type 1 headset. */
- cs8409_i2c_write(cs42l42, CS42L42_HS_SWITCH_CTL, CS42L42_HSDET_SW_COMP1);
-
- msleep(100);
-
- hs_det_status = cs8409_i2c_read(cs42l42, CS42L42_HS_DET_STATUS);
-
- hs_det_comp1 = (hs_det_status & CS42L42_HSDET_COMP1_OUT_MASK) >>
- CS42L42_HSDET_COMP1_OUT_SHIFT;
- hs_det_comp2 = (hs_det_status & CS42L42_HSDET_COMP2_OUT_MASK) >>
- CS42L42_HSDET_COMP2_OUT_SHIFT;
-
- /* Close the SW_HSB_HS3 switch for a Type 2 headset. */
- cs8409_i2c_write(cs42l42, CS42L42_HS_SWITCH_CTL, CS42L42_HSDET_SW_COMP2);
-
- msleep(100);
-
- hs_det_status = cs8409_i2c_read(cs42l42, CS42L42_HS_DET_STATUS);
-
- hs_det_comp1 |= ((hs_det_status & CS42L42_HSDET_COMP1_OUT_MASK) >>
- CS42L42_HSDET_COMP1_OUT_SHIFT) << 1;
- hs_det_comp2 |= ((hs_det_status & CS42L42_HSDET_COMP2_OUT_MASK) >>
- CS42L42_HSDET_COMP2_OUT_SHIFT) << 1;
-
- /* Use Comparator 1 with 1.25V Threshold. */
- switch (hs_det_comp1) {
- case CS42L42_HSDET_COMP_TYPE1:
- hs_type = CS42L42_PLUG_CTIA;
- hs_det_sw = CS42L42_HSDET_SW_TYPE1;
- break;
- case CS42L42_HSDET_COMP_TYPE2:
- hs_type = CS42L42_PLUG_OMTP;
- hs_det_sw = CS42L42_HSDET_SW_TYPE2;
- break;
- default:
- /* Fallback to Comparator 2 with 1.75V Threshold. */
- switch (hs_det_comp2) {
- case CS42L42_HSDET_COMP_TYPE1:
- hs_type = CS42L42_PLUG_CTIA;
- hs_det_sw = CS42L42_HSDET_SW_TYPE1;
- break;
- case CS42L42_HSDET_COMP_TYPE2:
- hs_type = CS42L42_PLUG_OMTP;
- hs_det_sw = CS42L42_HSDET_SW_TYPE2;
- break;
- case CS42L42_HSDET_COMP_TYPE3:
- hs_type = CS42L42_PLUG_HEADPHONE;
- hs_det_sw = CS42L42_HSDET_SW_TYPE3;
- break;
- default:
- hs_type = CS42L42_PLUG_INVALID;
- hs_det_sw = CS42L42_HSDET_SW_TYPE4;
- break;
- }
- }
-
- /* Set Switches */
- cs8409_i2c_write(cs42l42, CS42L42_HS_SWITCH_CTL, hs_det_sw);
-
- /* Set HSDET mode to Manual—Disabled */
- cs8409_i2c_write(cs42l42, CS42L42_HSDET_CTL2,
- (0 << CS42L42_HSDET_CTRL_SHIFT) |
- (0 << CS42L42_HSDET_SET_SHIFT) |
- (0 << CS42L42_HSBIAS_REF_SHIFT) |
- (0 << CS42L42_HSDET_AUTO_TIME_SHIFT));
-
- /* Configure HS DET comparator reference levels. */
- cs8409_i2c_write(cs42l42, CS42L42_HSDET_CTL1,
- (CS42L42_HSDET_COMP1_LVL_DEFAULT << CS42L42_HSDET_COMP1_LVL_SHIFT) |
- (CS42L42_HSDET_COMP2_LVL_DEFAULT << CS42L42_HSDET_COMP2_LVL_SHIFT));
-
- return hs_type;
-}
-
-static int cs42l42_handle_tip_sense(struct sub_codec *cs42l42, unsigned int reg_ts_status)
-{
- int status_changed = 0;
-
- /* TIP_SENSE INSERT/REMOVE */
- switch (reg_ts_status) {
- case CS42L42_TS_PLUG:
- if (cs42l42->no_type_dect) {
- status_changed = 1;
- cs42l42->hp_jack_in = 1;
- cs42l42->mic_jack_in = 0;
- } else {
- cs42l42_run_jack_detect(cs42l42);
- }
- break;
-
- case CS42L42_TS_UNPLUG:
- status_changed = 1;
- cs42l42->hp_jack_in = 0;
- cs42l42->mic_jack_in = 0;
- break;
- default:
- /* jack in transition */
- break;
- }
-
- codec_dbg(cs42l42->codec, "Tip Sense Detection: (%d)\n", reg_ts_status);
-
- return status_changed;
-}
-
-static int cs42l42_jack_unsol_event(struct sub_codec *cs42l42)
-{
- int current_plug_status;
- int status_changed = 0;
- int reg_cdc_status;
- int reg_hs_status;
- int reg_ts_status;
- int type;
-
- /* Read jack detect status registers */
- reg_cdc_status = cs8409_i2c_read(cs42l42, CS42L42_CODEC_STATUS);
- reg_hs_status = cs8409_i2c_read(cs42l42, CS42L42_HS_DET_STATUS);
- reg_ts_status = cs8409_i2c_read(cs42l42, CS42L42_TSRS_PLUG_STATUS);
-
- /* If status values are < 0, read error has occurred. */
- if (reg_cdc_status < 0 || reg_hs_status < 0 || reg_ts_status < 0)
- return -EIO;
-
- current_plug_status = (reg_ts_status & (CS42L42_TS_PLUG_MASK | CS42L42_TS_UNPLUG_MASK))
- >> CS42L42_TS_PLUG_SHIFT;
-
- /* HSDET_AUTO_DONE */
- if (reg_cdc_status & CS42L42_HSDET_AUTO_DONE_MASK) {
-
- /* Disable HSDET_AUTO_DONE */
- cs8409_i2c_write(cs42l42, CS42L42_CODEC_INT_MASK, 0xFF);
-
- type = (reg_hs_status & CS42L42_HSDET_TYPE_MASK) >> CS42L42_HSDET_TYPE_SHIFT;
-
- /* Configure the HSDET mode. */
- cs8409_i2c_write(cs42l42, CS42L42_HSDET_CTL2, 0x80);
-
- if (cs42l42->no_type_dect) {
- status_changed = cs42l42_handle_tip_sense(cs42l42, current_plug_status);
- } else {
- if (type == CS42L42_PLUG_INVALID || type == CS42L42_PLUG_HEADPHONE) {
- codec_dbg(cs42l42->codec,
- "Auto detect value not valid (%d), running manual det\n",
- type);
- type = cs42l42_manual_hs_det(cs42l42);
- }
-
- switch (type) {
- case CS42L42_PLUG_CTIA:
- case CS42L42_PLUG_OMTP:
- status_changed = 1;
- cs42l42->hp_jack_in = 1;
- cs42l42->mic_jack_in = 1;
- break;
- case CS42L42_PLUG_HEADPHONE:
- status_changed = 1;
- cs42l42->hp_jack_in = 1;
- cs42l42->mic_jack_in = 0;
- break;
- default:
- status_changed = 1;
- cs42l42->hp_jack_in = 0;
- cs42l42->mic_jack_in = 0;
- break;
- }
- codec_dbg(cs42l42->codec, "Detection done (%d)\n", type);
- }
-
- /* Enable the HPOUT ground clamp and configure the HP pull-down */
- cs8409_i2c_write(cs42l42, CS42L42_DAC_CTL2, 0x02);
- /* Re-Enable Tip Sense Interrupt */
- cs8409_i2c_write(cs42l42, CS42L42_TSRS_PLUG_INT_MASK, 0xF3);
- } else {
- status_changed = cs42l42_handle_tip_sense(cs42l42, current_plug_status);
- }
-
- return status_changed;
-}
-
-static void cs42l42_resume(struct sub_codec *cs42l42)
-{
- struct hda_codec *codec = cs42l42->codec;
- struct cs8409_spec *spec = codec->spec;
- struct cs8409_i2c_param irq_regs[] = {
- { CS42L42_CODEC_STATUS, 0x00 },
- { CS42L42_DET_INT_STATUS1, 0x00 },
- { CS42L42_DET_INT_STATUS2, 0x00 },
- { CS42L42_TSRS_PLUG_STATUS, 0x00 },
- };
- unsigned int fsv;
-
- /* Bring CS42L42 out of Reset */
- spec->gpio_data = snd_hda_codec_read(codec, CS8409_PIN_AFG, 0, AC_VERB_GET_GPIO_DATA, 0);
- spec->gpio_data |= cs42l42->reset_gpio;
- snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA, spec->gpio_data);
- usleep_range(10000, 15000);
-
- cs42l42->suspended = 0;
-
- /* Initialize CS42L42 companion codec */
- cs8409_i2c_bulk_write(cs42l42, cs42l42->init_seq, cs42l42->init_seq_num);
-
- /* Clear interrupts, by reading interrupt status registers */
- cs8409_i2c_bulk_read(cs42l42, irq_regs, ARRAY_SIZE(irq_regs));
-
- fsv = cs8409_i2c_read(cs42l42, CS42L42_HP_CTL);
- if (cs42l42->full_scale_vol) {
- // Set the full scale volume bit
- fsv |= CS42L42_FULL_SCALE_VOL_MASK;
- cs8409_i2c_write(cs42l42, CS42L42_HP_CTL, fsv);
- }
- // Unmute analog channels A and B
- fsv = (fsv & ~CS42L42_ANA_MUTE_AB);
- cs8409_i2c_write(cs42l42, CS42L42_HP_CTL, fsv);
-
- /* we have to explicitly allow unsol event handling even during the
- * resume phase so that the jack event is processed properly
- */
- snd_hda_codec_allow_unsol_events(cs42l42->codec);
-
- cs42l42_enable_jack_detect(cs42l42);
-}
-
-static void cs42l42_suspend(struct sub_codec *cs42l42)
-{
- struct hda_codec *codec = cs42l42->codec;
- struct cs8409_spec *spec = codec->spec;
- int reg_cdc_status = 0;
- const struct cs8409_i2c_param cs42l42_pwr_down_seq[] = {
- { CS42L42_DAC_CTL2, 0x02 },
- { CS42L42_HS_CLAMP_DISABLE, 0x00 },
- { CS42L42_MIXER_CHA_VOL, 0x3F },
- { CS42L42_MIXER_ADC_VOL, 0x3F },
- { CS42L42_MIXER_CHB_VOL, 0x3F },
- { CS42L42_HP_CTL, 0x0D },
- { CS42L42_ASP_RX_DAI0_EN, 0x00 },
- { CS42L42_ASP_CLK_CFG, 0x00 },
- { CS42L42_PWR_CTL1, 0xFE },
- { CS42L42_PWR_CTL2, 0x8C },
- { CS42L42_PWR_CTL1, 0xFF },
- };
-
- cs8409_i2c_bulk_write(cs42l42, cs42l42_pwr_down_seq, ARRAY_SIZE(cs42l42_pwr_down_seq));
-
- if (read_poll_timeout(cs8409_i2c_read, reg_cdc_status,
- (reg_cdc_status & 0x1), CS42L42_PDN_SLEEP_US, CS42L42_PDN_TIMEOUT_US,
- true, cs42l42, CS42L42_CODEC_STATUS) < 0)
- codec_warn(codec, "Timeout waiting for PDN_DONE for CS42L42\n");
-
- /* Power down CS42L42 ASP/EQ/MIX/HP */
- cs8409_i2c_write(cs42l42, CS42L42_PWR_CTL2, 0x9C);
- cs42l42->suspended = 1;
- cs42l42->last_page = 0;
- cs42l42->hp_jack_in = 0;
- cs42l42->mic_jack_in = 0;
-
- /* Put CS42L42 into Reset */
- spec->gpio_data = snd_hda_codec_read(codec, CS8409_PIN_AFG, 0, AC_VERB_GET_GPIO_DATA, 0);
- spec->gpio_data &= ~cs42l42->reset_gpio;
- snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA, spec->gpio_data);
-}
-
-static void cs8409_free(struct hda_codec *codec)
-{
- struct cs8409_spec *spec = codec->spec;
-
- /* Cancel i2c clock disable timer, and disable clock if left enabled */
- cancel_delayed_work_sync(&spec->i2c_clk_work);
- cs8409_disable_i2c_clock(codec);
-
- snd_hda_gen_free(codec);
-}
-
-/******************************************************************************
- * BULLSEYE / WARLOCK / CYBORG Specific Functions
- * CS8409/CS42L42
- ******************************************************************************/
-
-/*
- * In the case of CS8409 we do not have unsolicited events from NID's 0x24
- * and 0x34 where hs mic and hp are connected. Companion codec CS42L42 will
- * generate interrupt via gpio 4 to notify jack events. We have to overwrite
- * generic snd_hda_jack_unsol_event(), read CS42L42 jack detect status registers
- * and then notify status via generic snd_hda_jack_unsol_event() call.
- */
-static void cs8409_cs42l42_jack_unsol_event(struct hda_codec *codec, unsigned int res)
-{
- struct cs8409_spec *spec = codec->spec;
- struct sub_codec *cs42l42 = spec->scodecs[CS8409_CODEC0];
- struct hda_jack_tbl *jk;
-
- /* jack_unsol_event() will be called every time gpio line changing state.
- * In this case gpio4 line goes up as a result of reading interrupt status
- * registers in previous cs8409_jack_unsol_event() call.
- * We don't need to handle this event, ignoring...
- */
- if (res & cs42l42->irq_mask)
- return;
-
- if (cs42l42_jack_unsol_event(cs42l42)) {
- snd_hda_set_pin_ctl(codec, CS8409_CS42L42_SPK_PIN_NID,
- cs42l42->hp_jack_in ? 0 : PIN_OUT);
- /* Report jack*/
- jk = snd_hda_jack_tbl_get_mst(codec, CS8409_CS42L42_HP_PIN_NID, 0);
- if (jk)
- snd_hda_jack_unsol_event(codec, (jk->tag << AC_UNSOL_RES_TAG_SHIFT) &
- AC_UNSOL_RES_TAG);
- /* Report jack*/
- jk = snd_hda_jack_tbl_get_mst(codec, CS8409_CS42L42_AMIC_PIN_NID, 0);
- if (jk)
- snd_hda_jack_unsol_event(codec, (jk->tag << AC_UNSOL_RES_TAG_SHIFT) &
- AC_UNSOL_RES_TAG);
- }
-}
-
-/* Manage PDREF, when transition to D3hot */
-static int cs8409_cs42l42_suspend(struct hda_codec *codec)
-{
- struct cs8409_spec *spec = codec->spec;
- int i;
-
- spec->init_done = 0;
-
- cs8409_enable_ur(codec, 0);
-
- for (i = 0; i < spec->num_scodecs; i++)
- cs42l42_suspend(spec->scodecs[i]);
-
- /* Cancel i2c clock disable timer, and disable clock if left enabled */
- cancel_delayed_work_sync(&spec->i2c_clk_work);
- cs8409_disable_i2c_clock(codec);
-
- snd_hda_shutup_pins(codec);
-
- return 0;
-}
-
-/* Vendor specific HW configuration
- * PLL, ASP, I2C, SPI, GPIOs, DMIC etc...
- */
-static void cs8409_cs42l42_hw_init(struct hda_codec *codec)
-{
- const struct cs8409_cir_param *seq = cs8409_cs42l42_hw_cfg;
- const struct cs8409_cir_param *seq_bullseye = cs8409_cs42l42_bullseye_atn;
- struct cs8409_spec *spec = codec->spec;
- struct sub_codec *cs42l42 = spec->scodecs[CS8409_CODEC0];
-
- if (spec->gpio_mask) {
- snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_MASK,
- spec->gpio_mask);
- snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DIRECTION,
- spec->gpio_dir);
- snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA,
- spec->gpio_data);
- }
-
- for (; seq->nid; seq++)
- cs8409_vendor_coef_set(codec, seq->cir, seq->coeff);
-
- if (codec->fixup_id == CS8409_BULLSEYE) {
- for (; seq_bullseye->nid; seq_bullseye++)
- cs8409_vendor_coef_set(codec, seq_bullseye->cir, seq_bullseye->coeff);
- }
-
- switch (codec->fixup_id) {
- case CS8409_CYBORG:
- case CS8409_WARLOCK_MLK_DUAL_MIC:
- /* DMIC1_MO=00b, DMIC1/2_SR=1 */
- cs8409_vendor_coef_set(codec, CS8409_DMIC_CFG, 0x0003);
- break;
- case CS8409_ODIN:
- /* ASP1/2_xxx_EN=1, ASP1/2_MCLK_EN=0, DMIC1_SCL_EN=0 */
- cs8409_vendor_coef_set(codec, CS8409_PAD_CFG_SLW_RATE_CTRL, 0xfc00);
- break;
- default:
- break;
- }
-
- cs42l42_resume(cs42l42);
-
- /* Enable Unsolicited Response */
- cs8409_enable_ur(codec, 1);
-}
-
-static const struct hda_codec_ops cs8409_cs42l42_patch_ops = {
- .build_controls = cs8409_build_controls,
- .build_pcms = snd_hda_gen_build_pcms,
- .init = cs8409_init,
- .free = cs8409_free,
- .unsol_event = cs8409_cs42l42_jack_unsol_event,
- .suspend = cs8409_cs42l42_suspend,
-};
-
-static int cs8409_cs42l42_exec_verb(struct hdac_device *dev, unsigned int cmd, unsigned int flags,
- unsigned int *res)
-{
- struct hda_codec *codec = container_of(dev, struct hda_codec, core);
- struct cs8409_spec *spec = codec->spec;
- struct sub_codec *cs42l42 = spec->scodecs[CS8409_CODEC0];
-
- unsigned int nid = ((cmd >> 20) & 0x07f);
- unsigned int verb = ((cmd >> 8) & 0x0fff);
-
- /* CS8409 pins have no AC_PINSENSE_PRESENCE
- * capabilities. We have to intercept 2 calls for pins 0x24 and 0x34
- * and return correct pin sense values for read_pin_sense() call from
- * hda_jack based on CS42L42 jack detect status.
- */
- switch (nid) {
- case CS8409_CS42L42_HP_PIN_NID:
- if (verb == AC_VERB_GET_PIN_SENSE) {
- *res = (cs42l42->hp_jack_in) ? AC_PINSENSE_PRESENCE : 0;
- return 0;
- }
- break;
- case CS8409_CS42L42_AMIC_PIN_NID:
- if (verb == AC_VERB_GET_PIN_SENSE) {
- *res = (cs42l42->mic_jack_in) ? AC_PINSENSE_PRESENCE : 0;
- return 0;
- }
- break;
- default:
- break;
- }
-
- return spec->exec_verb(dev, cmd, flags, res);
-}
-
-void cs8409_cs42l42_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int action)
-{
- struct cs8409_spec *spec = codec->spec;
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- snd_hda_add_verbs(codec, cs8409_cs42l42_init_verbs);
- /* verb exec op override */
- spec->exec_verb = codec->core.exec_verb;
- codec->core.exec_verb = cs8409_cs42l42_exec_verb;
-
- spec->scodecs[CS8409_CODEC0] = &cs8409_cs42l42_codec;
- spec->num_scodecs = 1;
- spec->scodecs[CS8409_CODEC0]->codec = codec;
- codec->patch_ops = cs8409_cs42l42_patch_ops;
-
- spec->gen.suppress_auto_mute = 1;
- spec->gen.no_primary_hp = 1;
- spec->gen.suppress_vmaster = 1;
-
- spec->speaker_pdn_gpio = 0;
-
- /* GPIO 5 out, 3,4 in */
- spec->gpio_dir = spec->scodecs[CS8409_CODEC0]->reset_gpio;
- spec->gpio_data = 0;
- spec->gpio_mask = 0x03f;
-
- /* Basic initial sequence for specific hw configuration */
- snd_hda_sequence_write(codec, cs8409_cs42l42_init_verbs);
-
- cs8409_fix_caps(codec, CS8409_CS42L42_HP_PIN_NID);
- cs8409_fix_caps(codec, CS8409_CS42L42_AMIC_PIN_NID);
-
- spec->scodecs[CS8409_CODEC0]->hsbias_hiz = 0x0020;
-
- switch (codec->fixup_id) {
- case CS8409_CYBORG:
- spec->scodecs[CS8409_CODEC0]->full_scale_vol =
- CS42L42_FULL_SCALE_VOL_MINUS6DB;
- spec->speaker_pdn_gpio = CS8409_CYBORG_SPEAKER_PDN;
- break;
- case CS8409_ODIN:
- spec->scodecs[CS8409_CODEC0]->full_scale_vol = CS42L42_FULL_SCALE_VOL_0DB;
- spec->speaker_pdn_gpio = CS8409_CYBORG_SPEAKER_PDN;
- break;
- case CS8409_WARLOCK_MLK:
- case CS8409_WARLOCK_MLK_DUAL_MIC:
- spec->scodecs[CS8409_CODEC0]->full_scale_vol = CS42L42_FULL_SCALE_VOL_0DB;
- spec->speaker_pdn_gpio = CS8409_WARLOCK_SPEAKER_PDN;
- break;
- default:
- spec->scodecs[CS8409_CODEC0]->full_scale_vol =
- CS42L42_FULL_SCALE_VOL_MINUS6DB;
- spec->speaker_pdn_gpio = CS8409_WARLOCK_SPEAKER_PDN;
- break;
- }
-
- if (spec->speaker_pdn_gpio > 0) {
- spec->gpio_dir |= spec->speaker_pdn_gpio;
- spec->gpio_data |= spec->speaker_pdn_gpio;
- }
-
- break;
- case HDA_FIXUP_ACT_PROBE:
- /* Fix Sample Rate to 48kHz */
- spec->gen.stream_analog_playback = &cs42l42_48k_pcm_analog_playback;
- spec->gen.stream_analog_capture = &cs42l42_48k_pcm_analog_capture;
- /* add hooks */
- spec->gen.pcm_playback_hook = cs42l42_playback_pcm_hook;
- spec->gen.pcm_capture_hook = cs42l42_capture_pcm_hook;
- if (codec->fixup_id != CS8409_ODIN)
- /* Set initial DMIC volume to -26 dB */
- snd_hda_codec_amp_init_stereo(codec, CS8409_CS42L42_DMIC_ADC_PIN_NID,
- HDA_INPUT, 0, 0xff, 0x19);
- snd_hda_gen_add_kctl(&spec->gen, "Headphone Playback Volume",
- &cs42l42_dac_volume_mixer);
- snd_hda_gen_add_kctl(&spec->gen, "Mic Capture Volume",
- &cs42l42_adc_volume_mixer);
- if (spec->speaker_pdn_gpio > 0)
- snd_hda_gen_add_kctl(&spec->gen, "Speaker Playback Switch",
- &cs8409_spk_sw_ctrl);
- /* Disable Unsolicited Response during boot */
- cs8409_enable_ur(codec, 0);
- snd_hda_codec_set_name(codec, "CS8409/CS42L42");
- break;
- case HDA_FIXUP_ACT_INIT:
- cs8409_cs42l42_hw_init(codec);
- spec->init_done = 1;
- if (spec->init_done && spec->build_ctrl_done
- && !spec->scodecs[CS8409_CODEC0]->hp_jack_in)
- cs42l42_run_jack_detect(spec->scodecs[CS8409_CODEC0]);
- break;
- case HDA_FIXUP_ACT_BUILD:
- spec->build_ctrl_done = 1;
- /* Run jack auto detect first time on boot
- * after controls have been added, to check if jack has
- * been already plugged in.
- * Run immediately after init.
- */
- if (spec->init_done && spec->build_ctrl_done
- && !spec->scodecs[CS8409_CODEC0]->hp_jack_in)
- cs42l42_run_jack_detect(spec->scodecs[CS8409_CODEC0]);
- break;
- default:
- break;
- }
-}
-
-/******************************************************************************
- * Dolphin Specific Functions
- * CS8409/ 2 X CS42L42
- ******************************************************************************/
-
-/*
- * In the case of CS8409 we do not have unsolicited events when
- * hs mic and hp are connected. Companion codec CS42L42 will
- * generate interrupt via irq_mask to notify jack events. We have to overwrite
- * generic snd_hda_jack_unsol_event(), read CS42L42 jack detect status registers
- * and then notify status via generic snd_hda_jack_unsol_event() call.
- */
-static void dolphin_jack_unsol_event(struct hda_codec *codec, unsigned int res)
-{
- struct cs8409_spec *spec = codec->spec;
- struct sub_codec *cs42l42;
- struct hda_jack_tbl *jk;
-
- cs42l42 = spec->scodecs[CS8409_CODEC0];
- if (!cs42l42->suspended && (~res & cs42l42->irq_mask) &&
- cs42l42_jack_unsol_event(cs42l42)) {
- jk = snd_hda_jack_tbl_get_mst(codec, DOLPHIN_HP_PIN_NID, 0);
- if (jk)
- snd_hda_jack_unsol_event(codec,
- (jk->tag << AC_UNSOL_RES_TAG_SHIFT) &
- AC_UNSOL_RES_TAG);
-
- jk = snd_hda_jack_tbl_get_mst(codec, DOLPHIN_AMIC_PIN_NID, 0);
- if (jk)
- snd_hda_jack_unsol_event(codec,
- (jk->tag << AC_UNSOL_RES_TAG_SHIFT) &
- AC_UNSOL_RES_TAG);
- }
-
- cs42l42 = spec->scodecs[CS8409_CODEC1];
- if (!cs42l42->suspended && (~res & cs42l42->irq_mask) &&
- cs42l42_jack_unsol_event(cs42l42)) {
- jk = snd_hda_jack_tbl_get_mst(codec, DOLPHIN_LO_PIN_NID, 0);
- if (jk)
- snd_hda_jack_unsol_event(codec,
- (jk->tag << AC_UNSOL_RES_TAG_SHIFT) &
- AC_UNSOL_RES_TAG);
- }
-}
-
-/* Vendor specific HW configuration
- * PLL, ASP, I2C, SPI, GPIOs, DMIC etc...
- */
-static void dolphin_hw_init(struct hda_codec *codec)
-{
- const struct cs8409_cir_param *seq = dolphin_hw_cfg;
- struct cs8409_spec *spec = codec->spec;
- struct sub_codec *cs42l42;
- int i;
-
- if (spec->gpio_mask) {
- snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_MASK,
- spec->gpio_mask);
- snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DIRECTION,
- spec->gpio_dir);
- snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA,
- spec->gpio_data);
- }
-
- for (; seq->nid; seq++)
- cs8409_vendor_coef_set(codec, seq->cir, seq->coeff);
-
- for (i = 0; i < spec->num_scodecs; i++) {
- cs42l42 = spec->scodecs[i];
- cs42l42_resume(cs42l42);
- }
-
- /* Enable Unsolicited Response */
- cs8409_enable_ur(codec, 1);
-}
-
-static const struct hda_codec_ops cs8409_dolphin_patch_ops = {
- .build_controls = cs8409_build_controls,
- .build_pcms = snd_hda_gen_build_pcms,
- .init = cs8409_init,
- .free = cs8409_free,
- .unsol_event = dolphin_jack_unsol_event,
- .suspend = cs8409_cs42l42_suspend,
-};
-
-static int dolphin_exec_verb(struct hdac_device *dev, unsigned int cmd, unsigned int flags,
- unsigned int *res)
-{
- struct hda_codec *codec = container_of(dev, struct hda_codec, core);
- struct cs8409_spec *spec = codec->spec;
- struct sub_codec *cs42l42 = spec->scodecs[CS8409_CODEC0];
-
- unsigned int nid = ((cmd >> 20) & 0x07f);
- unsigned int verb = ((cmd >> 8) & 0x0fff);
-
- /* CS8409 pins have no AC_PINSENSE_PRESENCE
- * capabilities. We have to intercept calls for CS42L42 pins
- * and return correct pin sense values for read_pin_sense() call from
- * hda_jack based on CS42L42 jack detect status.
- */
- switch (nid) {
- case DOLPHIN_HP_PIN_NID:
- case DOLPHIN_LO_PIN_NID:
- if (nid == DOLPHIN_LO_PIN_NID)
- cs42l42 = spec->scodecs[CS8409_CODEC1];
- if (verb == AC_VERB_GET_PIN_SENSE) {
- *res = (cs42l42->hp_jack_in) ? AC_PINSENSE_PRESENCE : 0;
- return 0;
- }
- break;
- case DOLPHIN_AMIC_PIN_NID:
- if (verb == AC_VERB_GET_PIN_SENSE) {
- *res = (cs42l42->mic_jack_in) ? AC_PINSENSE_PRESENCE : 0;
- return 0;
- }
- break;
- default:
- break;
- }
-
- return spec->exec_verb(dev, cmd, flags, res);
-}
-
-void dolphin_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int action)
-{
- struct cs8409_spec *spec = codec->spec;
- struct snd_kcontrol_new *kctrl;
- int i;
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- snd_hda_add_verbs(codec, dolphin_init_verbs);
- /* verb exec op override */
- spec->exec_verb = codec->core.exec_verb;
- codec->core.exec_verb = dolphin_exec_verb;
-
- spec->scodecs[CS8409_CODEC0] = &dolphin_cs42l42_0;
- spec->scodecs[CS8409_CODEC0]->codec = codec;
- spec->scodecs[CS8409_CODEC1] = &dolphin_cs42l42_1;
- spec->scodecs[CS8409_CODEC1]->codec = codec;
- spec->num_scodecs = 2;
- spec->gen.suppress_vmaster = 1;
-
- codec->patch_ops = cs8409_dolphin_patch_ops;
-
- /* GPIO 1,5 out, 0,4 in */
- spec->gpio_dir = spec->scodecs[CS8409_CODEC0]->reset_gpio |
- spec->scodecs[CS8409_CODEC1]->reset_gpio;
- spec->gpio_data = 0;
- spec->gpio_mask = 0x03f;
-
- /* Basic initial sequence for specific hw configuration */
- snd_hda_sequence_write(codec, dolphin_init_verbs);
-
- snd_hda_jack_add_kctl(codec, DOLPHIN_LO_PIN_NID, "Line Out", true,
- SND_JACK_HEADPHONE, NULL);
-
- snd_hda_jack_add_kctl(codec, DOLPHIN_AMIC_PIN_NID, "Microphone", true,
- SND_JACK_MICROPHONE, NULL);
-
- cs8409_fix_caps(codec, DOLPHIN_HP_PIN_NID);
- cs8409_fix_caps(codec, DOLPHIN_LO_PIN_NID);
- cs8409_fix_caps(codec, DOLPHIN_AMIC_PIN_NID);
-
- spec->scodecs[CS8409_CODEC0]->full_scale_vol = CS42L42_FULL_SCALE_VOL_MINUS6DB;
- spec->scodecs[CS8409_CODEC1]->full_scale_vol = CS42L42_FULL_SCALE_VOL_MINUS6DB;
-
- break;
- case HDA_FIXUP_ACT_PROBE:
- /* Fix Sample Rate to 48kHz */
- spec->gen.stream_analog_playback = &cs42l42_48k_pcm_analog_playback;
- spec->gen.stream_analog_capture = &cs42l42_48k_pcm_analog_capture;
- /* add hooks */
- spec->gen.pcm_playback_hook = cs42l42_playback_pcm_hook;
- spec->gen.pcm_capture_hook = cs42l42_capture_pcm_hook;
- snd_hda_gen_add_kctl(&spec->gen, "Headphone Playback Volume",
- &cs42l42_dac_volume_mixer);
- snd_hda_gen_add_kctl(&spec->gen, "Mic Capture Volume", &cs42l42_adc_volume_mixer);
- kctrl = snd_hda_gen_add_kctl(&spec->gen, "Line Out Playback Volume",
- &cs42l42_dac_volume_mixer);
- /* Update Line Out kcontrol template */
- if (kctrl)
- kctrl->private_value = HDA_COMPOSE_AMP_VAL_OFS(DOLPHIN_HP_PIN_NID, 3, CS8409_CODEC1,
- HDA_OUTPUT, CS42L42_VOL_DAC) | HDA_AMP_VAL_MIN_MUTE;
- cs8409_enable_ur(codec, 0);
- snd_hda_codec_set_name(codec, "CS8409/CS42L42");
- break;
- case HDA_FIXUP_ACT_INIT:
- dolphin_hw_init(codec);
- spec->init_done = 1;
- if (spec->init_done && spec->build_ctrl_done) {
- for (i = 0; i < spec->num_scodecs; i++) {
- if (!spec->scodecs[i]->hp_jack_in)
- cs42l42_run_jack_detect(spec->scodecs[i]);
- }
- }
- break;
- case HDA_FIXUP_ACT_BUILD:
- spec->build_ctrl_done = 1;
- /* Run jack auto detect first time on boot
- * after controls have been added, to check if jack has
- * been already plugged in.
- * Run immediately after init.
- */
- if (spec->init_done && spec->build_ctrl_done) {
- for (i = 0; i < spec->num_scodecs; i++) {
- if (!spec->scodecs[i]->hp_jack_in)
- cs42l42_run_jack_detect(spec->scodecs[i]);
- }
- }
- break;
- default:
- break;
- }
-}
-
-static int patch_cs8409(struct hda_codec *codec)
-{
- int err;
-
- if (!cs8409_alloc_spec(codec))
- return -ENOMEM;
-
- snd_hda_pick_fixup(codec, cs8409_models, cs8409_fixup_tbl, cs8409_fixups);
-
- codec_dbg(codec, "Picked ID=%d, VID=%08x, DEV=%08x\n", codec->fixup_id,
- codec->bus->pci->subsystem_vendor,
- codec->bus->pci->subsystem_device);
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
-
- err = cs8409_parse_auto_config(codec);
- if (err < 0) {
- cs8409_free(codec);
- return err;
- }
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
- return 0;
-}
-
-static const struct hda_device_id snd_hda_id_cs8409[] = {
- HDA_CODEC_ENTRY(0x10138409, "CS8409", patch_cs8409),
- {} /* terminator */
-};
-MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_cs8409);
-
-static struct hda_codec_driver cs8409_driver = {
- .id = snd_hda_id_cs8409,
-};
-module_hda_codec_driver(cs8409_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Cirrus Logic HDA bridge");
diff --git a/sound/pci/hda/patch_cs8409.h b/sound/pci/hda/patch_cs8409.h
deleted file mode 100644
index e4bd2e12110b..000000000000
--- a/sound/pci/hda/patch_cs8409.h
+++ /dev/null
@@ -1,375 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * HD audio interface patch for Cirrus Logic CS8409 HDA bridge chip
- *
- * Copyright (C) 2021 Cirrus Logic, Inc. and
- * Cirrus Logic International Semiconductor Ltd.
- */
-
-#ifndef __CS8409_PATCH_H
-#define __CS8409_PATCH_H
-
-#include <linux/pci.h>
-#include <sound/tlv.h>
-#include <linux/workqueue.h>
-#include <sound/cs42l42.h>
-#include <sound/hda_codec.h>
-#include "hda_local.h"
-#include "hda_auto_parser.h"
-#include "hda_jack.h"
-#include "hda_generic.h"
-
-/* CS8409 Specific Definitions */
-
-enum cs8409_pins {
- CS8409_PIN_ROOT,
- CS8409_PIN_AFG,
- CS8409_PIN_ASP1_OUT_A,
- CS8409_PIN_ASP1_OUT_B,
- CS8409_PIN_ASP1_OUT_C,
- CS8409_PIN_ASP1_OUT_D,
- CS8409_PIN_ASP1_OUT_E,
- CS8409_PIN_ASP1_OUT_F,
- CS8409_PIN_ASP1_OUT_G,
- CS8409_PIN_ASP1_OUT_H,
- CS8409_PIN_ASP2_OUT_A,
- CS8409_PIN_ASP2_OUT_B,
- CS8409_PIN_ASP2_OUT_C,
- CS8409_PIN_ASP2_OUT_D,
- CS8409_PIN_ASP2_OUT_E,
- CS8409_PIN_ASP2_OUT_F,
- CS8409_PIN_ASP2_OUT_G,
- CS8409_PIN_ASP2_OUT_H,
- CS8409_PIN_ASP1_IN_A,
- CS8409_PIN_ASP1_IN_B,
- CS8409_PIN_ASP1_IN_C,
- CS8409_PIN_ASP1_IN_D,
- CS8409_PIN_ASP1_IN_E,
- CS8409_PIN_ASP1_IN_F,
- CS8409_PIN_ASP1_IN_G,
- CS8409_PIN_ASP1_IN_H,
- CS8409_PIN_ASP2_IN_A,
- CS8409_PIN_ASP2_IN_B,
- CS8409_PIN_ASP2_IN_C,
- CS8409_PIN_ASP2_IN_D,
- CS8409_PIN_ASP2_IN_E,
- CS8409_PIN_ASP2_IN_F,
- CS8409_PIN_ASP2_IN_G,
- CS8409_PIN_ASP2_IN_H,
- CS8409_PIN_DMIC1,
- CS8409_PIN_DMIC2,
- CS8409_PIN_ASP1_TRANSMITTER_A,
- CS8409_PIN_ASP1_TRANSMITTER_B,
- CS8409_PIN_ASP1_TRANSMITTER_C,
- CS8409_PIN_ASP1_TRANSMITTER_D,
- CS8409_PIN_ASP1_TRANSMITTER_E,
- CS8409_PIN_ASP1_TRANSMITTER_F,
- CS8409_PIN_ASP1_TRANSMITTER_G,
- CS8409_PIN_ASP1_TRANSMITTER_H,
- CS8409_PIN_ASP2_TRANSMITTER_A,
- CS8409_PIN_ASP2_TRANSMITTER_B,
- CS8409_PIN_ASP2_TRANSMITTER_C,
- CS8409_PIN_ASP2_TRANSMITTER_D,
- CS8409_PIN_ASP2_TRANSMITTER_E,
- CS8409_PIN_ASP2_TRANSMITTER_F,
- CS8409_PIN_ASP2_TRANSMITTER_G,
- CS8409_PIN_ASP2_TRANSMITTER_H,
- CS8409_PIN_ASP1_RECEIVER_A,
- CS8409_PIN_ASP1_RECEIVER_B,
- CS8409_PIN_ASP1_RECEIVER_C,
- CS8409_PIN_ASP1_RECEIVER_D,
- CS8409_PIN_ASP1_RECEIVER_E,
- CS8409_PIN_ASP1_RECEIVER_F,
- CS8409_PIN_ASP1_RECEIVER_G,
- CS8409_PIN_ASP1_RECEIVER_H,
- CS8409_PIN_ASP2_RECEIVER_A,
- CS8409_PIN_ASP2_RECEIVER_B,
- CS8409_PIN_ASP2_RECEIVER_C,
- CS8409_PIN_ASP2_RECEIVER_D,
- CS8409_PIN_ASP2_RECEIVER_E,
- CS8409_PIN_ASP2_RECEIVER_F,
- CS8409_PIN_ASP2_RECEIVER_G,
- CS8409_PIN_ASP2_RECEIVER_H,
- CS8409_PIN_DMIC1_IN,
- CS8409_PIN_DMIC2_IN,
- CS8409_PIN_BEEP_GEN,
- CS8409_PIN_VENDOR_WIDGET
-};
-
-enum cs8409_coefficient_index_registers {
- CS8409_DEV_CFG1,
- CS8409_DEV_CFG2,
- CS8409_DEV_CFG3,
- CS8409_ASP1_CLK_CTRL1,
- CS8409_ASP1_CLK_CTRL2,
- CS8409_ASP1_CLK_CTRL3,
- CS8409_ASP2_CLK_CTRL1,
- CS8409_ASP2_CLK_CTRL2,
- CS8409_ASP2_CLK_CTRL3,
- CS8409_DMIC_CFG,
- CS8409_BEEP_CFG,
- ASP1_RX_NULL_INS_RMV,
- ASP1_Rx_RATE1,
- ASP1_Rx_RATE2,
- ASP1_Tx_NULL_INS_RMV,
- ASP1_Tx_RATE1,
- ASP1_Tx_RATE2,
- ASP2_Rx_NULL_INS_RMV,
- ASP2_Rx_RATE1,
- ASP2_Rx_RATE2,
- ASP2_Tx_NULL_INS_RMV,
- ASP2_Tx_RATE1,
- ASP2_Tx_RATE2,
- ASP1_SYNC_CTRL,
- ASP2_SYNC_CTRL,
- ASP1_A_TX_CTRL1,
- ASP1_A_TX_CTRL2,
- ASP1_B_TX_CTRL1,
- ASP1_B_TX_CTRL2,
- ASP1_C_TX_CTRL1,
- ASP1_C_TX_CTRL2,
- ASP1_D_TX_CTRL1,
- ASP1_D_TX_CTRL2,
- ASP1_E_TX_CTRL1,
- ASP1_E_TX_CTRL2,
- ASP1_F_TX_CTRL1,
- ASP1_F_TX_CTRL2,
- ASP1_G_TX_CTRL1,
- ASP1_G_TX_CTRL2,
- ASP1_H_TX_CTRL1,
- ASP1_H_TX_CTRL2,
- ASP2_A_TX_CTRL1,
- ASP2_A_TX_CTRL2,
- ASP2_B_TX_CTRL1,
- ASP2_B_TX_CTRL2,
- ASP2_C_TX_CTRL1,
- ASP2_C_TX_CTRL2,
- ASP2_D_TX_CTRL1,
- ASP2_D_TX_CTRL2,
- ASP2_E_TX_CTRL1,
- ASP2_E_TX_CTRL2,
- ASP2_F_TX_CTRL1,
- ASP2_F_TX_CTRL2,
- ASP2_G_TX_CTRL1,
- ASP2_G_TX_CTRL2,
- ASP2_H_TX_CTRL1,
- ASP2_H_TX_CTRL2,
- ASP1_A_RX_CTRL1,
- ASP1_A_RX_CTRL2,
- ASP1_B_RX_CTRL1,
- ASP1_B_RX_CTRL2,
- ASP1_C_RX_CTRL1,
- ASP1_C_RX_CTRL2,
- ASP1_D_RX_CTRL1,
- ASP1_D_RX_CTRL2,
- ASP1_E_RX_CTRL1,
- ASP1_E_RX_CTRL2,
- ASP1_F_RX_CTRL1,
- ASP1_F_RX_CTRL2,
- ASP1_G_RX_CTRL1,
- ASP1_G_RX_CTRL2,
- ASP1_H_RX_CTRL1,
- ASP1_H_RX_CTRL2,
- ASP2_A_RX_CTRL1,
- ASP2_A_RX_CTRL2,
- ASP2_B_RX_CTRL1,
- ASP2_B_RX_CTRL2,
- ASP2_C_RX_CTRL1,
- ASP2_C_RX_CTRL2,
- ASP2_D_RX_CTRL1,
- ASP2_D_RX_CTRL2,
- ASP2_E_RX_CTRL1,
- ASP2_E_RX_CTRL2,
- ASP2_F_RX_CTRL1,
- ASP2_F_RX_CTRL2,
- ASP2_G_RX_CTRL1,
- ASP2_G_RX_CTRL2,
- ASP2_H_RX_CTRL1,
- ASP2_H_RX_CTRL2,
- CS8409_I2C_ADDR,
- CS8409_I2C_DATA,
- CS8409_I2C_CTRL,
- CS8409_I2C_STS,
- CS8409_I2C_QWRITE,
- CS8409_I2C_QREAD,
- CS8409_SPI_CTRL,
- CS8409_SPI_TX_DATA,
- CS8409_SPI_RX_DATA,
- CS8409_SPI_STS,
- CS8409_PFE_COEF_W1, /* Parametric filter engine coefficient write 1*/
- CS8409_PFE_COEF_W2,
- CS8409_PFE_CTRL1,
- CS8409_PFE_CTRL2,
- CS8409_PRE_SCALE_ATTN1,
- CS8409_PRE_SCALE_ATTN2,
- CS8409_PFE_COEF_MON1, /* Parametric filter engine coefficient monitor 1*/
- CS8409_PFE_COEF_MON2,
- CS8409_ASP1_INTRN_STS,
- CS8409_ASP2_INTRN_STS,
- CS8409_ASP1_RX_SCLK_COUNT,
- CS8409_ASP1_TX_SCLK_COUNT,
- CS8409_ASP2_RX_SCLK_COUNT,
- CS8409_ASP2_TX_SCLK_COUNT,
- CS8409_ASP_UNS_RESP_MASK,
- CS8409_LOOPBACK_CTRL = 0x80,
- CS8409_PAD_CFG_SLW_RATE_CTRL = 0x82, /* Pad Config and Slew Rate Control (CIR = 0x0082) */
-};
-
-/* CS42L42 Specific Definitions */
-
-#define CS8409_MAX_CODECS 8
-#define CS42L42_VOLUMES (4U)
-#define CS42L42_HP_VOL_REAL_MIN (-63)
-#define CS42L42_HP_VOL_REAL_MAX (0)
-#define CS42L42_AMIC_VOL_REAL_MIN (-97)
-#define CS42L42_AMIC_VOL_REAL_MAX (12)
-#define CS42L42_REG_AMIC_VOL_MASK (0x00FF)
-#define CS42L42_HSTYPE_MASK (0x03)
-#define CS42L42_I2C_TIMEOUT_US (20000)
-#define CS42L42_I2C_SLEEP_US (2000)
-#define CS42L42_PDN_TIMEOUT_US (250000)
-#define CS42L42_PDN_SLEEP_US (2000)
-#define CS42L42_ANA_MUTE_AB (0x0C)
-#define CS42L42_FULL_SCALE_VOL_MASK (2)
-#define CS42L42_FULL_SCALE_VOL_0DB (0)
-#define CS42L42_FULL_SCALE_VOL_MINUS6DB (1)
-
-/* Dell BULLSEYE / WARLOCK / CYBORG Specific Definitions */
-
-#define CS42L42_I2C_ADDR (0x48 << 1)
-#define CS8409_CS42L42_RESET GENMASK(5, 5) /* CS8409_GPIO5 */
-#define CS8409_CS42L42_INT GENMASK(4, 4) /* CS8409_GPIO4 */
-#define CS8409_CYBORG_SPEAKER_PDN GENMASK(2, 2) /* CS8409_GPIO2 */
-#define CS8409_WARLOCK_SPEAKER_PDN GENMASK(1, 1) /* CS8409_GPIO1 */
-#define CS8409_CS42L42_HP_PIN_NID CS8409_PIN_ASP1_TRANSMITTER_A
-#define CS8409_CS42L42_SPK_PIN_NID CS8409_PIN_ASP2_TRANSMITTER_A
-#define CS8409_CS42L42_AMIC_PIN_NID CS8409_PIN_ASP1_RECEIVER_A
-#define CS8409_CS42L42_DMIC_PIN_NID CS8409_PIN_DMIC1_IN
-#define CS8409_CS42L42_DMIC_ADC_PIN_NID CS8409_PIN_DMIC1
-
-/* Dolphin */
-
-#define DOLPHIN_C0_I2C_ADDR (0x48 << 1)
-#define DOLPHIN_C1_I2C_ADDR (0x49 << 1)
-#define DOLPHIN_HP_PIN_NID CS8409_PIN_ASP1_TRANSMITTER_A
-#define DOLPHIN_LO_PIN_NID CS8409_PIN_ASP1_TRANSMITTER_B
-#define DOLPHIN_AMIC_PIN_NID CS8409_PIN_ASP1_RECEIVER_A
-
-#define DOLPHIN_C0_INT GENMASK(4, 4)
-#define DOLPHIN_C1_INT GENMASK(0, 0)
-#define DOLPHIN_C0_RESET GENMASK(5, 5)
-#define DOLPHIN_C1_RESET GENMASK(1, 1)
-#define DOLPHIN_WAKE (DOLPHIN_C0_INT | DOLPHIN_C1_INT)
-
-enum {
- CS8409_BULLSEYE,
- CS8409_WARLOCK,
- CS8409_WARLOCK_MLK,
- CS8409_WARLOCK_MLK_DUAL_MIC,
- CS8409_CYBORG,
- CS8409_FIXUPS,
- CS8409_DOLPHIN,
- CS8409_DOLPHIN_FIXUPS,
- CS8409_ODIN,
-};
-
-enum {
- CS8409_CODEC0,
- CS8409_CODEC1
-};
-
-enum {
- CS42L42_VOL_ADC,
- CS42L42_VOL_DAC,
-};
-
-#define CS42L42_ADC_VOL_OFFSET (CS42L42_VOL_ADC)
-#define CS42L42_DAC_CH0_VOL_OFFSET (CS42L42_VOL_DAC)
-#define CS42L42_DAC_CH1_VOL_OFFSET (CS42L42_VOL_DAC + 1)
-
-struct cs8409_i2c_param {
- unsigned int addr;
- unsigned int value;
- unsigned int delay;
-};
-
-struct cs8409_cir_param {
- unsigned int nid;
- unsigned int cir;
- unsigned int coeff;
-};
-
-struct sub_codec {
- struct hda_codec *codec;
- unsigned int addr;
- unsigned int reset_gpio;
- unsigned int irq_mask;
- const struct cs8409_i2c_param *init_seq;
- unsigned int init_seq_num;
-
- unsigned int hp_jack_in:1;
- unsigned int mic_jack_in:1;
- unsigned int suspended:1;
- unsigned int paged:1;
- unsigned int last_page;
- unsigned int hsbias_hiz;
- unsigned int full_scale_vol:1;
- unsigned int no_type_dect:1;
-
- s8 vol[CS42L42_VOLUMES];
-};
-
-struct cs8409_spec {
- struct hda_gen_spec gen;
- struct hda_codec *codec;
-
- struct sub_codec *scodecs[CS8409_MAX_CODECS];
- unsigned int num_scodecs;
-
- unsigned int gpio_mask;
- unsigned int gpio_dir;
- unsigned int gpio_data;
-
- int speaker_pdn_gpio;
-
- struct mutex i2c_mux;
- unsigned int i2c_clck_enabled;
- unsigned int dev_addr;
- struct delayed_work i2c_clk_work;
-
- unsigned int playback_started:1;
- unsigned int capture_started:1;
- unsigned int init_done:1;
- unsigned int build_ctrl_done:1;
-
- /* verb exec op override */
- int (*exec_verb)(struct hdac_device *dev, unsigned int cmd, unsigned int flags,
- unsigned int *res);
-};
-
-extern const struct snd_kcontrol_new cs42l42_dac_volume_mixer;
-extern const struct snd_kcontrol_new cs42l42_adc_volume_mixer;
-
-int cs42l42_volume_info(struct snd_kcontrol *kctrl, struct snd_ctl_elem_info *uinfo);
-int cs42l42_volume_get(struct snd_kcontrol *kctrl, struct snd_ctl_elem_value *uctrl);
-int cs42l42_volume_put(struct snd_kcontrol *kctrl, struct snd_ctl_elem_value *uctrl);
-
-extern const struct hda_pcm_stream cs42l42_48k_pcm_analog_playback;
-extern const struct hda_pcm_stream cs42l42_48k_pcm_analog_capture;
-extern const struct hda_quirk cs8409_fixup_tbl[];
-extern const struct hda_model_fixup cs8409_models[];
-extern const struct hda_fixup cs8409_fixups[];
-extern const struct hda_verb cs8409_cs42l42_init_verbs[];
-extern const struct cs8409_cir_param cs8409_cs42l42_hw_cfg[];
-extern const struct cs8409_cir_param cs8409_cs42l42_bullseye_atn[];
-extern struct sub_codec cs8409_cs42l42_codec;
-
-extern const struct hda_verb dolphin_init_verbs[];
-extern const struct cs8409_cir_param dolphin_hw_cfg[];
-extern struct sub_codec dolphin_cs42l42_0;
-extern struct sub_codec dolphin_cs42l42_1;
-
-void cs8409_cs42l42_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int action);
-void dolphin_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int action);
-
-#endif
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
deleted file mode 100644
index 08308231b4ed..000000000000
--- a/sound/pci/hda/patch_hdmi.c
+++ /dev/null
@@ -1,4676 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- *
- * patch_hdmi.c - routines for HDMI/DisplayPort codecs
- *
- * Copyright(c) 2008-2010 Intel Corporation
- * Copyright (c) 2006 ATI Technologies Inc.
- * Copyright (c) 2008 NVIDIA Corp. All rights reserved.
- * Copyright (c) 2008 Wei Ni <wni@nvidia.com>
- * Copyright (c) 2013 Anssi Hannula <anssi.hannula@iki.fi>
- *
- * Authors:
- * Wu Fengguang <wfg@linux.intel.com>
- *
- * Maintained by:
- * Wu Fengguang <wfg@linux.intel.com>
- */
-
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/pm_runtime.h>
-#include <sound/core.h>
-#include <sound/jack.h>
-#include <sound/asoundef.h>
-#include <sound/tlv.h>
-#include <sound/hdaudio.h>
-#include <sound/hda_i915.h>
-#include <sound/hda_chmap.h>
-#include <sound/hda_codec.h>
-#include "hda_local.h"
-#include "hda_jack.h"
-#include "hda_controller.h"
-
-static bool static_hdmi_pcm;
-module_param(static_hdmi_pcm, bool, 0644);
-MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info");
-
-static bool enable_acomp = true;
-module_param(enable_acomp, bool, 0444);
-MODULE_PARM_DESC(enable_acomp, "Enable audio component binding (default=yes)");
-
-static bool enable_silent_stream =
-IS_ENABLED(CONFIG_SND_HDA_INTEL_HDMI_SILENT_STREAM);
-module_param(enable_silent_stream, bool, 0644);
-MODULE_PARM_DESC(enable_silent_stream, "Enable Silent Stream for HDMI devices");
-
-static bool enable_all_pins;
-module_param(enable_all_pins, bool, 0444);
-MODULE_PARM_DESC(enable_all_pins, "Forcibly enable all pins");
-
-struct hdmi_spec_per_cvt {
- hda_nid_t cvt_nid;
- bool assigned; /* the stream has been assigned */
- bool silent_stream; /* silent stream activated */
- unsigned int channels_min;
- unsigned int channels_max;
- u32 rates;
- u64 formats;
- unsigned int maxbps;
-};
-
-/* max. connections to a widget */
-#define HDA_MAX_CONNECTIONS 32
-
-struct hdmi_spec_per_pin {
- hda_nid_t pin_nid;
- int dev_id;
- /* pin idx, different device entries on the same pin use the same idx */
- int pin_nid_idx;
- int num_mux_nids;
- hda_nid_t mux_nids[HDA_MAX_CONNECTIONS];
- int mux_idx;
- hda_nid_t cvt_nid;
-
- struct hda_codec *codec;
- struct hdmi_eld sink_eld;
- struct mutex lock;
- struct delayed_work work;
- struct hdmi_pcm *pcm; /* pointer to spec->pcm_rec[n] dynamically*/
- int pcm_idx; /* which pcm is attached. -1 means no pcm is attached */
- int prev_pcm_idx; /* previously assigned pcm index */
- int repoll_count;
- bool setup; /* the stream has been set up by prepare callback */
- bool silent_stream;
- int channels; /* current number of channels */
- bool non_pcm;
- bool chmap_set; /* channel-map override by ALSA API? */
- unsigned char chmap[8]; /* ALSA API channel-map */
-#ifdef CONFIG_SND_PROC_FS
- struct snd_info_entry *proc_entry;
-#endif
-};
-
-/* operations used by generic code that can be overridden by patches */
-struct hdmi_ops {
- int (*pin_get_eld)(struct hda_codec *codec, hda_nid_t pin_nid,
- int dev_id, unsigned char *buf, int *eld_size);
-
- void (*pin_setup_infoframe)(struct hda_codec *codec, hda_nid_t pin_nid,
- int dev_id,
- int ca, int active_channels, int conn_type);
-
- /* enable/disable HBR (HD passthrough) */
- int (*pin_hbr_setup)(struct hda_codec *codec, hda_nid_t pin_nid,
- int dev_id, bool hbr);
-
- int (*setup_stream)(struct hda_codec *codec, hda_nid_t cvt_nid,
- hda_nid_t pin_nid, int dev_id, u32 stream_tag,
- int format);
-
- void (*pin_cvt_fixup)(struct hda_codec *codec,
- struct hdmi_spec_per_pin *per_pin,
- hda_nid_t cvt_nid);
-};
-
-struct hdmi_pcm {
- struct hda_pcm *pcm;
- struct snd_jack *jack;
- struct snd_kcontrol *eld_ctl;
-};
-
-enum {
- SILENT_STREAM_OFF = 0,
- SILENT_STREAM_KAE, /* use standard HDA Keep-Alive */
- SILENT_STREAM_I915, /* Intel i915 extension */
-};
-
-struct hdmi_spec {
- struct hda_codec *codec;
- int num_cvts;
- struct snd_array cvts; /* struct hdmi_spec_per_cvt */
- hda_nid_t cvt_nids[4]; /* only for haswell fix */
-
- /*
- * num_pins is the number of virtual pins
- * for example, there are 3 pins, and each pin
- * has 4 device entries, then the num_pins is 12
- */
- int num_pins;
- /*
- * num_nids is the number of real pins
- * In the above example, num_nids is 3
- */
- int num_nids;
- /*
- * dev_num is the number of device entries
- * on each pin.
- * In the above example, dev_num is 4
- */
- int dev_num;
- struct snd_array pins; /* struct hdmi_spec_per_pin */
- struct hdmi_pcm pcm_rec[8];
- struct mutex pcm_lock;
- struct mutex bind_lock; /* for audio component binding */
- /* pcm_bitmap means which pcms have been assigned to pins*/
- unsigned long pcm_bitmap;
- int pcm_used; /* counter of pcm_rec[] */
- /* bitmap shows whether the pcm is opened in user space
- * bit 0 means the first playback PCM (PCM3);
- * bit 1 means the second playback PCM, and so on.
- */
- unsigned long pcm_in_use;
-
- struct hdmi_eld temp_eld;
- struct hdmi_ops ops;
-
- bool dyn_pin_out;
- bool static_pcm_mapping;
- /* hdmi interrupt trigger control flag for Nvidia codec */
- bool hdmi_intr_trig_ctrl;
- bool nv_dp_workaround; /* workaround DP audio infoframe for Nvidia */
-
- bool intel_hsw_fixup; /* apply Intel platform-specific fixups */
- /*
- * Non-generic VIA/NVIDIA specific
- */
- struct hda_multi_out multiout;
- struct hda_pcm_stream pcm_playback;
-
- bool use_acomp_notifier; /* use eld_notify callback for hotplug */
- bool acomp_registered; /* audio component registered in this driver */
- bool force_connect; /* force connectivity */
- struct drm_audio_component_audio_ops drm_audio_ops;
- int (*port2pin)(struct hda_codec *, int); /* reverse port/pin mapping */
-
- struct hdac_chmap chmap;
- hda_nid_t vendor_nid;
- const int *port_map;
- int port_num;
- int silent_stream_type;
-};
-
-#ifdef CONFIG_SND_HDA_COMPONENT
-static inline bool codec_has_acomp(struct hda_codec *codec)
-{
- struct hdmi_spec *spec = codec->spec;
- return spec->use_acomp_notifier;
-}
-#else
-#define codec_has_acomp(codec) false
-#endif
-
-struct hdmi_audio_infoframe {
- u8 type; /* 0x84 */
- u8 ver; /* 0x01 */
- u8 len; /* 0x0a */
-
- u8 checksum;
-
- u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */
- u8 SS01_SF24;
- u8 CXT04;
- u8 CA;
- u8 LFEPBL01_LSV36_DM_INH7;
-};
-
-struct dp_audio_infoframe {
- u8 type; /* 0x84 */
- u8 len; /* 0x1b */
- u8 ver; /* 0x11 << 2 */
-
- u8 CC02_CT47; /* match with HDMI infoframe from this on */
- u8 SS01_SF24;
- u8 CXT04;
- u8 CA;
- u8 LFEPBL01_LSV36_DM_INH7;
-};
-
-union audio_infoframe {
- struct hdmi_audio_infoframe hdmi;
- struct dp_audio_infoframe dp;
- DECLARE_FLEX_ARRAY(u8, bytes);
-};
-
-/*
- * HDMI routines
- */
-
-#define get_pin(spec, idx) \
- ((struct hdmi_spec_per_pin *)snd_array_elem(&spec->pins, idx))
-#define get_cvt(spec, idx) \
- ((struct hdmi_spec_per_cvt *)snd_array_elem(&spec->cvts, idx))
-/* obtain hdmi_pcm object assigned to idx */
-#define get_hdmi_pcm(spec, idx) (&(spec)->pcm_rec[idx])
-/* obtain hda_pcm object assigned to idx */
-#define get_pcm_rec(spec, idx) (get_hdmi_pcm(spec, idx)->pcm)
-
-static int pin_id_to_pin_index(struct hda_codec *codec,
- hda_nid_t pin_nid, int dev_id)
-{
- struct hdmi_spec *spec = codec->spec;
- int pin_idx;
- struct hdmi_spec_per_pin *per_pin;
-
- /*
- * (dev_id == -1) means it is NON-MST pin
- * return the first virtual pin on this port
- */
- if (dev_id == -1)
- dev_id = 0;
-
- for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
- per_pin = get_pin(spec, pin_idx);
- if ((per_pin->pin_nid == pin_nid) &&
- (per_pin->dev_id == dev_id))
- return pin_idx;
- }
-
- codec_warn(codec, "HDMI: pin NID 0x%x not registered\n", pin_nid);
- return -EINVAL;
-}
-
-static int hinfo_to_pcm_index(struct hda_codec *codec,
- struct hda_pcm_stream *hinfo)
-{
- struct hdmi_spec *spec = codec->spec;
- int pcm_idx;
-
- for (pcm_idx = 0; pcm_idx < spec->pcm_used; pcm_idx++)
- if (get_pcm_rec(spec, pcm_idx)->stream == hinfo)
- return pcm_idx;
-
- codec_warn(codec, "HDMI: hinfo %p not tied to a PCM\n", hinfo);
- return -EINVAL;
-}
-
-static int hinfo_to_pin_index(struct hda_codec *codec,
- struct hda_pcm_stream *hinfo)
-{
- struct hdmi_spec *spec = codec->spec;
- struct hdmi_spec_per_pin *per_pin;
- int pin_idx;
-
- for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
- per_pin = get_pin(spec, pin_idx);
- if (per_pin->pcm &&
- per_pin->pcm->pcm->stream == hinfo)
- return pin_idx;
- }
-
- codec_dbg(codec, "HDMI: hinfo %p (pcm %d) not registered\n", hinfo,
- hinfo_to_pcm_index(codec, hinfo));
- return -EINVAL;
-}
-
-static struct hdmi_spec_per_pin *pcm_idx_to_pin(struct hdmi_spec *spec,
- int pcm_idx)
-{
- int i;
- struct hdmi_spec_per_pin *per_pin;
-
- for (i = 0; i < spec->num_pins; i++) {
- per_pin = get_pin(spec, i);
- if (per_pin->pcm_idx == pcm_idx)
- return per_pin;
- }
- return NULL;
-}
-
-static int cvt_nid_to_cvt_index(struct hda_codec *codec, hda_nid_t cvt_nid)
-{
- struct hdmi_spec *spec = codec->spec;
- int cvt_idx;
-
- for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++)
- if (get_cvt(spec, cvt_idx)->cvt_nid == cvt_nid)
- return cvt_idx;
-
- codec_warn(codec, "HDMI: cvt NID 0x%x not registered\n", cvt_nid);
- return -EINVAL;
-}
-
-static int hdmi_eld_ctl_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct hdmi_spec *spec = codec->spec;
- struct hdmi_spec_per_pin *per_pin;
- struct hdmi_eld *eld;
- int pcm_idx;
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
-
- pcm_idx = kcontrol->private_value;
- mutex_lock(&spec->pcm_lock);
- per_pin = pcm_idx_to_pin(spec, pcm_idx);
- if (!per_pin) {
- /* no pin is bound to the pcm */
- uinfo->count = 0;
- goto unlock;
- }
- eld = &per_pin->sink_eld;
- uinfo->count = eld->eld_valid ? eld->eld_size : 0;
-
- unlock:
- mutex_unlock(&spec->pcm_lock);
- return 0;
-}
-
-static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct hdmi_spec *spec = codec->spec;
- struct hdmi_spec_per_pin *per_pin;
- struct hdmi_eld *eld;
- int pcm_idx;
- int err = 0;
-
- pcm_idx = kcontrol->private_value;
- mutex_lock(&spec->pcm_lock);
- per_pin = pcm_idx_to_pin(spec, pcm_idx);
- if (!per_pin) {
- /* no pin is bound to the pcm */
- memset(ucontrol->value.bytes.data, 0,
- ARRAY_SIZE(ucontrol->value.bytes.data));
- goto unlock;
- }
-
- eld = &per_pin->sink_eld;
- if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data) ||
- eld->eld_size > ELD_MAX_SIZE) {
- snd_BUG();
- err = -EINVAL;
- goto unlock;
- }
-
- memset(ucontrol->value.bytes.data, 0,
- ARRAY_SIZE(ucontrol->value.bytes.data));
- if (eld->eld_valid)
- memcpy(ucontrol->value.bytes.data, eld->eld_buffer,
- eld->eld_size);
-
- unlock:
- mutex_unlock(&spec->pcm_lock);
- return err;
-}
-
-static const struct snd_kcontrol_new eld_bytes_ctl = {
- .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE |
- SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK,
- .iface = SNDRV_CTL_ELEM_IFACE_PCM,
- .name = "ELD",
- .info = hdmi_eld_ctl_info,
- .get = hdmi_eld_ctl_get,
-};
-
-static int hdmi_create_eld_ctl(struct hda_codec *codec, int pcm_idx,
- int device)
-{
- struct snd_kcontrol *kctl;
- struct hdmi_spec *spec = codec->spec;
- int err;
-
- kctl = snd_ctl_new1(&eld_bytes_ctl, codec);
- if (!kctl)
- return -ENOMEM;
- kctl->private_value = pcm_idx;
- kctl->id.device = device;
-
- /* no pin nid is associated with the kctl now
- * tbd: associate pin nid to eld ctl later
- */
- err = snd_hda_ctl_add(codec, 0, kctl);
- if (err < 0)
- return err;
-
- get_hdmi_pcm(spec, pcm_idx)->eld_ctl = kctl;
- return 0;
-}
-
-#ifdef BE_PARANOID
-static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
- int *packet_index, int *byte_index)
-{
- int val;
-
- val = snd_hda_codec_read(codec, pin_nid, 0,
- AC_VERB_GET_HDMI_DIP_INDEX, 0);
-
- *packet_index = val >> 5;
- *byte_index = val & 0x1f;
-}
-#endif
-
-static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
- int packet_index, int byte_index)
-{
- int val;
-
- val = (packet_index << 5) | (byte_index & 0x1f);
-
- snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val);
-}
-
-static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid,
- unsigned char val)
-{
- snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val);
-}
-
-static void hdmi_init_pin(struct hda_codec *codec, hda_nid_t pin_nid)
-{
- struct hdmi_spec *spec = codec->spec;
- int pin_out;
-
- /* Unmute */
- if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP)
- snd_hda_codec_write(codec, pin_nid, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
-
- if (spec->dyn_pin_out)
- /* Disable pin out until stream is active */
- pin_out = 0;
- else
- /* Enable pin out: some machines with GM965 gets broken output
- * when the pin is disabled or changed while using with HDMI
- */
- pin_out = PIN_OUT;
-
- snd_hda_codec_write(codec, pin_nid, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, pin_out);
-}
-
-/*
- * ELD proc files
- */
-
-#ifdef CONFIG_SND_PROC_FS
-static void print_eld_info(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- struct hdmi_spec_per_pin *per_pin = entry->private_data;
-
- mutex_lock(&per_pin->lock);
- snd_hdmi_print_eld_info(&per_pin->sink_eld, buffer, per_pin->pin_nid,
- per_pin->dev_id, per_pin->cvt_nid);
- mutex_unlock(&per_pin->lock);
-}
-
-static void write_eld_info(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- struct hdmi_spec_per_pin *per_pin = entry->private_data;
-
- mutex_lock(&per_pin->lock);
- snd_hdmi_write_eld_info(&per_pin->sink_eld, buffer);
- mutex_unlock(&per_pin->lock);
-}
-
-static int eld_proc_new(struct hdmi_spec_per_pin *per_pin, int index)
-{
- char name[32];
- struct hda_codec *codec = per_pin->codec;
- struct snd_info_entry *entry;
- int err;
-
- snprintf(name, sizeof(name), "eld#%d.%d", codec->addr, index);
- err = snd_card_proc_new(codec->card, name, &entry);
- if (err < 0)
- return err;
-
- snd_info_set_text_ops(entry, per_pin, print_eld_info);
- entry->c.text.write = write_eld_info;
- entry->mode |= 0200;
- per_pin->proc_entry = entry;
-
- return 0;
-}
-
-static void eld_proc_free(struct hdmi_spec_per_pin *per_pin)
-{
- if (!per_pin->codec->bus->shutdown) {
- snd_info_free_entry(per_pin->proc_entry);
- per_pin->proc_entry = NULL;
- }
-}
-#else
-static inline int eld_proc_new(struct hdmi_spec_per_pin *per_pin,
- int index)
-{
- return 0;
-}
-static inline void eld_proc_free(struct hdmi_spec_per_pin *per_pin)
-{
-}
-#endif
-
-/*
- * Audio InfoFrame routines
- */
-
-/*
- * Enable Audio InfoFrame Transmission
- */
-static void hdmi_start_infoframe_trans(struct hda_codec *codec,
- hda_nid_t pin_nid)
-{
- hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
- snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
- AC_DIPXMIT_BEST);
-}
-
-/*
- * Disable Audio InfoFrame Transmission
- */
-static void hdmi_stop_infoframe_trans(struct hda_codec *codec,
- hda_nid_t pin_nid)
-{
- hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
- snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
- AC_DIPXMIT_DISABLE);
-}
-
-static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-#ifdef CONFIG_SND_DEBUG_VERBOSE
- int i;
- int size;
-
- size = snd_hdmi_get_eld_size(codec, pin_nid);
- codec_dbg(codec, "HDMI: ELD buf size is %d\n", size);
-
- for (i = 0; i < 8; i++) {
- size = snd_hda_codec_read(codec, pin_nid, 0,
- AC_VERB_GET_HDMI_DIP_SIZE, i);
- codec_dbg(codec, "HDMI: DIP GP[%d] buf size is %d\n", i, size);
- }
-#endif
-}
-
-static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-#ifdef BE_PARANOID
- int i, j;
- int size;
- int pi, bi;
- for (i = 0; i < 8; i++) {
- size = snd_hda_codec_read(codec, pin_nid, 0,
- AC_VERB_GET_HDMI_DIP_SIZE, i);
- if (size == 0)
- continue;
-
- hdmi_set_dip_index(codec, pin_nid, i, 0x0);
- for (j = 1; j < 1000; j++) {
- hdmi_write_dip_byte(codec, pin_nid, 0x0);
- hdmi_get_dip_index(codec, pin_nid, &pi, &bi);
- if (pi != i)
- codec_dbg(codec, "dip index %d: %d != %d\n",
- bi, pi, i);
- if (bi == 0) /* byte index wrapped around */
- break;
- }
- codec_dbg(codec,
- "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n",
- i, size, j);
- }
-#endif
-}
-
-static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *hdmi_ai)
-{
- u8 *bytes = (u8 *)hdmi_ai;
- u8 sum = 0;
- int i;
-
- hdmi_ai->checksum = 0;
-
- for (i = 0; i < sizeof(*hdmi_ai); i++)
- sum += bytes[i];
-
- hdmi_ai->checksum = -sum;
-}
-
-static void hdmi_fill_audio_infoframe(struct hda_codec *codec,
- hda_nid_t pin_nid,
- u8 *dip, int size)
-{
- int i;
-
- hdmi_debug_dip_size(codec, pin_nid);
- hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */
-
- hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
- for (i = 0; i < size; i++)
- hdmi_write_dip_byte(codec, pin_nid, dip[i]);
-}
-
-static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
- u8 *dip, int size)
-{
- u8 val;
- int i;
-
- hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
- if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0)
- != AC_DIPXMIT_BEST)
- return false;
-
- for (i = 0; i < size; i++) {
- val = snd_hda_codec_read(codec, pin_nid, 0,
- AC_VERB_GET_HDMI_DIP_DATA, 0);
- if (val != dip[i])
- return false;
- }
-
- return true;
-}
-
-static int hdmi_pin_get_eld(struct hda_codec *codec, hda_nid_t nid,
- int dev_id, unsigned char *buf, int *eld_size)
-{
- snd_hda_set_dev_select(codec, nid, dev_id);
-
- return snd_hdmi_get_eld(codec, nid, buf, eld_size);
-}
-
-static void hdmi_pin_setup_infoframe(struct hda_codec *codec,
- hda_nid_t pin_nid, int dev_id,
- int ca, int active_channels,
- int conn_type)
-{
- struct hdmi_spec *spec = codec->spec;
- union audio_infoframe ai;
-
- memset(&ai, 0, sizeof(ai));
- if ((conn_type == 0) || /* HDMI */
- /* Nvidia DisplayPort: Nvidia HW expects same layout as HDMI */
- (conn_type == 1 && spec->nv_dp_workaround)) {
- struct hdmi_audio_infoframe *hdmi_ai = &ai.hdmi;
-
- if (conn_type == 0) { /* HDMI */
- hdmi_ai->type = 0x84;
- hdmi_ai->ver = 0x01;
- hdmi_ai->len = 0x0a;
- } else {/* Nvidia DP */
- hdmi_ai->type = 0x84;
- hdmi_ai->ver = 0x1b;
- hdmi_ai->len = 0x11 << 2;
- }
- hdmi_ai->CC02_CT47 = active_channels - 1;
- hdmi_ai->CA = ca;
- hdmi_checksum_audio_infoframe(hdmi_ai);
- } else if (conn_type == 1) { /* DisplayPort */
- struct dp_audio_infoframe *dp_ai = &ai.dp;
-
- dp_ai->type = 0x84;
- dp_ai->len = 0x1b;
- dp_ai->ver = 0x11 << 2;
- dp_ai->CC02_CT47 = active_channels - 1;
- dp_ai->CA = ca;
- } else {
- codec_dbg(codec, "HDMI: unknown connection type at pin NID 0x%x\n", pin_nid);
- return;
- }
-
- snd_hda_set_dev_select(codec, pin_nid, dev_id);
-
- /*
- * sizeof(ai) is used instead of sizeof(*hdmi_ai) or
- * sizeof(*dp_ai) to avoid partial match/update problems when
- * the user switches between HDMI/DP monitors.
- */
- if (!hdmi_infoframe_uptodate(codec, pin_nid, ai.bytes,
- sizeof(ai))) {
- codec_dbg(codec, "%s: pin NID=0x%x channels=%d ca=0x%02x\n",
- __func__, pin_nid, active_channels, ca);
- hdmi_stop_infoframe_trans(codec, pin_nid);
- hdmi_fill_audio_infoframe(codec, pin_nid,
- ai.bytes, sizeof(ai));
- hdmi_start_infoframe_trans(codec, pin_nid);
- }
-}
-
-static void hdmi_setup_audio_infoframe(struct hda_codec *codec,
- struct hdmi_spec_per_pin *per_pin,
- bool non_pcm)
-{
- struct hdmi_spec *spec = codec->spec;
- struct hdac_chmap *chmap = &spec->chmap;
- hda_nid_t pin_nid = per_pin->pin_nid;
- int dev_id = per_pin->dev_id;
- int channels = per_pin->channels;
- int active_channels;
- struct hdmi_eld *eld;
- int ca;
-
- if (!channels)
- return;
-
- snd_hda_set_dev_select(codec, pin_nid, dev_id);
-
- /* some HW (e.g. HSW+) needs reprogramming the amp at each time */
- if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP)
- snd_hda_codec_write(codec, pin_nid, 0,
- AC_VERB_SET_AMP_GAIN_MUTE,
- AMP_OUT_UNMUTE);
-
- eld = &per_pin->sink_eld;
-
- ca = snd_hdac_channel_allocation(&codec->core,
- eld->info.spk_alloc, channels,
- per_pin->chmap_set, non_pcm, per_pin->chmap);
-
- active_channels = snd_hdac_get_active_channels(ca);
-
- chmap->ops.set_channel_count(&codec->core, per_pin->cvt_nid,
- active_channels);
-
- /*
- * always configure channel mapping, it may have been changed by the
- * user in the meantime
- */
- snd_hdac_setup_channel_mapping(&spec->chmap,
- pin_nid, non_pcm, ca, channels,
- per_pin->chmap, per_pin->chmap_set);
-
- spec->ops.pin_setup_infoframe(codec, pin_nid, dev_id,
- ca, active_channels, eld->info.conn_type);
-
- per_pin->non_pcm = non_pcm;
-}
-
-/*
- * Unsolicited events
- */
-
-static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll);
-
-static void check_presence_and_report(struct hda_codec *codec, hda_nid_t nid,
- int dev_id)
-{
- struct hdmi_spec *spec = codec->spec;
- int pin_idx = pin_id_to_pin_index(codec, nid, dev_id);
-
- if (pin_idx < 0)
- return;
- mutex_lock(&spec->pcm_lock);
- hdmi_present_sense(get_pin(spec, pin_idx), 1);
- mutex_unlock(&spec->pcm_lock);
-}
-
-static void jack_callback(struct hda_codec *codec,
- struct hda_jack_callback *jack)
-{
- /* stop polling when notification is enabled */
- if (codec_has_acomp(codec))
- return;
-
- check_presence_and_report(codec, jack->nid, jack->dev_id);
-}
-
-static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res,
- struct hda_jack_tbl *jack)
-{
- jack->jack_dirty = 1;
-
- codec_dbg(codec,
- "HDMI hot plug event: Codec=%d NID=0x%x Device=%d Inactive=%d Presence_Detect=%d ELD_Valid=%d\n",
- codec->addr, jack->nid, jack->dev_id, !!(res & AC_UNSOL_RES_IA),
- !!(res & AC_UNSOL_RES_PD), !!(res & AC_UNSOL_RES_ELDV));
-
- check_presence_and_report(codec, jack->nid, jack->dev_id);
-}
-
-static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
-{
- int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
- int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
- int cp_state = !!(res & AC_UNSOL_RES_CP_STATE);
- int cp_ready = !!(res & AC_UNSOL_RES_CP_READY);
-
- codec_info(codec,
- "HDMI CP event: CODEC=%d TAG=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n",
- codec->addr,
- tag,
- subtag,
- cp_state,
- cp_ready);
-
- /* TODO */
- if (cp_state) {
- ;
- }
- if (cp_ready) {
- ;
- }
-}
-
-
-static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
-{
- int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
- int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
- struct hda_jack_tbl *jack;
-
- if (codec_has_acomp(codec))
- return;
-
- if (codec->dp_mst) {
- int dev_entry =
- (res & AC_UNSOL_RES_DE) >> AC_UNSOL_RES_DE_SHIFT;
-
- jack = snd_hda_jack_tbl_get_from_tag(codec, tag, dev_entry);
- } else {
- jack = snd_hda_jack_tbl_get_from_tag(codec, tag, 0);
- }
-
- if (!jack) {
- codec_dbg(codec, "Unexpected HDMI event tag 0x%x\n", tag);
- return;
- }
-
- if (subtag == 0)
- hdmi_intrinsic_event(codec, res, jack);
- else
- hdmi_non_intrinsic_event(codec, res);
-}
-
-static void haswell_verify_D0(struct hda_codec *codec,
- hda_nid_t cvt_nid, hda_nid_t nid)
-{
- int pwr;
-
- /* For Haswell, the converter 1/2 may keep in D3 state after bootup,
- * thus pins could only choose converter 0 for use. Make sure the
- * converters are in correct power state */
- if (!snd_hda_check_power_state(codec, cvt_nid, AC_PWRST_D0))
- snd_hda_codec_write(codec, cvt_nid, 0, AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
-
- if (!snd_hda_check_power_state(codec, nid, AC_PWRST_D0)) {
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE,
- AC_PWRST_D0);
- msleep(40);
- pwr = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_POWER_STATE, 0);
- pwr = (pwr & AC_PWRST_ACTUAL) >> AC_PWRST_ACTUAL_SHIFT;
- codec_dbg(codec, "Haswell HDMI audio: Power for NID 0x%x is now D%d\n", nid, pwr);
- }
-}
-
-/*
- * Callbacks
- */
-
-/* HBR should be Non-PCM, 8 channels */
-#define is_hbr_format(format) \
- ((format & AC_FMT_TYPE_NON_PCM) && (format & AC_FMT_CHAN_MASK) == 7)
-
-static int hdmi_pin_hbr_setup(struct hda_codec *codec, hda_nid_t pin_nid,
- int dev_id, bool hbr)
-{
- int pinctl, new_pinctl;
-
- if (snd_hda_query_pin_caps(codec, pin_nid) & AC_PINCAP_HBR) {
- snd_hda_set_dev_select(codec, pin_nid, dev_id);
- pinctl = snd_hda_codec_read(codec, pin_nid, 0,
- AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
-
- if (pinctl < 0)
- return hbr ? -EINVAL : 0;
-
- new_pinctl = pinctl & ~AC_PINCTL_EPT;
- if (hbr)
- new_pinctl |= AC_PINCTL_EPT_HBR;
- else
- new_pinctl |= AC_PINCTL_EPT_NATIVE;
-
- codec_dbg(codec,
- "hdmi_pin_hbr_setup: NID=0x%x, %spinctl=0x%x\n",
- pin_nid,
- pinctl == new_pinctl ? "" : "new-",
- new_pinctl);
-
- if (pinctl != new_pinctl)
- snd_hda_codec_write(codec, pin_nid, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- new_pinctl);
- } else if (hbr)
- return -EINVAL;
-
- return 0;
-}
-
-static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid,
- hda_nid_t pin_nid, int dev_id,
- u32 stream_tag, int format)
-{
- struct hdmi_spec *spec = codec->spec;
- unsigned int param;
- int err;
-
- err = spec->ops.pin_hbr_setup(codec, pin_nid, dev_id,
- is_hbr_format(format));
-
- if (err) {
- codec_dbg(codec, "hdmi_setup_stream: HBR is not supported\n");
- return err;
- }
-
- if (spec->intel_hsw_fixup) {
-
- /*
- * on recent platforms IEC Coding Type is required for HBR
- * support, read current Digital Converter settings and set
- * ICT bitfield if needed.
- */
- param = snd_hda_codec_read(codec, cvt_nid, 0,
- AC_VERB_GET_DIGI_CONVERT_1, 0);
-
- param = (param >> 16) & ~(AC_DIG3_ICT);
-
- /* on recent platforms ICT mode is required for HBR support */
- if (is_hbr_format(format))
- param |= 0x1;
-
- snd_hda_codec_write(codec, cvt_nid, 0,
- AC_VERB_SET_DIGI_CONVERT_3, param);
- }
-
- snd_hda_codec_setup_stream(codec, cvt_nid, stream_tag, 0, format);
- return 0;
-}
-
-/* Try to find an available converter
- * If pin_idx is less then zero, just try to find an available converter.
- * Otherwise, try to find an available converter and get the cvt mux index
- * of the pin.
- */
-static int hdmi_choose_cvt(struct hda_codec *codec,
- int pin_idx, int *cvt_id,
- bool silent)
-{
- struct hdmi_spec *spec = codec->spec;
- struct hdmi_spec_per_pin *per_pin;
- struct hdmi_spec_per_cvt *per_cvt = NULL;
- int cvt_idx, mux_idx = 0;
-
- /* pin_idx < 0 means no pin will be bound to the converter */
- if (pin_idx < 0)
- per_pin = NULL;
- else
- per_pin = get_pin(spec, pin_idx);
-
- if (per_pin && per_pin->silent_stream) {
- cvt_idx = cvt_nid_to_cvt_index(codec, per_pin->cvt_nid);
- per_cvt = get_cvt(spec, cvt_idx);
- if (per_cvt->assigned && !silent)
- return -EBUSY;
- if (cvt_id)
- *cvt_id = cvt_idx;
- return 0;
- }
-
- /* Dynamically assign converter to stream */
- for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) {
- per_cvt = get_cvt(spec, cvt_idx);
-
- /* Must not already be assigned */
- if (per_cvt->assigned || per_cvt->silent_stream)
- continue;
- if (per_pin == NULL)
- break;
- /* Must be in pin's mux's list of converters */
- for (mux_idx = 0; mux_idx < per_pin->num_mux_nids; mux_idx++)
- if (per_pin->mux_nids[mux_idx] == per_cvt->cvt_nid)
- break;
- /* Not in mux list */
- if (mux_idx == per_pin->num_mux_nids)
- continue;
- break;
- }
-
- /* No free converters */
- if (cvt_idx == spec->num_cvts)
- return -EBUSY;
-
- if (per_pin != NULL)
- per_pin->mux_idx = mux_idx;
-
- if (cvt_id)
- *cvt_id = cvt_idx;
-
- return 0;
-}
-
-/* Assure the pin select the right convetor */
-static void intel_verify_pin_cvt_connect(struct hda_codec *codec,
- struct hdmi_spec_per_pin *per_pin)
-{
- hda_nid_t pin_nid = per_pin->pin_nid;
- int mux_idx, curr;
-
- mux_idx = per_pin->mux_idx;
- curr = snd_hda_codec_read(codec, pin_nid, 0,
- AC_VERB_GET_CONNECT_SEL, 0);
- if (curr != mux_idx)
- snd_hda_codec_write_cache(codec, pin_nid, 0,
- AC_VERB_SET_CONNECT_SEL,
- mux_idx);
-}
-
-/* get the mux index for the converter of the pins
- * converter's mux index is the same for all pins on Intel platform
- */
-static int intel_cvt_id_to_mux_idx(struct hdmi_spec *spec,
- hda_nid_t cvt_nid)
-{
- int i;
-
- for (i = 0; i < spec->num_cvts; i++)
- if (spec->cvt_nids[i] == cvt_nid)
- return i;
- return -EINVAL;
-}
-
-/* Intel HDMI workaround to fix audio routing issue:
- * For some Intel display codecs, pins share the same connection list.
- * So a conveter can be selected by multiple pins and playback on any of these
- * pins will generate sound on the external display, because audio flows from
- * the same converter to the display pipeline. Also muting one pin may make
- * other pins have no sound output.
- * So this function assures that an assigned converter for a pin is not selected
- * by any other pins.
- */
-static void intel_not_share_assigned_cvt(struct hda_codec *codec,
- hda_nid_t pin_nid,
- int dev_id, int mux_idx)
-{
- struct hdmi_spec *spec = codec->spec;
- hda_nid_t nid;
- int cvt_idx, curr;
- struct hdmi_spec_per_cvt *per_cvt;
- struct hdmi_spec_per_pin *per_pin;
- int pin_idx;
-
- /* configure the pins connections */
- for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
- int dev_id_saved;
- int dev_num;
-
- per_pin = get_pin(spec, pin_idx);
- /*
- * pin not connected to monitor
- * no need to operate on it
- */
- if (!per_pin->pcm)
- continue;
-
- if ((per_pin->pin_nid == pin_nid) &&
- (per_pin->dev_id == dev_id))
- continue;
-
- /*
- * if per_pin->dev_id >= dev_num,
- * snd_hda_get_dev_select() will fail,
- * and the following operation is unpredictable.
- * So skip this situation.
- */
- dev_num = snd_hda_get_num_devices(codec, per_pin->pin_nid) + 1;
- if (per_pin->dev_id >= dev_num)
- continue;
-
- nid = per_pin->pin_nid;
-
- /*
- * Calling this function should not impact
- * on the device entry selection
- * So let's save the dev id for each pin,
- * and restore it when return
- */
- dev_id_saved = snd_hda_get_dev_select(codec, nid);
- snd_hda_set_dev_select(codec, nid, per_pin->dev_id);
- curr = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_CONNECT_SEL, 0);
- if (curr != mux_idx) {
- snd_hda_set_dev_select(codec, nid, dev_id_saved);
- continue;
- }
-
-
- /* choose an unassigned converter. The conveters in the
- * connection list are in the same order as in the codec.
- */
- for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) {
- per_cvt = get_cvt(spec, cvt_idx);
- if (!per_cvt->assigned) {
- codec_dbg(codec,
- "choose cvt %d for pin NID 0x%x\n",
- cvt_idx, nid);
- snd_hda_codec_write_cache(codec, nid, 0,
- AC_VERB_SET_CONNECT_SEL,
- cvt_idx);
- break;
- }
- }
- snd_hda_set_dev_select(codec, nid, dev_id_saved);
- }
-}
-
-/* A wrapper of intel_not_share_asigned_cvt() */
-static void intel_not_share_assigned_cvt_nid(struct hda_codec *codec,
- hda_nid_t pin_nid, int dev_id, hda_nid_t cvt_nid)
-{
- int mux_idx;
- struct hdmi_spec *spec = codec->spec;
-
- /* On Intel platform, the mapping of converter nid to
- * mux index of the pins are always the same.
- * The pin nid may be 0, this means all pins will not
- * share the converter.
- */
- mux_idx = intel_cvt_id_to_mux_idx(spec, cvt_nid);
- if (mux_idx >= 0)
- intel_not_share_assigned_cvt(codec, pin_nid, dev_id, mux_idx);
-}
-
-/* skeleton caller of pin_cvt_fixup ops */
-static void pin_cvt_fixup(struct hda_codec *codec,
- struct hdmi_spec_per_pin *per_pin,
- hda_nid_t cvt_nid)
-{
- struct hdmi_spec *spec = codec->spec;
-
- if (spec->ops.pin_cvt_fixup)
- spec->ops.pin_cvt_fixup(codec, per_pin, cvt_nid);
-}
-
-/* called in hdmi_pcm_open when no pin is assigned to the PCM */
-static int hdmi_pcm_open_no_pin(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- struct hdmi_spec *spec = codec->spec;
- struct snd_pcm_runtime *runtime = substream->runtime;
- int cvt_idx, pcm_idx;
- struct hdmi_spec_per_cvt *per_cvt = NULL;
- int err;
-
- pcm_idx = hinfo_to_pcm_index(codec, hinfo);
- if (pcm_idx < 0)
- return -EINVAL;
-
- err = hdmi_choose_cvt(codec, -1, &cvt_idx, false);
- if (err)
- return err;
-
- per_cvt = get_cvt(spec, cvt_idx);
- per_cvt->assigned = true;
- hinfo->nid = per_cvt->cvt_nid;
-
- pin_cvt_fixup(codec, NULL, per_cvt->cvt_nid);
-
- set_bit(pcm_idx, &spec->pcm_in_use);
- /* todo: setup spdif ctls assign */
-
- /* Initially set the converter's capabilities */
- hinfo->channels_min = per_cvt->channels_min;
- hinfo->channels_max = per_cvt->channels_max;
- hinfo->rates = per_cvt->rates;
- hinfo->formats = per_cvt->formats;
- hinfo->maxbps = per_cvt->maxbps;
-
- /* Store the updated parameters */
- runtime->hw.channels_min = hinfo->channels_min;
- runtime->hw.channels_max = hinfo->channels_max;
- runtime->hw.formats = hinfo->formats;
- runtime->hw.rates = hinfo->rates;
-
- snd_pcm_hw_constraint_step(substream->runtime, 0,
- SNDRV_PCM_HW_PARAM_CHANNELS, 2);
- return 0;
-}
-
-/*
- * HDA PCM callbacks
- */
-static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- struct hdmi_spec *spec = codec->spec;
- struct snd_pcm_runtime *runtime = substream->runtime;
- int pin_idx, cvt_idx, pcm_idx;
- struct hdmi_spec_per_pin *per_pin;
- struct hdmi_eld *eld;
- struct hdmi_spec_per_cvt *per_cvt = NULL;
- int err;
-
- /* Validate hinfo */
- pcm_idx = hinfo_to_pcm_index(codec, hinfo);
- if (pcm_idx < 0)
- return -EINVAL;
-
- mutex_lock(&spec->pcm_lock);
- pin_idx = hinfo_to_pin_index(codec, hinfo);
- /* no pin is assigned to the PCM
- * PA need pcm open successfully when probe
- */
- if (pin_idx < 0) {
- err = hdmi_pcm_open_no_pin(hinfo, codec, substream);
- goto unlock;
- }
-
- err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx, false);
- if (err < 0)
- goto unlock;
-
- per_cvt = get_cvt(spec, cvt_idx);
- /* Claim converter */
- per_cvt->assigned = true;
-
- set_bit(pcm_idx, &spec->pcm_in_use);
- per_pin = get_pin(spec, pin_idx);
- per_pin->cvt_nid = per_cvt->cvt_nid;
- hinfo->nid = per_cvt->cvt_nid;
-
- /* flip stripe flag for the assigned stream if supported */
- if (get_wcaps(codec, per_cvt->cvt_nid) & AC_WCAP_STRIPE)
- azx_stream(get_azx_dev(substream))->stripe = 1;
-
- snd_hda_set_dev_select(codec, per_pin->pin_nid, per_pin->dev_id);
- snd_hda_codec_write_cache(codec, per_pin->pin_nid, 0,
- AC_VERB_SET_CONNECT_SEL,
- per_pin->mux_idx);
-
- /* configure unused pins to choose other converters */
- pin_cvt_fixup(codec, per_pin, 0);
-
- snd_hda_spdif_ctls_assign(codec, pcm_idx, per_cvt->cvt_nid);
-
- /* Initially set the converter's capabilities */
- hinfo->channels_min = per_cvt->channels_min;
- hinfo->channels_max = per_cvt->channels_max;
- hinfo->rates = per_cvt->rates;
- hinfo->formats = per_cvt->formats;
- hinfo->maxbps = per_cvt->maxbps;
-
- eld = &per_pin->sink_eld;
- /* Restrict capabilities by ELD if this isn't disabled */
- if (!static_hdmi_pcm && eld->eld_valid) {
- snd_hdmi_eld_update_pcm_info(&eld->info, hinfo);
- if (hinfo->channels_min > hinfo->channels_max ||
- !hinfo->rates || !hinfo->formats) {
- per_cvt->assigned = false;
- hinfo->nid = 0;
- snd_hda_spdif_ctls_unassign(codec, pcm_idx);
- err = -ENODEV;
- goto unlock;
- }
- }
-
- /* Store the updated parameters */
- runtime->hw.channels_min = hinfo->channels_min;
- runtime->hw.channels_max = hinfo->channels_max;
- runtime->hw.formats = hinfo->formats;
- runtime->hw.rates = hinfo->rates;
-
- snd_pcm_hw_constraint_step(substream->runtime, 0,
- SNDRV_PCM_HW_PARAM_CHANNELS, 2);
- unlock:
- mutex_unlock(&spec->pcm_lock);
- return err;
-}
-
-/*
- * HDA/HDMI auto parsing
- */
-static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx)
-{
- struct hdmi_spec *spec = codec->spec;
- struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
- hda_nid_t pin_nid = per_pin->pin_nid;
- int dev_id = per_pin->dev_id;
- int conns;
-
- if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) {
- codec_warn(codec,
- "HDMI: pin NID 0x%x wcaps %#x does not support connection list\n",
- pin_nid, get_wcaps(codec, pin_nid));
- return -EINVAL;
- }
-
- snd_hda_set_dev_select(codec, pin_nid, dev_id);
-
- if (spec->intel_hsw_fixup) {
- conns = spec->num_cvts;
- memcpy(per_pin->mux_nids, spec->cvt_nids,
- sizeof(hda_nid_t) * conns);
- } else {
- conns = snd_hda_get_raw_connections(codec, pin_nid,
- per_pin->mux_nids,
- HDA_MAX_CONNECTIONS);
- }
-
- /* all the device entries on the same pin have the same conn list */
- per_pin->num_mux_nids = conns;
-
- return 0;
-}
-
-static int hdmi_find_pcm_slot(struct hdmi_spec *spec,
- struct hdmi_spec_per_pin *per_pin)
-{
- int i;
-
- for (i = 0; i < spec->pcm_used; i++) {
- if (!test_bit(i, &spec->pcm_bitmap))
- return i;
- }
- return -EBUSY;
-}
-
-static void hdmi_attach_hda_pcm(struct hdmi_spec *spec,
- struct hdmi_spec_per_pin *per_pin)
-{
- int idx;
-
- /* pcm already be attached to the pin */
- if (per_pin->pcm)
- return;
- /* try the previously used slot at first */
- idx = per_pin->prev_pcm_idx;
- if (idx >= 0) {
- if (!test_bit(idx, &spec->pcm_bitmap))
- goto found;
- per_pin->prev_pcm_idx = -1; /* no longer valid, clear it */
- }
- idx = hdmi_find_pcm_slot(spec, per_pin);
- if (idx == -EBUSY)
- return;
- found:
- per_pin->pcm_idx = idx;
- per_pin->pcm = get_hdmi_pcm(spec, idx);
- set_bit(idx, &spec->pcm_bitmap);
-}
-
-static void hdmi_detach_hda_pcm(struct hdmi_spec *spec,
- struct hdmi_spec_per_pin *per_pin)
-{
- int idx;
-
- /* pcm already be detached from the pin */
- if (!per_pin->pcm)
- return;
- idx = per_pin->pcm_idx;
- per_pin->pcm_idx = -1;
- per_pin->prev_pcm_idx = idx; /* remember the previous index */
- per_pin->pcm = NULL;
- if (idx >= 0 && idx < spec->pcm_used)
- clear_bit(idx, &spec->pcm_bitmap);
-}
-
-static int hdmi_get_pin_cvt_mux(struct hdmi_spec *spec,
- struct hdmi_spec_per_pin *per_pin, hda_nid_t cvt_nid)
-{
- int mux_idx;
-
- for (mux_idx = 0; mux_idx < per_pin->num_mux_nids; mux_idx++)
- if (per_pin->mux_nids[mux_idx] == cvt_nid)
- break;
- return mux_idx;
-}
-
-static bool check_non_pcm_per_cvt(struct hda_codec *codec, hda_nid_t cvt_nid);
-
-static void hdmi_pcm_setup_pin(struct hdmi_spec *spec,
- struct hdmi_spec_per_pin *per_pin)
-{
- struct hda_codec *codec = per_pin->codec;
- struct hda_pcm *pcm;
- struct hda_pcm_stream *hinfo;
- struct snd_pcm_substream *substream;
- int mux_idx;
- bool non_pcm;
-
- if (per_pin->pcm_idx < 0 || per_pin->pcm_idx >= spec->pcm_used)
- return;
- pcm = get_pcm_rec(spec, per_pin->pcm_idx);
- if (!pcm->pcm)
- return;
- if (!test_bit(per_pin->pcm_idx, &spec->pcm_in_use))
- return;
-
- /* hdmi audio only uses playback and one substream */
- hinfo = pcm->stream;
- substream = pcm->pcm->streams[0].substream;
-
- per_pin->cvt_nid = hinfo->nid;
-
- mux_idx = hdmi_get_pin_cvt_mux(spec, per_pin, hinfo->nid);
- if (mux_idx < per_pin->num_mux_nids) {
- snd_hda_set_dev_select(codec, per_pin->pin_nid,
- per_pin->dev_id);
- snd_hda_codec_write_cache(codec, per_pin->pin_nid, 0,
- AC_VERB_SET_CONNECT_SEL,
- mux_idx);
- }
- snd_hda_spdif_ctls_assign(codec, per_pin->pcm_idx, hinfo->nid);
-
- non_pcm = check_non_pcm_per_cvt(codec, hinfo->nid);
- if (substream->runtime)
- per_pin->channels = substream->runtime->channels;
- per_pin->setup = true;
- per_pin->mux_idx = mux_idx;
-
- hdmi_setup_audio_infoframe(codec, per_pin, non_pcm);
-}
-
-static void hdmi_pcm_reset_pin(struct hdmi_spec *spec,
- struct hdmi_spec_per_pin *per_pin)
-{
- if (per_pin->pcm_idx >= 0 && per_pin->pcm_idx < spec->pcm_used)
- snd_hda_spdif_ctls_unassign(per_pin->codec, per_pin->pcm_idx);
-
- per_pin->chmap_set = false;
- memset(per_pin->chmap, 0, sizeof(per_pin->chmap));
-
- per_pin->setup = false;
- per_pin->channels = 0;
-}
-
-static struct snd_jack *pin_idx_to_pcm_jack(struct hda_codec *codec,
- struct hdmi_spec_per_pin *per_pin)
-{
- struct hdmi_spec *spec = codec->spec;
-
- if (per_pin->pcm_idx >= 0)
- return spec->pcm_rec[per_pin->pcm_idx].jack;
- else
- return NULL;
-}
-
-/* update per_pin ELD from the given new ELD;
- * setup info frame and notification accordingly
- * also notify ELD kctl and report jack status changes
- */
-static void update_eld(struct hda_codec *codec,
- struct hdmi_spec_per_pin *per_pin,
- struct hdmi_eld *eld,
- int repoll)
-{
- struct hdmi_eld *pin_eld = &per_pin->sink_eld;
- struct hdmi_spec *spec = codec->spec;
- struct snd_jack *pcm_jack;
- bool old_eld_valid = pin_eld->eld_valid;
- bool eld_changed;
- int pcm_idx;
-
- if (eld->eld_valid) {
- if (eld->eld_size <= 0 ||
- snd_parse_eld(hda_codec_dev(codec), &eld->info,
- eld->eld_buffer, eld->eld_size) < 0) {
- eld->eld_valid = false;
- if (repoll) {
- schedule_delayed_work(&per_pin->work,
- msecs_to_jiffies(300));
- return;
- }
- }
- }
-
- if (!eld->eld_valid || eld->eld_size <= 0 || eld->info.sad_count <= 0) {
- eld->eld_valid = false;
- eld->eld_size = 0;
- }
-
- /* for monitor disconnection, save pcm_idx firstly */
- pcm_idx = per_pin->pcm_idx;
-
- /*
- * pcm_idx >=0 before update_eld() means it is in monitor
- * disconnected event. Jack must be fetched before update_eld().
- */
- pcm_jack = pin_idx_to_pcm_jack(codec, per_pin);
-
- if (!spec->static_pcm_mapping) {
- if (eld->eld_valid) {
- hdmi_attach_hda_pcm(spec, per_pin);
- hdmi_pcm_setup_pin(spec, per_pin);
- } else {
- hdmi_pcm_reset_pin(spec, per_pin);
- hdmi_detach_hda_pcm(spec, per_pin);
- }
- }
-
- /* if pcm_idx == -1, it means this is in monitor connection event
- * we can get the correct pcm_idx now.
- */
- if (pcm_idx == -1)
- pcm_idx = per_pin->pcm_idx;
- if (!pcm_jack)
- pcm_jack = pin_idx_to_pcm_jack(codec, per_pin);
-
- if (eld->eld_valid)
- snd_show_eld(hda_codec_dev(codec), &eld->info);
-
- eld_changed = (pin_eld->eld_valid != eld->eld_valid);
- eld_changed |= (pin_eld->monitor_present != eld->monitor_present);
- if (!eld_changed && eld->eld_valid && pin_eld->eld_valid)
- if (pin_eld->eld_size != eld->eld_size ||
- memcmp(pin_eld->eld_buffer, eld->eld_buffer,
- eld->eld_size) != 0)
- eld_changed = true;
-
- if (eld_changed) {
- pin_eld->monitor_present = eld->monitor_present;
- pin_eld->eld_valid = eld->eld_valid;
- pin_eld->eld_size = eld->eld_size;
- if (eld->eld_valid)
- memcpy(pin_eld->eld_buffer, eld->eld_buffer,
- eld->eld_size);
- pin_eld->info = eld->info;
- }
-
- /*
- * Re-setup pin and infoframe. This is needed e.g. when
- * - sink is first plugged-in
- * - transcoder can change during stream playback on Haswell
- * and this can make HW reset converter selection on a pin.
- */
- if (eld->eld_valid && !old_eld_valid && per_pin->setup) {
- pin_cvt_fixup(codec, per_pin, 0);
- hdmi_setup_audio_infoframe(codec, per_pin, per_pin->non_pcm);
- }
-
- if (eld_changed && pcm_idx >= 0)
- snd_ctl_notify(codec->card,
- SNDRV_CTL_EVENT_MASK_VALUE |
- SNDRV_CTL_EVENT_MASK_INFO,
- &get_hdmi_pcm(spec, pcm_idx)->eld_ctl->id);
-
- if (eld_changed && pcm_jack)
- snd_jack_report(pcm_jack,
- (eld->monitor_present && eld->eld_valid) ?
- SND_JACK_AVOUT : 0);
-}
-
-/* update ELD and jack state via HD-audio verbs */
-static void hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin,
- int repoll)
-{
- struct hda_codec *codec = per_pin->codec;
- struct hdmi_spec *spec = codec->spec;
- struct hdmi_eld *eld = &spec->temp_eld;
- struct device *dev = hda_codec_dev(codec);
- hda_nid_t pin_nid = per_pin->pin_nid;
- int dev_id = per_pin->dev_id;
- /*
- * Always execute a GetPinSense verb here, even when called from
- * hdmi_intrinsic_event; for some NVIDIA HW, the unsolicited
- * response's PD bit is not the real PD value, but indicates that
- * the real PD value changed. An older version of the HD-audio
- * specification worked this way. Hence, we just ignore the data in
- * the unsolicited response to avoid custom WARs.
- */
- int present;
- int ret;
-
-#ifdef CONFIG_PM
- if (dev->power.runtime_status == RPM_SUSPENDING)
- return;
-#endif
-
- ret = snd_hda_power_up_pm(codec);
- if (ret < 0 && pm_runtime_suspended(dev))
- goto out;
-
- present = snd_hda_jack_pin_sense(codec, pin_nid, dev_id);
-
- mutex_lock(&per_pin->lock);
- eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE);
- if (eld->monitor_present)
- eld->eld_valid = !!(present & AC_PINSENSE_ELDV);
- else
- eld->eld_valid = false;
-
- codec_dbg(codec,
- "HDMI status: Codec=%d NID=0x%x Presence_Detect=%d ELD_Valid=%d\n",
- codec->addr, pin_nid, eld->monitor_present, eld->eld_valid);
-
- if (eld->eld_valid) {
- if (spec->ops.pin_get_eld(codec, pin_nid, dev_id,
- eld->eld_buffer, &eld->eld_size) < 0)
- eld->eld_valid = false;
- }
-
- update_eld(codec, per_pin, eld, repoll);
- mutex_unlock(&per_pin->lock);
- out:
- snd_hda_power_down_pm(codec);
-}
-
-#define I915_SILENT_RATE 48000
-#define I915_SILENT_CHANNELS 2
-#define I915_SILENT_FORMAT_BITS 16
-#define I915_SILENT_FMT_MASK 0xf
-
-static void silent_stream_enable_i915(struct hda_codec *codec,
- struct hdmi_spec_per_pin *per_pin)
-{
- unsigned int format;
-
- snd_hdac_sync_audio_rate(&codec->core, per_pin->pin_nid,
- per_pin->dev_id, I915_SILENT_RATE);
-
- /* trigger silent stream generation in hw */
- format = snd_hdac_stream_format(I915_SILENT_CHANNELS, I915_SILENT_FORMAT_BITS,
- I915_SILENT_RATE);
- snd_hda_codec_setup_stream(codec, per_pin->cvt_nid,
- I915_SILENT_FMT_MASK, I915_SILENT_FMT_MASK, format);
- usleep_range(100, 200);
- snd_hda_codec_setup_stream(codec, per_pin->cvt_nid, I915_SILENT_FMT_MASK, 0, format);
-
- per_pin->channels = I915_SILENT_CHANNELS;
- hdmi_setup_audio_infoframe(codec, per_pin, per_pin->non_pcm);
-}
-
-static void silent_stream_set_kae(struct hda_codec *codec,
- struct hdmi_spec_per_pin *per_pin,
- bool enable)
-{
- unsigned int param;
-
- codec_dbg(codec, "HDMI: KAE %d cvt-NID=0x%x\n", enable, per_pin->cvt_nid);
-
- param = snd_hda_codec_read(codec, per_pin->cvt_nid, 0, AC_VERB_GET_DIGI_CONVERT_1, 0);
- param = (param >> 16) & 0xff;
-
- if (enable)
- param |= AC_DIG3_KAE;
- else
- param &= ~AC_DIG3_KAE;
-
- snd_hda_codec_write(codec, per_pin->cvt_nid, 0, AC_VERB_SET_DIGI_CONVERT_3, param);
-}
-
-static void silent_stream_enable(struct hda_codec *codec,
- struct hdmi_spec_per_pin *per_pin)
-{
- struct hdmi_spec *spec = codec->spec;
- struct hdmi_spec_per_cvt *per_cvt;
- int cvt_idx, pin_idx, err;
- int keep_power = 0;
-
- /*
- * Power-up will call hdmi_present_sense, so the PM calls
- * have to be done without mutex held.
- */
-
- err = snd_hda_power_up_pm(codec);
- if (err < 0 && err != -EACCES) {
- codec_err(codec,
- "Failed to power up codec for silent stream enable ret=[%d]\n", err);
- snd_hda_power_down_pm(codec);
- return;
- }
-
- mutex_lock(&per_pin->lock);
-
- if (per_pin->setup) {
- codec_dbg(codec, "hdmi: PCM already open, no silent stream\n");
- err = -EBUSY;
- goto unlock_out;
- }
-
- pin_idx = pin_id_to_pin_index(codec, per_pin->pin_nid, per_pin->dev_id);
- err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx, true);
- if (err) {
- codec_err(codec, "hdmi: no free converter to enable silent mode\n");
- goto unlock_out;
- }
-
- per_cvt = get_cvt(spec, cvt_idx);
- per_cvt->silent_stream = true;
- per_pin->cvt_nid = per_cvt->cvt_nid;
- per_pin->silent_stream = true;
-
- codec_dbg(codec, "hdmi: enabling silent stream pin-NID=0x%x cvt-NID=0x%x\n",
- per_pin->pin_nid, per_cvt->cvt_nid);
-
- snd_hda_set_dev_select(codec, per_pin->pin_nid, per_pin->dev_id);
- snd_hda_codec_write_cache(codec, per_pin->pin_nid, 0,
- AC_VERB_SET_CONNECT_SEL,
- per_pin->mux_idx);
-
- /* configure unused pins to choose other converters */
- pin_cvt_fixup(codec, per_pin, 0);
-
- switch (spec->silent_stream_type) {
- case SILENT_STREAM_KAE:
- silent_stream_enable_i915(codec, per_pin);
- silent_stream_set_kae(codec, per_pin, true);
- break;
- case SILENT_STREAM_I915:
- silent_stream_enable_i915(codec, per_pin);
- keep_power = 1;
- break;
- default:
- break;
- }
-
- unlock_out:
- mutex_unlock(&per_pin->lock);
-
- if (err || !keep_power)
- snd_hda_power_down_pm(codec);
-}
-
-static void silent_stream_disable(struct hda_codec *codec,
- struct hdmi_spec_per_pin *per_pin)
-{
- struct hdmi_spec *spec = codec->spec;
- struct hdmi_spec_per_cvt *per_cvt;
- int cvt_idx, err;
-
- err = snd_hda_power_up_pm(codec);
- if (err < 0 && err != -EACCES) {
- codec_err(codec,
- "Failed to power up codec for silent stream disable ret=[%d]\n",
- err);
- snd_hda_power_down_pm(codec);
- return;
- }
-
- mutex_lock(&per_pin->lock);
- if (!per_pin->silent_stream)
- goto unlock_out;
-
- codec_dbg(codec, "HDMI: disable silent stream on pin-NID=0x%x cvt-NID=0x%x\n",
- per_pin->pin_nid, per_pin->cvt_nid);
-
- cvt_idx = cvt_nid_to_cvt_index(codec, per_pin->cvt_nid);
- if (cvt_idx >= 0 && cvt_idx < spec->num_cvts) {
- per_cvt = get_cvt(spec, cvt_idx);
- per_cvt->silent_stream = false;
- }
-
- if (spec->silent_stream_type == SILENT_STREAM_I915) {
- /* release ref taken in silent_stream_enable() */
- snd_hda_power_down_pm(codec);
- } else if (spec->silent_stream_type == SILENT_STREAM_KAE) {
- silent_stream_set_kae(codec, per_pin, false);
- }
-
- per_pin->cvt_nid = 0;
- per_pin->silent_stream = false;
-
- unlock_out:
- mutex_unlock(&per_pin->lock);
-
- snd_hda_power_down_pm(codec);
-}
-
-/* update ELD and jack state via audio component */
-static void sync_eld_via_acomp(struct hda_codec *codec,
- struct hdmi_spec_per_pin *per_pin)
-{
- struct hdmi_spec *spec = codec->spec;
- struct hdmi_eld *eld = &spec->temp_eld;
- bool monitor_prev, monitor_next;
-
- mutex_lock(&per_pin->lock);
- eld->monitor_present = false;
- monitor_prev = per_pin->sink_eld.monitor_present;
- eld->eld_size = snd_hdac_acomp_get_eld(&codec->core, per_pin->pin_nid,
- per_pin->dev_id, &eld->monitor_present,
- eld->eld_buffer, ELD_MAX_SIZE);
- eld->eld_valid = (eld->eld_size > 0);
- update_eld(codec, per_pin, eld, 0);
- monitor_next = per_pin->sink_eld.monitor_present;
- mutex_unlock(&per_pin->lock);
-
- if (spec->silent_stream_type) {
- if (!monitor_prev && monitor_next)
- silent_stream_enable(codec, per_pin);
- else if (monitor_prev && !monitor_next)
- silent_stream_disable(codec, per_pin);
- }
-}
-
-static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
-{
- struct hda_codec *codec = per_pin->codec;
-
- if (!codec_has_acomp(codec))
- hdmi_present_sense_via_verbs(per_pin, repoll);
- else
- sync_eld_via_acomp(codec, per_pin);
-}
-
-static void hdmi_repoll_eld(struct work_struct *work)
-{
- struct hdmi_spec_per_pin *per_pin =
- container_of(to_delayed_work(work), struct hdmi_spec_per_pin, work);
- struct hda_codec *codec = per_pin->codec;
- struct hdmi_spec *spec = codec->spec;
- struct hda_jack_tbl *jack;
-
- jack = snd_hda_jack_tbl_get_mst(codec, per_pin->pin_nid,
- per_pin->dev_id);
- if (jack)
- jack->jack_dirty = 1;
-
- if (per_pin->repoll_count++ > 6)
- per_pin->repoll_count = 0;
-
- mutex_lock(&spec->pcm_lock);
- hdmi_present_sense(per_pin, per_pin->repoll_count);
- mutex_unlock(&spec->pcm_lock);
-}
-
-static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
-{
- struct hdmi_spec *spec = codec->spec;
- unsigned int caps, config;
- int pin_idx;
- struct hdmi_spec_per_pin *per_pin;
- int err;
- int dev_num, i;
-
- caps = snd_hda_query_pin_caps(codec, pin_nid);
- if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP)))
- return 0;
-
- /*
- * For DP MST audio, Configuration Default is the same for
- * all device entries on the same pin
- */
- config = snd_hda_codec_get_pincfg(codec, pin_nid);
- if (get_defcfg_connect(config) == AC_JACK_PORT_NONE &&
- !spec->force_connect)
- return 0;
-
- /*
- * To simplify the implementation, malloc all
- * the virtual pins in the initialization statically
- */
- if (spec->intel_hsw_fixup) {
- /*
- * On Intel platforms, device entries count returned
- * by AC_PAR_DEVLIST_LEN is dynamic, and depends on
- * the type of receiver that is connected. Allocate pin
- * structures based on worst case.
- */
- dev_num = spec->dev_num;
- } else if (codec->dp_mst) {
- dev_num = snd_hda_get_num_devices(codec, pin_nid) + 1;
- /*
- * spec->dev_num is the maxinum number of device entries
- * among all the pins
- */
- spec->dev_num = (spec->dev_num > dev_num) ?
- spec->dev_num : dev_num;
- } else {
- /*
- * If the platform doesn't support DP MST,
- * manually set dev_num to 1. This means
- * the pin has only one device entry.
- */
- dev_num = 1;
- spec->dev_num = 1;
- }
-
- for (i = 0; i < dev_num; i++) {
- pin_idx = spec->num_pins;
- per_pin = snd_array_new(&spec->pins);
-
- if (!per_pin)
- return -ENOMEM;
-
- per_pin->pcm = NULL;
- per_pin->pcm_idx = -1;
- per_pin->prev_pcm_idx = -1;
- per_pin->pin_nid = pin_nid;
- per_pin->pin_nid_idx = spec->num_nids;
- per_pin->dev_id = i;
- per_pin->non_pcm = false;
- snd_hda_set_dev_select(codec, pin_nid, i);
- err = hdmi_read_pin_conn(codec, pin_idx);
- if (err < 0)
- return err;
- if (!is_jack_detectable(codec, pin_nid))
- codec_warn(codec, "HDMI: pin NID 0x%x - jack not detectable\n", pin_nid);
- spec->num_pins++;
- }
- spec->num_nids++;
-
- return 0;
-}
-
-static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid)
-{
- struct hdmi_spec *spec = codec->spec;
- struct hdmi_spec_per_cvt *per_cvt;
- unsigned int chans;
- int err;
-
- chans = get_wcaps(codec, cvt_nid);
- chans = get_wcaps_channels(chans);
-
- per_cvt = snd_array_new(&spec->cvts);
- if (!per_cvt)
- return -ENOMEM;
-
- per_cvt->cvt_nid = cvt_nid;
- per_cvt->channels_min = 2;
- if (chans <= 16) {
- per_cvt->channels_max = chans;
- if (chans > spec->chmap.channels_max)
- spec->chmap.channels_max = chans;
- }
-
- err = snd_hda_query_supported_pcm(codec, cvt_nid,
- &per_cvt->rates,
- &per_cvt->formats,
- NULL,
- &per_cvt->maxbps);
- if (err < 0)
- return err;
-
- if (spec->num_cvts < ARRAY_SIZE(spec->cvt_nids))
- spec->cvt_nids[spec->num_cvts] = cvt_nid;
- spec->num_cvts++;
-
- return 0;
-}
-
-static const struct snd_pci_quirk force_connect_list[] = {
- SND_PCI_QUIRK(0x103c, 0x83e2, "HP EliteDesk 800 G4", 1),
- SND_PCI_QUIRK(0x103c, 0x83ef, "HP MP9 G4 Retail System AMS", 1),
- SND_PCI_QUIRK(0x103c, 0x870f, "HP", 1),
- SND_PCI_QUIRK(0x103c, 0x871a, "HP", 1),
- SND_PCI_QUIRK(0x103c, 0x8711, "HP", 1),
- SND_PCI_QUIRK(0x103c, 0x8715, "HP", 1),
- SND_PCI_QUIRK(0x1043, 0x86ae, "ASUS", 1), /* Z170 PRO */
- SND_PCI_QUIRK(0x1043, 0x86c7, "ASUS", 1), /* Z170M PLUS */
- SND_PCI_QUIRK(0x1462, 0xec94, "MS-7C94", 1),
- SND_PCI_QUIRK(0x8086, 0x2060, "Intel NUC5CPYB", 1),
- SND_PCI_QUIRK(0x8086, 0x2081, "Intel NUC 10", 1),
- {}
-};
-
-static int hdmi_parse_codec(struct hda_codec *codec)
-{
- struct hdmi_spec *spec = codec->spec;
- hda_nid_t start_nid;
- unsigned int caps;
- int i, nodes;
- const struct snd_pci_quirk *q;
-
- nodes = snd_hda_get_sub_nodes(codec, codec->core.afg, &start_nid);
- if (!start_nid || nodes < 0) {
- codec_warn(codec, "HDMI: failed to get afg sub nodes\n");
- return -EINVAL;
- }
-
- if (enable_all_pins)
- spec->force_connect = true;
-
- q = snd_pci_quirk_lookup(codec->bus->pci, force_connect_list);
-
- if (q && q->value)
- spec->force_connect = true;
-
- /*
- * hdmi_add_pin() assumes total amount of converters to
- * be known, so first discover all converters
- */
- for (i = 0; i < nodes; i++) {
- hda_nid_t nid = start_nid + i;
-
- caps = get_wcaps(codec, nid);
-
- if (!(caps & AC_WCAP_DIGITAL))
- continue;
-
- if (get_wcaps_type(caps) == AC_WID_AUD_OUT)
- hdmi_add_cvt(codec, nid);
- }
-
- /* discover audio pins */
- for (i = 0; i < nodes; i++) {
- hda_nid_t nid = start_nid + i;
-
- caps = get_wcaps(codec, nid);
-
- if (!(caps & AC_WCAP_DIGITAL))
- continue;
-
- if (get_wcaps_type(caps) == AC_WID_PIN)
- hdmi_add_pin(codec, nid);
- }
-
- return 0;
-}
-
-/*
- */
-static bool check_non_pcm_per_cvt(struct hda_codec *codec, hda_nid_t cvt_nid)
-{
- struct hda_spdif_out *spdif;
- bool non_pcm;
-
- mutex_lock(&codec->spdif_mutex);
- spdif = snd_hda_spdif_out_of_nid(codec, cvt_nid);
- /* Add sanity check to pass klockwork check.
- * This should never happen.
- */
- if (WARN_ON(spdif == NULL)) {
- mutex_unlock(&codec->spdif_mutex);
- return true;
- }
- non_pcm = !!(spdif->status & IEC958_AES0_NONAUDIO);
- mutex_unlock(&codec->spdif_mutex);
- return non_pcm;
-}
-
-/*
- * HDMI callbacks
- */
-
-static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- unsigned int stream_tag,
- unsigned int format,
- struct snd_pcm_substream *substream)
-{
- hda_nid_t cvt_nid = hinfo->nid;
- struct hdmi_spec *spec = codec->spec;
- int pin_idx;
- struct hdmi_spec_per_pin *per_pin;
- struct snd_pcm_runtime *runtime = substream->runtime;
- bool non_pcm;
- int pinctl, stripe;
- int err = 0;
-
- mutex_lock(&spec->pcm_lock);
- pin_idx = hinfo_to_pin_index(codec, hinfo);
- if (pin_idx < 0) {
- /* when pcm is not bound to a pin skip pin setup and return 0
- * to make audio playback be ongoing
- */
- pin_cvt_fixup(codec, NULL, cvt_nid);
- snd_hda_codec_setup_stream(codec, cvt_nid,
- stream_tag, 0, format);
- goto unlock;
- }
-
- per_pin = get_pin(spec, pin_idx);
-
- /* Verify pin:cvt selections to avoid silent audio after S3.
- * After S3, the audio driver restores pin:cvt selections
- * but this can happen before gfx is ready and such selection
- * is overlooked by HW. Thus multiple pins can share a same
- * default convertor and mute control will affect each other,
- * which can cause a resumed audio playback become silent
- * after S3.
- */
- pin_cvt_fixup(codec, per_pin, 0);
-
- /* Call sync_audio_rate to set the N/CTS/M manually if necessary */
- /* Todo: add DP1.2 MST audio support later */
- if (codec_has_acomp(codec))
- snd_hdac_sync_audio_rate(&codec->core, per_pin->pin_nid,
- per_pin->dev_id, runtime->rate);
-
- non_pcm = check_non_pcm_per_cvt(codec, cvt_nid);
- mutex_lock(&per_pin->lock);
- per_pin->channels = substream->runtime->channels;
- per_pin->setup = true;
-
- if (get_wcaps(codec, cvt_nid) & AC_WCAP_STRIPE) {
- stripe = snd_hdac_get_stream_stripe_ctl(&codec->bus->core,
- substream);
- snd_hda_codec_write(codec, cvt_nid, 0,
- AC_VERB_SET_STRIPE_CONTROL,
- stripe);
- }
-
- hdmi_setup_audio_infoframe(codec, per_pin, non_pcm);
- mutex_unlock(&per_pin->lock);
- if (spec->dyn_pin_out) {
- snd_hda_set_dev_select(codec, per_pin->pin_nid,
- per_pin->dev_id);
- pinctl = snd_hda_codec_read(codec, per_pin->pin_nid, 0,
- AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
- snd_hda_codec_write(codec, per_pin->pin_nid, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- pinctl | PIN_OUT);
- }
-
- /* snd_hda_set_dev_select() has been called before */
- err = spec->ops.setup_stream(codec, cvt_nid, per_pin->pin_nid,
- per_pin->dev_id, stream_tag, format);
- unlock:
- mutex_unlock(&spec->pcm_lock);
- return err;
-}
-
-static int generic_hdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- snd_hda_codec_cleanup_stream(codec, hinfo->nid);
- return 0;
-}
-
-static int hdmi_pcm_close(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- struct hdmi_spec *spec = codec->spec;
- int cvt_idx, pin_idx, pcm_idx;
- struct hdmi_spec_per_cvt *per_cvt;
- struct hdmi_spec_per_pin *per_pin;
- int pinctl;
- int err = 0;
-
- mutex_lock(&spec->pcm_lock);
- if (hinfo->nid) {
- pcm_idx = hinfo_to_pcm_index(codec, hinfo);
- if (snd_BUG_ON(pcm_idx < 0)) {
- err = -EINVAL;
- goto unlock;
- }
- cvt_idx = cvt_nid_to_cvt_index(codec, hinfo->nid);
- if (snd_BUG_ON(cvt_idx < 0)) {
- err = -EINVAL;
- goto unlock;
- }
- per_cvt = get_cvt(spec, cvt_idx);
- per_cvt->assigned = false;
- hinfo->nid = 0;
-
- azx_stream(get_azx_dev(substream))->stripe = 0;
-
- snd_hda_spdif_ctls_unassign(codec, pcm_idx);
- clear_bit(pcm_idx, &spec->pcm_in_use);
- pin_idx = hinfo_to_pin_index(codec, hinfo);
- /*
- * In such a case, return 0 to match the behavior in
- * hdmi_pcm_open()
- */
- if (pin_idx < 0)
- goto unlock;
-
- per_pin = get_pin(spec, pin_idx);
-
- if (spec->dyn_pin_out) {
- snd_hda_set_dev_select(codec, per_pin->pin_nid,
- per_pin->dev_id);
- pinctl = snd_hda_codec_read(codec, per_pin->pin_nid, 0,
- AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
- snd_hda_codec_write(codec, per_pin->pin_nid, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- pinctl & ~PIN_OUT);
- }
-
- mutex_lock(&per_pin->lock);
- per_pin->chmap_set = false;
- memset(per_pin->chmap, 0, sizeof(per_pin->chmap));
-
- per_pin->setup = false;
- per_pin->channels = 0;
- mutex_unlock(&per_pin->lock);
- }
-
-unlock:
- mutex_unlock(&spec->pcm_lock);
-
- return err;
-}
-
-static const struct hda_pcm_ops generic_ops = {
- .open = hdmi_pcm_open,
- .close = hdmi_pcm_close,
- .prepare = generic_hdmi_playback_pcm_prepare,
- .cleanup = generic_hdmi_playback_pcm_cleanup,
-};
-
-static int hdmi_get_spk_alloc(struct hdac_device *hdac, int pcm_idx)
-{
- struct hda_codec *codec = hdac_to_hda_codec(hdac);
- struct hdmi_spec *spec = codec->spec;
- struct hdmi_spec_per_pin *per_pin = pcm_idx_to_pin(spec, pcm_idx);
-
- if (!per_pin)
- return 0;
-
- return per_pin->sink_eld.info.spk_alloc;
-}
-
-static void hdmi_get_chmap(struct hdac_device *hdac, int pcm_idx,
- unsigned char *chmap)
-{
- struct hda_codec *codec = hdac_to_hda_codec(hdac);
- struct hdmi_spec *spec = codec->spec;
- struct hdmi_spec_per_pin *per_pin = pcm_idx_to_pin(spec, pcm_idx);
-
- /* chmap is already set to 0 in caller */
- if (!per_pin)
- return;
-
- memcpy(chmap, per_pin->chmap, ARRAY_SIZE(per_pin->chmap));
-}
-
-static void hdmi_set_chmap(struct hdac_device *hdac, int pcm_idx,
- unsigned char *chmap, int prepared)
-{
- struct hda_codec *codec = hdac_to_hda_codec(hdac);
- struct hdmi_spec *spec = codec->spec;
- struct hdmi_spec_per_pin *per_pin = pcm_idx_to_pin(spec, pcm_idx);
-
- if (!per_pin)
- return;
- mutex_lock(&per_pin->lock);
- per_pin->chmap_set = true;
- memcpy(per_pin->chmap, chmap, ARRAY_SIZE(per_pin->chmap));
- if (prepared)
- hdmi_setup_audio_infoframe(codec, per_pin, per_pin->non_pcm);
- mutex_unlock(&per_pin->lock);
-}
-
-static bool is_hdmi_pcm_attached(struct hdac_device *hdac, int pcm_idx)
-{
- struct hda_codec *codec = hdac_to_hda_codec(hdac);
- struct hdmi_spec *spec = codec->spec;
- struct hdmi_spec_per_pin *per_pin = pcm_idx_to_pin(spec, pcm_idx);
-
- return per_pin ? true:false;
-}
-
-static int generic_hdmi_build_pcms(struct hda_codec *codec)
-{
- struct hdmi_spec *spec = codec->spec;
- int idx, pcm_num;
-
- /* limit the PCM devices to the codec converters or available PINs */
- pcm_num = min(spec->num_cvts, spec->num_pins);
- codec_dbg(codec, "hdmi: pcm_num set to %d\n", pcm_num);
-
- for (idx = 0; idx < pcm_num; idx++) {
- struct hdmi_spec_per_cvt *per_cvt;
- struct hda_pcm *info;
- struct hda_pcm_stream *pstr;
-
- info = snd_hda_codec_pcm_new(codec, "HDMI %d", idx);
- if (!info)
- return -ENOMEM;
-
- spec->pcm_rec[idx].pcm = info;
- spec->pcm_used++;
- info->pcm_type = HDA_PCM_TYPE_HDMI;
- info->own_chmap = true;
-
- pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK];
- pstr->substreams = 1;
- pstr->ops = generic_ops;
-
- per_cvt = get_cvt(spec, 0);
- pstr->channels_min = per_cvt->channels_min;
- pstr->channels_max = per_cvt->channels_max;
-
- /* pcm number is less than pcm_rec array size */
- if (spec->pcm_used >= ARRAY_SIZE(spec->pcm_rec))
- break;
- /* other pstr fields are set in open */
- }
-
- return 0;
-}
-
-static void free_hdmi_jack_priv(struct snd_jack *jack)
-{
- struct hdmi_pcm *pcm = jack->private_data;
-
- pcm->jack = NULL;
-}
-
-static int generic_hdmi_build_jack(struct hda_codec *codec, int pcm_idx)
-{
- char hdmi_str[32] = "HDMI/DP";
- struct hdmi_spec *spec = codec->spec;
- struct snd_jack *jack;
- int pcmdev = get_pcm_rec(spec, pcm_idx)->device;
- int err;
-
- if (pcmdev > 0)
- sprintf(hdmi_str + strlen(hdmi_str), ",pcm=%d", pcmdev);
-
- err = snd_jack_new(codec->card, hdmi_str, SND_JACK_AVOUT, &jack,
- true, false);
- if (err < 0)
- return err;
-
- spec->pcm_rec[pcm_idx].jack = jack;
- jack->private_data = &spec->pcm_rec[pcm_idx];
- jack->private_free = free_hdmi_jack_priv;
- return 0;
-}
-
-static int generic_hdmi_build_controls(struct hda_codec *codec)
-{
- struct hdmi_spec *spec = codec->spec;
- int dev, err;
- int pin_idx, pcm_idx;
-
- for (pcm_idx = 0; pcm_idx < spec->pcm_used; pcm_idx++) {
- if (!get_pcm_rec(spec, pcm_idx)->pcm) {
- /* no PCM: mark this for skipping permanently */
- set_bit(pcm_idx, &spec->pcm_bitmap);
- continue;
- }
-
- err = generic_hdmi_build_jack(codec, pcm_idx);
- if (err < 0)
- return err;
-
- /* create the spdif for each pcm
- * pin will be bound when monitor is connected
- */
- err = snd_hda_create_dig_out_ctls(codec,
- 0, spec->cvt_nids[0],
- HDA_PCM_TYPE_HDMI);
- if (err < 0)
- return err;
- snd_hda_spdif_ctls_unassign(codec, pcm_idx);
-
- dev = get_pcm_rec(spec, pcm_idx)->device;
- if (dev != SNDRV_PCM_INVALID_DEVICE) {
- /* add control for ELD Bytes */
- err = hdmi_create_eld_ctl(codec, pcm_idx, dev);
- if (err < 0)
- return err;
- }
- }
-
- for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
- struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
- struct hdmi_eld *pin_eld = &per_pin->sink_eld;
-
- if (spec->static_pcm_mapping) {
- hdmi_attach_hda_pcm(spec, per_pin);
- hdmi_pcm_setup_pin(spec, per_pin);
- }
-
- pin_eld->eld_valid = false;
- hdmi_present_sense(per_pin, 0);
- }
-
- /* add channel maps */
- for (pcm_idx = 0; pcm_idx < spec->pcm_used; pcm_idx++) {
- struct hda_pcm *pcm;
-
- pcm = get_pcm_rec(spec, pcm_idx);
- if (!pcm || !pcm->pcm)
- break;
- err = snd_hdac_add_chmap_ctls(pcm->pcm, pcm_idx, &spec->chmap);
- if (err < 0)
- return err;
- }
-
- return 0;
-}
-
-static int generic_hdmi_init_per_pins(struct hda_codec *codec)
-{
- struct hdmi_spec *spec = codec->spec;
- int pin_idx;
-
- for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
- struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
-
- per_pin->codec = codec;
- mutex_init(&per_pin->lock);
- INIT_DELAYED_WORK(&per_pin->work, hdmi_repoll_eld);
- eld_proc_new(per_pin, pin_idx);
- }
- return 0;
-}
-
-static int generic_hdmi_init(struct hda_codec *codec)
-{
- struct hdmi_spec *spec = codec->spec;
- int pin_idx;
-
- mutex_lock(&spec->bind_lock);
- for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
- struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
- hda_nid_t pin_nid = per_pin->pin_nid;
- int dev_id = per_pin->dev_id;
-
- snd_hda_set_dev_select(codec, pin_nid, dev_id);
- hdmi_init_pin(codec, pin_nid);
- if (codec_has_acomp(codec))
- continue;
- snd_hda_jack_detect_enable_callback_mst(codec, pin_nid, dev_id,
- jack_callback);
- }
- mutex_unlock(&spec->bind_lock);
- return 0;
-}
-
-static void hdmi_array_init(struct hdmi_spec *spec, int nums)
-{
- snd_array_init(&spec->pins, sizeof(struct hdmi_spec_per_pin), nums);
- snd_array_init(&spec->cvts, sizeof(struct hdmi_spec_per_cvt), nums);
-}
-
-static void hdmi_array_free(struct hdmi_spec *spec)
-{
- snd_array_free(&spec->pins);
- snd_array_free(&spec->cvts);
-}
-
-static void generic_spec_free(struct hda_codec *codec)
-{
- struct hdmi_spec *spec = codec->spec;
-
- if (spec) {
- hdmi_array_free(spec);
- kfree(spec);
- codec->spec = NULL;
- }
- codec->dp_mst = false;
-}
-
-static void generic_hdmi_free(struct hda_codec *codec)
-{
- struct hdmi_spec *spec = codec->spec;
- int pin_idx, pcm_idx;
-
- if (spec->acomp_registered) {
- snd_hdac_acomp_exit(&codec->bus->core);
- } else if (codec_has_acomp(codec)) {
- snd_hdac_acomp_register_notifier(&codec->bus->core, NULL);
- }
- codec->relaxed_resume = 0;
-
- for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
- struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
- cancel_delayed_work_sync(&per_pin->work);
- eld_proc_free(per_pin);
- }
-
- for (pcm_idx = 0; pcm_idx < spec->pcm_used; pcm_idx++) {
- if (spec->pcm_rec[pcm_idx].jack == NULL)
- continue;
- snd_device_free(codec->card, spec->pcm_rec[pcm_idx].jack);
- }
-
- generic_spec_free(codec);
-}
-
-static int generic_hdmi_suspend(struct hda_codec *codec)
-{
- struct hdmi_spec *spec = codec->spec;
- int pin_idx;
-
- for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
- struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
- cancel_delayed_work_sync(&per_pin->work);
- }
- return 0;
-}
-
-static int generic_hdmi_resume(struct hda_codec *codec)
-{
- struct hdmi_spec *spec = codec->spec;
- int pin_idx;
-
- codec->patch_ops.init(codec);
- snd_hda_regmap_sync(codec);
-
- for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
- struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
- hdmi_present_sense(per_pin, 1);
- }
- return 0;
-}
-
-static const struct hda_codec_ops generic_hdmi_patch_ops = {
- .init = generic_hdmi_init,
- .free = generic_hdmi_free,
- .build_pcms = generic_hdmi_build_pcms,
- .build_controls = generic_hdmi_build_controls,
- .unsol_event = hdmi_unsol_event,
- .suspend = generic_hdmi_suspend,
- .resume = generic_hdmi_resume,
-};
-
-static const struct hdmi_ops generic_standard_hdmi_ops = {
- .pin_get_eld = hdmi_pin_get_eld,
- .pin_setup_infoframe = hdmi_pin_setup_infoframe,
- .pin_hbr_setup = hdmi_pin_hbr_setup,
- .setup_stream = hdmi_setup_stream,
-};
-
-/* allocate codec->spec and assign/initialize generic parser ops */
-static int alloc_generic_hdmi(struct hda_codec *codec)
-{
- struct hdmi_spec *spec;
-
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (!spec)
- return -ENOMEM;
-
- spec->codec = codec;
- spec->ops = generic_standard_hdmi_ops;
- spec->dev_num = 1; /* initialize to 1 */
- mutex_init(&spec->pcm_lock);
- mutex_init(&spec->bind_lock);
- snd_hdac_register_chmap_ops(&codec->core, &spec->chmap);
-
- spec->chmap.ops.get_chmap = hdmi_get_chmap;
- spec->chmap.ops.set_chmap = hdmi_set_chmap;
- spec->chmap.ops.is_pcm_attached = is_hdmi_pcm_attached;
- spec->chmap.ops.get_spk_alloc = hdmi_get_spk_alloc;
-
- codec->spec = spec;
- hdmi_array_init(spec, 4);
-
- codec->patch_ops = generic_hdmi_patch_ops;
-
- return 0;
-}
-
-/* generic HDMI parser */
-static int patch_generic_hdmi(struct hda_codec *codec)
-{
- int err;
-
- err = alloc_generic_hdmi(codec);
- if (err < 0)
- return err;
-
- err = hdmi_parse_codec(codec);
- if (err < 0) {
- generic_spec_free(codec);
- return err;
- }
-
- generic_hdmi_init_per_pins(codec);
- return 0;
-}
-
-/*
- * generic audio component binding
- */
-
-/* turn on / off the unsol event jack detection dynamically */
-static void reprogram_jack_detect(struct hda_codec *codec, hda_nid_t nid,
- int dev_id, bool use_acomp)
-{
- struct hda_jack_tbl *tbl;
-
- tbl = snd_hda_jack_tbl_get_mst(codec, nid, dev_id);
- if (tbl) {
- /* clear unsol even if component notifier is used, or re-enable
- * if notifier is cleared
- */
- unsigned int val = use_acomp ? 0 : (AC_USRSP_EN | tbl->tag);
- snd_hda_codec_write_cache(codec, nid, 0,
- AC_VERB_SET_UNSOLICITED_ENABLE, val);
- }
-}
-
-/* set up / clear component notifier dynamically */
-static void generic_acomp_notifier_set(struct drm_audio_component *acomp,
- bool use_acomp)
-{
- struct hdmi_spec *spec;
- int i;
-
- spec = container_of(acomp->audio_ops, struct hdmi_spec, drm_audio_ops);
- mutex_lock(&spec->bind_lock);
- spec->use_acomp_notifier = use_acomp;
- spec->codec->relaxed_resume = use_acomp;
- spec->codec->bus->keep_power = 0;
- /* reprogram each jack detection logic depending on the notifier */
- for (i = 0; i < spec->num_pins; i++)
- reprogram_jack_detect(spec->codec,
- get_pin(spec, i)->pin_nid,
- get_pin(spec, i)->dev_id,
- use_acomp);
- mutex_unlock(&spec->bind_lock);
-}
-
-/* enable / disable the notifier via master bind / unbind */
-static int generic_acomp_master_bind(struct device *dev,
- struct drm_audio_component *acomp)
-{
- generic_acomp_notifier_set(acomp, true);
- return 0;
-}
-
-static void generic_acomp_master_unbind(struct device *dev,
- struct drm_audio_component *acomp)
-{
- generic_acomp_notifier_set(acomp, false);
-}
-
-/* check whether both HD-audio and DRM PCI devices belong to the same bus */
-static int match_bound_vga(struct device *dev, int subtype, void *data)
-{
- struct hdac_bus *bus = data;
- struct pci_dev *pci, *master;
-
- if (!dev_is_pci(dev) || !dev_is_pci(bus->dev))
- return 0;
- master = to_pci_dev(bus->dev);
- pci = to_pci_dev(dev);
- return master->bus == pci->bus;
-}
-
-/* audio component notifier for AMD/Nvidia HDMI codecs */
-static void generic_acomp_pin_eld_notify(void *audio_ptr, int port, int dev_id)
-{
- struct hda_codec *codec = audio_ptr;
- struct hdmi_spec *spec = codec->spec;
- hda_nid_t pin_nid = spec->port2pin(codec, port);
-
- if (!pin_nid)
- return;
- if (get_wcaps_type(get_wcaps(codec, pin_nid)) != AC_WID_PIN)
- return;
- /* skip notification during system suspend (but not in runtime PM);
- * the state will be updated at resume
- */
- if (codec->core.dev.power.power_state.event == PM_EVENT_SUSPEND)
- return;
-
- check_presence_and_report(codec, pin_nid, dev_id);
-}
-
-/* set up the private drm_audio_ops from the template */
-static void setup_drm_audio_ops(struct hda_codec *codec,
- const struct drm_audio_component_audio_ops *ops)
-{
- struct hdmi_spec *spec = codec->spec;
-
- spec->drm_audio_ops.audio_ptr = codec;
- /* intel_audio_codec_enable() or intel_audio_codec_disable()
- * will call pin_eld_notify with using audio_ptr pointer
- * We need make sure audio_ptr is really setup
- */
- wmb();
- spec->drm_audio_ops.pin2port = ops->pin2port;
- spec->drm_audio_ops.pin_eld_notify = ops->pin_eld_notify;
- spec->drm_audio_ops.master_bind = ops->master_bind;
- spec->drm_audio_ops.master_unbind = ops->master_unbind;
-}
-
-/* initialize the generic HDMI audio component */
-static void generic_acomp_init(struct hda_codec *codec,
- const struct drm_audio_component_audio_ops *ops,
- int (*port2pin)(struct hda_codec *, int))
-{
- struct hdmi_spec *spec = codec->spec;
-
- if (!enable_acomp) {
- codec_info(codec, "audio component disabled by module option\n");
- return;
- }
-
- spec->port2pin = port2pin;
- setup_drm_audio_ops(codec, ops);
- if (!snd_hdac_acomp_init(&codec->bus->core, &spec->drm_audio_ops,
- match_bound_vga, 0)) {
- spec->acomp_registered = true;
- }
-}
-
-/*
- * Intel codec parsers and helpers
- */
-
-#define INTEL_GET_VENDOR_VERB 0xf81
-#define INTEL_SET_VENDOR_VERB 0x781
-#define INTEL_EN_DP12 0x02 /* enable DP 1.2 features */
-#define INTEL_EN_ALL_PIN_CVTS 0x01 /* enable 2nd & 3rd pins and convertors */
-
-static void intel_haswell_enable_all_pins(struct hda_codec *codec,
- bool update_tree)
-{
- unsigned int vendor_param;
- struct hdmi_spec *spec = codec->spec;
-
- vendor_param = snd_hda_codec_read(codec, spec->vendor_nid, 0,
- INTEL_GET_VENDOR_VERB, 0);
- if (vendor_param == -1 || vendor_param & INTEL_EN_ALL_PIN_CVTS)
- return;
-
- vendor_param |= INTEL_EN_ALL_PIN_CVTS;
- vendor_param = snd_hda_codec_read(codec, spec->vendor_nid, 0,
- INTEL_SET_VENDOR_VERB, vendor_param);
- if (vendor_param == -1)
- return;
-
- if (update_tree)
- snd_hda_codec_update_widgets(codec);
-}
-
-static void intel_haswell_fixup_enable_dp12(struct hda_codec *codec)
-{
- unsigned int vendor_param;
- struct hdmi_spec *spec = codec->spec;
-
- vendor_param = snd_hda_codec_read(codec, spec->vendor_nid, 0,
- INTEL_GET_VENDOR_VERB, 0);
- if (vendor_param == -1 || vendor_param & INTEL_EN_DP12)
- return;
-
- /* enable DP1.2 mode */
- vendor_param |= INTEL_EN_DP12;
- snd_hdac_regmap_add_vendor_verb(&codec->core, INTEL_SET_VENDOR_VERB);
- snd_hda_codec_write_cache(codec, spec->vendor_nid, 0,
- INTEL_SET_VENDOR_VERB, vendor_param);
-}
-
-/* Haswell needs to re-issue the vendor-specific verbs before turning to D0.
- * Otherwise you may get severe h/w communication errors.
- */
-static void haswell_set_power_state(struct hda_codec *codec, hda_nid_t fg,
- unsigned int power_state)
-{
- if (power_state == AC_PWRST_D0) {
- intel_haswell_enable_all_pins(codec, false);
- intel_haswell_fixup_enable_dp12(codec);
- }
-
- snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, power_state);
- snd_hda_codec_set_power_to_all(codec, fg, power_state);
-}
-
-/* There is a fixed mapping between audio pin node and display port.
- * on SNB, IVY, HSW, BSW, SKL, BXT, KBL:
- * Pin Widget 5 - PORT B (port = 1 in i915 driver)
- * Pin Widget 6 - PORT C (port = 2 in i915 driver)
- * Pin Widget 7 - PORT D (port = 3 in i915 driver)
- *
- * on VLV, ILK:
- * Pin Widget 4 - PORT B (port = 1 in i915 driver)
- * Pin Widget 5 - PORT C (port = 2 in i915 driver)
- * Pin Widget 6 - PORT D (port = 3 in i915 driver)
- */
-static int intel_base_nid(struct hda_codec *codec)
-{
- switch (codec->core.vendor_id) {
- case 0x80860054: /* ILK */
- case 0x80862804: /* ILK */
- case 0x80862882: /* VLV */
- return 4;
- default:
- return 5;
- }
-}
-
-static int intel_pin2port(void *audio_ptr, int pin_nid)
-{
- struct hda_codec *codec = audio_ptr;
- struct hdmi_spec *spec = codec->spec;
- int base_nid, i;
-
- if (!spec->port_num) {
- base_nid = intel_base_nid(codec);
- if (WARN_ON(pin_nid < base_nid || pin_nid >= base_nid + 3))
- return -1;
- return pin_nid - base_nid + 1;
- }
-
- /*
- * looking for the pin number in the mapping table and return
- * the index which indicate the port number
- */
- for (i = 0; i < spec->port_num; i++) {
- if (pin_nid == spec->port_map[i])
- return i;
- }
-
- codec_info(codec, "Can't find the HDMI/DP port for pin NID 0x%x\n", pin_nid);
- return -1;
-}
-
-static int intel_port2pin(struct hda_codec *codec, int port)
-{
- struct hdmi_spec *spec = codec->spec;
-
- if (!spec->port_num) {
- /* we assume only from port-B to port-D */
- if (port < 1 || port > 3)
- return 0;
- return port + intel_base_nid(codec) - 1;
- }
-
- if (port < 0 || port >= spec->port_num)
- return 0;
- return spec->port_map[port];
-}
-
-static void intel_pin_eld_notify(void *audio_ptr, int port, int pipe)
-{
- struct hda_codec *codec = audio_ptr;
- int pin_nid;
- int dev_id = pipe;
-
- pin_nid = intel_port2pin(codec, port);
- if (!pin_nid)
- return;
- /* skip notification during system suspend (but not in runtime PM);
- * the state will be updated at resume
- */
- if (codec->core.dev.power.power_state.event == PM_EVENT_SUSPEND)
- return;
-
- snd_hdac_i915_set_bclk(&codec->bus->core);
- check_presence_and_report(codec, pin_nid, dev_id);
-}
-
-static const struct drm_audio_component_audio_ops intel_audio_ops = {
- .pin2port = intel_pin2port,
- .pin_eld_notify = intel_pin_eld_notify,
-};
-
-/* register i915 component pin_eld_notify callback */
-static void register_i915_notifier(struct hda_codec *codec)
-{
- struct hdmi_spec *spec = codec->spec;
-
- spec->use_acomp_notifier = true;
- spec->port2pin = intel_port2pin;
- setup_drm_audio_ops(codec, &intel_audio_ops);
- snd_hdac_acomp_register_notifier(&codec->bus->core,
- &spec->drm_audio_ops);
- /* no need for forcible resume for jack check thanks to notifier */
- codec->relaxed_resume = 1;
-}
-
-/* setup_stream ops override for HSW+ */
-static int i915_hsw_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid,
- hda_nid_t pin_nid, int dev_id, u32 stream_tag,
- int format)
-{
- struct hdmi_spec *spec = codec->spec;
- int pin_idx = pin_id_to_pin_index(codec, pin_nid, dev_id);
- struct hdmi_spec_per_pin *per_pin;
- int res;
-
- if (pin_idx < 0)
- per_pin = NULL;
- else
- per_pin = get_pin(spec, pin_idx);
-
- haswell_verify_D0(codec, cvt_nid, pin_nid);
-
- if (spec->silent_stream_type == SILENT_STREAM_KAE && per_pin && per_pin->silent_stream) {
- silent_stream_set_kae(codec, per_pin, false);
- /* wait for pending transfers in codec to clear */
- usleep_range(100, 200);
- }
-
- res = hdmi_setup_stream(codec, cvt_nid, pin_nid, dev_id,
- stream_tag, format);
-
- if (spec->silent_stream_type == SILENT_STREAM_KAE && per_pin && per_pin->silent_stream) {
- usleep_range(100, 200);
- silent_stream_set_kae(codec, per_pin, true);
- }
-
- return res;
-}
-
-/* pin_cvt_fixup ops override for HSW+ and VLV+ */
-static void i915_pin_cvt_fixup(struct hda_codec *codec,
- struct hdmi_spec_per_pin *per_pin,
- hda_nid_t cvt_nid)
-{
- if (per_pin) {
- haswell_verify_D0(codec, per_pin->cvt_nid, per_pin->pin_nid);
- snd_hda_set_dev_select(codec, per_pin->pin_nid,
- per_pin->dev_id);
- intel_verify_pin_cvt_connect(codec, per_pin);
- intel_not_share_assigned_cvt(codec, per_pin->pin_nid,
- per_pin->dev_id, per_pin->mux_idx);
- } else {
- intel_not_share_assigned_cvt_nid(codec, 0, 0, cvt_nid);
- }
-}
-
-static int i915_adlp_hdmi_suspend(struct hda_codec *codec)
-{
- struct hdmi_spec *spec = codec->spec;
- bool silent_streams = false;
- int pin_idx, res;
-
- res = generic_hdmi_suspend(codec);
-
- for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
- struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
-
- if (per_pin->silent_stream) {
- silent_streams = true;
- break;
- }
- }
-
- if (silent_streams && spec->silent_stream_type == SILENT_STREAM_KAE) {
- /*
- * stream-id should remain programmed when codec goes
- * to runtime suspend
- */
- codec->no_stream_clean_at_suspend = 1;
-
- /*
- * the system might go to S3, in which case keep-alive
- * must be reprogrammed upon resume
- */
- codec->forced_resume = 1;
-
- codec_dbg(codec, "HDMI: KAE active at suspend\n");
- } else {
- codec->no_stream_clean_at_suspend = 0;
- codec->forced_resume = 0;
- }
-
- return res;
-}
-
-static int i915_adlp_hdmi_resume(struct hda_codec *codec)
-{
- struct hdmi_spec *spec = codec->spec;
- int pin_idx, res;
-
- res = generic_hdmi_resume(codec);
-
- /* KAE not programmed at suspend, nothing to do here */
- if (!codec->no_stream_clean_at_suspend)
- return res;
-
- for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
- struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
-
- /*
- * If system was in suspend with monitor connected,
- * the codec setting may have been lost. Re-enable
- * keep-alive.
- */
- if (per_pin->silent_stream) {
- unsigned int param;
-
- param = snd_hda_codec_read(codec, per_pin->cvt_nid, 0,
- AC_VERB_GET_CONV, 0);
- if (!param) {
- codec_dbg(codec, "HDMI: KAE: restore stream id\n");
- silent_stream_enable_i915(codec, per_pin);
- }
-
- param = snd_hda_codec_read(codec, per_pin->cvt_nid, 0,
- AC_VERB_GET_DIGI_CONVERT_1, 0);
- if (!(param & (AC_DIG3_KAE << 16))) {
- codec_dbg(codec, "HDMI: KAE: restore DIG3_KAE\n");
- silent_stream_set_kae(codec, per_pin, true);
- }
- }
- }
-
- return res;
-}
-
-/* precondition and allocation for Intel codecs */
-static int alloc_intel_hdmi(struct hda_codec *codec)
-{
- int err;
-
- /* requires i915 binding */
- if (!codec->bus->core.audio_component) {
- codec_info(codec, "No i915 binding for Intel HDMI/DP codec\n");
- /* set probe_id here to prevent generic fallback binding */
- codec->probe_id = HDA_CODEC_ID_SKIP_PROBE;
- return -ENODEV;
- }
-
- err = alloc_generic_hdmi(codec);
- if (err < 0)
- return err;
- /* no need to handle unsol events */
- codec->patch_ops.unsol_event = NULL;
- return 0;
-}
-
-/* parse and post-process for Intel codecs */
-static int parse_intel_hdmi(struct hda_codec *codec)
-{
- int err, retries = 3;
-
- do {
- err = hdmi_parse_codec(codec);
- } while (err < 0 && retries--);
-
- if (err < 0) {
- generic_spec_free(codec);
- return err;
- }
-
- generic_hdmi_init_per_pins(codec);
- register_i915_notifier(codec);
- return 0;
-}
-
-/* Intel Haswell and onwards; audio component with eld notifier */
-static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid,
- const int *port_map, int port_num, int dev_num,
- bool send_silent_stream)
-{
- struct hdmi_spec *spec;
- int err;
-
- err = alloc_intel_hdmi(codec);
- if (err < 0)
- return err;
- spec = codec->spec;
- codec->dp_mst = true;
- spec->vendor_nid = vendor_nid;
- spec->port_map = port_map;
- spec->port_num = port_num;
- spec->intel_hsw_fixup = true;
- spec->dev_num = dev_num;
-
- intel_haswell_enable_all_pins(codec, true);
- intel_haswell_fixup_enable_dp12(codec);
-
- codec->display_power_control = 1;
-
- codec->patch_ops.set_power_state = haswell_set_power_state;
- codec->depop_delay = 0;
- codec->auto_runtime_pm = 1;
-
- spec->ops.setup_stream = i915_hsw_setup_stream;
- spec->ops.pin_cvt_fixup = i915_pin_cvt_fixup;
-
- /*
- * Enable silent stream feature, if it is enabled via
- * module param or Kconfig option
- */
- if (send_silent_stream)
- spec->silent_stream_type = SILENT_STREAM_I915;
-
- return parse_intel_hdmi(codec);
-}
-
-static int patch_i915_hsw_hdmi(struct hda_codec *codec)
-{
- return intel_hsw_common_init(codec, 0x08, NULL, 0, 3,
- enable_silent_stream);
-}
-
-static int patch_i915_glk_hdmi(struct hda_codec *codec)
-{
- /*
- * Silent stream calls audio component .get_power() from
- * .pin_eld_notify(). On GLK this will deadlock in i915 due
- * to the audio vs. CDCLK workaround.
- */
- return intel_hsw_common_init(codec, 0x0b, NULL, 0, 3, false);
-}
-
-static int patch_i915_icl_hdmi(struct hda_codec *codec)
-{
- /*
- * pin to port mapping table where the value indicate the pin number and
- * the index indicate the port number.
- */
- static const int map[] = {0x0, 0x4, 0x6, 0x8, 0xa, 0xb};
-
- return intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map), 3,
- enable_silent_stream);
-}
-
-static int patch_i915_tgl_hdmi(struct hda_codec *codec)
-{
- /*
- * pin to port mapping table where the value indicate the pin number and
- * the index indicate the port number.
- */
- static const int map[] = {0x4, 0x6, 0x8, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
-
- return intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map), 4,
- enable_silent_stream);
-}
-
-static int patch_i915_adlp_hdmi(struct hda_codec *codec)
-{
- struct hdmi_spec *spec;
- int res;
-
- res = patch_i915_tgl_hdmi(codec);
- if (!res) {
- spec = codec->spec;
-
- if (spec->silent_stream_type) {
- spec->silent_stream_type = SILENT_STREAM_KAE;
-
- codec->patch_ops.resume = i915_adlp_hdmi_resume;
- codec->patch_ops.suspend = i915_adlp_hdmi_suspend;
- }
- }
-
- return res;
-}
-
-/* Intel Baytrail and Braswell; with eld notifier */
-static int patch_i915_byt_hdmi(struct hda_codec *codec)
-{
- struct hdmi_spec *spec;
- int err;
-
- err = alloc_intel_hdmi(codec);
- if (err < 0)
- return err;
- spec = codec->spec;
-
- /* For Valleyview/Cherryview, only the display codec is in the display
- * power well and can use link_power ops to request/release the power.
- */
- codec->display_power_control = 1;
-
- codec->depop_delay = 0;
- codec->auto_runtime_pm = 1;
-
- spec->ops.pin_cvt_fixup = i915_pin_cvt_fixup;
-
- return parse_intel_hdmi(codec);
-}
-
-/* Intel IronLake, SandyBridge and IvyBridge; with eld notifier */
-static int patch_i915_cpt_hdmi(struct hda_codec *codec)
-{
- int err;
-
- err = alloc_intel_hdmi(codec);
- if (err < 0)
- return err;
- return parse_intel_hdmi(codec);
-}
-
-/*
- * Shared non-generic implementations
- */
-
-static int simple_playback_build_pcms(struct hda_codec *codec)
-{
- struct hdmi_spec *spec = codec->spec;
- struct hda_pcm *info;
- unsigned int chans;
- struct hda_pcm_stream *pstr;
- struct hdmi_spec_per_cvt *per_cvt;
-
- per_cvt = get_cvt(spec, 0);
- chans = get_wcaps(codec, per_cvt->cvt_nid);
- chans = get_wcaps_channels(chans);
-
- info = snd_hda_codec_pcm_new(codec, "HDMI 0");
- if (!info)
- return -ENOMEM;
- spec->pcm_rec[0].pcm = info;
- info->pcm_type = HDA_PCM_TYPE_HDMI;
- pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK];
- *pstr = spec->pcm_playback;
- pstr->nid = per_cvt->cvt_nid;
- if (pstr->channels_max <= 2 && chans && chans <= 16)
- pstr->channels_max = chans;
-
- return 0;
-}
-
-/* unsolicited event for jack sensing */
-static void simple_hdmi_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- snd_hda_jack_set_dirty_all(codec);
- snd_hda_jack_report_sync(codec);
-}
-
-/* generic_hdmi_build_jack can be used for simple_hdmi, too,
- * as long as spec->pins[] is set correctly
- */
-#define simple_hdmi_build_jack generic_hdmi_build_jack
-
-static int simple_playback_build_controls(struct hda_codec *codec)
-{
- struct hdmi_spec *spec = codec->spec;
- struct hdmi_spec_per_cvt *per_cvt;
- int err;
-
- per_cvt = get_cvt(spec, 0);
- err = snd_hda_create_dig_out_ctls(codec, per_cvt->cvt_nid,
- per_cvt->cvt_nid,
- HDA_PCM_TYPE_HDMI);
- if (err < 0)
- return err;
- return simple_hdmi_build_jack(codec, 0);
-}
-
-static int simple_playback_init(struct hda_codec *codec)
-{
- struct hdmi_spec *spec = codec->spec;
- struct hdmi_spec_per_pin *per_pin = get_pin(spec, 0);
- hda_nid_t pin = per_pin->pin_nid;
-
- snd_hda_codec_write(codec, pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
- /* some codecs require to unmute the pin */
- if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP)
- snd_hda_codec_write(codec, pin, 0, AC_VERB_SET_AMP_GAIN_MUTE,
- AMP_OUT_UNMUTE);
- snd_hda_jack_detect_enable(codec, pin, per_pin->dev_id);
- return 0;
-}
-
-static void simple_playback_free(struct hda_codec *codec)
-{
- struct hdmi_spec *spec = codec->spec;
-
- hdmi_array_free(spec);
- kfree(spec);
-}
-
-/*
- * Nvidia specific implementations
- */
-
-#define Nv_VERB_SET_Channel_Allocation 0xF79
-#define Nv_VERB_SET_Info_Frame_Checksum 0xF7A
-#define Nv_VERB_SET_Audio_Protection_On 0xF98
-#define Nv_VERB_SET_Audio_Protection_Off 0xF99
-
-#define nvhdmi_master_con_nid_7x 0x04
-#define nvhdmi_master_pin_nid_7x 0x05
-
-static const hda_nid_t nvhdmi_con_nids_7x[4] = {
- /*front, rear, clfe, rear_surr */
- 0x6, 0x8, 0xa, 0xc,
-};
-
-static const struct hda_verb nvhdmi_basic_init_7x_2ch[] = {
- /* set audio protect on */
- { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1},
- /* enable digital output on pin widget */
- { 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
- {} /* terminator */
-};
-
-static const struct hda_verb nvhdmi_basic_init_7x_8ch[] = {
- /* set audio protect on */
- { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1},
- /* enable digital output on pin widget */
- { 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
- { 0x7, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
- { 0x9, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
- { 0xb, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
- { 0xd, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
- {} /* terminator */
-};
-
-#ifdef LIMITED_RATE_FMT_SUPPORT
-/* support only the safe format and rate */
-#define SUPPORTED_RATES SNDRV_PCM_RATE_48000
-#define SUPPORTED_MAXBPS 16
-#define SUPPORTED_FORMATS SNDRV_PCM_FMTBIT_S16_LE
-#else
-/* support all rates and formats */
-#define SUPPORTED_RATES \
- (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
- SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\
- SNDRV_PCM_RATE_192000)
-#define SUPPORTED_MAXBPS 24
-#define SUPPORTED_FORMATS \
- (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
-#endif
-
-static int nvhdmi_7x_init_2ch(struct hda_codec *codec)
-{
- snd_hda_sequence_write(codec, nvhdmi_basic_init_7x_2ch);
- return 0;
-}
-
-static int nvhdmi_7x_init_8ch(struct hda_codec *codec)
-{
- snd_hda_sequence_write(codec, nvhdmi_basic_init_7x_8ch);
- return 0;
-}
-
-static const unsigned int channels_2_6_8[] = {
- 2, 6, 8
-};
-
-static const unsigned int channels_2_8[] = {
- 2, 8
-};
-
-static const struct snd_pcm_hw_constraint_list hw_constraints_2_6_8_channels = {
- .count = ARRAY_SIZE(channels_2_6_8),
- .list = channels_2_6_8,
- .mask = 0,
-};
-
-static const struct snd_pcm_hw_constraint_list hw_constraints_2_8_channels = {
- .count = ARRAY_SIZE(channels_2_8),
- .list = channels_2_8,
- .mask = 0,
-};
-
-static int simple_playback_pcm_open(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- struct hdmi_spec *spec = codec->spec;
- const struct snd_pcm_hw_constraint_list *hw_constraints_channels = NULL;
-
- switch (codec->preset->vendor_id) {
- case 0x10de0002:
- case 0x10de0003:
- case 0x10de0005:
- case 0x10de0006:
- hw_constraints_channels = &hw_constraints_2_8_channels;
- break;
- case 0x10de0007:
- hw_constraints_channels = &hw_constraints_2_6_8_channels;
- break;
- default:
- break;
- }
-
- if (hw_constraints_channels != NULL) {
- snd_pcm_hw_constraint_list(substream->runtime, 0,
- SNDRV_PCM_HW_PARAM_CHANNELS,
- hw_constraints_channels);
- } else {
- snd_pcm_hw_constraint_step(substream->runtime, 0,
- SNDRV_PCM_HW_PARAM_CHANNELS, 2);
- }
-
- return snd_hda_multi_out_dig_open(codec, &spec->multiout);
-}
-
-static int simple_playback_pcm_close(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- struct hdmi_spec *spec = codec->spec;
- return snd_hda_multi_out_dig_close(codec, &spec->multiout);
-}
-
-static int simple_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- unsigned int stream_tag,
- unsigned int format,
- struct snd_pcm_substream *substream)
-{
- struct hdmi_spec *spec = codec->spec;
- return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
- stream_tag, format, substream);
-}
-
-static const struct hda_pcm_stream simple_pcm_playback = {
- .substreams = 1,
- .channels_min = 2,
- .channels_max = 2,
- .ops = {
- .open = simple_playback_pcm_open,
- .close = simple_playback_pcm_close,
- .prepare = simple_playback_pcm_prepare
- },
-};
-
-static const struct hda_codec_ops simple_hdmi_patch_ops = {
- .build_controls = simple_playback_build_controls,
- .build_pcms = simple_playback_build_pcms,
- .init = simple_playback_init,
- .free = simple_playback_free,
- .unsol_event = simple_hdmi_unsol_event,
-};
-
-static int patch_simple_hdmi(struct hda_codec *codec,
- hda_nid_t cvt_nid, hda_nid_t pin_nid)
-{
- struct hdmi_spec *spec;
- struct hdmi_spec_per_cvt *per_cvt;
- struct hdmi_spec_per_pin *per_pin;
-
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (!spec)
- return -ENOMEM;
-
- spec->codec = codec;
- codec->spec = spec;
- hdmi_array_init(spec, 1);
-
- spec->multiout.num_dacs = 0; /* no analog */
- spec->multiout.max_channels = 2;
- spec->multiout.dig_out_nid = cvt_nid;
- spec->num_cvts = 1;
- spec->num_pins = 1;
- per_pin = snd_array_new(&spec->pins);
- per_cvt = snd_array_new(&spec->cvts);
- if (!per_pin || !per_cvt) {
- simple_playback_free(codec);
- return -ENOMEM;
- }
- per_cvt->cvt_nid = cvt_nid;
- per_pin->pin_nid = pin_nid;
- spec->pcm_playback = simple_pcm_playback;
-
- codec->patch_ops = simple_hdmi_patch_ops;
-
- return 0;
-}
-
-static void nvhdmi_8ch_7x_set_info_frame_parameters(struct hda_codec *codec,
- int channels)
-{
- unsigned int chanmask;
- int chan = channels ? (channels - 1) : 1;
-
- switch (channels) {
- default:
- case 0:
- case 2:
- chanmask = 0x00;
- break;
- case 4:
- chanmask = 0x08;
- break;
- case 6:
- chanmask = 0x0b;
- break;
- case 8:
- chanmask = 0x13;
- break;
- }
-
- /* Set the audio infoframe channel allocation and checksum fields. The
- * channel count is computed implicitly by the hardware. */
- snd_hda_codec_write(codec, 0x1, 0,
- Nv_VERB_SET_Channel_Allocation, chanmask);
-
- snd_hda_codec_write(codec, 0x1, 0,
- Nv_VERB_SET_Info_Frame_Checksum,
- (0x71 - chan - chanmask));
-}
-
-static int nvhdmi_8ch_7x_pcm_close(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- struct hdmi_spec *spec = codec->spec;
- int i;
-
- snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x,
- 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
- for (i = 0; i < 4; i++) {
- /* set the stream id */
- snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0,
- AC_VERB_SET_CHANNEL_STREAMID, 0);
- /* set the stream format */
- snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0,
- AC_VERB_SET_STREAM_FORMAT, 0);
- }
-
- /* The audio hardware sends a channel count of 0x7 (8ch) when all the
- * streams are disabled. */
- nvhdmi_8ch_7x_set_info_frame_parameters(codec, 8);
-
- return snd_hda_multi_out_dig_close(codec, &spec->multiout);
-}
-
-static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- unsigned int stream_tag,
- unsigned int format,
- struct snd_pcm_substream *substream)
-{
- int chs;
- unsigned int dataDCC2, channel_id;
- int i;
- struct hdmi_spec *spec = codec->spec;
- struct hda_spdif_out *spdif;
- struct hdmi_spec_per_cvt *per_cvt;
-
- mutex_lock(&codec->spdif_mutex);
- per_cvt = get_cvt(spec, 0);
- spdif = snd_hda_spdif_out_of_nid(codec, per_cvt->cvt_nid);
-
- chs = substream->runtime->channels;
-
- dataDCC2 = 0x2;
-
- /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
- if (codec->spdif_status_reset && (spdif->ctls & AC_DIG1_ENABLE))
- snd_hda_codec_write(codec,
- nvhdmi_master_con_nid_7x,
- 0,
- AC_VERB_SET_DIGI_CONVERT_1,
- spdif->ctls & ~AC_DIG1_ENABLE & 0xff);
-
- /* set the stream id */
- snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0,
- AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0);
-
- /* set the stream format */
- snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0,
- AC_VERB_SET_STREAM_FORMAT, format);
-
- /* turn on again (if needed) */
- /* enable and set the channel status audio/data flag */
- if (codec->spdif_status_reset && (spdif->ctls & AC_DIG1_ENABLE)) {
- snd_hda_codec_write(codec,
- nvhdmi_master_con_nid_7x,
- 0,
- AC_VERB_SET_DIGI_CONVERT_1,
- spdif->ctls & 0xff);
- snd_hda_codec_write(codec,
- nvhdmi_master_con_nid_7x,
- 0,
- AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
- }
-
- for (i = 0; i < 4; i++) {
- if (chs == 2)
- channel_id = 0;
- else
- channel_id = i * 2;
-
- /* turn off SPDIF once;
- *otherwise the IEC958 bits won't be updated
- */
- if (codec->spdif_status_reset &&
- (spdif->ctls & AC_DIG1_ENABLE))
- snd_hda_codec_write(codec,
- nvhdmi_con_nids_7x[i],
- 0,
- AC_VERB_SET_DIGI_CONVERT_1,
- spdif->ctls & ~AC_DIG1_ENABLE & 0xff);
- /* set the stream id */
- snd_hda_codec_write(codec,
- nvhdmi_con_nids_7x[i],
- 0,
- AC_VERB_SET_CHANNEL_STREAMID,
- (stream_tag << 4) | channel_id);
- /* set the stream format */
- snd_hda_codec_write(codec,
- nvhdmi_con_nids_7x[i],
- 0,
- AC_VERB_SET_STREAM_FORMAT,
- format);
- /* turn on again (if needed) */
- /* enable and set the channel status audio/data flag */
- if (codec->spdif_status_reset &&
- (spdif->ctls & AC_DIG1_ENABLE)) {
- snd_hda_codec_write(codec,
- nvhdmi_con_nids_7x[i],
- 0,
- AC_VERB_SET_DIGI_CONVERT_1,
- spdif->ctls & 0xff);
- snd_hda_codec_write(codec,
- nvhdmi_con_nids_7x[i],
- 0,
- AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
- }
- }
-
- nvhdmi_8ch_7x_set_info_frame_parameters(codec, chs);
-
- mutex_unlock(&codec->spdif_mutex);
- return 0;
-}
-
-static const struct hda_pcm_stream nvhdmi_pcm_playback_8ch_7x = {
- .substreams = 1,
- .channels_min = 2,
- .channels_max = 8,
- .nid = nvhdmi_master_con_nid_7x,
- .rates = SUPPORTED_RATES,
- .maxbps = SUPPORTED_MAXBPS,
- .formats = SUPPORTED_FORMATS,
- .ops = {
- .open = simple_playback_pcm_open,
- .close = nvhdmi_8ch_7x_pcm_close,
- .prepare = nvhdmi_8ch_7x_pcm_prepare
- },
-};
-
-static int patch_nvhdmi_2ch(struct hda_codec *codec)
-{
- struct hdmi_spec *spec;
- int err = patch_simple_hdmi(codec, nvhdmi_master_con_nid_7x,
- nvhdmi_master_pin_nid_7x);
- if (err < 0)
- return err;
-
- codec->patch_ops.init = nvhdmi_7x_init_2ch;
- /* override the PCM rates, etc, as the codec doesn't give full list */
- spec = codec->spec;
- spec->pcm_playback.rates = SUPPORTED_RATES;
- spec->pcm_playback.maxbps = SUPPORTED_MAXBPS;
- spec->pcm_playback.formats = SUPPORTED_FORMATS;
- spec->nv_dp_workaround = true;
- return 0;
-}
-
-static int nvhdmi_7x_8ch_build_pcms(struct hda_codec *codec)
-{
- struct hdmi_spec *spec = codec->spec;
- int err = simple_playback_build_pcms(codec);
- if (!err) {
- struct hda_pcm *info = get_pcm_rec(spec, 0);
- info->own_chmap = true;
- }
- return err;
-}
-
-static int nvhdmi_7x_8ch_build_controls(struct hda_codec *codec)
-{
- struct hdmi_spec *spec = codec->spec;
- struct hda_pcm *info;
- struct snd_pcm_chmap *chmap;
- int err;
-
- err = simple_playback_build_controls(codec);
- if (err < 0)
- return err;
-
- /* add channel maps */
- info = get_pcm_rec(spec, 0);
- err = snd_pcm_add_chmap_ctls(info->pcm,
- SNDRV_PCM_STREAM_PLAYBACK,
- snd_pcm_alt_chmaps, 8, 0, &chmap);
- if (err < 0)
- return err;
- switch (codec->preset->vendor_id) {
- case 0x10de0002:
- case 0x10de0003:
- case 0x10de0005:
- case 0x10de0006:
- chmap->channel_mask = (1U << 2) | (1U << 8);
- break;
- case 0x10de0007:
- chmap->channel_mask = (1U << 2) | (1U << 6) | (1U << 8);
- }
- return 0;
-}
-
-static int patch_nvhdmi_8ch_7x(struct hda_codec *codec)
-{
- struct hdmi_spec *spec;
- int err = patch_nvhdmi_2ch(codec);
- if (err < 0)
- return err;
- spec = codec->spec;
- spec->multiout.max_channels = 8;
- spec->pcm_playback = nvhdmi_pcm_playback_8ch_7x;
- codec->patch_ops.init = nvhdmi_7x_init_8ch;
- codec->patch_ops.build_pcms = nvhdmi_7x_8ch_build_pcms;
- codec->patch_ops.build_controls = nvhdmi_7x_8ch_build_controls;
-
- /* Initialize the audio infoframe channel mask and checksum to something
- * valid */
- nvhdmi_8ch_7x_set_info_frame_parameters(codec, 8);
-
- return 0;
-}
-
-/*
- * NVIDIA codecs ignore ASP mapping for 2ch - confirmed on:
- * - 0x10de0015
- * - 0x10de0040
- */
-static int nvhdmi_chmap_cea_alloc_validate_get_type(struct hdac_chmap *chmap,
- struct hdac_cea_channel_speaker_allocation *cap, int channels)
-{
- if (cap->ca_index == 0x00 && channels == 2)
- return SNDRV_CTL_TLVT_CHMAP_FIXED;
-
- /* If the speaker allocation matches the channel count, it is OK. */
- if (cap->channels != channels)
- return -1;
-
- /* all channels are remappable freely */
- return SNDRV_CTL_TLVT_CHMAP_VAR;
-}
-
-static int nvhdmi_chmap_validate(struct hdac_chmap *chmap,
- int ca, int chs, unsigned char *map)
-{
- if (ca == 0x00 && (map[0] != SNDRV_CHMAP_FL || map[1] != SNDRV_CHMAP_FR))
- return -EINVAL;
-
- return 0;
-}
-
-/* map from pin NID to port; port is 0-based */
-/* for Nvidia: assume widget NID starting from 4, with step 1 (4, 5, 6, ...) */
-static int nvhdmi_pin2port(void *audio_ptr, int pin_nid)
-{
- return pin_nid - 4;
-}
-
-/* reverse-map from port to pin NID: see above */
-static int nvhdmi_port2pin(struct hda_codec *codec, int port)
-{
- return port + 4;
-}
-
-static const struct drm_audio_component_audio_ops nvhdmi_audio_ops = {
- .pin2port = nvhdmi_pin2port,
- .pin_eld_notify = generic_acomp_pin_eld_notify,
- .master_bind = generic_acomp_master_bind,
- .master_unbind = generic_acomp_master_unbind,
-};
-
-static int patch_nvhdmi(struct hda_codec *codec)
-{
- struct hdmi_spec *spec;
- int err;
-
- err = alloc_generic_hdmi(codec);
- if (err < 0)
- return err;
- codec->dp_mst = true;
-
- spec = codec->spec;
-
- err = hdmi_parse_codec(codec);
- if (err < 0) {
- generic_spec_free(codec);
- return err;
- }
-
- generic_hdmi_init_per_pins(codec);
-
- spec->dyn_pin_out = true;
-
- spec->chmap.ops.chmap_cea_alloc_validate_get_type =
- nvhdmi_chmap_cea_alloc_validate_get_type;
- spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate;
- spec->nv_dp_workaround = true;
-
- codec->link_down_at_suspend = 1;
-
- generic_acomp_init(codec, &nvhdmi_audio_ops, nvhdmi_port2pin);
-
- return 0;
-}
-
-static int patch_nvhdmi_legacy(struct hda_codec *codec)
-{
- struct hdmi_spec *spec;
- int err;
-
- err = patch_generic_hdmi(codec);
- if (err)
- return err;
-
- spec = codec->spec;
- spec->dyn_pin_out = true;
-
- spec->chmap.ops.chmap_cea_alloc_validate_get_type =
- nvhdmi_chmap_cea_alloc_validate_get_type;
- spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate;
- spec->nv_dp_workaround = true;
-
- codec->link_down_at_suspend = 1;
-
- return 0;
-}
-
-/*
- * The HDA codec on NVIDIA Tegra contains two scratch registers that are
- * accessed using vendor-defined verbs. These registers can be used for
- * interoperability between the HDA and HDMI drivers.
- */
-
-/* Audio Function Group node */
-#define NVIDIA_AFG_NID 0x01
-
-/*
- * The SCRATCH0 register is used to notify the HDMI codec of changes in audio
- * format. On Tegra, bit 31 is used as a trigger that causes an interrupt to
- * be raised in the HDMI codec. The remainder of the bits is arbitrary. This
- * implementation stores the HDA format (see AC_FMT_*) in bits [15:0] and an
- * additional bit (at position 30) to signal the validity of the format.
- *
- * | 31 | 30 | 29 16 | 15 0 |
- * +---------+-------+--------+--------+
- * | TRIGGER | VALID | UNUSED | FORMAT |
- * +-----------------------------------|
- *
- * Note that for the trigger bit to take effect it needs to change value
- * (i.e. it needs to be toggled). The trigger bit is not applicable from
- * TEGRA234 chip onwards, as new verb id 0xf80 will be used for interrupt
- * trigger to hdmi.
- */
-#define NVIDIA_SET_HOST_INTR 0xf80
-#define NVIDIA_GET_SCRATCH0 0xfa6
-#define NVIDIA_SET_SCRATCH0_BYTE0 0xfa7
-#define NVIDIA_SET_SCRATCH0_BYTE1 0xfa8
-#define NVIDIA_SET_SCRATCH0_BYTE2 0xfa9
-#define NVIDIA_SET_SCRATCH0_BYTE3 0xfaa
-#define NVIDIA_SCRATCH_TRIGGER (1 << 7)
-#define NVIDIA_SCRATCH_VALID (1 << 6)
-
-#define NVIDIA_GET_SCRATCH1 0xfab
-#define NVIDIA_SET_SCRATCH1_BYTE0 0xfac
-#define NVIDIA_SET_SCRATCH1_BYTE1 0xfad
-#define NVIDIA_SET_SCRATCH1_BYTE2 0xfae
-#define NVIDIA_SET_SCRATCH1_BYTE3 0xfaf
-
-/*
- * The format parameter is the HDA audio format (see AC_FMT_*). If set to 0,
- * the format is invalidated so that the HDMI codec can be disabled.
- */
-static void tegra_hdmi_set_format(struct hda_codec *codec,
- hda_nid_t cvt_nid,
- unsigned int format)
-{
- unsigned int value;
- unsigned int nid = NVIDIA_AFG_NID;
- struct hdmi_spec *spec = codec->spec;
-
- /*
- * Tegra HDA codec design from TEGRA234 chip onwards support DP MST.
- * This resulted in moving scratch registers from audio function
- * group to converter widget context. So CVT NID should be used for
- * scratch register read/write for DP MST supported Tegra HDA codec.
- */
- if (codec->dp_mst)
- nid = cvt_nid;
-
- /* bits [31:30] contain the trigger and valid bits */
- value = snd_hda_codec_read(codec, nid, 0,
- NVIDIA_GET_SCRATCH0, 0);
- value = (value >> 24) & 0xff;
-
- /* bits [15:0] are used to store the HDA format */
- snd_hda_codec_write(codec, nid, 0,
- NVIDIA_SET_SCRATCH0_BYTE0,
- (format >> 0) & 0xff);
- snd_hda_codec_write(codec, nid, 0,
- NVIDIA_SET_SCRATCH0_BYTE1,
- (format >> 8) & 0xff);
-
- /* bits [16:24] are unused */
- snd_hda_codec_write(codec, nid, 0,
- NVIDIA_SET_SCRATCH0_BYTE2, 0);
-
- /*
- * Bit 30 signals that the data is valid and hence that HDMI audio can
- * be enabled.
- */
- if (format == 0)
- value &= ~NVIDIA_SCRATCH_VALID;
- else
- value |= NVIDIA_SCRATCH_VALID;
-
- if (spec->hdmi_intr_trig_ctrl) {
- /*
- * For Tegra HDA Codec design from TEGRA234 onwards, the
- * Interrupt to hdmi driver is triggered by writing
- * non-zero values to verb 0xF80 instead of 31st bit of
- * scratch register.
- */
- snd_hda_codec_write(codec, nid, 0,
- NVIDIA_SET_SCRATCH0_BYTE3, value);
- snd_hda_codec_write(codec, nid, 0,
- NVIDIA_SET_HOST_INTR, 0x1);
- } else {
- /*
- * Whenever the 31st trigger bit is toggled, an interrupt is raised
- * in the HDMI codec. The HDMI driver will use that as trigger
- * to update its configuration.
- */
- value ^= NVIDIA_SCRATCH_TRIGGER;
-
- snd_hda_codec_write(codec, nid, 0,
- NVIDIA_SET_SCRATCH0_BYTE3, value);
- }
-}
-
-static int tegra_hdmi_pcm_prepare(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- unsigned int stream_tag,
- unsigned int format,
- struct snd_pcm_substream *substream)
-{
- int err;
-
- err = generic_hdmi_playback_pcm_prepare(hinfo, codec, stream_tag,
- format, substream);
- if (err < 0)
- return err;
-
- /* notify the HDMI codec of the format change */
- tegra_hdmi_set_format(codec, hinfo->nid, format);
-
- return 0;
-}
-
-static int tegra_hdmi_pcm_cleanup(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- /* invalidate the format in the HDMI codec */
- tegra_hdmi_set_format(codec, hinfo->nid, 0);
-
- return generic_hdmi_playback_pcm_cleanup(hinfo, codec, substream);
-}
-
-static struct hda_pcm *hda_find_pcm_by_type(struct hda_codec *codec, int type)
-{
- struct hdmi_spec *spec = codec->spec;
- unsigned int i;
-
- for (i = 0; i < spec->num_pins; i++) {
- struct hda_pcm *pcm = get_pcm_rec(spec, i);
-
- if (pcm->pcm_type == type)
- return pcm;
- }
-
- return NULL;
-}
-
-static int tegra_hdmi_build_pcms(struct hda_codec *codec)
-{
- struct hda_pcm_stream *stream;
- struct hda_pcm *pcm;
- int err;
-
- err = generic_hdmi_build_pcms(codec);
- if (err < 0)
- return err;
-
- pcm = hda_find_pcm_by_type(codec, HDA_PCM_TYPE_HDMI);
- if (!pcm)
- return -ENODEV;
-
- /*
- * Override ->prepare() and ->cleanup() operations to notify the HDMI
- * codec about format changes.
- */
- stream = &pcm->stream[SNDRV_PCM_STREAM_PLAYBACK];
- stream->ops.prepare = tegra_hdmi_pcm_prepare;
- stream->ops.cleanup = tegra_hdmi_pcm_cleanup;
-
- return 0;
-}
-
-static int tegra_hdmi_init(struct hda_codec *codec)
-{
- struct hdmi_spec *spec = codec->spec;
- int i, err;
-
- err = hdmi_parse_codec(codec);
- if (err < 0) {
- generic_spec_free(codec);
- return err;
- }
-
- for (i = 0; i < spec->num_cvts; i++)
- snd_hda_codec_write(codec, spec->cvt_nids[i], 0,
- AC_VERB_SET_DIGI_CONVERT_1,
- AC_DIG1_ENABLE);
-
- generic_hdmi_init_per_pins(codec);
-
- codec->depop_delay = 10;
- codec->patch_ops.build_pcms = tegra_hdmi_build_pcms;
- spec->chmap.ops.chmap_cea_alloc_validate_get_type =
- nvhdmi_chmap_cea_alloc_validate_get_type;
- spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate;
-
- spec->chmap.ops.chmap_cea_alloc_validate_get_type =
- nvhdmi_chmap_cea_alloc_validate_get_type;
- spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate;
- spec->nv_dp_workaround = true;
-
- return 0;
-}
-
-static int patch_tegra_hdmi(struct hda_codec *codec)
-{
- int err;
-
- err = alloc_generic_hdmi(codec);
- if (err < 0)
- return err;
-
- return tegra_hdmi_init(codec);
-}
-
-static int patch_tegra234_hdmi(struct hda_codec *codec)
-{
- struct hdmi_spec *spec;
- int err;
-
- err = alloc_generic_hdmi(codec);
- if (err < 0)
- return err;
-
- codec->dp_mst = true;
- spec = codec->spec;
- spec->dyn_pin_out = true;
- spec->hdmi_intr_trig_ctrl = true;
-
- return tegra_hdmi_init(codec);
-}
-
-/*
- * ATI/AMD-specific implementations
- */
-
-#define is_amdhdmi_rev3_or_later(codec) \
- ((codec)->core.vendor_id == 0x1002aa01 && \
- ((codec)->core.revision_id & 0xff00) >= 0x0300)
-#define has_amd_full_remap_support(codec) is_amdhdmi_rev3_or_later(codec)
-
-/* ATI/AMD specific HDA pin verbs, see the AMD HDA Verbs specification */
-#define ATI_VERB_SET_CHANNEL_ALLOCATION 0x771
-#define ATI_VERB_SET_DOWNMIX_INFO 0x772
-#define ATI_VERB_SET_MULTICHANNEL_01 0x777
-#define ATI_VERB_SET_MULTICHANNEL_23 0x778
-#define ATI_VERB_SET_MULTICHANNEL_45 0x779
-#define ATI_VERB_SET_MULTICHANNEL_67 0x77a
-#define ATI_VERB_SET_HBR_CONTROL 0x77c
-#define ATI_VERB_SET_MULTICHANNEL_1 0x785
-#define ATI_VERB_SET_MULTICHANNEL_3 0x786
-#define ATI_VERB_SET_MULTICHANNEL_5 0x787
-#define ATI_VERB_SET_MULTICHANNEL_7 0x788
-#define ATI_VERB_SET_MULTICHANNEL_MODE 0x789
-#define ATI_VERB_GET_CHANNEL_ALLOCATION 0xf71
-#define ATI_VERB_GET_DOWNMIX_INFO 0xf72
-#define ATI_VERB_GET_MULTICHANNEL_01 0xf77
-#define ATI_VERB_GET_MULTICHANNEL_23 0xf78
-#define ATI_VERB_GET_MULTICHANNEL_45 0xf79
-#define ATI_VERB_GET_MULTICHANNEL_67 0xf7a
-#define ATI_VERB_GET_HBR_CONTROL 0xf7c
-#define ATI_VERB_GET_MULTICHANNEL_1 0xf85
-#define ATI_VERB_GET_MULTICHANNEL_3 0xf86
-#define ATI_VERB_GET_MULTICHANNEL_5 0xf87
-#define ATI_VERB_GET_MULTICHANNEL_7 0xf88
-#define ATI_VERB_GET_MULTICHANNEL_MODE 0xf89
-
-/* AMD specific HDA cvt verbs */
-#define ATI_VERB_SET_RAMP_RATE 0x770
-#define ATI_VERB_GET_RAMP_RATE 0xf70
-
-#define ATI_OUT_ENABLE 0x1
-
-#define ATI_MULTICHANNEL_MODE_PAIRED 0
-#define ATI_MULTICHANNEL_MODE_SINGLE 1
-
-#define ATI_HBR_CAPABLE 0x01
-#define ATI_HBR_ENABLE 0x10
-
-static int atihdmi_pin_get_eld(struct hda_codec *codec, hda_nid_t nid,
- int dev_id, unsigned char *buf, int *eld_size)
-{
- WARN_ON(dev_id != 0);
- /* call hda_eld.c ATI/AMD-specific function */
- return snd_hdmi_get_eld_ati(codec, nid, buf, eld_size,
- is_amdhdmi_rev3_or_later(codec));
-}
-
-static void atihdmi_pin_setup_infoframe(struct hda_codec *codec,
- hda_nid_t pin_nid, int dev_id, int ca,
- int active_channels, int conn_type)
-{
- WARN_ON(dev_id != 0);
- snd_hda_codec_write(codec, pin_nid, 0, ATI_VERB_SET_CHANNEL_ALLOCATION, ca);
-}
-
-static int atihdmi_paired_swap_fc_lfe(int pos)
-{
- /*
- * ATI/AMD have automatic FC/LFE swap built-in
- * when in pairwise mapping mode.
- */
-
- switch (pos) {
- /* see channel_allocations[].speakers[] */
- case 2: return 3;
- case 3: return 2;
- default: break;
- }
-
- return pos;
-}
-
-static int atihdmi_paired_chmap_validate(struct hdac_chmap *chmap,
- int ca, int chs, unsigned char *map)
-{
- struct hdac_cea_channel_speaker_allocation *cap;
- int i, j;
-
- /* check that only channel pairs need to be remapped on old pre-rev3 ATI/AMD */
-
- cap = snd_hdac_get_ch_alloc_from_ca(ca);
- for (i = 0; i < chs; ++i) {
- int mask = snd_hdac_chmap_to_spk_mask(map[i]);
- bool ok = false;
- bool companion_ok = false;
-
- if (!mask)
- continue;
-
- for (j = 0 + i % 2; j < 8; j += 2) {
- int chan_idx = 7 - atihdmi_paired_swap_fc_lfe(j);
- if (cap->speakers[chan_idx] == mask) {
- /* channel is in a supported position */
- ok = true;
-
- if (i % 2 == 0 && i + 1 < chs) {
- /* even channel, check the odd companion */
- int comp_chan_idx = 7 - atihdmi_paired_swap_fc_lfe(j + 1);
- int comp_mask_req = snd_hdac_chmap_to_spk_mask(map[i+1]);
- int comp_mask_act = cap->speakers[comp_chan_idx];
-
- if (comp_mask_req == comp_mask_act)
- companion_ok = true;
- else
- return -EINVAL;
- }
- break;
- }
- }
-
- if (!ok)
- return -EINVAL;
-
- if (companion_ok)
- i++; /* companion channel already checked */
- }
-
- return 0;
-}
-
-static int atihdmi_pin_set_slot_channel(struct hdac_device *hdac,
- hda_nid_t pin_nid, int hdmi_slot, int stream_channel)
-{
- struct hda_codec *codec = hdac_to_hda_codec(hdac);
- int verb;
- int ati_channel_setup = 0;
-
- if (hdmi_slot > 7)
- return -EINVAL;
-
- if (!has_amd_full_remap_support(codec)) {
- hdmi_slot = atihdmi_paired_swap_fc_lfe(hdmi_slot);
-
- /* In case this is an odd slot but without stream channel, do not
- * disable the slot since the corresponding even slot could have a
- * channel. In case neither have a channel, the slot pair will be
- * disabled when this function is called for the even slot. */
- if (hdmi_slot % 2 != 0 && stream_channel == 0xf)
- return 0;
-
- hdmi_slot -= hdmi_slot % 2;
-
- if (stream_channel != 0xf)
- stream_channel -= stream_channel % 2;
- }
-
- verb = ATI_VERB_SET_MULTICHANNEL_01 + hdmi_slot/2 + (hdmi_slot % 2) * 0x00e;
-
- /* ati_channel_setup format: [7..4] = stream_channel_id, [1] = mute, [0] = enable */
-
- if (stream_channel != 0xf)
- ati_channel_setup = (stream_channel << 4) | ATI_OUT_ENABLE;
-
- return snd_hda_codec_write(codec, pin_nid, 0, verb, ati_channel_setup);
-}
-
-static int atihdmi_pin_get_slot_channel(struct hdac_device *hdac,
- hda_nid_t pin_nid, int asp_slot)
-{
- struct hda_codec *codec = hdac_to_hda_codec(hdac);
- bool was_odd = false;
- int ati_asp_slot = asp_slot;
- int verb;
- int ati_channel_setup;
-
- if (asp_slot > 7)
- return -EINVAL;
-
- if (!has_amd_full_remap_support(codec)) {
- ati_asp_slot = atihdmi_paired_swap_fc_lfe(asp_slot);
- if (ati_asp_slot % 2 != 0) {
- ati_asp_slot -= 1;
- was_odd = true;
- }
- }
-
- verb = ATI_VERB_GET_MULTICHANNEL_01 + ati_asp_slot/2 + (ati_asp_slot % 2) * 0x00e;
-
- ati_channel_setup = snd_hda_codec_read(codec, pin_nid, 0, verb, 0);
-
- if (!(ati_channel_setup & ATI_OUT_ENABLE))
- return 0xf;
-
- return ((ati_channel_setup & 0xf0) >> 4) + !!was_odd;
-}
-
-static int atihdmi_paired_chmap_cea_alloc_validate_get_type(
- struct hdac_chmap *chmap,
- struct hdac_cea_channel_speaker_allocation *cap,
- int channels)
-{
- int c;
-
- /*
- * Pre-rev3 ATI/AMD codecs operate in a paired channel mode, so
- * we need to take that into account (a single channel may take 2
- * channel slots if we need to carry a silent channel next to it).
- * On Rev3+ AMD codecs this function is not used.
- */
- int chanpairs = 0;
-
- /* We only produce even-numbered channel count TLVs */
- if ((channels % 2) != 0)
- return -1;
-
- for (c = 0; c < 7; c += 2) {
- if (cap->speakers[c] || cap->speakers[c+1])
- chanpairs++;
- }
-
- if (chanpairs * 2 != channels)
- return -1;
-
- return SNDRV_CTL_TLVT_CHMAP_PAIRED;
-}
-
-static void atihdmi_paired_cea_alloc_to_tlv_chmap(struct hdac_chmap *hchmap,
- struct hdac_cea_channel_speaker_allocation *cap,
- unsigned int *chmap, int channels)
-{
- /* produce paired maps for pre-rev3 ATI/AMD codecs */
- int count = 0;
- int c;
-
- for (c = 7; c >= 0; c--) {
- int chan = 7 - atihdmi_paired_swap_fc_lfe(7 - c);
- int spk = cap->speakers[chan];
- if (!spk) {
- /* add N/A channel if the companion channel is occupied */
- if (cap->speakers[chan + (chan % 2 ? -1 : 1)])
- chmap[count++] = SNDRV_CHMAP_NA;
-
- continue;
- }
-
- chmap[count++] = snd_hdac_spk_to_chmap(spk);
- }
-
- WARN_ON(count != channels);
-}
-
-static int atihdmi_pin_hbr_setup(struct hda_codec *codec, hda_nid_t pin_nid,
- int dev_id, bool hbr)
-{
- int hbr_ctl, hbr_ctl_new;
-
- WARN_ON(dev_id != 0);
-
- hbr_ctl = snd_hda_codec_read(codec, pin_nid, 0, ATI_VERB_GET_HBR_CONTROL, 0);
- if (hbr_ctl >= 0 && (hbr_ctl & ATI_HBR_CAPABLE)) {
- if (hbr)
- hbr_ctl_new = hbr_ctl | ATI_HBR_ENABLE;
- else
- hbr_ctl_new = hbr_ctl & ~ATI_HBR_ENABLE;
-
- codec_dbg(codec,
- "atihdmi_pin_hbr_setup: NID=0x%x, %shbr-ctl=0x%x\n",
- pin_nid,
- hbr_ctl == hbr_ctl_new ? "" : "new-",
- hbr_ctl_new);
-
- if (hbr_ctl != hbr_ctl_new)
- snd_hda_codec_write(codec, pin_nid, 0,
- ATI_VERB_SET_HBR_CONTROL,
- hbr_ctl_new);
-
- } else if (hbr)
- return -EINVAL;
-
- return 0;
-}
-
-static int atihdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid,
- hda_nid_t pin_nid, int dev_id,
- u32 stream_tag, int format)
-{
- if (is_amdhdmi_rev3_or_later(codec)) {
- int ramp_rate = 180; /* default as per AMD spec */
- /* disable ramp-up/down for non-pcm as per AMD spec */
- if (format & AC_FMT_TYPE_NON_PCM)
- ramp_rate = 0;
-
- snd_hda_codec_write(codec, cvt_nid, 0, ATI_VERB_SET_RAMP_RATE, ramp_rate);
- }
-
- return hdmi_setup_stream(codec, cvt_nid, pin_nid, dev_id,
- stream_tag, format);
-}
-
-
-static int atihdmi_init(struct hda_codec *codec)
-{
- struct hdmi_spec *spec = codec->spec;
- int pin_idx, err;
-
- err = generic_hdmi_init(codec);
-
- if (err)
- return err;
-
- for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
- struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
-
- /* make sure downmix information in infoframe is zero */
- snd_hda_codec_write(codec, per_pin->pin_nid, 0, ATI_VERB_SET_DOWNMIX_INFO, 0);
-
- /* enable channel-wise remap mode if supported */
- if (has_amd_full_remap_support(codec))
- snd_hda_codec_write(codec, per_pin->pin_nid, 0,
- ATI_VERB_SET_MULTICHANNEL_MODE,
- ATI_MULTICHANNEL_MODE_SINGLE);
- }
- codec->auto_runtime_pm = 1;
-
- return 0;
-}
-
-/* map from pin NID to port; port is 0-based */
-/* for AMD: assume widget NID starting from 3, with step 2 (3, 5, 7, ...) */
-static int atihdmi_pin2port(void *audio_ptr, int pin_nid)
-{
- return pin_nid / 2 - 1;
-}
-
-/* reverse-map from port to pin NID: see above */
-static int atihdmi_port2pin(struct hda_codec *codec, int port)
-{
- return port * 2 + 3;
-}
-
-static const struct drm_audio_component_audio_ops atihdmi_audio_ops = {
- .pin2port = atihdmi_pin2port,
- .pin_eld_notify = generic_acomp_pin_eld_notify,
- .master_bind = generic_acomp_master_bind,
- .master_unbind = generic_acomp_master_unbind,
-};
-
-static int patch_atihdmi(struct hda_codec *codec)
-{
- struct hdmi_spec *spec;
- struct hdmi_spec_per_cvt *per_cvt;
- int err, cvt_idx;
-
- err = patch_generic_hdmi(codec);
-
- if (err)
- return err;
-
- codec->patch_ops.init = atihdmi_init;
-
- spec = codec->spec;
-
- spec->static_pcm_mapping = true;
-
- spec->ops.pin_get_eld = atihdmi_pin_get_eld;
- spec->ops.pin_setup_infoframe = atihdmi_pin_setup_infoframe;
- spec->ops.pin_hbr_setup = atihdmi_pin_hbr_setup;
- spec->ops.setup_stream = atihdmi_setup_stream;
-
- spec->chmap.ops.pin_get_slot_channel = atihdmi_pin_get_slot_channel;
- spec->chmap.ops.pin_set_slot_channel = atihdmi_pin_set_slot_channel;
-
- if (!has_amd_full_remap_support(codec)) {
- /* override to ATI/AMD-specific versions with pairwise mapping */
- spec->chmap.ops.chmap_cea_alloc_validate_get_type =
- atihdmi_paired_chmap_cea_alloc_validate_get_type;
- spec->chmap.ops.cea_alloc_to_tlv_chmap =
- atihdmi_paired_cea_alloc_to_tlv_chmap;
- spec->chmap.ops.chmap_validate = atihdmi_paired_chmap_validate;
- }
-
- /* ATI/AMD converters do not advertise all of their capabilities */
- for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) {
- per_cvt = get_cvt(spec, cvt_idx);
- per_cvt->channels_max = max(per_cvt->channels_max, 8u);
- per_cvt->rates |= SUPPORTED_RATES;
- per_cvt->formats |= SUPPORTED_FORMATS;
- per_cvt->maxbps = max(per_cvt->maxbps, 24u);
- }
-
- spec->chmap.channels_max = max(spec->chmap.channels_max, 8u);
-
- /* AMD GPUs have neither EPSS nor CLKSTOP bits, hence preventing
- * the link-down as is. Tell the core to allow it.
- */
- codec->link_down_at_suspend = 1;
-
- generic_acomp_init(codec, &atihdmi_audio_ops, atihdmi_port2pin);
-
- return 0;
-}
-
-/* VIA HDMI Implementation */
-#define VIAHDMI_CVT_NID 0x02 /* audio converter1 */
-#define VIAHDMI_PIN_NID 0x03 /* HDMI output pin1 */
-
-static int patch_via_hdmi(struct hda_codec *codec)
-{
- return patch_simple_hdmi(codec, VIAHDMI_CVT_NID, VIAHDMI_PIN_NID);
-}
-
-static int patch_gf_hdmi(struct hda_codec *codec)
-{
- int err;
-
- err = patch_generic_hdmi(codec);
- if (err)
- return err;
-
- /*
- * Glenfly GPUs have two codecs, stream switches from one codec to
- * another, need to do actual clean-ups in codec_cleanup_stream
- */
- codec->no_sticky_stream = 1;
- return 0;
-}
-
-/*
- * patch entries
- */
-static const struct hda_device_id snd_hda_id_hdmi[] = {
-HDA_CODEC_ENTRY(0x00147a47, "Loongson HDMI", patch_generic_hdmi),
-HDA_CODEC_ENTRY(0x1002793c, "RS600 HDMI", patch_atihdmi),
-HDA_CODEC_ENTRY(0x10027919, "RS600 HDMI", patch_atihdmi),
-HDA_CODEC_ENTRY(0x1002791a, "RS690/780 HDMI", patch_atihdmi),
-HDA_CODEC_ENTRY(0x1002aa01, "R6xx HDMI", patch_atihdmi),
-HDA_CODEC_ENTRY(0x10951390, "SiI1390 HDMI", patch_generic_hdmi),
-HDA_CODEC_ENTRY(0x10951392, "SiI1392 HDMI", patch_generic_hdmi),
-HDA_CODEC_ENTRY(0x17e80047, "Chrontel HDMI", patch_generic_hdmi),
-HDA_CODEC_ENTRY(0x10de0001, "MCP73 HDMI", patch_nvhdmi_2ch),
-HDA_CODEC_ENTRY(0x10de0002, "MCP77/78 HDMI", patch_nvhdmi_8ch_7x),
-HDA_CODEC_ENTRY(0x10de0003, "MCP77/78 HDMI", patch_nvhdmi_8ch_7x),
-HDA_CODEC_ENTRY(0x10de0004, "GPU 04 HDMI", patch_nvhdmi_8ch_7x),
-HDA_CODEC_ENTRY(0x10de0005, "MCP77/78 HDMI", patch_nvhdmi_8ch_7x),
-HDA_CODEC_ENTRY(0x10de0006, "MCP77/78 HDMI", patch_nvhdmi_8ch_7x),
-HDA_CODEC_ENTRY(0x10de0007, "MCP79/7A HDMI", patch_nvhdmi_8ch_7x),
-HDA_CODEC_ENTRY(0x10de0008, "GPU 08 HDMI/DP", patch_nvhdmi_legacy),
-HDA_CODEC_ENTRY(0x10de0009, "GPU 09 HDMI/DP", patch_nvhdmi_legacy),
-HDA_CODEC_ENTRY(0x10de000a, "GPU 0a HDMI/DP", patch_nvhdmi_legacy),
-HDA_CODEC_ENTRY(0x10de000b, "GPU 0b HDMI/DP", patch_nvhdmi_legacy),
-HDA_CODEC_ENTRY(0x10de000c, "MCP89 HDMI", patch_nvhdmi_legacy),
-HDA_CODEC_ENTRY(0x10de000d, "GPU 0d HDMI/DP", patch_nvhdmi_legacy),
-HDA_CODEC_ENTRY(0x10de0010, "GPU 10 HDMI/DP", patch_nvhdmi_legacy),
-HDA_CODEC_ENTRY(0x10de0011, "GPU 11 HDMI/DP", patch_nvhdmi_legacy),
-HDA_CODEC_ENTRY(0x10de0012, "GPU 12 HDMI/DP", patch_nvhdmi_legacy),
-HDA_CODEC_ENTRY(0x10de0013, "GPU 13 HDMI/DP", patch_nvhdmi_legacy),
-HDA_CODEC_ENTRY(0x10de0014, "GPU 14 HDMI/DP", patch_nvhdmi_legacy),
-HDA_CODEC_ENTRY(0x10de0015, "GPU 15 HDMI/DP", patch_nvhdmi_legacy),
-HDA_CODEC_ENTRY(0x10de0016, "GPU 16 HDMI/DP", patch_nvhdmi_legacy),
-/* 17 is known to be absent */
-HDA_CODEC_ENTRY(0x10de0018, "GPU 18 HDMI/DP", patch_nvhdmi_legacy),
-HDA_CODEC_ENTRY(0x10de0019, "GPU 19 HDMI/DP", patch_nvhdmi_legacy),
-HDA_CODEC_ENTRY(0x10de001a, "GPU 1a HDMI/DP", patch_nvhdmi_legacy),
-HDA_CODEC_ENTRY(0x10de001b, "GPU 1b HDMI/DP", patch_nvhdmi_legacy),
-HDA_CODEC_ENTRY(0x10de001c, "GPU 1c HDMI/DP", patch_nvhdmi_legacy),
-HDA_CODEC_ENTRY(0x10de0020, "Tegra30 HDMI", patch_tegra_hdmi),
-HDA_CODEC_ENTRY(0x10de0022, "Tegra114 HDMI", patch_tegra_hdmi),
-HDA_CODEC_ENTRY(0x10de0028, "Tegra124 HDMI", patch_tegra_hdmi),
-HDA_CODEC_ENTRY(0x10de0029, "Tegra210 HDMI/DP", patch_tegra_hdmi),
-HDA_CODEC_ENTRY(0x10de002d, "Tegra186 HDMI/DP0", patch_tegra_hdmi),
-HDA_CODEC_ENTRY(0x10de002e, "Tegra186 HDMI/DP1", patch_tegra_hdmi),
-HDA_CODEC_ENTRY(0x10de002f, "Tegra194 HDMI/DP2", patch_tegra_hdmi),
-HDA_CODEC_ENTRY(0x10de0030, "Tegra194 HDMI/DP3", patch_tegra_hdmi),
-HDA_CODEC_ENTRY(0x10de0031, "Tegra234 HDMI/DP", patch_tegra234_hdmi),
-HDA_CODEC_ENTRY(0x10de0034, "Tegra264 HDMI/DP", patch_tegra234_hdmi),
-HDA_CODEC_ENTRY(0x10de0040, "GPU 40 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0041, "GPU 41 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0042, "GPU 42 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0043, "GPU 43 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0044, "GPU 44 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0045, "GPU 45 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0050, "GPU 50 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0051, "GPU 51 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0052, "GPU 52 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0060, "GPU 60 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0061, "GPU 61 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0062, "GPU 62 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0067, "MCP67 HDMI", patch_nvhdmi_2ch),
-HDA_CODEC_ENTRY(0x10de0070, "GPU 70 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0071, "GPU 71 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0072, "GPU 72 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0073, "GPU 73 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0074, "GPU 74 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0076, "GPU 76 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de007b, "GPU 7b HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de007c, "GPU 7c HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de007d, "GPU 7d HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de007e, "GPU 7e HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0080, "GPU 80 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0081, "GPU 81 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0082, "GPU 82 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0083, "GPU 83 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0084, "GPU 84 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0090, "GPU 90 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0091, "GPU 91 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0092, "GPU 92 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0093, "GPU 93 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0094, "GPU 94 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0095, "GPU 95 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0097, "GPU 97 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0098, "GPU 98 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de0099, "GPU 99 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de009a, "GPU 9a HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de009d, "GPU 9d HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de009e, "GPU 9e HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de009f, "GPU 9f HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de00a0, "GPU a0 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de00a3, "GPU a3 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de00a4, "GPU a4 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de00a5, "GPU a5 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de00a6, "GPU a6 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de00a7, "GPU a7 HDMI/DP", patch_nvhdmi),
-HDA_CODEC_ENTRY(0x10de8001, "MCP73 HDMI", patch_nvhdmi_2ch),
-HDA_CODEC_ENTRY(0x10de8067, "MCP67/68 HDMI", patch_nvhdmi_2ch),
-HDA_CODEC_ENTRY(0x67663d82, "Arise 82 HDMI/DP", patch_gf_hdmi),
-HDA_CODEC_ENTRY(0x67663d83, "Arise 83 HDMI/DP", patch_gf_hdmi),
-HDA_CODEC_ENTRY(0x67663d84, "Arise 84 HDMI/DP", patch_gf_hdmi),
-HDA_CODEC_ENTRY(0x67663d85, "Arise 85 HDMI/DP", patch_gf_hdmi),
-HDA_CODEC_ENTRY(0x67663d86, "Arise 86 HDMI/DP", patch_gf_hdmi),
-HDA_CODEC_ENTRY(0x67663d87, "Arise 87 HDMI/DP", patch_gf_hdmi),
-HDA_CODEC_ENTRY(0x11069f80, "VX900 HDMI/DP", patch_via_hdmi),
-HDA_CODEC_ENTRY(0x11069f81, "VX900 HDMI/DP", patch_via_hdmi),
-HDA_CODEC_ENTRY(0x11069f84, "VX11 HDMI/DP", patch_generic_hdmi),
-HDA_CODEC_ENTRY(0x11069f85, "VX11 HDMI/DP", patch_generic_hdmi),
-HDA_CODEC_ENTRY(0x1d179f86, "ZX-100S HDMI/DP", patch_gf_hdmi),
-HDA_CODEC_ENTRY(0x1d179f87, "ZX-100S HDMI/DP", patch_gf_hdmi),
-HDA_CODEC_ENTRY(0x1d179f88, "KX-5000 HDMI/DP", patch_gf_hdmi),
-HDA_CODEC_ENTRY(0x1d179f89, "KX-5000 HDMI/DP", patch_gf_hdmi),
-HDA_CODEC_ENTRY(0x1d179f8a, "KX-6000 HDMI/DP", patch_gf_hdmi),
-HDA_CODEC_ENTRY(0x1d179f8b, "KX-6000 HDMI/DP", patch_gf_hdmi),
-HDA_CODEC_ENTRY(0x1d179f8c, "KX-6000G HDMI/DP", patch_gf_hdmi),
-HDA_CODEC_ENTRY(0x1d179f8d, "KX-6000G HDMI/DP", patch_gf_hdmi),
-HDA_CODEC_ENTRY(0x1d179f8e, "KX-7000 HDMI/DP", patch_gf_hdmi),
-HDA_CODEC_ENTRY(0x1d179f8f, "KX-7000 HDMI/DP", patch_gf_hdmi),
-HDA_CODEC_ENTRY(0x1d179f90, "KX-7000 HDMI/DP", patch_gf_hdmi),
-HDA_CODEC_ENTRY(0x80860054, "IbexPeak HDMI", patch_i915_cpt_hdmi),
-HDA_CODEC_ENTRY(0x80862800, "Geminilake HDMI", patch_i915_glk_hdmi),
-HDA_CODEC_ENTRY(0x80862801, "Bearlake HDMI", patch_generic_hdmi),
-HDA_CODEC_ENTRY(0x80862802, "Cantiga HDMI", patch_generic_hdmi),
-HDA_CODEC_ENTRY(0x80862803, "Eaglelake HDMI", patch_generic_hdmi),
-HDA_CODEC_ENTRY(0x80862804, "IbexPeak HDMI", patch_i915_cpt_hdmi),
-HDA_CODEC_ENTRY(0x80862805, "CougarPoint HDMI", patch_i915_cpt_hdmi),
-HDA_CODEC_ENTRY(0x80862806, "PantherPoint HDMI", patch_i915_cpt_hdmi),
-HDA_CODEC_ENTRY(0x80862807, "Haswell HDMI", patch_i915_hsw_hdmi),
-HDA_CODEC_ENTRY(0x80862808, "Broadwell HDMI", patch_i915_hsw_hdmi),
-HDA_CODEC_ENTRY(0x80862809, "Skylake HDMI", patch_i915_hsw_hdmi),
-HDA_CODEC_ENTRY(0x8086280a, "Broxton HDMI", patch_i915_hsw_hdmi),
-HDA_CODEC_ENTRY(0x8086280b, "Kabylake HDMI", patch_i915_hsw_hdmi),
-HDA_CODEC_ENTRY(0x8086280c, "Cannonlake HDMI", patch_i915_glk_hdmi),
-HDA_CODEC_ENTRY(0x8086280d, "Geminilake HDMI", patch_i915_glk_hdmi),
-HDA_CODEC_ENTRY(0x8086280f, "Icelake HDMI", patch_i915_icl_hdmi),
-HDA_CODEC_ENTRY(0x80862812, "Tigerlake HDMI", patch_i915_tgl_hdmi),
-HDA_CODEC_ENTRY(0x80862814, "DG1 HDMI", patch_i915_tgl_hdmi),
-HDA_CODEC_ENTRY(0x80862815, "Alderlake HDMI", patch_i915_tgl_hdmi),
-HDA_CODEC_ENTRY(0x80862816, "Rocketlake HDMI", patch_i915_tgl_hdmi),
-HDA_CODEC_ENTRY(0x80862818, "Raptorlake HDMI", patch_i915_tgl_hdmi),
-HDA_CODEC_ENTRY(0x80862819, "DG2 HDMI", patch_i915_tgl_hdmi),
-HDA_CODEC_ENTRY(0x8086281a, "Jasperlake HDMI", patch_i915_icl_hdmi),
-HDA_CODEC_ENTRY(0x8086281b, "Elkhartlake HDMI", patch_i915_icl_hdmi),
-HDA_CODEC_ENTRY(0x8086281c, "Alderlake-P HDMI", patch_i915_adlp_hdmi),
-HDA_CODEC_ENTRY(0x8086281d, "Meteor Lake HDMI", patch_i915_adlp_hdmi),
-HDA_CODEC_ENTRY(0x8086281e, "Battlemage HDMI", patch_i915_adlp_hdmi),
-HDA_CODEC_ENTRY(0x8086281f, "Raptor Lake P HDMI", patch_i915_adlp_hdmi),
-HDA_CODEC_ENTRY(0x80862820, "Lunar Lake HDMI", patch_i915_adlp_hdmi),
-HDA_CODEC_ENTRY(0x80862822, "Panther Lake HDMI", patch_i915_adlp_hdmi),
-HDA_CODEC_ENTRY(0x80862823, "Wildcat Lake HDMI", patch_i915_adlp_hdmi),
-HDA_CODEC_ENTRY(0x80862880, "CedarTrail HDMI", patch_generic_hdmi),
-HDA_CODEC_ENTRY(0x80862882, "Valleyview2 HDMI", patch_i915_byt_hdmi),
-HDA_CODEC_ENTRY(0x80862883, "Braswell HDMI", patch_i915_byt_hdmi),
-HDA_CODEC_ENTRY(0x808629fb, "Crestline HDMI", patch_generic_hdmi),
-/* special ID for generic HDMI */
-HDA_CODEC_ENTRY(HDA_CODEC_ID_GENERIC_HDMI, "Generic HDMI", patch_generic_hdmi),
-{} /* terminator */
-};
-MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_hdmi);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("HDMI HD-audio codec");
-MODULE_ALIAS("snd-hda-codec-intelhdmi");
-MODULE_ALIAS("snd-hda-codec-nvhdmi");
-MODULE_ALIAS("snd-hda-codec-atihdmi");
-
-static struct hda_codec_driver hdmi_driver = {
- .id = snd_hda_id_hdmi,
-};
-
-module_hda_codec_driver(hdmi_driver);
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
deleted file mode 100644
index 2e1618494c20..000000000000
--- a/sound/pci/hda/patch_realtek.c
+++ /dev/null
@@ -1,13756 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Universal Interface for Intel High Definition Audio Codec
- *
- * HD audio interface patch for Realtek ALC codecs
- *
- * Copyright (c) 2004 Kailang Yang <kailang@realtek.com.tw>
- * PeiSen Hou <pshou@realtek.com.tw>
- * Takashi Iwai <tiwai@suse.de>
- * Jonathan Woithe <jwoithe@just42.net>
- */
-
-#include <linux/acpi.h>
-#include <linux/cleanup.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/pci.h>
-#include <linux/dmi.h>
-#include <linux/module.h>
-#include <linux/i2c.h>
-#include <linux/input.h>
-#include <linux/leds.h>
-#include <linux/ctype.h>
-#include <linux/spi/spi.h>
-#include <sound/core.h>
-#include <sound/jack.h>
-#include <sound/hda_codec.h>
-#include "hda_local.h"
-#include "hda_auto_parser.h"
-#include "hda_beep.h"
-#include "hda_jack.h"
-#include "hda_generic.h"
-#include "hda_component.h"
-
-/* keep halting ALC5505 DSP, for power saving */
-#define HALT_REALTEK_ALC5505
-
-/* extra amp-initialization sequence types */
-enum {
- ALC_INIT_UNDEFINED,
- ALC_INIT_NONE,
- ALC_INIT_DEFAULT,
-};
-
-enum {
- ALC_HEADSET_MODE_UNKNOWN,
- ALC_HEADSET_MODE_UNPLUGGED,
- ALC_HEADSET_MODE_HEADSET,
- ALC_HEADSET_MODE_MIC,
- ALC_HEADSET_MODE_HEADPHONE,
-};
-
-enum {
- ALC_HEADSET_TYPE_UNKNOWN,
- ALC_HEADSET_TYPE_CTIA,
- ALC_HEADSET_TYPE_OMTP,
-};
-
-enum {
- ALC_KEY_MICMUTE_INDEX,
-};
-
-struct alc_customize_define {
- unsigned int sku_cfg;
- unsigned char port_connectivity;
- unsigned char check_sum;
- unsigned char customization;
- unsigned char external_amp;
- unsigned int enable_pcbeep:1;
- unsigned int platform_type:1;
- unsigned int swap:1;
- unsigned int override:1;
- unsigned int fixup:1; /* Means that this sku is set by driver, not read from hw */
-};
-
-struct alc_coef_led {
- unsigned int idx;
- unsigned int mask;
- unsigned int on;
- unsigned int off;
-};
-
-struct alc_spec {
- struct hda_gen_spec gen; /* must be at head */
-
- /* codec parameterization */
- struct alc_customize_define cdefine;
- unsigned int parse_flags; /* flag for snd_hda_parse_pin_defcfg() */
-
- /* GPIO bits */
- unsigned int gpio_mask;
- unsigned int gpio_dir;
- unsigned int gpio_data;
- bool gpio_write_delay; /* add a delay before writing gpio_data */
-
- /* mute LED for HP laptops, see vref_mute_led_set() */
- int mute_led_polarity;
- int micmute_led_polarity;
- hda_nid_t mute_led_nid;
- hda_nid_t cap_mute_led_nid;
-
- unsigned int gpio_mute_led_mask;
- unsigned int gpio_mic_led_mask;
- struct alc_coef_led mute_led_coef;
- struct alc_coef_led mic_led_coef;
- struct mutex coef_mutex;
-
- hda_nid_t headset_mic_pin;
- hda_nid_t headphone_mic_pin;
- int current_headset_mode;
- int current_headset_type;
-
- /* hooks */
- void (*init_hook)(struct hda_codec *codec);
- void (*power_hook)(struct hda_codec *codec);
- void (*shutup)(struct hda_codec *codec);
-
- int init_amp;
- int codec_variant; /* flag for other variants */
- unsigned int has_alc5505_dsp:1;
- unsigned int no_depop_delay:1;
- unsigned int done_hp_init:1;
- unsigned int no_shutup_pins:1;
- unsigned int ultra_low_power:1;
- unsigned int has_hs_key:1;
- unsigned int no_internal_mic_pin:1;
- unsigned int en_3kpull_low:1;
- int num_speaker_amps;
-
- /* for PLL fix */
- hda_nid_t pll_nid;
- unsigned int pll_coef_idx, pll_coef_bit;
- unsigned int coef0;
- struct input_dev *kb_dev;
- u8 alc_mute_keycode_map[1];
-
- /* component binding */
- struct hda_component_parent comps;
-};
-
-/*
- * COEF access helper functions
- */
-
-static void coef_mutex_lock(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- snd_hda_power_up_pm(codec);
- mutex_lock(&spec->coef_mutex);
-}
-
-static void coef_mutex_unlock(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- mutex_unlock(&spec->coef_mutex);
- snd_hda_power_down_pm(codec);
-}
-
-static int __alc_read_coefex_idx(struct hda_codec *codec, hda_nid_t nid,
- unsigned int coef_idx)
-{
- unsigned int val;
-
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_COEF_INDEX, coef_idx);
- val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PROC_COEF, 0);
- return val;
-}
-
-static int alc_read_coefex_idx(struct hda_codec *codec, hda_nid_t nid,
- unsigned int coef_idx)
-{
- unsigned int val;
-
- coef_mutex_lock(codec);
- val = __alc_read_coefex_idx(codec, nid, coef_idx);
- coef_mutex_unlock(codec);
- return val;
-}
-
-#define alc_read_coef_idx(codec, coef_idx) \
- alc_read_coefex_idx(codec, 0x20, coef_idx)
-
-static void __alc_write_coefex_idx(struct hda_codec *codec, hda_nid_t nid,
- unsigned int coef_idx, unsigned int coef_val)
-{
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_COEF_INDEX, coef_idx);
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PROC_COEF, coef_val);
-}
-
-static void alc_write_coefex_idx(struct hda_codec *codec, hda_nid_t nid,
- unsigned int coef_idx, unsigned int coef_val)
-{
- coef_mutex_lock(codec);
- __alc_write_coefex_idx(codec, nid, coef_idx, coef_val);
- coef_mutex_unlock(codec);
-}
-
-#define alc_write_coef_idx(codec, coef_idx, coef_val) \
- alc_write_coefex_idx(codec, 0x20, coef_idx, coef_val)
-
-static void __alc_update_coefex_idx(struct hda_codec *codec, hda_nid_t nid,
- unsigned int coef_idx, unsigned int mask,
- unsigned int bits_set)
-{
- unsigned int val = __alc_read_coefex_idx(codec, nid, coef_idx);
-
- if (val != -1)
- __alc_write_coefex_idx(codec, nid, coef_idx,
- (val & ~mask) | bits_set);
-}
-
-static void alc_update_coefex_idx(struct hda_codec *codec, hda_nid_t nid,
- unsigned int coef_idx, unsigned int mask,
- unsigned int bits_set)
-{
- coef_mutex_lock(codec);
- __alc_update_coefex_idx(codec, nid, coef_idx, mask, bits_set);
- coef_mutex_unlock(codec);
-}
-
-#define alc_update_coef_idx(codec, coef_idx, mask, bits_set) \
- alc_update_coefex_idx(codec, 0x20, coef_idx, mask, bits_set)
-
-/* a special bypass for COEF 0; read the cached value at the second time */
-static unsigned int alc_get_coef0(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- if (!spec->coef0)
- spec->coef0 = alc_read_coef_idx(codec, 0);
- return spec->coef0;
-}
-
-/* coef writes/updates batch */
-struct coef_fw {
- unsigned char nid;
- unsigned char idx;
- unsigned short mask;
- unsigned short val;
-};
-
-#define UPDATE_COEFEX(_nid, _idx, _mask, _val) \
- { .nid = (_nid), .idx = (_idx), .mask = (_mask), .val = (_val) }
-#define WRITE_COEFEX(_nid, _idx, _val) UPDATE_COEFEX(_nid, _idx, -1, _val)
-#define WRITE_COEF(_idx, _val) WRITE_COEFEX(0x20, _idx, _val)
-#define UPDATE_COEF(_idx, _mask, _val) UPDATE_COEFEX(0x20, _idx, _mask, _val)
-
-static void alc_process_coef_fw(struct hda_codec *codec,
- const struct coef_fw *fw)
-{
- coef_mutex_lock(codec);
- for (; fw->nid; fw++) {
- if (fw->mask == (unsigned short)-1)
- __alc_write_coefex_idx(codec, fw->nid, fw->idx, fw->val);
- else
- __alc_update_coefex_idx(codec, fw->nid, fw->idx,
- fw->mask, fw->val);
- }
- coef_mutex_unlock(codec);
-}
-
-/*
- * GPIO setup tables, used in initialization
- */
-
-/* Enable GPIO mask and set output */
-static void alc_setup_gpio(struct hda_codec *codec, unsigned int mask)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->gpio_mask |= mask;
- spec->gpio_dir |= mask;
- spec->gpio_data |= mask;
-}
-
-static void alc_write_gpio_data(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
- spec->gpio_data);
-}
-
-static void alc_update_gpio_data(struct hda_codec *codec, unsigned int mask,
- bool on)
-{
- struct alc_spec *spec = codec->spec;
- unsigned int oldval = spec->gpio_data;
-
- if (on)
- spec->gpio_data |= mask;
- else
- spec->gpio_data &= ~mask;
- if (oldval != spec->gpio_data)
- alc_write_gpio_data(codec);
-}
-
-static void alc_write_gpio(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- if (!spec->gpio_mask)
- return;
-
- snd_hda_codec_write(codec, codec->core.afg, 0,
- AC_VERB_SET_GPIO_MASK, spec->gpio_mask);
- snd_hda_codec_write(codec, codec->core.afg, 0,
- AC_VERB_SET_GPIO_DIRECTION, spec->gpio_dir);
- if (spec->gpio_write_delay)
- msleep(1);
- alc_write_gpio_data(codec);
-}
-
-static void alc_fixup_gpio(struct hda_codec *codec, int action,
- unsigned int mask)
-{
- if (action == HDA_FIXUP_ACT_PRE_PROBE)
- alc_setup_gpio(codec, mask);
-}
-
-static void alc_fixup_gpio1(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- alc_fixup_gpio(codec, action, 0x01);
-}
-
-static void alc_fixup_gpio2(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- alc_fixup_gpio(codec, action, 0x02);
-}
-
-static void alc_fixup_gpio3(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- alc_fixup_gpio(codec, action, 0x03);
-}
-
-static void alc_fixup_gpio4(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- alc_fixup_gpio(codec, action, 0x04);
-}
-
-static void alc_fixup_micmute_led(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_PRE_PROBE)
- snd_hda_gen_add_micmute_led_cdev(codec, NULL);
-}
-
-/*
- * Fix hardware PLL issue
- * On some codecs, the analog PLL gating control must be off while
- * the default value is 1.
- */
-static void alc_fix_pll(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- if (spec->pll_nid)
- alc_update_coefex_idx(codec, spec->pll_nid, spec->pll_coef_idx,
- 1 << spec->pll_coef_bit, 0);
-}
-
-static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
- unsigned int coef_idx, unsigned int coef_bit)
-{
- struct alc_spec *spec = codec->spec;
- spec->pll_nid = nid;
- spec->pll_coef_idx = coef_idx;
- spec->pll_coef_bit = coef_bit;
- alc_fix_pll(codec);
-}
-
-/* update the master volume per volume-knob's unsol event */
-static void alc_update_knob_master(struct hda_codec *codec,
- struct hda_jack_callback *jack)
-{
- unsigned int val;
- struct snd_kcontrol *kctl;
- struct snd_ctl_elem_value *uctl;
-
- kctl = snd_hda_find_mixer_ctl(codec, "Master Playback Volume");
- if (!kctl)
- return;
- uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
- if (!uctl)
- return;
- val = snd_hda_codec_read(codec, jack->nid, 0,
- AC_VERB_GET_VOLUME_KNOB_CONTROL, 0);
- val &= HDA_AMP_VOLMASK;
- uctl->value.integer.value[0] = val;
- uctl->value.integer.value[1] = val;
- kctl->put(kctl, uctl);
- kfree(uctl);
-}
-
-static void alc880_unsol_event(struct hda_codec *codec, unsigned int res)
-{
- /* For some reason, the res given from ALC880 is broken.
- Here we adjust it properly. */
- snd_hda_jack_unsol_event(codec, res >> 2);
-}
-
-/* Change EAPD to verb control */
-static void alc_fill_eapd_coef(struct hda_codec *codec)
-{
- int coef;
-
- coef = alc_get_coef0(codec);
-
- switch (codec->core.vendor_id) {
- case 0x10ec0262:
- alc_update_coef_idx(codec, 0x7, 0, 1<<5);
- break;
- case 0x10ec0267:
- case 0x10ec0268:
- alc_update_coef_idx(codec, 0x7, 0, 1<<13);
- break;
- case 0x10ec0269:
- if ((coef & 0x00f0) == 0x0010)
- alc_update_coef_idx(codec, 0xd, 0, 1<<14);
- if ((coef & 0x00f0) == 0x0020)
- alc_update_coef_idx(codec, 0x4, 1<<15, 0);
- if ((coef & 0x00f0) == 0x0030)
- alc_update_coef_idx(codec, 0x10, 1<<9, 0);
- break;
- case 0x10ec0280:
- case 0x10ec0284:
- case 0x10ec0290:
- case 0x10ec0292:
- alc_update_coef_idx(codec, 0x4, 1<<15, 0);
- break;
- case 0x10ec0225:
- case 0x10ec0295:
- case 0x10ec0299:
- alc_update_coef_idx(codec, 0x67, 0xf000, 0x3000);
- fallthrough;
- case 0x10ec0215:
- case 0x10ec0236:
- case 0x10ec0245:
- case 0x10ec0256:
- case 0x10ec0257:
- case 0x10ec0285:
- case 0x10ec0289:
- alc_update_coef_idx(codec, 0x36, 1<<13, 0);
- fallthrough;
- case 0x10ec0230:
- case 0x10ec0233:
- case 0x10ec0235:
- case 0x10ec0255:
- case 0x19e58326:
- case 0x10ec0282:
- case 0x10ec0283:
- case 0x10ec0286:
- case 0x10ec0288:
- case 0x10ec0298:
- case 0x10ec0300:
- alc_update_coef_idx(codec, 0x10, 1<<9, 0);
- break;
- case 0x10ec0275:
- alc_update_coef_idx(codec, 0xe, 0, 1<<0);
- break;
- case 0x10ec0287:
- alc_update_coef_idx(codec, 0x10, 1<<9, 0);
- alc_write_coef_idx(codec, 0x8, 0x4ab7);
- break;
- case 0x10ec0293:
- alc_update_coef_idx(codec, 0xa, 1<<13, 0);
- break;
- case 0x10ec0234:
- case 0x10ec0274:
- alc_write_coef_idx(codec, 0x6e, 0x0c25);
- fallthrough;
- case 0x10ec0294:
- case 0x10ec0700:
- case 0x10ec0701:
- case 0x10ec0703:
- case 0x10ec0711:
- alc_update_coef_idx(codec, 0x10, 1<<15, 0);
- break;
- case 0x10ec0662:
- if ((coef & 0x00f0) == 0x0030)
- alc_update_coef_idx(codec, 0x4, 1<<10, 0); /* EAPD Ctrl */
- break;
- case 0x10ec0272:
- case 0x10ec0273:
- case 0x10ec0663:
- case 0x10ec0665:
- case 0x10ec0670:
- case 0x10ec0671:
- case 0x10ec0672:
- alc_update_coef_idx(codec, 0xd, 0, 1<<14); /* EAPD Ctrl */
- break;
- case 0x10ec0222:
- case 0x10ec0623:
- alc_update_coef_idx(codec, 0x19, 1<<13, 0);
- break;
- case 0x10ec0668:
- alc_update_coef_idx(codec, 0x7, 3<<13, 0);
- break;
- case 0x10ec0867:
- alc_update_coef_idx(codec, 0x4, 1<<10, 0);
- break;
- case 0x10ec0888:
- if ((coef & 0x00f0) == 0x0020 || (coef & 0x00f0) == 0x0030)
- alc_update_coef_idx(codec, 0x7, 1<<5, 0);
- break;
- case 0x10ec0892:
- case 0x10ec0897:
- alc_update_coef_idx(codec, 0x7, 1<<5, 0);
- break;
- case 0x10ec0899:
- case 0x10ec0900:
- case 0x10ec0b00:
- case 0x10ec1168:
- case 0x10ec1220:
- alc_update_coef_idx(codec, 0x7, 1<<1, 0);
- break;
- }
-}
-
-/* additional initialization for ALC888 variants */
-static void alc888_coef_init(struct hda_codec *codec)
-{
- switch (alc_get_coef0(codec) & 0x00f0) {
- /* alc888-VA */
- case 0x00:
- /* alc888-VB */
- case 0x10:
- alc_update_coef_idx(codec, 7, 0, 0x2030); /* Turn EAPD to High */
- break;
- }
-}
-
-/* turn on/off EAPD control (only if available) */
-static void set_eapd(struct hda_codec *codec, hda_nid_t nid, int on)
-{
- if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
- return;
- if (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
- on ? 2 : 0);
-}
-
-/* turn on/off EAPD controls of the codec */
-static void alc_auto_setup_eapd(struct hda_codec *codec, bool on)
-{
- /* We currently only handle front, HP */
- static const hda_nid_t pins[] = {
- 0x0f, 0x10, 0x14, 0x15, 0x17, 0
- };
- const hda_nid_t *p;
- for (p = pins; *p; p++)
- set_eapd(codec, *p, on);
-}
-
-static int find_ext_mic_pin(struct hda_codec *codec);
-
-static void alc_headset_mic_no_shutup(struct hda_codec *codec)
-{
- const struct hda_pincfg *pin;
- int mic_pin = find_ext_mic_pin(codec);
- int i;
-
- /* don't shut up pins when unloading the driver; otherwise it breaks
- * the default pin setup at the next load of the driver
- */
- if (codec->bus->shutdown)
- return;
-
- snd_array_for_each(&codec->init_pins, i, pin) {
- /* use read here for syncing after issuing each verb */
- if (pin->nid != mic_pin)
- snd_hda_codec_read(codec, pin->nid, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
- }
-
- codec->pins_shutup = 1;
-}
-
-static void alc_shutup_pins(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- if (spec->no_shutup_pins)
- return;
-
- switch (codec->core.vendor_id) {
- case 0x10ec0236:
- case 0x10ec0256:
- case 0x10ec0257:
- case 0x19e58326:
- case 0x10ec0283:
- case 0x10ec0285:
- case 0x10ec0286:
- case 0x10ec0287:
- case 0x10ec0288:
- case 0x10ec0295:
- case 0x10ec0298:
- alc_headset_mic_no_shutup(codec);
- break;
- default:
- snd_hda_shutup_pins(codec);
- break;
- }
-}
-
-/* generic shutup callback;
- * just turning off EAPD and a little pause for avoiding pop-noise
- */
-static void alc_eapd_shutup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- alc_auto_setup_eapd(codec, false);
- if (!spec->no_depop_delay)
- msleep(200);
- alc_shutup_pins(codec);
-}
-
-/* generic EAPD initialization */
-static void alc_auto_init_amp(struct hda_codec *codec, int type)
-{
- alc_auto_setup_eapd(codec, true);
- alc_write_gpio(codec);
- switch (type) {
- case ALC_INIT_DEFAULT:
- switch (codec->core.vendor_id) {
- case 0x10ec0260:
- alc_update_coefex_idx(codec, 0x1a, 7, 0, 0x2010);
- break;
- case 0x10ec0880:
- case 0x10ec0882:
- case 0x10ec0883:
- case 0x10ec0885:
- alc_update_coef_idx(codec, 7, 0, 0x2030);
- break;
- case 0x10ec0888:
- alc888_coef_init(codec);
- break;
- }
- break;
- }
-}
-
-/* get a primary headphone pin if available */
-static hda_nid_t alc_get_hp_pin(struct alc_spec *spec)
-{
- if (spec->gen.autocfg.hp_pins[0])
- return spec->gen.autocfg.hp_pins[0];
- if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT)
- return spec->gen.autocfg.line_out_pins[0];
- return 0;
-}
-
-/*
- * Realtek SSID verification
- */
-
-/* Could be any non-zero and even value. When used as fixup, tells
- * the driver to ignore any present sku defines.
- */
-#define ALC_FIXUP_SKU_IGNORE (2)
-
-static void alc_fixup_sku_ignore(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->cdefine.fixup = 1;
- spec->cdefine.sku_cfg = ALC_FIXUP_SKU_IGNORE;
- }
-}
-
-static void alc_fixup_no_depop_delay(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PROBE) {
- spec->no_depop_delay = 1;
- codec->depop_delay = 0;
- }
-}
-
-static int alc_auto_parse_customize_define(struct hda_codec *codec)
-{
- unsigned int ass, tmp, i;
- unsigned nid = 0;
- struct alc_spec *spec = codec->spec;
-
- spec->cdefine.enable_pcbeep = 1; /* assume always enabled */
-
- if (spec->cdefine.fixup) {
- ass = spec->cdefine.sku_cfg;
- if (ass == ALC_FIXUP_SKU_IGNORE)
- return -1;
- goto do_sku;
- }
-
- if (!codec->bus->pci)
- return -1;
- ass = codec->core.subsystem_id & 0xffff;
- if (ass != codec->bus->pci->subsystem_device && (ass & 1))
- goto do_sku;
-
- nid = 0x1d;
- if (codec->core.vendor_id == 0x10ec0260)
- nid = 0x17;
- ass = snd_hda_codec_get_pincfg(codec, nid);
-
- if (!(ass & 1)) {
- codec_info(codec, "%s: SKU not ready 0x%08x\n",
- codec->core.chip_name, ass);
- return -1;
- }
-
- /* check sum */
- tmp = 0;
- for (i = 1; i < 16; i++) {
- if ((ass >> i) & 1)
- tmp++;
- }
- if (((ass >> 16) & 0xf) != tmp)
- return -1;
-
- spec->cdefine.port_connectivity = ass >> 30;
- spec->cdefine.enable_pcbeep = (ass & 0x100000) >> 20;
- spec->cdefine.check_sum = (ass >> 16) & 0xf;
- spec->cdefine.customization = ass >> 8;
-do_sku:
- spec->cdefine.sku_cfg = ass;
- spec->cdefine.external_amp = (ass & 0x38) >> 3;
- spec->cdefine.platform_type = (ass & 0x4) >> 2;
- spec->cdefine.swap = (ass & 0x2) >> 1;
- spec->cdefine.override = ass & 0x1;
-
- codec_dbg(codec, "SKU: Nid=0x%x sku_cfg=0x%08x\n",
- nid, spec->cdefine.sku_cfg);
- codec_dbg(codec, "SKU: port_connectivity=0x%x\n",
- spec->cdefine.port_connectivity);
- codec_dbg(codec, "SKU: enable_pcbeep=0x%x\n", spec->cdefine.enable_pcbeep);
- codec_dbg(codec, "SKU: check_sum=0x%08x\n", spec->cdefine.check_sum);
- codec_dbg(codec, "SKU: customization=0x%08x\n", spec->cdefine.customization);
- codec_dbg(codec, "SKU: external_amp=0x%x\n", spec->cdefine.external_amp);
- codec_dbg(codec, "SKU: platform_type=0x%x\n", spec->cdefine.platform_type);
- codec_dbg(codec, "SKU: swap=0x%x\n", spec->cdefine.swap);
- codec_dbg(codec, "SKU: override=0x%x\n", spec->cdefine.override);
-
- return 0;
-}
-
-/* return the position of NID in the list, or -1 if not found */
-static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
-{
- int i;
- for (i = 0; i < nums; i++)
- if (list[i] == nid)
- return i;
- return -1;
-}
-/* return true if the given NID is found in the list */
-static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
-{
- return find_idx_in_nid_list(nid, list, nums) >= 0;
-}
-
-/* check subsystem ID and set up device-specific initialization;
- * return 1 if initialized, 0 if invalid SSID
- */
-/* 32-bit subsystem ID for BIOS loading in HD Audio codec.
- * 31 ~ 16 : Manufacture ID
- * 15 ~ 8 : SKU ID
- * 7 ~ 0 : Assembly ID
- * port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36
- */
-static int alc_subsystem_id(struct hda_codec *codec, const hda_nid_t *ports)
-{
- unsigned int ass, tmp, i;
- unsigned nid;
- struct alc_spec *spec = codec->spec;
-
- if (spec->cdefine.fixup) {
- ass = spec->cdefine.sku_cfg;
- if (ass == ALC_FIXUP_SKU_IGNORE)
- return 0;
- goto do_sku;
- }
-
- ass = codec->core.subsystem_id & 0xffff;
- if (codec->bus->pci &&
- ass != codec->bus->pci->subsystem_device && (ass & 1))
- goto do_sku;
-
- /* invalid SSID, check the special NID pin defcfg instead */
- /*
- * 31~30 : port connectivity
- * 29~21 : reserve
- * 20 : PCBEEP input
- * 19~16 : Check sum (15:1)
- * 15~1 : Custom
- * 0 : override
- */
- nid = 0x1d;
- if (codec->core.vendor_id == 0x10ec0260)
- nid = 0x17;
- ass = snd_hda_codec_get_pincfg(codec, nid);
- codec_dbg(codec,
- "realtek: No valid SSID, checking pincfg 0x%08x for NID 0x%x\n",
- ass, nid);
- if (!(ass & 1))
- return 0;
- if ((ass >> 30) != 1) /* no physical connection */
- return 0;
-
- /* check sum */
- tmp = 0;
- for (i = 1; i < 16; i++) {
- if ((ass >> i) & 1)
- tmp++;
- }
- if (((ass >> 16) & 0xf) != tmp)
- return 0;
-do_sku:
- codec_dbg(codec, "realtek: Enabling init ASM_ID=0x%04x CODEC_ID=%08x\n",
- ass & 0xffff, codec->core.vendor_id);
- /*
- * 0 : override
- * 1 : Swap Jack
- * 2 : 0 --> Desktop, 1 --> Laptop
- * 3~5 : External Amplifier control
- * 7~6 : Reserved
- */
- tmp = (ass & 0x38) >> 3; /* external Amp control */
- if (spec->init_amp == ALC_INIT_UNDEFINED) {
- switch (tmp) {
- case 1:
- alc_setup_gpio(codec, 0x01);
- break;
- case 3:
- alc_setup_gpio(codec, 0x02);
- break;
- case 7:
- alc_setup_gpio(codec, 0x04);
- break;
- case 5:
- default:
- spec->init_amp = ALC_INIT_DEFAULT;
- break;
- }
- }
-
- /* is laptop or Desktop and enable the function "Mute internal speaker
- * when the external headphone out jack is plugged"
- */
- if (!(ass & 0x8000))
- return 1;
- /*
- * 10~8 : Jack location
- * 12~11: Headphone out -> 00: PortA, 01: PortE, 02: PortD, 03: Resvered
- * 14~13: Resvered
- * 15 : 1 --> enable the function "Mute internal speaker
- * when the external headphone out jack is plugged"
- */
- if (!alc_get_hp_pin(spec)) {
- hda_nid_t nid;
- tmp = (ass >> 11) & 0x3; /* HP to chassis */
- nid = ports[tmp];
- if (found_in_nid_list(nid, spec->gen.autocfg.line_out_pins,
- spec->gen.autocfg.line_outs))
- return 1;
- spec->gen.autocfg.hp_pins[0] = nid;
- }
- return 1;
-}
-
-/* Check the validity of ALC subsystem-id
- * ports contains an array of 4 pin NIDs for port-A, E, D and I */
-static void alc_ssid_check(struct hda_codec *codec, const hda_nid_t *ports)
-{
- if (!alc_subsystem_id(codec, ports)) {
- struct alc_spec *spec = codec->spec;
- if (spec->init_amp == ALC_INIT_UNDEFINED) {
- codec_dbg(codec,
- "realtek: Enable default setup for auto mode as fallback\n");
- spec->init_amp = ALC_INIT_DEFAULT;
- }
- }
-}
-
-/* inverted digital-mic */
-static void alc_fixup_inv_dmic(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->gen.inv_dmic_split = 1;
-}
-
-
-static int alc_build_controls(struct hda_codec *codec)
-{
- int err;
-
- err = snd_hda_gen_build_controls(codec);
- if (err < 0)
- return err;
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_BUILD);
- return 0;
-}
-
-
-/*
- * Common callbacks
- */
-
-static void alc_pre_init(struct hda_codec *codec)
-{
- alc_fill_eapd_coef(codec);
-}
-
-#define is_s3_resume(codec) \
- ((codec)->core.dev.power.power_state.event == PM_EVENT_RESUME)
-#define is_s4_resume(codec) \
- ((codec)->core.dev.power.power_state.event == PM_EVENT_RESTORE)
-#define is_s4_suspend(codec) \
- ((codec)->core.dev.power.power_state.event == PM_EVENT_FREEZE)
-
-static int alc_init(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- /* hibernation resume needs the full chip initialization */
- if (is_s4_resume(codec))
- alc_pre_init(codec);
-
- if (spec->init_hook)
- spec->init_hook(codec);
-
- spec->gen.skip_verbs = 1; /* applied in below */
- snd_hda_gen_init(codec);
- alc_fix_pll(codec);
- alc_auto_init_amp(codec, spec->init_amp);
- snd_hda_apply_verbs(codec); /* apply verbs here after own init */
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT);
-
- return 0;
-}
-
-/* forward declaration */
-static const struct component_master_ops comp_master_ops;
-
-static void alc_free(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- if (spec)
- hda_component_manager_free(&spec->comps, &comp_master_ops);
-
- snd_hda_gen_free(codec);
-}
-
-static inline void alc_shutup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- if (!snd_hda_get_bool_hint(codec, "shutup"))
- return; /* disabled explicitly by hints */
-
- if (spec && spec->shutup)
- spec->shutup(codec);
- else
- alc_shutup_pins(codec);
-}
-
-static void alc_power_eapd(struct hda_codec *codec)
-{
- alc_auto_setup_eapd(codec, false);
-}
-
-static int alc_suspend(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- alc_shutup(codec);
- if (spec && spec->power_hook)
- spec->power_hook(codec);
- return 0;
-}
-
-static int alc_resume(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- if (!spec->no_depop_delay)
- msleep(150); /* to avoid pop noise */
- codec->patch_ops.init(codec);
- snd_hda_regmap_sync(codec);
- hda_call_check_power_status(codec, 0x01);
- return 0;
-}
-
-/*
- */
-static const struct hda_codec_ops alc_patch_ops = {
- .build_controls = alc_build_controls,
- .build_pcms = snd_hda_gen_build_pcms,
- .init = alc_init,
- .free = alc_free,
- .unsol_event = snd_hda_jack_unsol_event,
- .resume = alc_resume,
- .suspend = alc_suspend,
- .check_power_status = snd_hda_gen_check_power_status,
-};
-
-
-#define alc_codec_rename(codec, name) snd_hda_codec_set_name(codec, name)
-
-/*
- * Rename codecs appropriately from COEF value or subvendor id
- */
-struct alc_codec_rename_table {
- unsigned int vendor_id;
- unsigned short coef_mask;
- unsigned short coef_bits;
- const char *name;
-};
-
-struct alc_codec_rename_pci_table {
- unsigned int codec_vendor_id;
- unsigned short pci_subvendor;
- unsigned short pci_subdevice;
- const char *name;
-};
-
-static const struct alc_codec_rename_table rename_tbl[] = {
- { 0x10ec0221, 0xf00f, 0x1003, "ALC231" },
- { 0x10ec0269, 0xfff0, 0x3010, "ALC277" },
- { 0x10ec0269, 0xf0f0, 0x2010, "ALC259" },
- { 0x10ec0269, 0xf0f0, 0x3010, "ALC258" },
- { 0x10ec0269, 0x00f0, 0x0010, "ALC269VB" },
- { 0x10ec0269, 0xffff, 0xa023, "ALC259" },
- { 0x10ec0269, 0xffff, 0x6023, "ALC281X" },
- { 0x10ec0269, 0x00f0, 0x0020, "ALC269VC" },
- { 0x10ec0269, 0x00f0, 0x0030, "ALC269VD" },
- { 0x10ec0662, 0xffff, 0x4020, "ALC656" },
- { 0x10ec0887, 0x00f0, 0x0030, "ALC887-VD" },
- { 0x10ec0888, 0x00f0, 0x0030, "ALC888-VD" },
- { 0x10ec0888, 0xf0f0, 0x3020, "ALC886" },
- { 0x10ec0899, 0x2000, 0x2000, "ALC899" },
- { 0x10ec0892, 0xffff, 0x8020, "ALC661" },
- { 0x10ec0892, 0xffff, 0x8011, "ALC661" },
- { 0x10ec0892, 0xffff, 0x4011, "ALC656" },
- { } /* terminator */
-};
-
-static const struct alc_codec_rename_pci_table rename_pci_tbl[] = {
- { 0x10ec0280, 0x1028, 0, "ALC3220" },
- { 0x10ec0282, 0x1028, 0, "ALC3221" },
- { 0x10ec0283, 0x1028, 0, "ALC3223" },
- { 0x10ec0288, 0x1028, 0, "ALC3263" },
- { 0x10ec0292, 0x1028, 0, "ALC3226" },
- { 0x10ec0293, 0x1028, 0, "ALC3235" },
- { 0x10ec0255, 0x1028, 0, "ALC3234" },
- { 0x10ec0668, 0x1028, 0, "ALC3661" },
- { 0x10ec0275, 0x1028, 0, "ALC3260" },
- { 0x10ec0899, 0x1028, 0, "ALC3861" },
- { 0x10ec0298, 0x1028, 0, "ALC3266" },
- { 0x10ec0236, 0x1028, 0, "ALC3204" },
- { 0x10ec0256, 0x1028, 0, "ALC3246" },
- { 0x10ec0225, 0x1028, 0, "ALC3253" },
- { 0x10ec0295, 0x1028, 0, "ALC3254" },
- { 0x10ec0299, 0x1028, 0, "ALC3271" },
- { 0x10ec0670, 0x1025, 0, "ALC669X" },
- { 0x10ec0676, 0x1025, 0, "ALC679X" },
- { 0x10ec0282, 0x1043, 0, "ALC3229" },
- { 0x10ec0233, 0x1043, 0, "ALC3236" },
- { 0x10ec0280, 0x103c, 0, "ALC3228" },
- { 0x10ec0282, 0x103c, 0, "ALC3227" },
- { 0x10ec0286, 0x103c, 0, "ALC3242" },
- { 0x10ec0290, 0x103c, 0, "ALC3241" },
- { 0x10ec0668, 0x103c, 0, "ALC3662" },
- { 0x10ec0283, 0x17aa, 0, "ALC3239" },
- { 0x10ec0292, 0x17aa, 0, "ALC3232" },
- { } /* terminator */
-};
-
-static int alc_codec_rename_from_preset(struct hda_codec *codec)
-{
- const struct alc_codec_rename_table *p;
- const struct alc_codec_rename_pci_table *q;
-
- for (p = rename_tbl; p->vendor_id; p++) {
- if (p->vendor_id != codec->core.vendor_id)
- continue;
- if ((alc_get_coef0(codec) & p->coef_mask) == p->coef_bits)
- return alc_codec_rename(codec, p->name);
- }
-
- if (!codec->bus->pci)
- return 0;
- for (q = rename_pci_tbl; q->codec_vendor_id; q++) {
- if (q->codec_vendor_id != codec->core.vendor_id)
- continue;
- if (q->pci_subvendor != codec->bus->pci->subsystem_vendor)
- continue;
- if (!q->pci_subdevice ||
- q->pci_subdevice == codec->bus->pci->subsystem_device)
- return alc_codec_rename(codec, q->name);
- }
-
- return 0;
-}
-
-
-/*
- * Digital-beep handlers
- */
-#ifdef CONFIG_SND_HDA_INPUT_BEEP
-
-/* additional beep mixers; private_value will be overwritten */
-static const struct snd_kcontrol_new alc_beep_mixer[] = {
- HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT),
- HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_INPUT),
-};
-
-/* set up and create beep controls */
-static int set_beep_amp(struct alc_spec *spec, hda_nid_t nid,
- int idx, int dir)
-{
- struct snd_kcontrol_new *knew;
- unsigned int beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir);
- int i;
-
- for (i = 0; i < ARRAY_SIZE(alc_beep_mixer); i++) {
- knew = snd_hda_gen_add_kctl(&spec->gen, NULL,
- &alc_beep_mixer[i]);
- if (!knew)
- return -ENOMEM;
- knew->private_value = beep_amp;
- }
- return 0;
-}
-
-static const struct snd_pci_quirk beep_allow_list[] = {
- SND_PCI_QUIRK(0x1043, 0x103c, "ASUS", 1),
- SND_PCI_QUIRK(0x1043, 0x115d, "ASUS", 1),
- SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1),
- SND_PCI_QUIRK(0x1043, 0x8376, "EeePC", 1),
- SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1),
- SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1),
- SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1),
- SND_PCI_QUIRK(0x1458, 0xa002, "GA-MA790X", 1),
- SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1),
- /* denylist -- no beep available */
- SND_PCI_QUIRK(0x17aa, 0x309e, "Lenovo ThinkCentre M73", 0),
- SND_PCI_QUIRK(0x17aa, 0x30a3, "Lenovo ThinkCentre M93", 0),
- {}
-};
-
-static inline int has_cdefine_beep(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- const struct snd_pci_quirk *q;
- q = snd_pci_quirk_lookup(codec->bus->pci, beep_allow_list);
- if (q)
- return q->value;
- return spec->cdefine.enable_pcbeep;
-}
-#else
-#define set_beep_amp(spec, nid, idx, dir) 0
-#define has_cdefine_beep(codec) 0
-#endif
-
-/* parse the BIOS configuration and set up the alc_spec */
-/* return 1 if successful, 0 if the proper config is not found,
- * or a negative error code
- */
-static int alc_parse_auto_config(struct hda_codec *codec,
- const hda_nid_t *ignore_nids,
- const hda_nid_t *ssid_nids)
-{
- struct alc_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->gen.autocfg;
- int err;
-
- err = snd_hda_parse_pin_defcfg(codec, cfg, ignore_nids,
- spec->parse_flags);
- if (err < 0)
- return err;
-
- if (ssid_nids)
- alc_ssid_check(codec, ssid_nids);
-
- err = snd_hda_gen_parse_auto_config(codec, cfg);
- if (err < 0)
- return err;
-
- return 1;
-}
-
-/* common preparation job for alc_spec */
-static int alc_alloc_spec(struct hda_codec *codec, hda_nid_t mixer_nid)
-{
- struct alc_spec *spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- int err;
-
- if (!spec)
- return -ENOMEM;
- codec->spec = spec;
- snd_hda_gen_spec_init(&spec->gen);
- spec->gen.mixer_nid = mixer_nid;
- spec->gen.own_eapd_ctl = 1;
- codec->single_adc_amp = 1;
- /* FIXME: do we need this for all Realtek codec models? */
- codec->spdif_status_reset = 1;
- codec->forced_resume = 1;
- codec->patch_ops = alc_patch_ops;
- mutex_init(&spec->coef_mutex);
-
- err = alc_codec_rename_from_preset(codec);
- if (err < 0) {
- kfree(spec);
- return err;
- }
- return 0;
-}
-
-static int alc880_parse_auto_config(struct hda_codec *codec)
-{
- static const hda_nid_t alc880_ignore[] = { 0x1d, 0 };
- static const hda_nid_t alc880_ssids[] = { 0x15, 0x1b, 0x14, 0 };
- return alc_parse_auto_config(codec, alc880_ignore, alc880_ssids);
-}
-
-/*
- * ALC880 fix-ups
- */
-enum {
- ALC880_FIXUP_GPIO1,
- ALC880_FIXUP_GPIO2,
- ALC880_FIXUP_MEDION_RIM,
- ALC880_FIXUP_LG,
- ALC880_FIXUP_LG_LW25,
- ALC880_FIXUP_W810,
- ALC880_FIXUP_EAPD_COEF,
- ALC880_FIXUP_TCL_S700,
- ALC880_FIXUP_VOL_KNOB,
- ALC880_FIXUP_FUJITSU,
- ALC880_FIXUP_F1734,
- ALC880_FIXUP_UNIWILL,
- ALC880_FIXUP_UNIWILL_DIG,
- ALC880_FIXUP_Z71V,
- ALC880_FIXUP_ASUS_W5A,
- ALC880_FIXUP_3ST_BASE,
- ALC880_FIXUP_3ST,
- ALC880_FIXUP_3ST_DIG,
- ALC880_FIXUP_5ST_BASE,
- ALC880_FIXUP_5ST,
- ALC880_FIXUP_5ST_DIG,
- ALC880_FIXUP_6ST_BASE,
- ALC880_FIXUP_6ST,
- ALC880_FIXUP_6ST_DIG,
- ALC880_FIXUP_6ST_AUTOMUTE,
-};
-
-/* enable the volume-knob widget support on NID 0x21 */
-static void alc880_fixup_vol_knob(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_PROBE)
- snd_hda_jack_detect_enable_callback(codec, 0x21,
- alc_update_knob_master);
-}
-
-static const struct hda_fixup alc880_fixups[] = {
- [ALC880_FIXUP_GPIO1] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_gpio1,
- },
- [ALC880_FIXUP_GPIO2] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_gpio2,
- },
- [ALC880_FIXUP_MEDION_RIM] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x3060 },
- { }
- },
- .chained = true,
- .chain_id = ALC880_FIXUP_GPIO2,
- },
- [ALC880_FIXUP_LG] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- /* disable bogus unused pins */
- { 0x16, 0x411111f0 },
- { 0x18, 0x411111f0 },
- { 0x1a, 0x411111f0 },
- { }
- }
- },
- [ALC880_FIXUP_LG_LW25] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1a, 0x0181344f }, /* line-in */
- { 0x1b, 0x0321403f }, /* headphone */
- { }
- }
- },
- [ALC880_FIXUP_W810] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- /* disable bogus unused pins */
- { 0x17, 0x411111f0 },
- { }
- },
- .chained = true,
- .chain_id = ALC880_FIXUP_GPIO2,
- },
- [ALC880_FIXUP_EAPD_COEF] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- /* change to EAPD mode */
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x3060 },
- {}
- },
- },
- [ALC880_FIXUP_TCL_S700] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- /* change to EAPD mode */
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x3070 },
- {}
- },
- .chained = true,
- .chain_id = ALC880_FIXUP_GPIO2,
- },
- [ALC880_FIXUP_VOL_KNOB] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc880_fixup_vol_knob,
- },
- [ALC880_FIXUP_FUJITSU] = {
- /* override all pins as BIOS on old Amilo is broken */
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x14, 0x0121401f }, /* HP */
- { 0x15, 0x99030120 }, /* speaker */
- { 0x16, 0x99030130 }, /* bass speaker */
- { 0x17, 0x411111f0 }, /* N/A */
- { 0x18, 0x411111f0 }, /* N/A */
- { 0x19, 0x01a19950 }, /* mic-in */
- { 0x1a, 0x411111f0 }, /* N/A */
- { 0x1b, 0x411111f0 }, /* N/A */
- { 0x1c, 0x411111f0 }, /* N/A */
- { 0x1d, 0x411111f0 }, /* N/A */
- { 0x1e, 0x01454140 }, /* SPDIF out */
- { }
- },
- .chained = true,
- .chain_id = ALC880_FIXUP_VOL_KNOB,
- },
- [ALC880_FIXUP_F1734] = {
- /* almost compatible with FUJITSU, but no bass and SPDIF */
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x14, 0x0121401f }, /* HP */
- { 0x15, 0x99030120 }, /* speaker */
- { 0x16, 0x411111f0 }, /* N/A */
- { 0x17, 0x411111f0 }, /* N/A */
- { 0x18, 0x411111f0 }, /* N/A */
- { 0x19, 0x01a19950 }, /* mic-in */
- { 0x1a, 0x411111f0 }, /* N/A */
- { 0x1b, 0x411111f0 }, /* N/A */
- { 0x1c, 0x411111f0 }, /* N/A */
- { 0x1d, 0x411111f0 }, /* N/A */
- { 0x1e, 0x411111f0 }, /* N/A */
- { }
- },
- .chained = true,
- .chain_id = ALC880_FIXUP_VOL_KNOB,
- },
- [ALC880_FIXUP_UNIWILL] = {
- /* need to fix HP and speaker pins to be parsed correctly */
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x14, 0x0121411f }, /* HP */
- { 0x15, 0x99030120 }, /* speaker */
- { 0x16, 0x99030130 }, /* bass speaker */
- { }
- },
- },
- [ALC880_FIXUP_UNIWILL_DIG] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- /* disable bogus unused pins */
- { 0x17, 0x411111f0 },
- { 0x19, 0x411111f0 },
- { 0x1b, 0x411111f0 },
- { 0x1f, 0x411111f0 },
- { }
- }
- },
- [ALC880_FIXUP_Z71V] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- /* set up the whole pins as BIOS is utterly broken */
- { 0x14, 0x99030120 }, /* speaker */
- { 0x15, 0x0121411f }, /* HP */
- { 0x16, 0x411111f0 }, /* N/A */
- { 0x17, 0x411111f0 }, /* N/A */
- { 0x18, 0x01a19950 }, /* mic-in */
- { 0x19, 0x411111f0 }, /* N/A */
- { 0x1a, 0x01813031 }, /* line-in */
- { 0x1b, 0x411111f0 }, /* N/A */
- { 0x1c, 0x411111f0 }, /* N/A */
- { 0x1d, 0x411111f0 }, /* N/A */
- { 0x1e, 0x0144111e }, /* SPDIF */
- { }
- }
- },
- [ALC880_FIXUP_ASUS_W5A] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- /* set up the whole pins as BIOS is utterly broken */
- { 0x14, 0x0121411f }, /* HP */
- { 0x15, 0x411111f0 }, /* N/A */
- { 0x16, 0x411111f0 }, /* N/A */
- { 0x17, 0x411111f0 }, /* N/A */
- { 0x18, 0x90a60160 }, /* mic */
- { 0x19, 0x411111f0 }, /* N/A */
- { 0x1a, 0x411111f0 }, /* N/A */
- { 0x1b, 0x411111f0 }, /* N/A */
- { 0x1c, 0x411111f0 }, /* N/A */
- { 0x1d, 0x411111f0 }, /* N/A */
- { 0x1e, 0xb743111e }, /* SPDIF out */
- { }
- },
- .chained = true,
- .chain_id = ALC880_FIXUP_GPIO1,
- },
- [ALC880_FIXUP_3ST_BASE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x14, 0x01014010 }, /* line-out */
- { 0x15, 0x411111f0 }, /* N/A */
- { 0x16, 0x411111f0 }, /* N/A */
- { 0x17, 0x411111f0 }, /* N/A */
- { 0x18, 0x01a19c30 }, /* mic-in */
- { 0x19, 0x0121411f }, /* HP */
- { 0x1a, 0x01813031 }, /* line-in */
- { 0x1b, 0x02a19c40 }, /* front-mic */
- { 0x1c, 0x411111f0 }, /* N/A */
- { 0x1d, 0x411111f0 }, /* N/A */
- /* 0x1e is filled in below */
- { 0x1f, 0x411111f0 }, /* N/A */
- { }
- }
- },
- [ALC880_FIXUP_3ST] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1e, 0x411111f0 }, /* N/A */
- { }
- },
- .chained = true,
- .chain_id = ALC880_FIXUP_3ST_BASE,
- },
- [ALC880_FIXUP_3ST_DIG] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1e, 0x0144111e }, /* SPDIF */
- { }
- },
- .chained = true,
- .chain_id = ALC880_FIXUP_3ST_BASE,
- },
- [ALC880_FIXUP_5ST_BASE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x14, 0x01014010 }, /* front */
- { 0x15, 0x411111f0 }, /* N/A */
- { 0x16, 0x01011411 }, /* CLFE */
- { 0x17, 0x01016412 }, /* surr */
- { 0x18, 0x01a19c30 }, /* mic-in */
- { 0x19, 0x0121411f }, /* HP */
- { 0x1a, 0x01813031 }, /* line-in */
- { 0x1b, 0x02a19c40 }, /* front-mic */
- { 0x1c, 0x411111f0 }, /* N/A */
- { 0x1d, 0x411111f0 }, /* N/A */
- /* 0x1e is filled in below */
- { 0x1f, 0x411111f0 }, /* N/A */
- { }
- }
- },
- [ALC880_FIXUP_5ST] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1e, 0x411111f0 }, /* N/A */
- { }
- },
- .chained = true,
- .chain_id = ALC880_FIXUP_5ST_BASE,
- },
- [ALC880_FIXUP_5ST_DIG] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1e, 0x0144111e }, /* SPDIF */
- { }
- },
- .chained = true,
- .chain_id = ALC880_FIXUP_5ST_BASE,
- },
- [ALC880_FIXUP_6ST_BASE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x14, 0x01014010 }, /* front */
- { 0x15, 0x01016412 }, /* surr */
- { 0x16, 0x01011411 }, /* CLFE */
- { 0x17, 0x01012414 }, /* side */
- { 0x18, 0x01a19c30 }, /* mic-in */
- { 0x19, 0x02a19c40 }, /* front-mic */
- { 0x1a, 0x01813031 }, /* line-in */
- { 0x1b, 0x0121411f }, /* HP */
- { 0x1c, 0x411111f0 }, /* N/A */
- { 0x1d, 0x411111f0 }, /* N/A */
- /* 0x1e is filled in below */
- { 0x1f, 0x411111f0 }, /* N/A */
- { }
- }
- },
- [ALC880_FIXUP_6ST] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1e, 0x411111f0 }, /* N/A */
- { }
- },
- .chained = true,
- .chain_id = ALC880_FIXUP_6ST_BASE,
- },
- [ALC880_FIXUP_6ST_DIG] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1e, 0x0144111e }, /* SPDIF */
- { }
- },
- .chained = true,
- .chain_id = ALC880_FIXUP_6ST_BASE,
- },
- [ALC880_FIXUP_6ST_AUTOMUTE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1b, 0x0121401f }, /* HP with jack detect */
- { }
- },
- .chained_before = true,
- .chain_id = ALC880_FIXUP_6ST_BASE,
- },
-};
-
-static const struct hda_quirk alc880_fixup_tbl[] = {
- SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_FIXUP_W810),
- SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS W5A", ALC880_FIXUP_ASUS_W5A),
- SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_FIXUP_Z71V),
- SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_FIXUP_GPIO1),
- SND_PCI_QUIRK(0x147b, 0x1045, "ABit AA8XE", ALC880_FIXUP_6ST_AUTOMUTE),
- SND_PCI_QUIRK(0x1558, 0x5401, "Clevo GPIO2", ALC880_FIXUP_GPIO2),
- SND_PCI_QUIRK_VENDOR(0x1558, "Clevo", ALC880_FIXUP_EAPD_COEF),
- SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_FIXUP_UNIWILL_DIG),
- SND_PCI_QUIRK(0x1584, 0x9054, "Uniwill", ALC880_FIXUP_F1734),
- SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_FIXUP_UNIWILL),
- SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_FIXUP_VOL_KNOB),
- SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_FIXUP_W810),
- SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_FIXUP_MEDION_RIM),
- SND_PCI_QUIRK(0x1631, 0xe011, "PB 13201056", ALC880_FIXUP_6ST_AUTOMUTE),
- SND_PCI_QUIRK(0x1734, 0x107c, "FSC Amilo M1437", ALC880_FIXUP_FUJITSU),
- SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FIXUP_FUJITSU),
- SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_FIXUP_F1734),
- SND_PCI_QUIRK(0x1734, 0x10b0, "FSC Amilo Pi1556", ALC880_FIXUP_FUJITSU),
- SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_FIXUP_LG),
- SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_FIXUP_LG),
- SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_FIXUP_LG),
- SND_PCI_QUIRK(0x1854, 0x0077, "LG LW25", ALC880_FIXUP_LG_LW25),
- SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_FIXUP_TCL_S700),
-
- /* Below is the copied entries from alc880_quirks.c.
- * It's not quite sure whether BIOS sets the correct pin-config table
- * on these machines, thus they are kept to be compatible with
- * the old static quirks. Once when it's confirmed to work without
- * these overrides, it'd be better to remove.
- */
- SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_FIXUP_5ST_DIG),
- SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_FIXUP_6ST),
- SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_FIXUP_3ST_DIG),
- SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_FIXUP_6ST_DIG),
- SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_FIXUP_6ST_DIG),
- SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_FIXUP_6ST_DIG),
- SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_FIXUP_3ST_DIG),
- SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_FIXUP_3ST),
- SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_FIXUP_6ST_DIG),
- SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_FIXUP_3ST),
- SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_FIXUP_3ST),
- SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_FIXUP_5ST),
- SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_FIXUP_5ST),
- SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_FIXUP_5ST),
- SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_FIXUP_6ST_DIG),
- SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_FIXUP_6ST_DIG),
- SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_FIXUP_6ST_DIG),
- SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_FIXUP_6ST_DIG),
- SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_FIXUP_5ST_DIG),
- SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_FIXUP_5ST_DIG),
- SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_FIXUP_5ST_DIG),
- SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_FIXUP_6ST_DIG), /* broken BIOS */
- SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_FIXUP_6ST_DIG),
- SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_FIXUP_5ST_DIG),
- SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_FIXUP_5ST_DIG),
- SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_FIXUP_5ST_DIG),
- SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_FIXUP_3ST_DIG),
- SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_FIXUP_5ST_DIG),
- SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_FIXUP_3ST_DIG),
- SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_FIXUP_3ST_DIG),
- SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_FIXUP_5ST_DIG),
- SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_FIXUP_5ST_DIG),
- SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_FIXUP_5ST_DIG),
- /* default Intel */
- SND_PCI_QUIRK_VENDOR(0x8086, "Intel mobo", ALC880_FIXUP_3ST),
- SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_FIXUP_5ST_DIG),
- SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_FIXUP_6ST_DIG),
- {}
-};
-
-static const struct hda_model_fixup alc880_fixup_models[] = {
- {.id = ALC880_FIXUP_3ST, .name = "3stack"},
- {.id = ALC880_FIXUP_3ST_DIG, .name = "3stack-digout"},
- {.id = ALC880_FIXUP_5ST, .name = "5stack"},
- {.id = ALC880_FIXUP_5ST_DIG, .name = "5stack-digout"},
- {.id = ALC880_FIXUP_6ST, .name = "6stack"},
- {.id = ALC880_FIXUP_6ST_DIG, .name = "6stack-digout"},
- {.id = ALC880_FIXUP_6ST_AUTOMUTE, .name = "6stack-automute"},
- {}
-};
-
-
-/*
- * OK, here we have finally the patch for ALC880
- */
-static int patch_alc880(struct hda_codec *codec)
-{
- struct alc_spec *spec;
- int err;
-
- err = alc_alloc_spec(codec, 0x0b);
- if (err < 0)
- return err;
-
- spec = codec->spec;
- spec->gen.need_dac_fix = 1;
- spec->gen.beep_nid = 0x01;
-
- codec->patch_ops.unsol_event = alc880_unsol_event;
-
- alc_pre_init(codec);
-
- snd_hda_pick_fixup(codec, alc880_fixup_models, alc880_fixup_tbl,
- alc880_fixups);
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
-
- /* automatic parse from the BIOS config */
- err = alc880_parse_auto_config(codec);
- if (err < 0)
- goto error;
-
- if (!spec->gen.no_analog) {
- err = set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
- if (err < 0)
- goto error;
- }
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
-
- return 0;
-
- error:
- alc_free(codec);
- return err;
-}
-
-
-/*
- * ALC260 support
- */
-static int alc260_parse_auto_config(struct hda_codec *codec)
-{
- static const hda_nid_t alc260_ignore[] = { 0x17, 0 };
- static const hda_nid_t alc260_ssids[] = { 0x10, 0x15, 0x0f, 0 };
- return alc_parse_auto_config(codec, alc260_ignore, alc260_ssids);
-}
-
-/*
- * Pin config fixes
- */
-enum {
- ALC260_FIXUP_HP_DC5750,
- ALC260_FIXUP_HP_PIN_0F,
- ALC260_FIXUP_COEF,
- ALC260_FIXUP_GPIO1,
- ALC260_FIXUP_GPIO1_TOGGLE,
- ALC260_FIXUP_REPLACER,
- ALC260_FIXUP_HP_B1900,
- ALC260_FIXUP_KN1,
- ALC260_FIXUP_FSC_S7020,
- ALC260_FIXUP_FSC_S7020_JWSE,
- ALC260_FIXUP_VAIO_PINS,
-};
-
-static void alc260_gpio1_automute(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- alc_update_gpio_data(codec, 0x01, spec->gen.hp_jack_present);
-}
-
-static void alc260_fixup_gpio1_toggle(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
- if (action == HDA_FIXUP_ACT_PROBE) {
- /* although the machine has only one output pin, we need to
- * toggle GPIO1 according to the jack state
- */
- spec->gen.automute_hook = alc260_gpio1_automute;
- spec->gen.detect_hp = 1;
- spec->gen.automute_speaker = 1;
- spec->gen.autocfg.hp_pins[0] = 0x0f; /* copy it for automute */
- snd_hda_jack_detect_enable_callback(codec, 0x0f,
- snd_hda_gen_hp_automute);
- alc_setup_gpio(codec, 0x01);
- }
-}
-
-static void alc260_fixup_kn1(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
- static const struct hda_pintbl pincfgs[] = {
- { 0x0f, 0x02214000 }, /* HP/speaker */
- { 0x12, 0x90a60160 }, /* int mic */
- { 0x13, 0x02a19000 }, /* ext mic */
- { 0x18, 0x01446000 }, /* SPDIF out */
- /* disable bogus I/O pins */
- { 0x10, 0x411111f0 },
- { 0x11, 0x411111f0 },
- { 0x14, 0x411111f0 },
- { 0x15, 0x411111f0 },
- { 0x16, 0x411111f0 },
- { 0x17, 0x411111f0 },
- { 0x19, 0x411111f0 },
- { }
- };
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- snd_hda_apply_pincfgs(codec, pincfgs);
- spec->init_amp = ALC_INIT_NONE;
- break;
- }
-}
-
-static void alc260_fixup_fsc_s7020(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
- if (action == HDA_FIXUP_ACT_PRE_PROBE)
- spec->init_amp = ALC_INIT_NONE;
-}
-
-static void alc260_fixup_fsc_s7020_jwse(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->gen.add_jack_modes = 1;
- spec->gen.hp_mic = 1;
- }
-}
-
-static const struct hda_fixup alc260_fixups[] = {
- [ALC260_FIXUP_HP_DC5750] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x11, 0x90130110 }, /* speaker */
- { }
- }
- },
- [ALC260_FIXUP_HP_PIN_0F] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x0f, 0x01214000 }, /* HP */
- { }
- }
- },
- [ALC260_FIXUP_COEF] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- { 0x1a, AC_VERB_SET_COEF_INDEX, 0x07 },
- { 0x1a, AC_VERB_SET_PROC_COEF, 0x3040 },
- { }
- },
- },
- [ALC260_FIXUP_GPIO1] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_gpio1,
- },
- [ALC260_FIXUP_GPIO1_TOGGLE] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc260_fixup_gpio1_toggle,
- .chained = true,
- .chain_id = ALC260_FIXUP_HP_PIN_0F,
- },
- [ALC260_FIXUP_REPLACER] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- { 0x1a, AC_VERB_SET_COEF_INDEX, 0x07 },
- { 0x1a, AC_VERB_SET_PROC_COEF, 0x3050 },
- { }
- },
- .chained = true,
- .chain_id = ALC260_FIXUP_GPIO1_TOGGLE,
- },
- [ALC260_FIXUP_HP_B1900] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc260_fixup_gpio1_toggle,
- .chained = true,
- .chain_id = ALC260_FIXUP_COEF,
- },
- [ALC260_FIXUP_KN1] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc260_fixup_kn1,
- },
- [ALC260_FIXUP_FSC_S7020] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc260_fixup_fsc_s7020,
- },
- [ALC260_FIXUP_FSC_S7020_JWSE] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc260_fixup_fsc_s7020_jwse,
- .chained = true,
- .chain_id = ALC260_FIXUP_FSC_S7020,
- },
- [ALC260_FIXUP_VAIO_PINS] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- /* Pin configs are missing completely on some VAIOs */
- { 0x0f, 0x01211020 },
- { 0x10, 0x0001003f },
- { 0x11, 0x411111f0 },
- { 0x12, 0x01a15930 },
- { 0x13, 0x411111f0 },
- { 0x14, 0x411111f0 },
- { 0x15, 0x411111f0 },
- { 0x16, 0x411111f0 },
- { 0x17, 0x411111f0 },
- { 0x18, 0x411111f0 },
- { 0x19, 0x411111f0 },
- { }
- }
- },
-};
-
-static const struct hda_quirk alc260_fixup_tbl[] = {
- SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_FIXUP_GPIO1),
- SND_PCI_QUIRK(0x1025, 0x007f, "Acer Aspire 9500", ALC260_FIXUP_COEF),
- SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_FIXUP_GPIO1),
- SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", ALC260_FIXUP_HP_DC5750),
- SND_PCI_QUIRK(0x103c, 0x30ba, "HP Presario B1900", ALC260_FIXUP_HP_B1900),
- SND_PCI_QUIRK(0x104d, 0x81bb, "Sony VAIO", ALC260_FIXUP_VAIO_PINS),
- SND_PCI_QUIRK(0x104d, 0x81e2, "Sony VAIO TX", ALC260_FIXUP_HP_PIN_0F),
- SND_PCI_QUIRK(0x10cf, 0x1326, "FSC LifeBook S7020", ALC260_FIXUP_FSC_S7020),
- SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FIXUP_GPIO1),
- SND_PCI_QUIRK(0x152d, 0x0729, "Quanta KN1", ALC260_FIXUP_KN1),
- SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_FIXUP_REPLACER),
- SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_FIXUP_COEF),
- {}
-};
-
-static const struct hda_model_fixup alc260_fixup_models[] = {
- {.id = ALC260_FIXUP_GPIO1, .name = "gpio1"},
- {.id = ALC260_FIXUP_COEF, .name = "coef"},
- {.id = ALC260_FIXUP_FSC_S7020, .name = "fujitsu"},
- {.id = ALC260_FIXUP_FSC_S7020_JWSE, .name = "fujitsu-jwse"},
- {}
-};
-
-/*
- */
-static int patch_alc260(struct hda_codec *codec)
-{
- struct alc_spec *spec;
- int err;
-
- err = alc_alloc_spec(codec, 0x07);
- if (err < 0)
- return err;
-
- spec = codec->spec;
- /* as quite a few machines require HP amp for speaker outputs,
- * it's easier to enable it unconditionally; even if it's unneeded,
- * it's almost harmless.
- */
- spec->gen.prefer_hp_amp = 1;
- spec->gen.beep_nid = 0x01;
-
- spec->shutup = alc_eapd_shutup;
-
- alc_pre_init(codec);
-
- snd_hda_pick_fixup(codec, alc260_fixup_models, alc260_fixup_tbl,
- alc260_fixups);
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
-
- /* automatic parse from the BIOS config */
- err = alc260_parse_auto_config(codec);
- if (err < 0)
- goto error;
-
- if (!spec->gen.no_analog) {
- err = set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
- if (err < 0)
- goto error;
- }
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
-
- return 0;
-
- error:
- alc_free(codec);
- return err;
-}
-
-
-/*
- * ALC882/883/885/888/889 support
- *
- * ALC882 is almost identical with ALC880 but has cleaner and more flexible
- * configuration. Each pin widget can choose any input DACs and a mixer.
- * Each ADC is connected from a mixer of all inputs. This makes possible
- * 6-channel independent captures.
- *
- * In addition, an independent DAC for the multi-playback (not used in this
- * driver yet).
- */
-
-/*
- * Pin config fixes
- */
-enum {
- ALC882_FIXUP_ABIT_AW9D_MAX,
- ALC882_FIXUP_LENOVO_Y530,
- ALC882_FIXUP_PB_M5210,
- ALC882_FIXUP_ACER_ASPIRE_7736,
- ALC882_FIXUP_ASUS_W90V,
- ALC889_FIXUP_CD,
- ALC889_FIXUP_FRONT_HP_NO_PRESENCE,
- ALC889_FIXUP_VAIO_TT,
- ALC888_FIXUP_EEE1601,
- ALC886_FIXUP_EAPD,
- ALC882_FIXUP_EAPD,
- ALC883_FIXUP_EAPD,
- ALC883_FIXUP_ACER_EAPD,
- ALC882_FIXUP_GPIO1,
- ALC882_FIXUP_GPIO2,
- ALC882_FIXUP_GPIO3,
- ALC889_FIXUP_COEF,
- ALC882_FIXUP_ASUS_W2JC,
- ALC882_FIXUP_ACER_ASPIRE_4930G,
- ALC882_FIXUP_ACER_ASPIRE_8930G,
- ALC882_FIXUP_ASPIRE_8930G_VERBS,
- ALC885_FIXUP_MACPRO_GPIO,
- ALC889_FIXUP_DAC_ROUTE,
- ALC889_FIXUP_MBP_VREF,
- ALC889_FIXUP_IMAC91_VREF,
- ALC889_FIXUP_MBA11_VREF,
- ALC889_FIXUP_MBA21_VREF,
- ALC889_FIXUP_MP11_VREF,
- ALC889_FIXUP_MP41_VREF,
- ALC882_FIXUP_INV_DMIC,
- ALC882_FIXUP_NO_PRIMARY_HP,
- ALC887_FIXUP_ASUS_BASS,
- ALC887_FIXUP_BASS_CHMAP,
- ALC1220_FIXUP_GB_DUAL_CODECS,
- ALC1220_FIXUP_GB_X570,
- ALC1220_FIXUP_CLEVO_P950,
- ALC1220_FIXUP_CLEVO_PB51ED,
- ALC1220_FIXUP_CLEVO_PB51ED_PINS,
- ALC887_FIXUP_ASUS_AUDIO,
- ALC887_FIXUP_ASUS_HMIC,
- ALCS1200A_FIXUP_MIC_VREF,
- ALC888VD_FIXUP_MIC_100VREF,
-};
-
-static void alc889_fixup_coef(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action != HDA_FIXUP_ACT_INIT)
- return;
- alc_update_coef_idx(codec, 7, 0, 0x2030);
-}
-
-/* set up GPIO at initialization */
-static void alc885_fixup_macpro_gpio(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->gpio_write_delay = true;
- alc_fixup_gpio3(codec, fix, action);
-}
-
-/* Fix the connection of some pins for ALC889:
- * At least, Acer Aspire 5935 shows the connections to DAC3/4 don't
- * work correctly (bko#42740)
- */
-static void alc889_fixup_dac_route(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- /* fake the connections during parsing the tree */
- static const hda_nid_t conn1[] = { 0x0c, 0x0d };
- static const hda_nid_t conn2[] = { 0x0e, 0x0f };
- snd_hda_override_conn_list(codec, 0x14, ARRAY_SIZE(conn1), conn1);
- snd_hda_override_conn_list(codec, 0x15, ARRAY_SIZE(conn1), conn1);
- snd_hda_override_conn_list(codec, 0x18, ARRAY_SIZE(conn2), conn2);
- snd_hda_override_conn_list(codec, 0x1a, ARRAY_SIZE(conn2), conn2);
- } else if (action == HDA_FIXUP_ACT_PROBE) {
- /* restore the connections */
- static const hda_nid_t conn[] = { 0x0c, 0x0d, 0x0e, 0x0f, 0x26 };
- snd_hda_override_conn_list(codec, 0x14, ARRAY_SIZE(conn), conn);
- snd_hda_override_conn_list(codec, 0x15, ARRAY_SIZE(conn), conn);
- snd_hda_override_conn_list(codec, 0x18, ARRAY_SIZE(conn), conn);
- snd_hda_override_conn_list(codec, 0x1a, ARRAY_SIZE(conn), conn);
- }
-}
-
-/* Set VREF on HP pin */
-static void alc889_fixup_mbp_vref(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- static const hda_nid_t nids[] = { 0x14, 0x15, 0x19 };
- struct alc_spec *spec = codec->spec;
- int i;
-
- if (action != HDA_FIXUP_ACT_INIT)
- return;
- for (i = 0; i < ARRAY_SIZE(nids); i++) {
- unsigned int val = snd_hda_codec_get_pincfg(codec, nids[i]);
- if (get_defcfg_device(val) != AC_JACK_HP_OUT)
- continue;
- val = snd_hda_codec_get_pin_target(codec, nids[i]);
- val |= AC_PINCTL_VREF_80;
- snd_hda_set_pin_ctl(codec, nids[i], val);
- spec->gen.keep_vref_in_automute = 1;
- break;
- }
-}
-
-static void alc889_fixup_mac_pins(struct hda_codec *codec,
- const hda_nid_t *nids, int num_nids)
-{
- struct alc_spec *spec = codec->spec;
- int i;
-
- for (i = 0; i < num_nids; i++) {
- unsigned int val;
- val = snd_hda_codec_get_pin_target(codec, nids[i]);
- val |= AC_PINCTL_VREF_50;
- snd_hda_set_pin_ctl(codec, nids[i], val);
- }
- spec->gen.keep_vref_in_automute = 1;
-}
-
-/* Set VREF on speaker pins on imac91 */
-static void alc889_fixup_imac91_vref(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- static const hda_nid_t nids[] = { 0x18, 0x1a };
-
- if (action == HDA_FIXUP_ACT_INIT)
- alc889_fixup_mac_pins(codec, nids, ARRAY_SIZE(nids));
-}
-
-/* Set VREF on speaker pins on mba11 */
-static void alc889_fixup_mba11_vref(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- static const hda_nid_t nids[] = { 0x18 };
-
- if (action == HDA_FIXUP_ACT_INIT)
- alc889_fixup_mac_pins(codec, nids, ARRAY_SIZE(nids));
-}
-
-/* Set VREF on speaker pins on mba21 */
-static void alc889_fixup_mba21_vref(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- static const hda_nid_t nids[] = { 0x18, 0x19 };
-
- if (action == HDA_FIXUP_ACT_INIT)
- alc889_fixup_mac_pins(codec, nids, ARRAY_SIZE(nids));
-}
-
-/* Don't take HP output as primary
- * Strangely, the speaker output doesn't work on Vaio Z and some Vaio
- * all-in-one desktop PCs (for example VGC-LN51JGB) through DAC 0x05
- */
-static void alc882_fixup_no_primary_hp(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->gen.no_primary_hp = 1;
- spec->gen.no_multi_io = 1;
- }
-}
-
-static void alc_fixup_bass_chmap(struct hda_codec *codec,
- const struct hda_fixup *fix, int action);
-
-/* For dual-codec configuration, we need to disable some features to avoid
- * conflicts of kctls and PCM streams
- */
-static void alc_fixup_dual_codecs(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
-
- if (action != HDA_FIXUP_ACT_PRE_PROBE)
- return;
- /* disable vmaster */
- spec->gen.suppress_vmaster = 1;
- /* auto-mute and auto-mic switch don't work with multiple codecs */
- spec->gen.suppress_auto_mute = 1;
- spec->gen.suppress_auto_mic = 1;
- /* disable aamix as well */
- spec->gen.mixer_nid = 0;
- /* add location prefix to avoid conflicts */
- codec->force_pin_prefix = 1;
-}
-
-static void rename_ctl(struct hda_codec *codec, const char *oldname,
- const char *newname)
-{
- struct snd_kcontrol *kctl;
-
- kctl = snd_hda_find_mixer_ctl(codec, oldname);
- if (kctl)
- snd_ctl_rename(codec->card, kctl, newname);
-}
-
-static void alc1220_fixup_gb_dual_codecs(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- alc_fixup_dual_codecs(codec, fix, action);
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- /* override card longname to provide a unique UCM profile */
- strcpy(codec->card->longname, "HDAudio-Gigabyte-ALC1220DualCodecs");
- break;
- case HDA_FIXUP_ACT_BUILD:
- /* rename Capture controls depending on the codec */
- rename_ctl(codec, "Capture Volume",
- codec->addr == 0 ?
- "Rear-Panel Capture Volume" :
- "Front-Panel Capture Volume");
- rename_ctl(codec, "Capture Switch",
- codec->addr == 0 ?
- "Rear-Panel Capture Switch" :
- "Front-Panel Capture Switch");
- break;
- }
-}
-
-static void alc1220_fixup_gb_x570(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- static const hda_nid_t conn1[] = { 0x0c };
- static const struct coef_fw gb_x570_coefs[] = {
- WRITE_COEF(0x07, 0x03c0),
- WRITE_COEF(0x1a, 0x01c1),
- WRITE_COEF(0x1b, 0x0202),
- WRITE_COEF(0x43, 0x3005),
- {}
- };
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- snd_hda_override_conn_list(codec, 0x14, ARRAY_SIZE(conn1), conn1);
- snd_hda_override_conn_list(codec, 0x1b, ARRAY_SIZE(conn1), conn1);
- break;
- case HDA_FIXUP_ACT_INIT:
- alc_process_coef_fw(codec, gb_x570_coefs);
- break;
- }
-}
-
-static void alc1220_fixup_clevo_p950(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- static const hda_nid_t conn1[] = { 0x0c };
-
- if (action != HDA_FIXUP_ACT_PRE_PROBE)
- return;
-
- alc_update_coef_idx(codec, 0x7, 0, 0x3c3);
- /* We therefore want to make sure 0x14 (front headphone) and
- * 0x1b (speakers) use the stereo DAC 0x02
- */
- snd_hda_override_conn_list(codec, 0x14, ARRAY_SIZE(conn1), conn1);
- snd_hda_override_conn_list(codec, 0x1b, ARRAY_SIZE(conn1), conn1);
-}
-
-static void alc_fixup_headset_mode_no_hp_mic(struct hda_codec *codec,
- const struct hda_fixup *fix, int action);
-
-static void alc1220_fixup_clevo_pb51ed(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- alc1220_fixup_clevo_p950(codec, fix, action);
- alc_fixup_headset_mode_no_hp_mic(codec, fix, action);
-}
-
-static void alc887_asus_hp_automute_hook(struct hda_codec *codec,
- struct hda_jack_callback *jack)
-{
- struct alc_spec *spec = codec->spec;
- unsigned int vref;
-
- snd_hda_gen_hp_automute(codec, jack);
-
- if (spec->gen.hp_jack_present)
- vref = AC_PINCTL_VREF_80;
- else
- vref = AC_PINCTL_VREF_HIZ;
- snd_hda_set_pin_ctl(codec, 0x19, PIN_HP | vref);
-}
-
-static void alc887_fixup_asus_jack(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
- if (action != HDA_FIXUP_ACT_PROBE)
- return;
- snd_hda_set_pin_ctl_cache(codec, 0x1b, PIN_HP);
- spec->gen.hp_automute_hook = alc887_asus_hp_automute_hook;
-}
-
-static const struct hda_fixup alc882_fixups[] = {
- [ALC882_FIXUP_ABIT_AW9D_MAX] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x15, 0x01080104 }, /* side */
- { 0x16, 0x01011012 }, /* rear */
- { 0x17, 0x01016011 }, /* clfe */
- { }
- }
- },
- [ALC882_FIXUP_LENOVO_Y530] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x15, 0x99130112 }, /* rear int speakers */
- { 0x16, 0x99130111 }, /* subwoofer */
- { }
- }
- },
- [ALC882_FIXUP_PB_M5210] = {
- .type = HDA_FIXUP_PINCTLS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, PIN_VREF50 },
- {}
- }
- },
- [ALC882_FIXUP_ACER_ASPIRE_7736] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_sku_ignore,
- },
- [ALC882_FIXUP_ASUS_W90V] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x16, 0x99130110 }, /* fix sequence for CLFE */
- { }
- }
- },
- [ALC889_FIXUP_CD] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1c, 0x993301f0 }, /* CD */
- { }
- }
- },
- [ALC889_FIXUP_FRONT_HP_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1b, 0x02214120 }, /* Front HP jack is flaky, disable jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC889_FIXUP_CD,
- },
- [ALC889_FIXUP_VAIO_TT] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x17, 0x90170111 }, /* hidden surround speaker */
- { }
- }
- },
- [ALC888_FIXUP_EEE1601] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x0b },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0838 },
- { }
- }
- },
- [ALC886_FIXUP_EAPD] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- /* change to EAPD mode */
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0068 },
- { }
- }
- },
- [ALC882_FIXUP_EAPD] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- /* change to EAPD mode */
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x3060 },
- { }
- }
- },
- [ALC883_FIXUP_EAPD] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- /* change to EAPD mode */
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x3070 },
- { }
- }
- },
- [ALC883_FIXUP_ACER_EAPD] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- /* eanable EAPD on Acer laptops */
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 },
- { }
- }
- },
- [ALC882_FIXUP_GPIO1] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_gpio1,
- },
- [ALC882_FIXUP_GPIO2] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_gpio2,
- },
- [ALC882_FIXUP_GPIO3] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_gpio3,
- },
- [ALC882_FIXUP_ASUS_W2JC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_gpio1,
- .chained = true,
- .chain_id = ALC882_FIXUP_EAPD,
- },
- [ALC889_FIXUP_COEF] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc889_fixup_coef,
- },
- [ALC882_FIXUP_ACER_ASPIRE_4930G] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x16, 0x99130111 }, /* CLFE speaker */
- { 0x17, 0x99130112 }, /* surround speaker */
- { }
- },
- .chained = true,
- .chain_id = ALC882_FIXUP_GPIO1,
- },
- [ALC882_FIXUP_ACER_ASPIRE_8930G] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x16, 0x99130111 }, /* CLFE speaker */
- { 0x1b, 0x99130112 }, /* surround speaker */
- { }
- },
- .chained = true,
- .chain_id = ALC882_FIXUP_ASPIRE_8930G_VERBS,
- },
- [ALC882_FIXUP_ASPIRE_8930G_VERBS] = {
- /* additional init verbs for Acer Aspire 8930G */
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- /* Enable all DACs */
- /* DAC DISABLE/MUTE 1? */
- /* setting bits 1-5 disables DAC nids 0x02-0x06
- * apparently. Init=0x38 */
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x03 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
- /* DAC DISABLE/MUTE 2? */
- /* some bit here disables the other DACs.
- * Init=0x4900 */
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x08 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
- /* DMIC fix
- * This laptop has a stereo digital microphone.
- * The mics are only 1cm apart which makes the stereo
- * useless. However, either the mic or the ALC889
- * makes the signal become a difference/sum signal
- * instead of standard stereo, which is annoying.
- * So instead we flip this bit which makes the
- * codec replicate the sum signal to both channels,
- * turning it into a normal mono mic.
- */
- /* DMIC_CONTROL? Init value = 0x0001 */
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x0b },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0003 },
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 },
- { }
- },
- .chained = true,
- .chain_id = ALC882_FIXUP_GPIO1,
- },
- [ALC885_FIXUP_MACPRO_GPIO] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc885_fixup_macpro_gpio,
- },
- [ALC889_FIXUP_DAC_ROUTE] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc889_fixup_dac_route,
- },
- [ALC889_FIXUP_MBP_VREF] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc889_fixup_mbp_vref,
- .chained = true,
- .chain_id = ALC882_FIXUP_GPIO1,
- },
- [ALC889_FIXUP_IMAC91_VREF] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc889_fixup_imac91_vref,
- .chained = true,
- .chain_id = ALC882_FIXUP_GPIO1,
- },
- [ALC889_FIXUP_MBA11_VREF] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc889_fixup_mba11_vref,
- .chained = true,
- .chain_id = ALC889_FIXUP_MBP_VREF,
- },
- [ALC889_FIXUP_MBA21_VREF] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc889_fixup_mba21_vref,
- .chained = true,
- .chain_id = ALC889_FIXUP_MBP_VREF,
- },
- [ALC889_FIXUP_MP11_VREF] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc889_fixup_mba11_vref,
- .chained = true,
- .chain_id = ALC885_FIXUP_MACPRO_GPIO,
- },
- [ALC889_FIXUP_MP41_VREF] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc889_fixup_mbp_vref,
- .chained = true,
- .chain_id = ALC885_FIXUP_MACPRO_GPIO,
- },
- [ALC882_FIXUP_INV_DMIC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_inv_dmic,
- },
- [ALC882_FIXUP_NO_PRIMARY_HP] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc882_fixup_no_primary_hp,
- },
- [ALC887_FIXUP_ASUS_BASS] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- {0x16, 0x99130130}, /* bass speaker */
- {}
- },
- .chained = true,
- .chain_id = ALC887_FIXUP_BASS_CHMAP,
- },
- [ALC887_FIXUP_BASS_CHMAP] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_bass_chmap,
- },
- [ALC1220_FIXUP_GB_DUAL_CODECS] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc1220_fixup_gb_dual_codecs,
- },
- [ALC1220_FIXUP_GB_X570] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc1220_fixup_gb_x570,
- },
- [ALC1220_FIXUP_CLEVO_P950] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc1220_fixup_clevo_p950,
- },
- [ALC1220_FIXUP_CLEVO_PB51ED] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc1220_fixup_clevo_pb51ed,
- },
- [ALC1220_FIXUP_CLEVO_PB51ED_PINS] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
- {}
- },
- .chained = true,
- .chain_id = ALC1220_FIXUP_CLEVO_PB51ED,
- },
- [ALC887_FIXUP_ASUS_AUDIO] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x15, 0x02a14150 }, /* use as headset mic, without its own jack detect */
- { 0x19, 0x22219420 },
- {}
- },
- },
- [ALC887_FIXUP_ASUS_HMIC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc887_fixup_asus_jack,
- .chained = true,
- .chain_id = ALC887_FIXUP_ASUS_AUDIO,
- },
- [ALCS1200A_FIXUP_MIC_VREF] = {
- .type = HDA_FIXUP_PINCTLS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x18, PIN_VREF50 }, /* rear mic */
- { 0x19, PIN_VREF50 }, /* front mic */
- {}
- }
- },
- [ALC888VD_FIXUP_MIC_100VREF] = {
- .type = HDA_FIXUP_PINCTLS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x18, PIN_VREF100 }, /* headset mic */
- {}
- }
- },
-};
-
-static const struct hda_quirk alc882_fixup_tbl[] = {
- SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_FIXUP_ACER_EAPD),
- SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_FIXUP_ACER_EAPD),
- SND_PCI_QUIRK(0x1025, 0x0107, "Acer Aspire", ALC883_FIXUP_ACER_EAPD),
- SND_PCI_QUIRK(0x1025, 0x010a, "Acer Ferrari 5000", ALC883_FIXUP_ACER_EAPD),
- SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_FIXUP_ACER_EAPD),
- SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_FIXUP_ACER_EAPD),
- SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_FIXUP_ACER_EAPD),
- SND_PCI_QUIRK(0x1025, 0x013e, "Acer Aspire 4930G",
- ALC882_FIXUP_ACER_ASPIRE_4930G),
- SND_PCI_QUIRK(0x1025, 0x013f, "Acer Aspire 5930G",
- ALC882_FIXUP_ACER_ASPIRE_4930G),
- SND_PCI_QUIRK(0x1025, 0x0145, "Acer Aspire 8930G",
- ALC882_FIXUP_ACER_ASPIRE_8930G),
- SND_PCI_QUIRK(0x1025, 0x0146, "Acer Aspire 6935G",
- ALC882_FIXUP_ACER_ASPIRE_8930G),
- SND_PCI_QUIRK(0x1025, 0x0142, "Acer Aspire 7730G",
- ALC882_FIXUP_ACER_ASPIRE_4930G),
- SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", ALC882_FIXUP_PB_M5210),
- SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G",
- ALC882_FIXUP_ACER_ASPIRE_4930G),
- SND_PCI_QUIRK(0x1025, 0x0166, "Acer Aspire 6530G",
- ALC882_FIXUP_ACER_ASPIRE_4930G),
- SND_PCI_QUIRK(0x1025, 0x021e, "Acer Aspire 5739G",
- ALC882_FIXUP_ACER_ASPIRE_4930G),
- SND_PCI_QUIRK(0x1025, 0x0259, "Acer Aspire 5935", ALC889_FIXUP_DAC_ROUTE),
- SND_PCI_QUIRK(0x1025, 0x026b, "Acer Aspire 8940G", ALC882_FIXUP_ACER_ASPIRE_8930G),
- SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", ALC882_FIXUP_ACER_ASPIRE_7736),
- SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_FIXUP_EAPD),
- SND_PCI_QUIRK(0x1043, 0x1873, "ASUS W90V", ALC882_FIXUP_ASUS_W90V),
- SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_FIXUP_ASUS_W2JC),
- SND_PCI_QUIRK(0x1043, 0x2390, "Asus D700SA", ALC887_FIXUP_ASUS_HMIC),
- SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_FIXUP_EEE1601),
- SND_PCI_QUIRK(0x1043, 0x84bc, "ASUS ET2700", ALC887_FIXUP_ASUS_BASS),
- SND_PCI_QUIRK(0x1043, 0x8691, "ASUS ROG Ranger VIII", ALC882_FIXUP_GPIO3),
- SND_PCI_QUIRK(0x1043, 0x8797, "ASUS TUF B550M-PLUS", ALCS1200A_FIXUP_MIC_VREF),
- SND_PCI_QUIRK(0x104d, 0x9043, "Sony Vaio VGC-LN51JGB", ALC882_FIXUP_NO_PRIMARY_HP),
- SND_PCI_QUIRK(0x104d, 0x9044, "Sony VAIO AiO", ALC882_FIXUP_NO_PRIMARY_HP),
- SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT),
- SND_PCI_QUIRK(0x104d, 0x905a, "Sony Vaio Z", ALC882_FIXUP_NO_PRIMARY_HP),
- SND_PCI_QUIRK(0x104d, 0x9060, "Sony Vaio VPCL14M1R", ALC882_FIXUP_NO_PRIMARY_HP),
-
- /* All Apple entries are in codec SSIDs */
- SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC889_FIXUP_MBP_VREF),
- SND_PCI_QUIRK(0x106b, 0x00a1, "Macbook", ALC889_FIXUP_MBP_VREF),
- SND_PCI_QUIRK(0x106b, 0x00a4, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF),
- SND_PCI_QUIRK(0x106b, 0x0c00, "Mac Pro", ALC889_FIXUP_MP11_VREF),
- SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_FIXUP_MACPRO_GPIO),
- SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_FIXUP_MACPRO_GPIO),
- SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC889_FIXUP_MBP_VREF),
- SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889_FIXUP_MBP_VREF),
- SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_FIXUP_EAPD),
- SND_PCI_QUIRK(0x106b, 0x3400, "MacBookAir 1,1", ALC889_FIXUP_MBA11_VREF),
- SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC889_FIXUP_MBA21_VREF),
- SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889_FIXUP_MBP_VREF),
- SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF),
- SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_FIXUP_MACPRO_GPIO),
- SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC889_FIXUP_IMAC91_VREF),
- SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC889_FIXUP_IMAC91_VREF),
- SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC889_FIXUP_IMAC91_VREF),
- SND_PCI_QUIRK(0x106b, 0x4200, "Mac Pro 4,1/5,1", ALC889_FIXUP_MP41_VREF),
- SND_PCI_QUIRK(0x106b, 0x4300, "iMac 9,1", ALC889_FIXUP_IMAC91_VREF),
- SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC889_FIXUP_IMAC91_VREF),
- SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC889_FIXUP_IMAC91_VREF),
- SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_MBA11_VREF),
-
- SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
- SND_PCI_QUIRK(0x10ec, 0x12d8, "iBase Elo Touch", ALC888VD_FIXUP_MIC_100VREF),
- SND_PCI_QUIRK(0x13fe, 0x1009, "Advantech MIT-W101", ALC886_FIXUP_EAPD),
- SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE),
- SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
- SND_PCI_QUIRK(0x1458, 0xa0cd, "Gigabyte X570 Aorus Master", ALC1220_FIXUP_GB_X570),
- SND_PCI_QUIRK(0x1458, 0xa0ce, "Gigabyte X570 Aorus Xtreme", ALC1220_FIXUP_GB_X570),
- SND_PCI_QUIRK(0x1458, 0xa0d5, "Gigabyte X570S Aorus Master", ALC1220_FIXUP_GB_X570),
- SND_PCI_QUIRK(0x1462, 0x11f7, "MSI-GE63", ALC1220_FIXUP_CLEVO_P950),
- SND_PCI_QUIRK(0x1462, 0x1228, "MSI-GP63", ALC1220_FIXUP_CLEVO_P950),
- SND_PCI_QUIRK(0x1462, 0x1229, "MSI-GP73", ALC1220_FIXUP_CLEVO_P950),
- SND_PCI_QUIRK(0x1462, 0x1275, "MSI-GL63", ALC1220_FIXUP_CLEVO_P950),
- SND_PCI_QUIRK(0x1462, 0x1276, "MSI-GL73", ALC1220_FIXUP_CLEVO_P950),
- SND_PCI_QUIRK(0x1462, 0x1293, "MSI-GP65", ALC1220_FIXUP_CLEVO_P950),
- SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
- SND_PCI_QUIRK(0x1462, 0xcc34, "MSI Godlike X570", ALC1220_FIXUP_GB_DUAL_CODECS),
- SND_PCI_QUIRK(0x1462, 0xda57, "MSI Z270-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
- SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
- SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX),
- SND_PCI_QUIRK(0x1558, 0x3702, "Clevo X370SN[VW]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
- SND_PCI_QUIRK(0x1558, 0x50d3, "Clevo PC50[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
- SND_PCI_QUIRK(0x1558, 0x65d1, "Clevo PB51[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
- SND_PCI_QUIRK(0x1558, 0x65d2, "Clevo PB51R[CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
- SND_PCI_QUIRK(0x1558, 0x65e1, "Clevo PB51[ED][DF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
- SND_PCI_QUIRK(0x1558, 0x65e5, "Clevo PC50D[PRS](?:-D|-G)?", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
- SND_PCI_QUIRK(0x1558, 0x65f1, "Clevo PC50HS", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
- SND_PCI_QUIRK(0x1558, 0x65f5, "Clevo PD50PN[NRT]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
- SND_PCI_QUIRK(0x1558, 0x66a2, "Clevo PE60RNE", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
- SND_PCI_QUIRK(0x1558, 0x66a6, "Clevo PE60SN[CDE]-[GS]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
- SND_PCI_QUIRK(0x1558, 0x67d1, "Clevo PB71[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
- SND_PCI_QUIRK(0x1558, 0x67e1, "Clevo PB71[DE][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
- SND_PCI_QUIRK(0x1558, 0x67e5, "Clevo PC70D[PRS](?:-D|-G)?", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
- SND_PCI_QUIRK(0x1558, 0x67f1, "Clevo PC70H[PRS]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
- SND_PCI_QUIRK(0x1558, 0x67f5, "Clevo PD70PN[NRT]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
- SND_PCI_QUIRK(0x1558, 0x70d1, "Clevo PC70[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
- SND_PCI_QUIRK(0x1558, 0x7714, "Clevo X170SM", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
- SND_PCI_QUIRK(0x1558, 0x7715, "Clevo X170KM-G", ALC1220_FIXUP_CLEVO_PB51ED),
- SND_PCI_QUIRK(0x1558, 0x9501, "Clevo P950HR", ALC1220_FIXUP_CLEVO_P950),
- SND_PCI_QUIRK(0x1558, 0x9506, "Clevo P955HQ", ALC1220_FIXUP_CLEVO_P950),
- SND_PCI_QUIRK(0x1558, 0x950a, "Clevo P955H[PR]", ALC1220_FIXUP_CLEVO_P950),
- SND_PCI_QUIRK(0x1558, 0x95e1, "Clevo P95xER", ALC1220_FIXUP_CLEVO_P950),
- SND_PCI_QUIRK(0x1558, 0x95e2, "Clevo P950ER", ALC1220_FIXUP_CLEVO_P950),
- SND_PCI_QUIRK(0x1558, 0x95e3, "Clevo P955[ER]T", ALC1220_FIXUP_CLEVO_P950),
- SND_PCI_QUIRK(0x1558, 0x95e4, "Clevo P955ER", ALC1220_FIXUP_CLEVO_P950),
- SND_PCI_QUIRK(0x1558, 0x95e5, "Clevo P955EE6", ALC1220_FIXUP_CLEVO_P950),
- SND_PCI_QUIRK(0x1558, 0x95e6, "Clevo P950R[CDF]", ALC1220_FIXUP_CLEVO_P950),
- SND_PCI_QUIRK(0x1558, 0x96e1, "Clevo P960[ER][CDFN]-K", ALC1220_FIXUP_CLEVO_P950),
- SND_PCI_QUIRK(0x1558, 0x97e1, "Clevo P970[ER][CDFN]", ALC1220_FIXUP_CLEVO_P950),
- SND_PCI_QUIRK(0x1558, 0x97e2, "Clevo P970RC-M", ALC1220_FIXUP_CLEVO_P950),
- SND_PCI_QUIRK(0x1558, 0xd502, "Clevo PD50SNE", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
- SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
- SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
- SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", ALC882_FIXUP_LENOVO_Y530),
- SND_PCI_QUIRK(0x8086, 0x0022, "DX58SO", ALC889_FIXUP_COEF),
- {}
-};
-
-static const struct hda_model_fixup alc882_fixup_models[] = {
- {.id = ALC882_FIXUP_ABIT_AW9D_MAX, .name = "abit-aw9d"},
- {.id = ALC882_FIXUP_LENOVO_Y530, .name = "lenovo-y530"},
- {.id = ALC882_FIXUP_ACER_ASPIRE_7736, .name = "acer-aspire-7736"},
- {.id = ALC882_FIXUP_ASUS_W90V, .name = "asus-w90v"},
- {.id = ALC889_FIXUP_CD, .name = "cd"},
- {.id = ALC889_FIXUP_FRONT_HP_NO_PRESENCE, .name = "no-front-hp"},
- {.id = ALC889_FIXUP_VAIO_TT, .name = "vaio-tt"},
- {.id = ALC888_FIXUP_EEE1601, .name = "eee1601"},
- {.id = ALC882_FIXUP_EAPD, .name = "alc882-eapd"},
- {.id = ALC883_FIXUP_EAPD, .name = "alc883-eapd"},
- {.id = ALC882_FIXUP_GPIO1, .name = "gpio1"},
- {.id = ALC882_FIXUP_GPIO2, .name = "gpio2"},
- {.id = ALC882_FIXUP_GPIO3, .name = "gpio3"},
- {.id = ALC889_FIXUP_COEF, .name = "alc889-coef"},
- {.id = ALC882_FIXUP_ASUS_W2JC, .name = "asus-w2jc"},
- {.id = ALC882_FIXUP_ACER_ASPIRE_4930G, .name = "acer-aspire-4930g"},
- {.id = ALC882_FIXUP_ACER_ASPIRE_8930G, .name = "acer-aspire-8930g"},
- {.id = ALC883_FIXUP_ACER_EAPD, .name = "acer-aspire"},
- {.id = ALC885_FIXUP_MACPRO_GPIO, .name = "macpro-gpio"},
- {.id = ALC889_FIXUP_DAC_ROUTE, .name = "dac-route"},
- {.id = ALC889_FIXUP_MBP_VREF, .name = "mbp-vref"},
- {.id = ALC889_FIXUP_IMAC91_VREF, .name = "imac91-vref"},
- {.id = ALC889_FIXUP_MBA11_VREF, .name = "mba11-vref"},
- {.id = ALC889_FIXUP_MBA21_VREF, .name = "mba21-vref"},
- {.id = ALC889_FIXUP_MP11_VREF, .name = "mp11-vref"},
- {.id = ALC889_FIXUP_MP41_VREF, .name = "mp41-vref"},
- {.id = ALC882_FIXUP_INV_DMIC, .name = "inv-dmic"},
- {.id = ALC882_FIXUP_NO_PRIMARY_HP, .name = "no-primary-hp"},
- {.id = ALC887_FIXUP_ASUS_BASS, .name = "asus-bass"},
- {.id = ALC1220_FIXUP_GB_DUAL_CODECS, .name = "dual-codecs"},
- {.id = ALC1220_FIXUP_GB_X570, .name = "gb-x570"},
- {.id = ALC1220_FIXUP_CLEVO_P950, .name = "clevo-p950"},
- {}
-};
-
-static const struct snd_hda_pin_quirk alc882_pin_fixup_tbl[] = {
- SND_HDA_PIN_QUIRK(0x10ec1220, 0x1043, "ASUS", ALC1220_FIXUP_CLEVO_P950,
- {0x14, 0x01014010},
- {0x15, 0x01011012},
- {0x16, 0x01016011},
- {0x18, 0x01a19040},
- {0x19, 0x02a19050},
- {0x1a, 0x0181304f},
- {0x1b, 0x0221401f},
- {0x1e, 0x01456130}),
- SND_HDA_PIN_QUIRK(0x10ec1220, 0x1462, "MS-7C35", ALC1220_FIXUP_CLEVO_P950,
- {0x14, 0x01015010},
- {0x15, 0x01011012},
- {0x16, 0x01011011},
- {0x18, 0x01a11040},
- {0x19, 0x02a19050},
- {0x1a, 0x0181104f},
- {0x1b, 0x0221401f},
- {0x1e, 0x01451130}),
- {}
-};
-
-/*
- * BIOS auto configuration
- */
-/* almost identical with ALC880 parser... */
-static int alc882_parse_auto_config(struct hda_codec *codec)
-{
- static const hda_nid_t alc882_ignore[] = { 0x1d, 0 };
- static const hda_nid_t alc882_ssids[] = { 0x15, 0x1b, 0x14, 0 };
- return alc_parse_auto_config(codec, alc882_ignore, alc882_ssids);
-}
-
-/*
- */
-static int patch_alc882(struct hda_codec *codec)
-{
- struct alc_spec *spec;
- int err;
-
- err = alc_alloc_spec(codec, 0x0b);
- if (err < 0)
- return err;
-
- spec = codec->spec;
-
- switch (codec->core.vendor_id) {
- case 0x10ec0882:
- case 0x10ec0885:
- case 0x10ec0900:
- case 0x10ec0b00:
- case 0x10ec1220:
- break;
- default:
- /* ALC883 and variants */
- alc_fix_pll_init(codec, 0x20, 0x0a, 10);
- break;
- }
-
- alc_pre_init(codec);
-
- snd_hda_pick_fixup(codec, alc882_fixup_models, alc882_fixup_tbl,
- alc882_fixups);
- snd_hda_pick_pin_fixup(codec, alc882_pin_fixup_tbl, alc882_fixups, true);
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
-
- alc_auto_parse_customize_define(codec);
-
- if (has_cdefine_beep(codec))
- spec->gen.beep_nid = 0x01;
-
- /* automatic parse from the BIOS config */
- err = alc882_parse_auto_config(codec);
- if (err < 0)
- goto error;
-
- if (!spec->gen.no_analog && spec->gen.beep_nid) {
- err = set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
- if (err < 0)
- goto error;
- }
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
-
- return 0;
-
- error:
- alc_free(codec);
- return err;
-}
-
-
-/*
- * ALC262 support
- */
-static int alc262_parse_auto_config(struct hda_codec *codec)
-{
- static const hda_nid_t alc262_ignore[] = { 0x1d, 0 };
- static const hda_nid_t alc262_ssids[] = { 0x15, 0x1b, 0x14, 0 };
- return alc_parse_auto_config(codec, alc262_ignore, alc262_ssids);
-}
-
-/*
- * Pin config fixes
- */
-enum {
- ALC262_FIXUP_FSC_H270,
- ALC262_FIXUP_FSC_S7110,
- ALC262_FIXUP_HP_Z200,
- ALC262_FIXUP_TYAN,
- ALC262_FIXUP_LENOVO_3000,
- ALC262_FIXUP_BENQ,
- ALC262_FIXUP_BENQ_T31,
- ALC262_FIXUP_INV_DMIC,
- ALC262_FIXUP_INTEL_BAYLEYBAY,
-};
-
-static const struct hda_fixup alc262_fixups[] = {
- [ALC262_FIXUP_FSC_H270] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x14, 0x99130110 }, /* speaker */
- { 0x15, 0x0221142f }, /* front HP */
- { 0x1b, 0x0121141f }, /* rear HP */
- { }
- }
- },
- [ALC262_FIXUP_FSC_S7110] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x15, 0x90170110 }, /* speaker */
- { }
- },
- .chained = true,
- .chain_id = ALC262_FIXUP_BENQ,
- },
- [ALC262_FIXUP_HP_Z200] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x16, 0x99130120 }, /* internal speaker */
- { }
- }
- },
- [ALC262_FIXUP_TYAN] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x14, 0x1993e1f0 }, /* int AUX */
- { }
- }
- },
- [ALC262_FIXUP_LENOVO_3000] = {
- .type = HDA_FIXUP_PINCTLS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, PIN_VREF50 },
- {}
- },
- .chained = true,
- .chain_id = ALC262_FIXUP_BENQ,
- },
- [ALC262_FIXUP_BENQ] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x3070 },
- {}
- }
- },
- [ALC262_FIXUP_BENQ_T31] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 },
- {}
- }
- },
- [ALC262_FIXUP_INV_DMIC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_inv_dmic,
- },
- [ALC262_FIXUP_INTEL_BAYLEYBAY] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_no_depop_delay,
- },
-};
-
-static const struct hda_quirk alc262_fixup_tbl[] = {
- SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200", ALC262_FIXUP_HP_Z200),
- SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu Lifebook S7110", ALC262_FIXUP_FSC_S7110),
- SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FIXUP_BENQ),
- SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_FIXUP_TYAN),
- SND_PCI_QUIRK(0x1734, 0x1141, "FSC ESPRIMO U9210", ALC262_FIXUP_FSC_H270),
- SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", ALC262_FIXUP_FSC_H270),
- SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000", ALC262_FIXUP_LENOVO_3000),
- SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_FIXUP_BENQ),
- SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_FIXUP_BENQ_T31),
- SND_PCI_QUIRK(0x8086, 0x7270, "BayleyBay", ALC262_FIXUP_INTEL_BAYLEYBAY),
- {}
-};
-
-static const struct hda_model_fixup alc262_fixup_models[] = {
- {.id = ALC262_FIXUP_INV_DMIC, .name = "inv-dmic"},
- {.id = ALC262_FIXUP_FSC_H270, .name = "fsc-h270"},
- {.id = ALC262_FIXUP_FSC_S7110, .name = "fsc-s7110"},
- {.id = ALC262_FIXUP_HP_Z200, .name = "hp-z200"},
- {.id = ALC262_FIXUP_TYAN, .name = "tyan"},
- {.id = ALC262_FIXUP_LENOVO_3000, .name = "lenovo-3000"},
- {.id = ALC262_FIXUP_BENQ, .name = "benq"},
- {.id = ALC262_FIXUP_BENQ_T31, .name = "benq-t31"},
- {.id = ALC262_FIXUP_INTEL_BAYLEYBAY, .name = "bayleybay"},
- {}
-};
-
-/*
- */
-static int patch_alc262(struct hda_codec *codec)
-{
- struct alc_spec *spec;
- int err;
-
- err = alc_alloc_spec(codec, 0x0b);
- if (err < 0)
- return err;
-
- spec = codec->spec;
- spec->gen.shared_mic_vref_pin = 0x18;
-
- spec->shutup = alc_eapd_shutup;
-
-#if 0
- /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is
- * under-run
- */
- alc_update_coefex_idx(codec, 0x1a, 7, 0, 0x80);
-#endif
- alc_fix_pll_init(codec, 0x20, 0x0a, 10);
-
- alc_pre_init(codec);
-
- snd_hda_pick_fixup(codec, alc262_fixup_models, alc262_fixup_tbl,
- alc262_fixups);
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
-
- alc_auto_parse_customize_define(codec);
-
- if (has_cdefine_beep(codec))
- spec->gen.beep_nid = 0x01;
-
- /* automatic parse from the BIOS config */
- err = alc262_parse_auto_config(codec);
- if (err < 0)
- goto error;
-
- if (!spec->gen.no_analog && spec->gen.beep_nid) {
- err = set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
- if (err < 0)
- goto error;
- }
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
-
- return 0;
-
- error:
- alc_free(codec);
- return err;
-}
-
-/*
- * ALC268
- */
-/* bind Beep switches of both NID 0x0f and 0x10 */
-static int alc268_beep_switch_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- unsigned long pval;
- int err;
-
- mutex_lock(&codec->control_mutex);
- pval = kcontrol->private_value;
- kcontrol->private_value = (pval & ~0xff) | 0x0f;
- err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
- if (err >= 0) {
- kcontrol->private_value = (pval & ~0xff) | 0x10;
- err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
- }
- kcontrol->private_value = pval;
- mutex_unlock(&codec->control_mutex);
- return err;
-}
-
-static const struct snd_kcontrol_new alc268_beep_mixer[] = {
- HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Beep Playback Switch",
- .subdevice = HDA_SUBDEV_AMP_FLAG,
- .info = snd_hda_mixer_amp_switch_info,
- .get = snd_hda_mixer_amp_switch_get,
- .put = alc268_beep_switch_put,
- .private_value = HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT)
- },
-};
-
-/* set PCBEEP vol = 0, mute connections */
-static const struct hda_verb alc268_beep_init_verbs[] = {
- {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- { }
-};
-
-enum {
- ALC268_FIXUP_INV_DMIC,
- ALC268_FIXUP_HP_EAPD,
- ALC268_FIXUP_SPDIF,
-};
-
-static const struct hda_fixup alc268_fixups[] = {
- [ALC268_FIXUP_INV_DMIC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_inv_dmic,
- },
- [ALC268_FIXUP_HP_EAPD] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- {0x15, AC_VERB_SET_EAPD_BTLENABLE, 0},
- {}
- }
- },
- [ALC268_FIXUP_SPDIF] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1e, 0x014b1180 }, /* enable SPDIF out */
- {}
- }
- },
-};
-
-static const struct hda_model_fixup alc268_fixup_models[] = {
- {.id = ALC268_FIXUP_INV_DMIC, .name = "inv-dmic"},
- {.id = ALC268_FIXUP_HP_EAPD, .name = "hp-eapd"},
- {.id = ALC268_FIXUP_SPDIF, .name = "spdif"},
- {}
-};
-
-static const struct hda_quirk alc268_fixup_tbl[] = {
- SND_PCI_QUIRK(0x1025, 0x0139, "Acer TravelMate 6293", ALC268_FIXUP_SPDIF),
- SND_PCI_QUIRK(0x1025, 0x015b, "Acer AOA 150 (ZG5)", ALC268_FIXUP_INV_DMIC),
- /* below is codec SSID since multiple Toshiba laptops have the
- * same PCI SSID 1179:ff00
- */
- SND_PCI_QUIRK(0x1179, 0xff06, "Toshiba P200", ALC268_FIXUP_HP_EAPD),
- {}
-};
-
-/*
- * BIOS auto configuration
- */
-static int alc268_parse_auto_config(struct hda_codec *codec)
-{
- static const hda_nid_t alc268_ssids[] = { 0x15, 0x1b, 0x14, 0 };
- return alc_parse_auto_config(codec, NULL, alc268_ssids);
-}
-
-/*
- */
-static int patch_alc268(struct hda_codec *codec)
-{
- struct alc_spec *spec;
- int i, err;
-
- /* ALC268 has no aa-loopback mixer */
- err = alc_alloc_spec(codec, 0);
- if (err < 0)
- return err;
-
- spec = codec->spec;
- if (has_cdefine_beep(codec))
- spec->gen.beep_nid = 0x01;
-
- spec->shutup = alc_eapd_shutup;
-
- alc_pre_init(codec);
-
- snd_hda_pick_fixup(codec, alc268_fixup_models, alc268_fixup_tbl, alc268_fixups);
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
-
- /* automatic parse from the BIOS config */
- err = alc268_parse_auto_config(codec);
- if (err < 0)
- goto error;
-
- if (err > 0 && !spec->gen.no_analog &&
- spec->gen.autocfg.speaker_pins[0] != 0x1d) {
- for (i = 0; i < ARRAY_SIZE(alc268_beep_mixer); i++) {
- if (!snd_hda_gen_add_kctl(&spec->gen, NULL,
- &alc268_beep_mixer[i])) {
- err = -ENOMEM;
- goto error;
- }
- }
- snd_hda_add_verbs(codec, alc268_beep_init_verbs);
- if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
- /* override the amp caps for beep generator */
- snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT,
- (0x0c << AC_AMPCAP_OFFSET_SHIFT) |
- (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) |
- (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) |
- (0 << AC_AMPCAP_MUTE_SHIFT));
- }
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
-
- return 0;
-
- error:
- alc_free(codec);
- return err;
-}
-
-/*
- * ALC269
- */
-
-static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
- .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
-};
-
-static const struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
- .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
-};
-
-/* different alc269-variants */
-enum {
- ALC269_TYPE_ALC269VA,
- ALC269_TYPE_ALC269VB,
- ALC269_TYPE_ALC269VC,
- ALC269_TYPE_ALC269VD,
- ALC269_TYPE_ALC280,
- ALC269_TYPE_ALC282,
- ALC269_TYPE_ALC283,
- ALC269_TYPE_ALC284,
- ALC269_TYPE_ALC293,
- ALC269_TYPE_ALC286,
- ALC269_TYPE_ALC298,
- ALC269_TYPE_ALC255,
- ALC269_TYPE_ALC256,
- ALC269_TYPE_ALC257,
- ALC269_TYPE_ALC215,
- ALC269_TYPE_ALC225,
- ALC269_TYPE_ALC245,
- ALC269_TYPE_ALC287,
- ALC269_TYPE_ALC294,
- ALC269_TYPE_ALC300,
- ALC269_TYPE_ALC623,
- ALC269_TYPE_ALC700,
-};
-
-/*
- * BIOS auto configuration
- */
-static int alc269_parse_auto_config(struct hda_codec *codec)
-{
- static const hda_nid_t alc269_ignore[] = { 0x1d, 0 };
- static const hda_nid_t alc269_ssids[] = { 0, 0x1b, 0x14, 0x21 };
- static const hda_nid_t alc269va_ssids[] = { 0x15, 0x1b, 0x14, 0 };
- struct alc_spec *spec = codec->spec;
- const hda_nid_t *ssids;
-
- switch (spec->codec_variant) {
- case ALC269_TYPE_ALC269VA:
- case ALC269_TYPE_ALC269VC:
- case ALC269_TYPE_ALC280:
- case ALC269_TYPE_ALC284:
- case ALC269_TYPE_ALC293:
- ssids = alc269va_ssids;
- break;
- case ALC269_TYPE_ALC269VB:
- case ALC269_TYPE_ALC269VD:
- case ALC269_TYPE_ALC282:
- case ALC269_TYPE_ALC283:
- case ALC269_TYPE_ALC286:
- case ALC269_TYPE_ALC298:
- case ALC269_TYPE_ALC255:
- case ALC269_TYPE_ALC256:
- case ALC269_TYPE_ALC257:
- case ALC269_TYPE_ALC215:
- case ALC269_TYPE_ALC225:
- case ALC269_TYPE_ALC245:
- case ALC269_TYPE_ALC287:
- case ALC269_TYPE_ALC294:
- case ALC269_TYPE_ALC300:
- case ALC269_TYPE_ALC623:
- case ALC269_TYPE_ALC700:
- ssids = alc269_ssids;
- break;
- default:
- ssids = alc269_ssids;
- break;
- }
-
- return alc_parse_auto_config(codec, alc269_ignore, ssids);
-}
-
-static const struct hda_jack_keymap alc_headset_btn_keymap[] = {
- { SND_JACK_BTN_0, KEY_PLAYPAUSE },
- { SND_JACK_BTN_1, KEY_VOICECOMMAND },
- { SND_JACK_BTN_2, KEY_VOLUMEUP },
- { SND_JACK_BTN_3, KEY_VOLUMEDOWN },
- {}
-};
-
-static void alc_headset_btn_callback(struct hda_codec *codec,
- struct hda_jack_callback *jack)
-{
- int report = 0;
-
- if (jack->unsol_res & (7 << 13))
- report |= SND_JACK_BTN_0;
-
- if (jack->unsol_res & (1 << 16 | 3 << 8))
- report |= SND_JACK_BTN_1;
-
- /* Volume up key */
- if (jack->unsol_res & (7 << 23))
- report |= SND_JACK_BTN_2;
-
- /* Volume down key */
- if (jack->unsol_res & (7 << 10))
- report |= SND_JACK_BTN_3;
-
- snd_hda_jack_set_button_state(codec, jack->nid, report);
-}
-
-static void alc_disable_headset_jack_key(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- if (!spec->has_hs_key)
- return;
-
- switch (codec->core.vendor_id) {
- case 0x10ec0215:
- case 0x10ec0225:
- case 0x10ec0285:
- case 0x10ec0287:
- case 0x10ec0295:
- case 0x10ec0289:
- case 0x10ec0299:
- alc_write_coef_idx(codec, 0x48, 0x0);
- alc_update_coef_idx(codec, 0x49, 0x0045, 0x0);
- alc_update_coef_idx(codec, 0x44, 0x0045 << 8, 0x0);
- break;
- case 0x10ec0230:
- case 0x10ec0236:
- case 0x10ec0256:
- case 0x10ec0257:
- case 0x19e58326:
- alc_write_coef_idx(codec, 0x48, 0x0);
- alc_update_coef_idx(codec, 0x49, 0x0045, 0x0);
- break;
- }
-}
-
-static void alc_enable_headset_jack_key(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- if (!spec->has_hs_key)
- return;
-
- switch (codec->core.vendor_id) {
- case 0x10ec0215:
- case 0x10ec0225:
- case 0x10ec0285:
- case 0x10ec0287:
- case 0x10ec0295:
- case 0x10ec0289:
- case 0x10ec0299:
- alc_write_coef_idx(codec, 0x48, 0xd011);
- alc_update_coef_idx(codec, 0x49, 0x007f, 0x0045);
- alc_update_coef_idx(codec, 0x44, 0x007f << 8, 0x0045 << 8);
- break;
- case 0x10ec0230:
- case 0x10ec0236:
- case 0x10ec0256:
- case 0x10ec0257:
- case 0x19e58326:
- alc_write_coef_idx(codec, 0x48, 0xd011);
- alc_update_coef_idx(codec, 0x49, 0x007f, 0x0045);
- break;
- }
-}
-
-static void alc_fixup_headset_jack(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
- hda_nid_t hp_pin;
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- spec->has_hs_key = 1;
- snd_hda_jack_detect_enable_callback(codec, 0x55,
- alc_headset_btn_callback);
- break;
- case HDA_FIXUP_ACT_BUILD:
- hp_pin = alc_get_hp_pin(spec);
- if (!hp_pin || snd_hda_jack_bind_keymap(codec, 0x55,
- alc_headset_btn_keymap,
- hp_pin))
- snd_hda_jack_add_kctl(codec, 0x55, "Headset Jack",
- false, SND_JACK_HEADSET,
- alc_headset_btn_keymap);
-
- alc_enable_headset_jack_key(codec);
- break;
- }
-}
-
-static void alc269vb_toggle_power_output(struct hda_codec *codec, int power_up)
-{
- alc_update_coef_idx(codec, 0x04, 1 << 11, power_up ? (1 << 11) : 0);
-}
-
-static void alc269_shutup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- if (spec->codec_variant == ALC269_TYPE_ALC269VB)
- alc269vb_toggle_power_output(codec, 0);
- if (spec->codec_variant == ALC269_TYPE_ALC269VB &&
- (alc_get_coef0(codec) & 0x00ff) == 0x018) {
- msleep(150);
- }
- alc_shutup_pins(codec);
-}
-
-static const struct coef_fw alc282_coefs[] = {
- WRITE_COEF(0x03, 0x0002), /* Power Down Control */
- UPDATE_COEF(0x05, 0xff3f, 0x0700), /* FIFO and filter clock */
- WRITE_COEF(0x07, 0x0200), /* DMIC control */
- UPDATE_COEF(0x06, 0x00f0, 0), /* Analog clock */
- UPDATE_COEF(0x08, 0xfffc, 0x0c2c), /* JD */
- WRITE_COEF(0x0a, 0xcccc), /* JD offset1 */
- WRITE_COEF(0x0b, 0xcccc), /* JD offset2 */
- WRITE_COEF(0x0e, 0x6e00), /* LDO1/2/3, DAC/ADC */
- UPDATE_COEF(0x0f, 0xf800, 0x1000), /* JD */
- UPDATE_COEF(0x10, 0xfc00, 0x0c00), /* Capless */
- WRITE_COEF(0x6f, 0x0), /* Class D test 4 */
- UPDATE_COEF(0x0c, 0xfe00, 0), /* IO power down directly */
- WRITE_COEF(0x34, 0xa0c0), /* ANC */
- UPDATE_COEF(0x16, 0x0008, 0), /* AGC MUX */
- UPDATE_COEF(0x1d, 0x00e0, 0), /* DAC simple content protection */
- UPDATE_COEF(0x1f, 0x00e0, 0), /* ADC simple content protection */
- WRITE_COEF(0x21, 0x8804), /* DAC ADC Zero Detection */
- WRITE_COEF(0x63, 0x2902), /* PLL */
- WRITE_COEF(0x68, 0xa080), /* capless control 2 */
- WRITE_COEF(0x69, 0x3400), /* capless control 3 */
- WRITE_COEF(0x6a, 0x2f3e), /* capless control 4 */
- WRITE_COEF(0x6b, 0x0), /* capless control 5 */
- UPDATE_COEF(0x6d, 0x0fff, 0x0900), /* class D test 2 */
- WRITE_COEF(0x6e, 0x110a), /* class D test 3 */
- UPDATE_COEF(0x70, 0x00f8, 0x00d8), /* class D test 5 */
- WRITE_COEF(0x71, 0x0014), /* class D test 6 */
- WRITE_COEF(0x72, 0xc2ba), /* classD OCP */
- UPDATE_COEF(0x77, 0x0f80, 0), /* classD pure DC test */
- WRITE_COEF(0x6c, 0xfc06), /* Class D amp control */
- {}
-};
-
-static void alc282_restore_default_value(struct hda_codec *codec)
-{
- alc_process_coef_fw(codec, alc282_coefs);
-}
-
-static void alc282_init(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- hda_nid_t hp_pin = alc_get_hp_pin(spec);
- bool hp_pin_sense;
- int coef78;
-
- alc282_restore_default_value(codec);
-
- if (!hp_pin)
- return;
- hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
- coef78 = alc_read_coef_idx(codec, 0x78);
-
- /* Index 0x78 Direct Drive HP AMP LPM Control 1 */
- /* Headphone capless set to high power mode */
- alc_write_coef_idx(codec, 0x78, 0x9004);
-
- if (hp_pin_sense)
- msleep(2);
-
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
-
- if (hp_pin_sense)
- msleep(85);
-
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
-
- if (hp_pin_sense)
- msleep(100);
-
- /* Headphone capless set to normal mode */
- alc_write_coef_idx(codec, 0x78, coef78);
-}
-
-static void alc282_shutup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- hda_nid_t hp_pin = alc_get_hp_pin(spec);
- bool hp_pin_sense;
- int coef78;
-
- if (!hp_pin) {
- alc269_shutup(codec);
- return;
- }
-
- hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
- coef78 = alc_read_coef_idx(codec, 0x78);
- alc_write_coef_idx(codec, 0x78, 0x9004);
-
- if (hp_pin_sense)
- msleep(2);
-
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
-
- if (hp_pin_sense)
- msleep(85);
-
- if (!spec->no_shutup_pins)
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
-
- if (hp_pin_sense)
- msleep(100);
-
- alc_auto_setup_eapd(codec, false);
- alc_shutup_pins(codec);
- alc_write_coef_idx(codec, 0x78, coef78);
-}
-
-static const struct coef_fw alc283_coefs[] = {
- WRITE_COEF(0x03, 0x0002), /* Power Down Control */
- UPDATE_COEF(0x05, 0xff3f, 0x0700), /* FIFO and filter clock */
- WRITE_COEF(0x07, 0x0200), /* DMIC control */
- UPDATE_COEF(0x06, 0x00f0, 0), /* Analog clock */
- UPDATE_COEF(0x08, 0xfffc, 0x0c2c), /* JD */
- WRITE_COEF(0x0a, 0xcccc), /* JD offset1 */
- WRITE_COEF(0x0b, 0xcccc), /* JD offset2 */
- WRITE_COEF(0x0e, 0x6fc0), /* LDO1/2/3, DAC/ADC */
- UPDATE_COEF(0x0f, 0xf800, 0x1000), /* JD */
- UPDATE_COEF(0x10, 0xfc00, 0x0c00), /* Capless */
- WRITE_COEF(0x3a, 0x0), /* Class D test 4 */
- UPDATE_COEF(0x0c, 0xfe00, 0x0), /* IO power down directly */
- WRITE_COEF(0x22, 0xa0c0), /* ANC */
- UPDATE_COEFEX(0x53, 0x01, 0x000f, 0x0008), /* AGC MUX */
- UPDATE_COEF(0x1d, 0x00e0, 0), /* DAC simple content protection */
- UPDATE_COEF(0x1f, 0x00e0, 0), /* ADC simple content protection */
- WRITE_COEF(0x21, 0x8804), /* DAC ADC Zero Detection */
- WRITE_COEF(0x2e, 0x2902), /* PLL */
- WRITE_COEF(0x33, 0xa080), /* capless control 2 */
- WRITE_COEF(0x34, 0x3400), /* capless control 3 */
- WRITE_COEF(0x35, 0x2f3e), /* capless control 4 */
- WRITE_COEF(0x36, 0x0), /* capless control 5 */
- UPDATE_COEF(0x38, 0x0fff, 0x0900), /* class D test 2 */
- WRITE_COEF(0x39, 0x110a), /* class D test 3 */
- UPDATE_COEF(0x3b, 0x00f8, 0x00d8), /* class D test 5 */
- WRITE_COEF(0x3c, 0x0014), /* class D test 6 */
- WRITE_COEF(0x3d, 0xc2ba), /* classD OCP */
- UPDATE_COEF(0x42, 0x0f80, 0x0), /* classD pure DC test */
- WRITE_COEF(0x49, 0x0), /* test mode */
- UPDATE_COEF(0x40, 0xf800, 0x9800), /* Class D DC enable */
- UPDATE_COEF(0x42, 0xf000, 0x2000), /* DC offset */
- WRITE_COEF(0x37, 0xfc06), /* Class D amp control */
- UPDATE_COEF(0x1b, 0x8000, 0), /* HP JD control */
- {}
-};
-
-static void alc283_restore_default_value(struct hda_codec *codec)
-{
- alc_process_coef_fw(codec, alc283_coefs);
-}
-
-static void alc283_init(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- hda_nid_t hp_pin = alc_get_hp_pin(spec);
- bool hp_pin_sense;
-
- alc283_restore_default_value(codec);
-
- if (!hp_pin)
- return;
-
- msleep(30);
- hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
-
- /* Index 0x43 Direct Drive HP AMP LPM Control 1 */
- /* Headphone capless set to high power mode */
- alc_write_coef_idx(codec, 0x43, 0x9004);
-
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
-
- if (hp_pin_sense)
- msleep(85);
-
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
-
- if (hp_pin_sense)
- msleep(85);
- /* Index 0x46 Combo jack auto switch control 2 */
- /* 3k pull low control for Headset jack. */
- alc_update_coef_idx(codec, 0x46, 3 << 12, 0);
- /* Headphone capless set to normal mode */
- alc_write_coef_idx(codec, 0x43, 0x9614);
-}
-
-static void alc283_shutup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- hda_nid_t hp_pin = alc_get_hp_pin(spec);
- bool hp_pin_sense;
-
- if (!hp_pin) {
- alc269_shutup(codec);
- return;
- }
-
- hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
-
- alc_write_coef_idx(codec, 0x43, 0x9004);
-
- /*depop hp during suspend*/
- alc_write_coef_idx(codec, 0x06, 0x2100);
-
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
-
- if (hp_pin_sense)
- msleep(100);
-
- if (!spec->no_shutup_pins)
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
-
- alc_update_coef_idx(codec, 0x46, 0, 3 << 12);
-
- if (hp_pin_sense)
- msleep(100);
- alc_auto_setup_eapd(codec, false);
- alc_shutup_pins(codec);
- alc_write_coef_idx(codec, 0x43, 0x9614);
-}
-
-static void alc256_init(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- hda_nid_t hp_pin = alc_get_hp_pin(spec);
- bool hp_pin_sense;
-
- if (spec->ultra_low_power) {
- alc_update_coef_idx(codec, 0x03, 1<<1, 1<<1);
- alc_update_coef_idx(codec, 0x08, 3<<2, 3<<2);
- alc_update_coef_idx(codec, 0x08, 7<<4, 0);
- alc_update_coef_idx(codec, 0x3b, 1<<15, 0);
- alc_update_coef_idx(codec, 0x0e, 7<<6, 7<<6);
- msleep(30);
- }
-
- if (!hp_pin)
- hp_pin = 0x21;
-
- msleep(30);
-
- hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
-
- if (hp_pin_sense) {
- msleep(2);
- alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */
-
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
-
- msleep(75);
-
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
-
- msleep(75);
- alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x4); /* Hight power */
- }
- alc_update_coef_idx(codec, 0x46, 3 << 12, 0);
- alc_update_coefex_idx(codec, 0x53, 0x02, 0x8000, 1 << 15); /* Clear bit */
- alc_update_coefex_idx(codec, 0x53, 0x02, 0x8000, 0 << 15);
- /*
- * Expose headphone mic (or possibly Line In on some machines) instead
- * of PC Beep on 1Ah, and disable 1Ah loopback for all outputs. See
- * Documentation/sound/hd-audio/realtek-pc-beep.rst for details of
- * this register.
- */
- alc_write_coef_idx(codec, 0x36, 0x5757);
-}
-
-static void alc256_shutup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- hda_nid_t hp_pin = alc_get_hp_pin(spec);
- bool hp_pin_sense;
-
- if (!hp_pin)
- hp_pin = 0x21;
-
- alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */
- hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
-
- if (hp_pin_sense) {
- msleep(2);
-
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
-
- msleep(75);
-
- /* 3k pull low control for Headset jack. */
- /* NOTE: call this before clearing the pin, otherwise codec stalls */
- /* If disable 3k pulldown control for alc257, the Mic detection will not work correctly
- * when booting with headset plugged. So skip setting it for the codec alc257
- */
- if (spec->en_3kpull_low)
- alc_update_coef_idx(codec, 0x46, 0, 3 << 12);
-
- if (!spec->no_shutup_pins)
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
-
- msleep(75);
- }
-
- alc_auto_setup_eapd(codec, false);
- alc_shutup_pins(codec);
- if (spec->ultra_low_power) {
- msleep(50);
- alc_update_coef_idx(codec, 0x03, 1<<1, 0);
- alc_update_coef_idx(codec, 0x08, 7<<4, 7<<4);
- alc_update_coef_idx(codec, 0x08, 3<<2, 0);
- alc_update_coef_idx(codec, 0x3b, 1<<15, 1<<15);
- alc_update_coef_idx(codec, 0x0e, 7<<6, 0);
- msleep(30);
- }
-}
-
-static void alc285_hp_init(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- hda_nid_t hp_pin = alc_get_hp_pin(spec);
- int i, val;
- int coef38, coef0d, coef36;
-
- alc_write_coefex_idx(codec, 0x58, 0x00, 0x1888); /* write default value */
- alc_update_coef_idx(codec, 0x4a, 1<<15, 1<<15); /* Reset HP JD */
- coef38 = alc_read_coef_idx(codec, 0x38); /* Amp control */
- coef0d = alc_read_coef_idx(codec, 0x0d); /* Digital Misc control */
- coef36 = alc_read_coef_idx(codec, 0x36); /* Passthrough Control */
- alc_update_coef_idx(codec, 0x38, 1<<4, 0x0);
- alc_update_coef_idx(codec, 0x0d, 0x110, 0x0);
-
- alc_update_coef_idx(codec, 0x67, 0xf000, 0x3000);
-
- if (hp_pin)
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
-
- msleep(130);
- alc_update_coef_idx(codec, 0x36, 1<<14, 1<<14);
- alc_update_coef_idx(codec, 0x36, 1<<13, 0x0);
-
- if (hp_pin)
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
- msleep(10);
- alc_write_coef_idx(codec, 0x67, 0x0); /* Set HP depop to manual mode */
- alc_write_coefex_idx(codec, 0x58, 0x00, 0x7880);
- alc_write_coefex_idx(codec, 0x58, 0x0f, 0xf049);
- alc_update_coefex_idx(codec, 0x58, 0x03, 0x00f0, 0x00c0);
-
- alc_write_coefex_idx(codec, 0x58, 0x00, 0xf888); /* HP depop procedure start */
- val = alc_read_coefex_idx(codec, 0x58, 0x00);
- for (i = 0; i < 20 && val & 0x8000; i++) {
- msleep(50);
- val = alc_read_coefex_idx(codec, 0x58, 0x00);
- } /* Wait for depop procedure finish */
-
- alc_write_coefex_idx(codec, 0x58, 0x00, val); /* write back the result */
- alc_update_coef_idx(codec, 0x38, 1<<4, coef38);
- alc_update_coef_idx(codec, 0x0d, 0x110, coef0d);
- alc_update_coef_idx(codec, 0x36, 3<<13, coef36);
-
- msleep(50);
- alc_update_coef_idx(codec, 0x4a, 1<<15, 0);
-}
-
-static void alc225_init(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- hda_nid_t hp_pin = alc_get_hp_pin(spec);
- bool hp1_pin_sense, hp2_pin_sense;
-
- if (spec->ultra_low_power) {
- alc_update_coef_idx(codec, 0x08, 0x0f << 2, 3<<2);
- alc_update_coef_idx(codec, 0x0e, 7<<6, 7<<6);
- alc_update_coef_idx(codec, 0x33, 1<<11, 0);
- msleep(30);
- }
-
- if (spec->codec_variant != ALC269_TYPE_ALC287 &&
- spec->codec_variant != ALC269_TYPE_ALC245)
- /* required only at boot or S3 and S4 resume time */
- if (!spec->done_hp_init ||
- is_s3_resume(codec) ||
- is_s4_resume(codec)) {
- alc285_hp_init(codec);
- spec->done_hp_init = true;
- }
-
- if (!hp_pin)
- hp_pin = 0x21;
- msleep(30);
-
- hp1_pin_sense = snd_hda_jack_detect(codec, hp_pin);
- hp2_pin_sense = snd_hda_jack_detect(codec, 0x16);
-
- if (hp1_pin_sense || hp2_pin_sense) {
- msleep(2);
- alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */
-
- if (hp1_pin_sense)
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
- if (hp2_pin_sense)
- snd_hda_codec_write(codec, 0x16, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
- msleep(75);
-
- if (hp1_pin_sense)
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
- if (hp2_pin_sense)
- snd_hda_codec_write(codec, 0x16, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
-
- msleep(75);
- alc_update_coef_idx(codec, 0x4a, 3 << 10, 0);
- alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x4); /* Hight power */
- }
-}
-
-static void alc225_shutup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- hda_nid_t hp_pin = alc_get_hp_pin(spec);
- bool hp1_pin_sense, hp2_pin_sense;
-
- if (!hp_pin)
- hp_pin = 0x21;
-
- hp1_pin_sense = snd_hda_jack_detect(codec, hp_pin);
- hp2_pin_sense = snd_hda_jack_detect(codec, 0x16);
-
- if (hp1_pin_sense || hp2_pin_sense) {
- alc_disable_headset_jack_key(codec);
- /* 3k pull low control for Headset jack. */
- alc_update_coef_idx(codec, 0x4a, 0, 3 << 10);
- msleep(2);
-
- if (hp1_pin_sense)
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
- if (hp2_pin_sense)
- snd_hda_codec_write(codec, 0x16, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
-
- msleep(75);
-
- if (hp1_pin_sense)
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
- if (hp2_pin_sense)
- snd_hda_codec_write(codec, 0x16, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
-
- msleep(75);
- alc_update_coef_idx(codec, 0x4a, 3 << 10, 0);
- alc_enable_headset_jack_key(codec);
- }
- alc_auto_setup_eapd(codec, false);
- alc_shutup_pins(codec);
- if (spec->ultra_low_power) {
- msleep(50);
- alc_update_coef_idx(codec, 0x08, 0x0f << 2, 0x0c << 2);
- alc_update_coef_idx(codec, 0x0e, 7<<6, 0);
- alc_update_coef_idx(codec, 0x33, 1<<11, 1<<11);
- alc_update_coef_idx(codec, 0x4a, 3<<4, 2<<4);
- msleep(30);
- }
-}
-
-static void alc222_init(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- hda_nid_t hp_pin = alc_get_hp_pin(spec);
- bool hp1_pin_sense, hp2_pin_sense;
-
- if (!hp_pin)
- return;
-
- msleep(30);
-
- hp1_pin_sense = snd_hda_jack_detect(codec, hp_pin);
- hp2_pin_sense = snd_hda_jack_detect(codec, 0x14);
-
- if (hp1_pin_sense || hp2_pin_sense) {
- msleep(2);
-
- if (hp1_pin_sense)
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
- if (hp2_pin_sense)
- snd_hda_codec_write(codec, 0x14, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
- msleep(75);
-
- if (hp1_pin_sense)
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
- if (hp2_pin_sense)
- snd_hda_codec_write(codec, 0x14, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
-
- msleep(75);
- }
-}
-
-static void alc222_shutup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- hda_nid_t hp_pin = alc_get_hp_pin(spec);
- bool hp1_pin_sense, hp2_pin_sense;
-
- if (!hp_pin)
- hp_pin = 0x21;
-
- hp1_pin_sense = snd_hda_jack_detect(codec, hp_pin);
- hp2_pin_sense = snd_hda_jack_detect(codec, 0x14);
-
- if (hp1_pin_sense || hp2_pin_sense) {
- msleep(2);
-
- if (hp1_pin_sense)
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
- if (hp2_pin_sense)
- snd_hda_codec_write(codec, 0x14, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
-
- msleep(75);
-
- if (hp1_pin_sense)
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
- if (hp2_pin_sense)
- snd_hda_codec_write(codec, 0x14, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
-
- msleep(75);
- }
- alc_auto_setup_eapd(codec, false);
- alc_shutup_pins(codec);
-}
-
-static void alc_default_init(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- hda_nid_t hp_pin = alc_get_hp_pin(spec);
- bool hp_pin_sense;
-
- if (!hp_pin)
- return;
-
- msleep(30);
-
- hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
-
- if (hp_pin_sense) {
- msleep(2);
-
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
-
- msleep(75);
-
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
- msleep(75);
- }
-}
-
-static void alc_default_shutup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- hda_nid_t hp_pin = alc_get_hp_pin(spec);
- bool hp_pin_sense;
-
- if (!hp_pin) {
- alc269_shutup(codec);
- return;
- }
-
- hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
-
- if (hp_pin_sense) {
- msleep(2);
-
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
-
- msleep(75);
-
- if (!spec->no_shutup_pins)
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
-
- msleep(75);
- }
- alc_auto_setup_eapd(codec, false);
- alc_shutup_pins(codec);
-}
-
-static void alc294_hp_init(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- hda_nid_t hp_pin = alc_get_hp_pin(spec);
- int i, val;
-
- if (!hp_pin)
- return;
-
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
-
- msleep(100);
-
- if (!spec->no_shutup_pins)
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
-
- alc_update_coef_idx(codec, 0x6f, 0x000f, 0);/* Set HP depop to manual mode */
- alc_update_coefex_idx(codec, 0x58, 0x00, 0x8000, 0x8000); /* HP depop procedure start */
-
- /* Wait for depop procedure finish */
- val = alc_read_coefex_idx(codec, 0x58, 0x01);
- for (i = 0; i < 20 && val & 0x0080; i++) {
- msleep(50);
- val = alc_read_coefex_idx(codec, 0x58, 0x01);
- }
- /* Set HP depop to auto mode */
- alc_update_coef_idx(codec, 0x6f, 0x000f, 0x000b);
- msleep(50);
-}
-
-static void alc294_init(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- /* required only at boot or S4 resume time */
- if (!spec->done_hp_init ||
- codec->core.dev.power.power_state.event == PM_EVENT_RESTORE) {
- alc294_hp_init(codec);
- spec->done_hp_init = true;
- }
- alc_default_init(codec);
-}
-
-static void alc5505_coef_set(struct hda_codec *codec, unsigned int index_reg,
- unsigned int val)
-{
- snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_COEF_INDEX, index_reg >> 1);
- snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_PROC_COEF, val & 0xffff); /* LSB */
- snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_PROC_COEF, val >> 16); /* MSB */
-}
-
-static int alc5505_coef_get(struct hda_codec *codec, unsigned int index_reg)
-{
- unsigned int val;
-
- snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_COEF_INDEX, index_reg >> 1);
- val = snd_hda_codec_read(codec, 0x51, 0, AC_VERB_GET_PROC_COEF, 0)
- & 0xffff;
- val |= snd_hda_codec_read(codec, 0x51, 0, AC_VERB_GET_PROC_COEF, 0)
- << 16;
- return val;
-}
-
-static void alc5505_dsp_halt(struct hda_codec *codec)
-{
- unsigned int val;
-
- alc5505_coef_set(codec, 0x3000, 0x000c); /* DSP CPU stop */
- alc5505_coef_set(codec, 0x880c, 0x0008); /* DDR enter self refresh */
- alc5505_coef_set(codec, 0x61c0, 0x11110080); /* Clock control for PLL and CPU */
- alc5505_coef_set(codec, 0x6230, 0xfc0d4011); /* Disable Input OP */
- alc5505_coef_set(codec, 0x61b4, 0x040a2b03); /* Stop PLL2 */
- alc5505_coef_set(codec, 0x61b0, 0x00005b17); /* Stop PLL1 */
- alc5505_coef_set(codec, 0x61b8, 0x04133303); /* Stop PLL3 */
- val = alc5505_coef_get(codec, 0x6220);
- alc5505_coef_set(codec, 0x6220, (val | 0x3000)); /* switch Ringbuffer clock to DBUS clock */
-}
-
-static void alc5505_dsp_back_from_halt(struct hda_codec *codec)
-{
- alc5505_coef_set(codec, 0x61b8, 0x04133302);
- alc5505_coef_set(codec, 0x61b0, 0x00005b16);
- alc5505_coef_set(codec, 0x61b4, 0x040a2b02);
- alc5505_coef_set(codec, 0x6230, 0xf80d4011);
- alc5505_coef_set(codec, 0x6220, 0x2002010f);
- alc5505_coef_set(codec, 0x880c, 0x00000004);
-}
-
-static void alc5505_dsp_init(struct hda_codec *codec)
-{
- unsigned int val;
-
- alc5505_dsp_halt(codec);
- alc5505_dsp_back_from_halt(codec);
- alc5505_coef_set(codec, 0x61b0, 0x5b14); /* PLL1 control */
- alc5505_coef_set(codec, 0x61b0, 0x5b16);
- alc5505_coef_set(codec, 0x61b4, 0x04132b00); /* PLL2 control */
- alc5505_coef_set(codec, 0x61b4, 0x04132b02);
- alc5505_coef_set(codec, 0x61b8, 0x041f3300); /* PLL3 control*/
- alc5505_coef_set(codec, 0x61b8, 0x041f3302);
- snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_CODEC_RESET, 0); /* Function reset */
- alc5505_coef_set(codec, 0x61b8, 0x041b3302);
- alc5505_coef_set(codec, 0x61b8, 0x04173302);
- alc5505_coef_set(codec, 0x61b8, 0x04163302);
- alc5505_coef_set(codec, 0x8800, 0x348b328b); /* DRAM control */
- alc5505_coef_set(codec, 0x8808, 0x00020022); /* DRAM control */
- alc5505_coef_set(codec, 0x8818, 0x00000400); /* DRAM control */
-
- val = alc5505_coef_get(codec, 0x6200) >> 16; /* Read revision ID */
- if (val <= 3)
- alc5505_coef_set(codec, 0x6220, 0x2002010f); /* I/O PAD Configuration */
- else
- alc5505_coef_set(codec, 0x6220, 0x6002018f);
-
- alc5505_coef_set(codec, 0x61ac, 0x055525f0); /**/
- alc5505_coef_set(codec, 0x61c0, 0x12230080); /* Clock control */
- alc5505_coef_set(codec, 0x61b4, 0x040e2b02); /* PLL2 control */
- alc5505_coef_set(codec, 0x61bc, 0x010234f8); /* OSC Control */
- alc5505_coef_set(codec, 0x880c, 0x00000004); /* DRAM Function control */
- alc5505_coef_set(codec, 0x880c, 0x00000003);
- alc5505_coef_set(codec, 0x880c, 0x00000010);
-
-#ifdef HALT_REALTEK_ALC5505
- alc5505_dsp_halt(codec);
-#endif
-}
-
-#ifdef HALT_REALTEK_ALC5505
-#define alc5505_dsp_suspend(codec) do { } while (0) /* NOP */
-#define alc5505_dsp_resume(codec) do { } while (0) /* NOP */
-#else
-#define alc5505_dsp_suspend(codec) alc5505_dsp_halt(codec)
-#define alc5505_dsp_resume(codec) alc5505_dsp_back_from_halt(codec)
-#endif
-
-static int alc269_suspend(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- if (spec->has_alc5505_dsp)
- alc5505_dsp_suspend(codec);
-
- return alc_suspend(codec);
-}
-
-static int alc269_resume(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- if (spec->codec_variant == ALC269_TYPE_ALC269VB)
- alc269vb_toggle_power_output(codec, 0);
- if (spec->codec_variant == ALC269_TYPE_ALC269VB &&
- (alc_get_coef0(codec) & 0x00ff) == 0x018) {
- msleep(150);
- }
-
- codec->patch_ops.init(codec);
-
- if (spec->codec_variant == ALC269_TYPE_ALC269VB)
- alc269vb_toggle_power_output(codec, 1);
- if (spec->codec_variant == ALC269_TYPE_ALC269VB &&
- (alc_get_coef0(codec) & 0x00ff) == 0x017) {
- msleep(200);
- }
-
- snd_hda_regmap_sync(codec);
- hda_call_check_power_status(codec, 0x01);
-
- /* on some machine, the BIOS will clear the codec gpio data when enter
- * suspend, and won't restore the data after resume, so we restore it
- * in the driver.
- */
- if (spec->gpio_data)
- alc_write_gpio_data(codec);
-
- if (spec->has_alc5505_dsp)
- alc5505_dsp_resume(codec);
-
- return 0;
-}
-
-static void alc269_fixup_pincfg_no_hp_to_lineout(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE)
- spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
-}
-
-static void alc269_fixup_pincfg_U7x7_headset_mic(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- unsigned int cfg_headphone = snd_hda_codec_get_pincfg(codec, 0x21);
- unsigned int cfg_headset_mic = snd_hda_codec_get_pincfg(codec, 0x19);
-
- if (cfg_headphone && cfg_headset_mic == 0x411111f0)
- snd_hda_codec_set_pincfg(codec, 0x19,
- (cfg_headphone & ~AC_DEFCFG_DEVICE) |
- (AC_JACK_MIC_IN << AC_DEFCFG_DEVICE_SHIFT));
-}
-
-static void alc269_fixup_hweq(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_INIT)
- alc_update_coef_idx(codec, 0x1e, 0, 0x80);
-}
-
-static void alc269_fixup_headset_mic(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE)
- spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
-}
-
-static void alc271_fixup_dmic(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- static const struct hda_verb verbs[] = {
- {0x20, AC_VERB_SET_COEF_INDEX, 0x0d},
- {0x20, AC_VERB_SET_PROC_COEF, 0x4000},
- {}
- };
- unsigned int cfg;
-
- if (strcmp(codec->core.chip_name, "ALC271X") &&
- strcmp(codec->core.chip_name, "ALC269VB"))
- return;
- cfg = snd_hda_codec_get_pincfg(codec, 0x12);
- if (get_defcfg_connect(cfg) == AC_JACK_PORT_FIXED)
- snd_hda_sequence_write(codec, verbs);
-}
-
-/* Fix the speaker amp after resume, etc */
-static void alc269vb_fixup_aspire_e1_coef(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- if (action == HDA_FIXUP_ACT_INIT)
- alc_update_coef_idx(codec, 0x0d, 0x6000, 0x6000);
-}
-
-static void alc269_fixup_pcm_44k(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
-
- if (action != HDA_FIXUP_ACT_PROBE)
- return;
-
- /* Due to a hardware problem on Lenovo Ideadpad, we need to
- * fix the sample rate of analog I/O to 44.1kHz
- */
- spec->gen.stream_analog_playback = &alc269_44k_pcm_analog_playback;
- spec->gen.stream_analog_capture = &alc269_44k_pcm_analog_capture;
-}
-
-static void alc269_fixup_stereo_dmic(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- /* The digital-mic unit sends PDM (differential signal) instead of
- * the standard PCM, thus you can't record a valid mono stream as is.
- * Below is a workaround specific to ALC269 to control the dmic
- * signal source as mono.
- */
- if (action == HDA_FIXUP_ACT_INIT)
- alc_update_coef_idx(codec, 0x07, 0, 0x80);
-}
-
-static void alc269_quanta_automute(struct hda_codec *codec)
-{
- snd_hda_gen_update_outputs(codec);
-
- alc_write_coef_idx(codec, 0x0c, 0x680);
- alc_write_coef_idx(codec, 0x0c, 0x480);
-}
-
-static void alc269_fixup_quanta_mute(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
- if (action != HDA_FIXUP_ACT_PROBE)
- return;
- spec->gen.automute_hook = alc269_quanta_automute;
-}
-
-static void alc269_x101_hp_automute_hook(struct hda_codec *codec,
- struct hda_jack_callback *jack)
-{
- struct alc_spec *spec = codec->spec;
- int vref;
- msleep(200);
- snd_hda_gen_hp_automute(codec, jack);
-
- vref = spec->gen.hp_jack_present ? PIN_VREF80 : 0;
- msleep(100);
- snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
- vref);
- msleep(500);
- snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
- vref);
-}
-
-/*
- * Magic sequence to make Huawei Matebook X right speaker working (bko#197801)
- */
-struct hda_alc298_mbxinit {
- unsigned char value_0x23;
- unsigned char value_0x25;
-};
-
-static void alc298_huawei_mbx_stereo_seq(struct hda_codec *codec,
- const struct hda_alc298_mbxinit *initval,
- bool first)
-{
- snd_hda_codec_write(codec, 0x06, 0, AC_VERB_SET_DIGI_CONVERT_3, 0x0);
- alc_write_coef_idx(codec, 0x26, 0xb000);
-
- if (first)
- snd_hda_codec_write(codec, 0x21, 0, AC_VERB_GET_PIN_SENSE, 0x0);
-
- snd_hda_codec_write(codec, 0x6, 0, AC_VERB_SET_DIGI_CONVERT_3, 0x80);
- alc_write_coef_idx(codec, 0x26, 0xf000);
- alc_write_coef_idx(codec, 0x23, initval->value_0x23);
-
- if (initval->value_0x23 != 0x1e)
- alc_write_coef_idx(codec, 0x25, initval->value_0x25);
-
- snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0x26);
- snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, 0xb010);
-}
-
-static void alc298_fixup_huawei_mbx_stereo(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- /* Initialization magic */
- static const struct hda_alc298_mbxinit dac_init[] = {
- {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
- {0x10, 0x00}, {0x1a, 0x40}, {0x1b, 0x82}, {0x1c, 0x00},
- {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
- {0x20, 0xc2}, {0x21, 0xc8}, {0x22, 0x26}, {0x23, 0x24},
- {0x27, 0xff}, {0x28, 0xff}, {0x29, 0xff}, {0x2a, 0x8f},
- {0x2b, 0x02}, {0x2c, 0x48}, {0x2d, 0x34}, {0x2e, 0x00},
- {0x2f, 0x00},
- {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
- {0x34, 0x00}, {0x35, 0x01}, {0x36, 0x93}, {0x37, 0x0c},
- {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0xf8}, {0x38, 0x80},
- {}
- };
- const struct hda_alc298_mbxinit *seq;
-
- if (action != HDA_FIXUP_ACT_INIT)
- return;
-
- /* Start */
- snd_hda_codec_write(codec, 0x06, 0, AC_VERB_SET_DIGI_CONVERT_3, 0x00);
- snd_hda_codec_write(codec, 0x06, 0, AC_VERB_SET_DIGI_CONVERT_3, 0x80);
- alc_write_coef_idx(codec, 0x26, 0xf000);
- alc_write_coef_idx(codec, 0x22, 0x31);
- alc_write_coef_idx(codec, 0x23, 0x0b);
- alc_write_coef_idx(codec, 0x25, 0x00);
- snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0x26);
- snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, 0xb010);
-
- for (seq = dac_init; seq->value_0x23; seq++)
- alc298_huawei_mbx_stereo_seq(codec, seq, seq == dac_init);
-}
-
-static void alc269_fixup_x101_headset_mic(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
- spec->gen.hp_automute_hook = alc269_x101_hp_automute_hook;
- }
-}
-
-static void alc_update_vref_led(struct hda_codec *codec, hda_nid_t pin,
- bool polarity, bool on)
-{
- unsigned int pinval;
-
- if (!pin)
- return;
- if (polarity)
- on = !on;
- pinval = snd_hda_codec_get_pin_target(codec, pin);
- pinval &= ~AC_PINCTL_VREFEN;
- pinval |= on ? AC_PINCTL_VREF_80 : AC_PINCTL_VREF_HIZ;
- /* temporarily power up/down for setting VREF */
- snd_hda_power_up_pm(codec);
- snd_hda_set_pin_ctl_cache(codec, pin, pinval);
- snd_hda_power_down_pm(codec);
-}
-
-/* update mute-LED according to the speaker mute state via mic VREF pin */
-static int vref_mute_led_set(struct led_classdev *led_cdev,
- enum led_brightness brightness)
-{
- struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent);
- struct alc_spec *spec = codec->spec;
-
- alc_update_vref_led(codec, spec->mute_led_nid,
- spec->mute_led_polarity, brightness);
- return 0;
-}
-
-/* Make sure the led works even in runtime suspend */
-static unsigned int led_power_filter(struct hda_codec *codec,
- hda_nid_t nid,
- unsigned int power_state)
-{
- struct alc_spec *spec = codec->spec;
-
- if (power_state != AC_PWRST_D3 || nid == 0 ||
- (nid != spec->mute_led_nid && nid != spec->cap_mute_led_nid))
- return power_state;
-
- /* Set pin ctl again, it might have just been set to 0 */
- snd_hda_set_pin_ctl(codec, nid,
- snd_hda_codec_get_pin_target(codec, nid));
-
- return snd_hda_gen_path_power_filter(codec, nid, power_state);
-}
-
-static void alc269_fixup_hp_mute_led(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
- const struct dmi_device *dev = NULL;
-
- if (action != HDA_FIXUP_ACT_PRE_PROBE)
- return;
-
- while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, NULL, dev))) {
- int pol, pin;
- if (sscanf(dev->name, "HP_Mute_LED_%d_%x", &pol, &pin) != 2)
- continue;
- if (pin < 0x0a || pin >= 0x10)
- break;
- spec->mute_led_polarity = pol;
- spec->mute_led_nid = pin - 0x0a + 0x18;
- snd_hda_gen_add_mute_led_cdev(codec, vref_mute_led_set);
- codec->power_filter = led_power_filter;
- codec_dbg(codec,
- "Detected mute LED for %x:%d\n", spec->mute_led_nid,
- spec->mute_led_polarity);
- break;
- }
-}
-
-static void alc269_fixup_hp_mute_led_micx(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action, hda_nid_t pin)
-{
- struct alc_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->mute_led_polarity = 0;
- spec->mute_led_nid = pin;
- snd_hda_gen_add_mute_led_cdev(codec, vref_mute_led_set);
- codec->power_filter = led_power_filter;
- }
-}
-
-static void alc269_fixup_hp_mute_led_mic1(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- alc269_fixup_hp_mute_led_micx(codec, fix, action, 0x18);
-}
-
-static void alc269_fixup_hp_mute_led_mic2(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- alc269_fixup_hp_mute_led_micx(codec, fix, action, 0x19);
-}
-
-static void alc269_fixup_hp_mute_led_mic3(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- alc269_fixup_hp_mute_led_micx(codec, fix, action, 0x1b);
-}
-
-/* update LED status via GPIO */
-static void alc_update_gpio_led(struct hda_codec *codec, unsigned int mask,
- int polarity, bool enabled)
-{
- if (polarity)
- enabled = !enabled;
- alc_update_gpio_data(codec, mask, !enabled); /* muted -> LED on */
-}
-
-/* turn on/off mute LED via GPIO per vmaster hook */
-static int gpio_mute_led_set(struct led_classdev *led_cdev,
- enum led_brightness brightness)
-{
- struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent);
- struct alc_spec *spec = codec->spec;
-
- alc_update_gpio_led(codec, spec->gpio_mute_led_mask,
- spec->mute_led_polarity, !brightness);
- return 0;
-}
-
-/* turn on/off mic-mute LED via GPIO per capture hook */
-static int micmute_led_set(struct led_classdev *led_cdev,
- enum led_brightness brightness)
-{
- struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent);
- struct alc_spec *spec = codec->spec;
-
- alc_update_gpio_led(codec, spec->gpio_mic_led_mask,
- spec->micmute_led_polarity, !brightness);
- return 0;
-}
-
-/* setup mute and mic-mute GPIO bits, add hooks appropriately */
-static void alc_fixup_hp_gpio_led(struct hda_codec *codec,
- int action,
- unsigned int mute_mask,
- unsigned int micmute_mask)
-{
- struct alc_spec *spec = codec->spec;
-
- alc_fixup_gpio(codec, action, mute_mask | micmute_mask);
-
- if (action != HDA_FIXUP_ACT_PRE_PROBE)
- return;
- if (mute_mask) {
- spec->gpio_mute_led_mask = mute_mask;
- snd_hda_gen_add_mute_led_cdev(codec, gpio_mute_led_set);
- }
- if (micmute_mask) {
- spec->gpio_mic_led_mask = micmute_mask;
- snd_hda_gen_add_micmute_led_cdev(codec, micmute_led_set);
- }
-}
-
-static void alc236_fixup_hp_gpio_led(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- alc_fixup_hp_gpio_led(codec, action, 0x02, 0x01);
-}
-
-static void alc269_fixup_hp_gpio_led(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- alc_fixup_hp_gpio_led(codec, action, 0x08, 0x10);
-}
-
-static void alc285_fixup_hp_gpio_led(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- alc_fixup_hp_gpio_led(codec, action, 0x04, 0x01);
-}
-
-static void alc286_fixup_hp_gpio_led(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- alc_fixup_hp_gpio_led(codec, action, 0x02, 0x20);
-}
-
-static void alc287_fixup_hp_gpio_led(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- alc_fixup_hp_gpio_led(codec, action, 0x10, 0);
-}
-
-static void alc245_fixup_hp_gpio_led(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE)
- spec->micmute_led_polarity = 1;
- alc_fixup_hp_gpio_led(codec, action, 0, 0x04);
-}
-
-/* turn on/off mic-mute LED per capture hook via VREF change */
-static int vref_micmute_led_set(struct led_classdev *led_cdev,
- enum led_brightness brightness)
-{
- struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent);
- struct alc_spec *spec = codec->spec;
-
- alc_update_vref_led(codec, spec->cap_mute_led_nid,
- spec->micmute_led_polarity, brightness);
- return 0;
-}
-
-static void alc269_fixup_hp_gpio_mic1_led(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
-
- alc_fixup_hp_gpio_led(codec, action, 0x08, 0);
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- /* Like hp_gpio_mic1_led, but also needs GPIO4 low to
- * enable headphone amp
- */
- spec->gpio_mask |= 0x10;
- spec->gpio_dir |= 0x10;
- spec->cap_mute_led_nid = 0x18;
- snd_hda_gen_add_micmute_led_cdev(codec, vref_micmute_led_set);
- codec->power_filter = led_power_filter;
- }
-}
-
-static void alc280_fixup_hp_gpio4(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
-
- alc_fixup_hp_gpio_led(codec, action, 0x08, 0);
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->cap_mute_led_nid = 0x18;
- snd_hda_gen_add_micmute_led_cdev(codec, vref_micmute_led_set);
- codec->power_filter = led_power_filter;
- }
-}
-
-/* HP Spectre x360 14 model needs a unique workaround for enabling the amp;
- * it needs to toggle the GPIO0 once on and off at each time (bko#210633)
- */
-static void alc245_fixup_hp_x360_amp(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- spec->gpio_mask |= 0x01;
- spec->gpio_dir |= 0x01;
- break;
- case HDA_FIXUP_ACT_INIT:
- /* need to toggle GPIO to enable the amp */
- alc_update_gpio_data(codec, 0x01, true);
- msleep(100);
- alc_update_gpio_data(codec, 0x01, false);
- break;
- }
-}
-
-/* toggle GPIO2 at each time stream is started; we use PREPARE state instead */
-static void alc274_hp_envy_pcm_hook(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream,
- int action)
-{
- switch (action) {
- case HDA_GEN_PCM_ACT_PREPARE:
- alc_update_gpio_data(codec, 0x04, true);
- break;
- case HDA_GEN_PCM_ACT_CLEANUP:
- alc_update_gpio_data(codec, 0x04, false);
- break;
- }
-}
-
-static void alc274_fixup_hp_envy_gpio(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- struct alc_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PROBE) {
- spec->gpio_mask |= 0x04;
- spec->gpio_dir |= 0x04;
- spec->gen.pcm_playback_hook = alc274_hp_envy_pcm_hook;
- }
-}
-
-static void alc_update_coef_led(struct hda_codec *codec,
- struct alc_coef_led *led,
- bool polarity, bool on)
-{
- if (polarity)
- on = !on;
- /* temporarily power up/down for setting COEF bit */
- alc_update_coef_idx(codec, led->idx, led->mask,
- on ? led->on : led->off);
-}
-
-/* update mute-LED according to the speaker mute state via COEF bit */
-static int coef_mute_led_set(struct led_classdev *led_cdev,
- enum led_brightness brightness)
-{
- struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent);
- struct alc_spec *spec = codec->spec;
-
- alc_update_coef_led(codec, &spec->mute_led_coef,
- spec->mute_led_polarity, brightness);
- return 0;
-}
-
-static void alc285_fixup_hp_mute_led_coefbit(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- struct alc_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->mute_led_polarity = 0;
- spec->mute_led_coef.idx = 0x0b;
- spec->mute_led_coef.mask = 1 << 3;
- spec->mute_led_coef.on = 1 << 3;
- spec->mute_led_coef.off = 0;
- snd_hda_gen_add_mute_led_cdev(codec, coef_mute_led_set);
- }
-}
-
-static void alc236_fixup_hp_mute_led_coefbit(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- struct alc_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->mute_led_polarity = 0;
- spec->mute_led_coef.idx = 0x34;
- spec->mute_led_coef.mask = 1 << 5;
- spec->mute_led_coef.on = 0;
- spec->mute_led_coef.off = 1 << 5;
- snd_hda_gen_add_mute_led_cdev(codec, coef_mute_led_set);
- }
-}
-
-static void alc236_fixup_hp_mute_led_coefbit2(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->mute_led_polarity = 0;
- spec->mute_led_coef.idx = 0x07;
- spec->mute_led_coef.mask = 1;
- spec->mute_led_coef.on = 1;
- spec->mute_led_coef.off = 0;
- snd_hda_gen_add_mute_led_cdev(codec, coef_mute_led_set);
- }
-}
-
-static void alc245_fixup_hp_mute_led_coefbit(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- struct alc_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->mute_led_polarity = 0;
- spec->mute_led_coef.idx = 0x0b;
- spec->mute_led_coef.mask = 3 << 2;
- spec->mute_led_coef.on = 2 << 2;
- spec->mute_led_coef.off = 1 << 2;
- snd_hda_gen_add_mute_led_cdev(codec, coef_mute_led_set);
- }
-}
-
-static void alc245_fixup_hp_mute_led_v1_coefbit(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- struct alc_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->mute_led_polarity = 0;
- spec->mute_led_coef.idx = 0x0b;
- spec->mute_led_coef.mask = 1 << 3;
- spec->mute_led_coef.on = 1 << 3;
- spec->mute_led_coef.off = 0;
- snd_hda_gen_add_mute_led_cdev(codec, coef_mute_led_set);
- }
-}
-
-/* turn on/off mic-mute LED per capture hook by coef bit */
-static int coef_micmute_led_set(struct led_classdev *led_cdev,
- enum led_brightness brightness)
-{
- struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent);
- struct alc_spec *spec = codec->spec;
-
- alc_update_coef_led(codec, &spec->mic_led_coef,
- spec->micmute_led_polarity, brightness);
- return 0;
-}
-
-static void alc285_fixup_hp_coef_micmute_led(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->mic_led_coef.idx = 0x19;
- spec->mic_led_coef.mask = 1 << 13;
- spec->mic_led_coef.on = 1 << 13;
- spec->mic_led_coef.off = 0;
- snd_hda_gen_add_micmute_led_cdev(codec, coef_micmute_led_set);
- }
-}
-
-static void alc285_fixup_hp_gpio_micmute_led(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE)
- spec->micmute_led_polarity = 1;
- alc_fixup_hp_gpio_led(codec, action, 0, 0x04);
-}
-
-static void alc236_fixup_hp_coef_micmute_led(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->mic_led_coef.idx = 0x35;
- spec->mic_led_coef.mask = 3 << 2;
- spec->mic_led_coef.on = 2 << 2;
- spec->mic_led_coef.off = 1 << 2;
- snd_hda_gen_add_micmute_led_cdev(codec, coef_micmute_led_set);
- }
-}
-
-static void alc295_fixup_hp_mute_led_coefbit11(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->mute_led_polarity = 0;
- spec->mute_led_coef.idx = 0xb;
- spec->mute_led_coef.mask = 3 << 3;
- spec->mute_led_coef.on = 1 << 3;
- spec->mute_led_coef.off = 1 << 4;
- snd_hda_gen_add_mute_led_cdev(codec, coef_mute_led_set);
- }
-}
-
-static void alc285_fixup_hp_mute_led(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- alc285_fixup_hp_mute_led_coefbit(codec, fix, action);
- alc285_fixup_hp_coef_micmute_led(codec, fix, action);
-}
-
-static void alc285_fixup_hp_spectre_x360_mute_led(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- alc285_fixup_hp_mute_led_coefbit(codec, fix, action);
- alc285_fixup_hp_gpio_micmute_led(codec, fix, action);
-}
-
-static void alc236_fixup_hp_mute_led(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- alc236_fixup_hp_mute_led_coefbit(codec, fix, action);
- alc236_fixup_hp_coef_micmute_led(codec, fix, action);
-}
-
-static void alc236_fixup_hp_micmute_led_vref(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->cap_mute_led_nid = 0x1a;
- snd_hda_gen_add_micmute_led_cdev(codec, vref_micmute_led_set);
- codec->power_filter = led_power_filter;
- }
-}
-
-static void alc236_fixup_hp_mute_led_micmute_vref(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- alc236_fixup_hp_mute_led_coefbit(codec, fix, action);
- alc236_fixup_hp_micmute_led_vref(codec, fix, action);
-}
-
-static inline void alc298_samsung_write_coef_pack(struct hda_codec *codec,
- const unsigned short coefs[2])
-{
- alc_write_coef_idx(codec, 0x23, coefs[0]);
- alc_write_coef_idx(codec, 0x25, coefs[1]);
- alc_write_coef_idx(codec, 0x26, 0xb011);
-}
-
-struct alc298_samsung_amp_desc {
- unsigned char nid;
- unsigned short init_seq[2][2];
-};
-
-static void alc298_fixup_samsung_amp(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- int i, j;
- static const unsigned short init_seq[][2] = {
- { 0x19, 0x00 }, { 0x20, 0xc0 }, { 0x22, 0x44 }, { 0x23, 0x08 },
- { 0x24, 0x85 }, { 0x25, 0x41 }, { 0x35, 0x40 }, { 0x36, 0x01 },
- { 0x38, 0x81 }, { 0x3a, 0x03 }, { 0x3b, 0x81 }, { 0x40, 0x3e },
- { 0x41, 0x07 }, { 0x400, 0x1 }
- };
- static const struct alc298_samsung_amp_desc amps[] = {
- { 0x3a, { { 0x18, 0x1 }, { 0x26, 0x0 } } },
- { 0x39, { { 0x18, 0x2 }, { 0x26, 0x1 } } }
- };
-
- if (action != HDA_FIXUP_ACT_INIT)
- return;
-
- for (i = 0; i < ARRAY_SIZE(amps); i++) {
- alc_write_coef_idx(codec, 0x22, amps[i].nid);
-
- for (j = 0; j < ARRAY_SIZE(amps[i].init_seq); j++)
- alc298_samsung_write_coef_pack(codec, amps[i].init_seq[j]);
-
- for (j = 0; j < ARRAY_SIZE(init_seq); j++)
- alc298_samsung_write_coef_pack(codec, init_seq[j]);
- }
-}
-
-struct alc298_samsung_v2_amp_desc {
- unsigned short nid;
- int init_seq_size;
- unsigned short init_seq[18][2];
-};
-
-static const struct alc298_samsung_v2_amp_desc
-alc298_samsung_v2_amp_desc_tbl[] = {
- { 0x38, 18, {
- { 0x23e1, 0x0000 }, { 0x2012, 0x006f }, { 0x2014, 0x0000 },
- { 0x201b, 0x0001 }, { 0x201d, 0x0001 }, { 0x201f, 0x00fe },
- { 0x2021, 0x0000 }, { 0x2022, 0x0010 }, { 0x203d, 0x0005 },
- { 0x203f, 0x0003 }, { 0x2050, 0x002c }, { 0x2076, 0x000e },
- { 0x207c, 0x004a }, { 0x2081, 0x0003 }, { 0x2399, 0x0003 },
- { 0x23a4, 0x00b5 }, { 0x23a5, 0x0001 }, { 0x23ba, 0x0094 }
- }},
- { 0x39, 18, {
- { 0x23e1, 0x0000 }, { 0x2012, 0x006f }, { 0x2014, 0x0000 },
- { 0x201b, 0x0002 }, { 0x201d, 0x0002 }, { 0x201f, 0x00fd },
- { 0x2021, 0x0001 }, { 0x2022, 0x0010 }, { 0x203d, 0x0005 },
- { 0x203f, 0x0003 }, { 0x2050, 0x002c }, { 0x2076, 0x000e },
- { 0x207c, 0x004a }, { 0x2081, 0x0003 }, { 0x2399, 0x0003 },
- { 0x23a4, 0x00b5 }, { 0x23a5, 0x0001 }, { 0x23ba, 0x0094 }
- }},
- { 0x3c, 15, {
- { 0x23e1, 0x0000 }, { 0x2012, 0x006f }, { 0x2014, 0x0000 },
- { 0x201b, 0x0001 }, { 0x201d, 0x0001 }, { 0x201f, 0x00fe },
- { 0x2021, 0x0000 }, { 0x2022, 0x0010 }, { 0x203d, 0x0005 },
- { 0x203f, 0x0003 }, { 0x2050, 0x002c }, { 0x2076, 0x000e },
- { 0x207c, 0x004a }, { 0x2081, 0x0003 }, { 0x23ba, 0x008d }
- }},
- { 0x3d, 15, {
- { 0x23e1, 0x0000 }, { 0x2012, 0x006f }, { 0x2014, 0x0000 },
- { 0x201b, 0x0002 }, { 0x201d, 0x0002 }, { 0x201f, 0x00fd },
- { 0x2021, 0x0001 }, { 0x2022, 0x0010 }, { 0x203d, 0x0005 },
- { 0x203f, 0x0003 }, { 0x2050, 0x002c }, { 0x2076, 0x000e },
- { 0x207c, 0x004a }, { 0x2081, 0x0003 }, { 0x23ba, 0x008d }
- }}
-};
-
-static void alc298_samsung_v2_enable_amps(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- static const unsigned short enable_seq[][2] = {
- { 0x203a, 0x0081 }, { 0x23ff, 0x0001 },
- };
- int i, j;
-
- for (i = 0; i < spec->num_speaker_amps; i++) {
- alc_write_coef_idx(codec, 0x22, alc298_samsung_v2_amp_desc_tbl[i].nid);
- for (j = 0; j < ARRAY_SIZE(enable_seq); j++)
- alc298_samsung_write_coef_pack(codec, enable_seq[j]);
- codec_dbg(codec, "alc298_samsung_v2: Enabled speaker amp 0x%02x\n",
- alc298_samsung_v2_amp_desc_tbl[i].nid);
- }
-}
-
-static void alc298_samsung_v2_disable_amps(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- static const unsigned short disable_seq[][2] = {
- { 0x23ff, 0x0000 }, { 0x203a, 0x0080 },
- };
- int i, j;
-
- for (i = 0; i < spec->num_speaker_amps; i++) {
- alc_write_coef_idx(codec, 0x22, alc298_samsung_v2_amp_desc_tbl[i].nid);
- for (j = 0; j < ARRAY_SIZE(disable_seq); j++)
- alc298_samsung_write_coef_pack(codec, disable_seq[j]);
- codec_dbg(codec, "alc298_samsung_v2: Disabled speaker amp 0x%02x\n",
- alc298_samsung_v2_amp_desc_tbl[i].nid);
- }
-}
-
-static void alc298_samsung_v2_playback_hook(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream,
- int action)
-{
- /* Dynamically enable/disable speaker amps before and after playback */
- if (action == HDA_GEN_PCM_ACT_OPEN)
- alc298_samsung_v2_enable_amps(codec);
- if (action == HDA_GEN_PCM_ACT_CLOSE)
- alc298_samsung_v2_disable_amps(codec);
-}
-
-static void alc298_samsung_v2_init_amps(struct hda_codec *codec,
- int num_speaker_amps)
-{
- struct alc_spec *spec = codec->spec;
- int i, j;
-
- /* Set spec's num_speaker_amps before doing anything else */
- spec->num_speaker_amps = num_speaker_amps;
-
- /* Disable speaker amps before init to prevent any physical damage */
- alc298_samsung_v2_disable_amps(codec);
-
- /* Initialize the speaker amps */
- for (i = 0; i < spec->num_speaker_amps; i++) {
- alc_write_coef_idx(codec, 0x22, alc298_samsung_v2_amp_desc_tbl[i].nid);
- for (j = 0; j < alc298_samsung_v2_amp_desc_tbl[i].init_seq_size; j++) {
- alc298_samsung_write_coef_pack(codec,
- alc298_samsung_v2_amp_desc_tbl[i].init_seq[j]);
- }
- alc_write_coef_idx(codec, 0x89, 0x0);
- codec_dbg(codec, "alc298_samsung_v2: Initialized speaker amp 0x%02x\n",
- alc298_samsung_v2_amp_desc_tbl[i].nid);
- }
-
- /* register hook to enable speaker amps only when they are needed */
- spec->gen.pcm_playback_hook = alc298_samsung_v2_playback_hook;
-}
-
-static void alc298_fixup_samsung_amp_v2_2_amps(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_PROBE)
- alc298_samsung_v2_init_amps(codec, 2);
-}
-
-static void alc298_fixup_samsung_amp_v2_4_amps(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_PROBE)
- alc298_samsung_v2_init_amps(codec, 4);
-}
-
-static void gpio2_mic_hotkey_event(struct hda_codec *codec,
- struct hda_jack_callback *event)
-{
- struct alc_spec *spec = codec->spec;
-
- /* GPIO2 just toggles on a keypress/keyrelease cycle. Therefore
- send both key on and key off event for every interrupt. */
- input_report_key(spec->kb_dev, spec->alc_mute_keycode_map[ALC_KEY_MICMUTE_INDEX], 1);
- input_sync(spec->kb_dev);
- input_report_key(spec->kb_dev, spec->alc_mute_keycode_map[ALC_KEY_MICMUTE_INDEX], 0);
- input_sync(spec->kb_dev);
-}
-
-static int alc_register_micmute_input_device(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- int i;
-
- spec->kb_dev = input_allocate_device();
- if (!spec->kb_dev) {
- codec_err(codec, "Out of memory (input_allocate_device)\n");
- return -ENOMEM;
- }
-
- spec->alc_mute_keycode_map[ALC_KEY_MICMUTE_INDEX] = KEY_MICMUTE;
-
- spec->kb_dev->name = "Microphone Mute Button";
- spec->kb_dev->evbit[0] = BIT_MASK(EV_KEY);
- spec->kb_dev->keycodesize = sizeof(spec->alc_mute_keycode_map[0]);
- spec->kb_dev->keycodemax = ARRAY_SIZE(spec->alc_mute_keycode_map);
- spec->kb_dev->keycode = spec->alc_mute_keycode_map;
- for (i = 0; i < ARRAY_SIZE(spec->alc_mute_keycode_map); i++)
- set_bit(spec->alc_mute_keycode_map[i], spec->kb_dev->keybit);
-
- if (input_register_device(spec->kb_dev)) {
- codec_err(codec, "input_register_device failed\n");
- input_free_device(spec->kb_dev);
- spec->kb_dev = NULL;
- return -ENOMEM;
- }
-
- return 0;
-}
-
-/* GPIO1 = set according to SKU external amp
- * GPIO2 = mic mute hotkey
- * GPIO3 = mute LED
- * GPIO4 = mic mute LED
- */
-static void alc280_fixup_hp_gpio2_mic_hotkey(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
-
- alc_fixup_hp_gpio_led(codec, action, 0x08, 0x10);
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->init_amp = ALC_INIT_DEFAULT;
- if (alc_register_micmute_input_device(codec) != 0)
- return;
-
- spec->gpio_mask |= 0x06;
- spec->gpio_dir |= 0x02;
- spec->gpio_data |= 0x02;
- snd_hda_codec_write_cache(codec, codec->core.afg, 0,
- AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x04);
- snd_hda_jack_detect_enable_callback(codec, codec->core.afg,
- gpio2_mic_hotkey_event);
- return;
- }
-
- if (!spec->kb_dev)
- return;
-
- switch (action) {
- case HDA_FIXUP_ACT_FREE:
- input_unregister_device(spec->kb_dev);
- spec->kb_dev = NULL;
- }
-}
-
-/* Line2 = mic mute hotkey
- * GPIO2 = mic mute LED
- */
-static void alc233_fixup_lenovo_line2_mic_hotkey(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
-
- alc_fixup_hp_gpio_led(codec, action, 0, 0x04);
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->init_amp = ALC_INIT_DEFAULT;
- if (alc_register_micmute_input_device(codec) != 0)
- return;
-
- snd_hda_jack_detect_enable_callback(codec, 0x1b,
- gpio2_mic_hotkey_event);
- return;
- }
-
- if (!spec->kb_dev)
- return;
-
- switch (action) {
- case HDA_FIXUP_ACT_FREE:
- input_unregister_device(spec->kb_dev);
- spec->kb_dev = NULL;
- }
-}
-
-static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
-
- alc269_fixup_hp_mute_led_micx(codec, fix, action, 0x1a);
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->cap_mute_led_nid = 0x18;
- snd_hda_gen_add_micmute_led_cdev(codec, vref_micmute_led_set);
- }
-}
-
-static void alc233_fixup_lenovo_low_en_micmute_led(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE)
- spec->micmute_led_polarity = 1;
- alc233_fixup_lenovo_line2_mic_hotkey(codec, fix, action);
-}
-
-static void alc_hp_mute_disable(struct hda_codec *codec, unsigned int delay)
-{
- if (delay <= 0)
- delay = 75;
- snd_hda_codec_write(codec, 0x21, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
- msleep(delay);
- snd_hda_codec_write(codec, 0x21, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
- msleep(delay);
-}
-
-static void alc_hp_enable_unmute(struct hda_codec *codec, unsigned int delay)
-{
- if (delay <= 0)
- delay = 75;
- snd_hda_codec_write(codec, 0x21, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
- msleep(delay);
- snd_hda_codec_write(codec, 0x21, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
- msleep(delay);
-}
-
-static const struct coef_fw alc225_pre_hsmode[] = {
- UPDATE_COEF(0x4a, 1<<8, 0),
- UPDATE_COEFEX(0x57, 0x05, 1<<14, 0),
- UPDATE_COEF(0x63, 3<<14, 3<<14),
- UPDATE_COEF(0x4a, 3<<4, 2<<4),
- UPDATE_COEF(0x4a, 3<<10, 3<<10),
- UPDATE_COEF(0x45, 0x3f<<10, 0x34<<10),
- UPDATE_COEF(0x4a, 3<<10, 0),
- {}
-};
-
-static void alc_headset_mode_unplugged(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- static const struct coef_fw coef0255[] = {
- WRITE_COEF(0x1b, 0x0c0b), /* LDO and MISC control */
- WRITE_COEF(0x45, 0xd089), /* UAJ function set to menual mode */
- UPDATE_COEFEX(0x57, 0x05, 1<<14, 0), /* Direct Drive HP Amp control(Set to verb control)*/
- WRITE_COEF(0x06, 0x6104), /* Set MIC2 Vref gate with HP */
- WRITE_COEFEX(0x57, 0x03, 0x8aa6), /* Direct Drive HP Amp control */
- {}
- };
- static const struct coef_fw coef0256[] = {
- WRITE_COEF(0x1b, 0x0c4b), /* LDO and MISC control */
- WRITE_COEF(0x45, 0xd089), /* UAJ function set to menual mode */
- WRITE_COEF(0x06, 0x6104), /* Set MIC2 Vref gate with HP */
- WRITE_COEFEX(0x57, 0x03, 0x09a3), /* Direct Drive HP Amp control */
- UPDATE_COEFEX(0x57, 0x05, 1<<14, 0), /* Direct Drive HP Amp control(Set to verb control)*/
- {}
- };
- static const struct coef_fw coef0233[] = {
- WRITE_COEF(0x1b, 0x0c0b),
- WRITE_COEF(0x45, 0xc429),
- UPDATE_COEF(0x35, 0x4000, 0),
- WRITE_COEF(0x06, 0x2104),
- WRITE_COEF(0x1a, 0x0001),
- WRITE_COEF(0x26, 0x0004),
- WRITE_COEF(0x32, 0x42a3),
- {}
- };
- static const struct coef_fw coef0288[] = {
- UPDATE_COEF(0x4f, 0xfcc0, 0xc400),
- UPDATE_COEF(0x50, 0x2000, 0x2000),
- UPDATE_COEF(0x56, 0x0006, 0x0006),
- UPDATE_COEF(0x66, 0x0008, 0),
- UPDATE_COEF(0x67, 0x2000, 0),
- {}
- };
- static const struct coef_fw coef0298[] = {
- UPDATE_COEF(0x19, 0x1300, 0x0300),
- {}
- };
- static const struct coef_fw coef0292[] = {
- WRITE_COEF(0x76, 0x000e),
- WRITE_COEF(0x6c, 0x2400),
- WRITE_COEF(0x18, 0x7308),
- WRITE_COEF(0x6b, 0xc429),
- {}
- };
- static const struct coef_fw coef0293[] = {
- UPDATE_COEF(0x10, 7<<8, 6<<8), /* SET Line1 JD to 0 */
- UPDATE_COEFEX(0x57, 0x05, 1<<15|1<<13, 0x0), /* SET charge pump by verb */
- UPDATE_COEFEX(0x57, 0x03, 1<<10, 1<<10), /* SET EN_OSW to 1 */
- UPDATE_COEF(0x1a, 1<<3, 1<<3), /* Combo JD gating with LINE1-VREFO */
- WRITE_COEF(0x45, 0xc429), /* Set to TRS type */
- UPDATE_COEF(0x4a, 0x000f, 0x000e), /* Combo Jack auto detect */
- {}
- };
- static const struct coef_fw coef0668[] = {
- WRITE_COEF(0x15, 0x0d40),
- WRITE_COEF(0xb7, 0x802b),
- {}
- };
- static const struct coef_fw coef0225[] = {
- UPDATE_COEF(0x63, 3<<14, 0),
- {}
- };
- static const struct coef_fw coef0274[] = {
- UPDATE_COEF(0x4a, 0x0100, 0),
- UPDATE_COEFEX(0x57, 0x05, 0x4000, 0),
- UPDATE_COEF(0x6b, 0xf000, 0x5000),
- UPDATE_COEF(0x4a, 0x0010, 0),
- UPDATE_COEF(0x4a, 0x0c00, 0x0c00),
- WRITE_COEF(0x45, 0x5289),
- UPDATE_COEF(0x4a, 0x0c00, 0),
- {}
- };
-
- if (spec->no_internal_mic_pin) {
- alc_update_coef_idx(codec, 0x45, 0xf<<12 | 1<<10, 5<<12);
- return;
- }
-
- switch (codec->core.vendor_id) {
- case 0x10ec0255:
- alc_process_coef_fw(codec, coef0255);
- break;
- case 0x10ec0230:
- case 0x10ec0236:
- case 0x10ec0256:
- case 0x19e58326:
- alc_hp_mute_disable(codec, 75);
- alc_process_coef_fw(codec, coef0256);
- break;
- case 0x10ec0234:
- case 0x10ec0274:
- case 0x10ec0294:
- alc_process_coef_fw(codec, coef0274);
- break;
- case 0x10ec0233:
- case 0x10ec0283:
- alc_process_coef_fw(codec, coef0233);
- break;
- case 0x10ec0286:
- case 0x10ec0288:
- alc_process_coef_fw(codec, coef0288);
- break;
- case 0x10ec0298:
- alc_process_coef_fw(codec, coef0298);
- alc_process_coef_fw(codec, coef0288);
- break;
- case 0x10ec0292:
- alc_process_coef_fw(codec, coef0292);
- break;
- case 0x10ec0293:
- alc_process_coef_fw(codec, coef0293);
- break;
- case 0x10ec0668:
- alc_process_coef_fw(codec, coef0668);
- break;
- case 0x10ec0215:
- case 0x10ec0225:
- case 0x10ec0285:
- case 0x10ec0295:
- case 0x10ec0289:
- case 0x10ec0299:
- alc_hp_mute_disable(codec, 75);
- alc_process_coef_fw(codec, alc225_pre_hsmode);
- alc_process_coef_fw(codec, coef0225);
- break;
- case 0x10ec0867:
- alc_update_coefex_idx(codec, 0x57, 0x5, 1<<14, 0);
- break;
- }
- codec_dbg(codec, "Headset jack set to unplugged mode.\n");
-}
-
-
-static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin,
- hda_nid_t mic_pin)
-{
- static const struct coef_fw coef0255[] = {
- WRITE_COEFEX(0x57, 0x03, 0x8aa6),
- WRITE_COEF(0x06, 0x6100), /* Set MIC2 Vref gate to normal */
- {}
- };
- static const struct coef_fw coef0256[] = {
- UPDATE_COEFEX(0x57, 0x05, 1<<14, 1<<14), /* Direct Drive HP Amp control(Set to verb control)*/
- WRITE_COEFEX(0x57, 0x03, 0x09a3),
- WRITE_COEF(0x06, 0x6100), /* Set MIC2 Vref gate to normal */
- {}
- };
- static const struct coef_fw coef0233[] = {
- UPDATE_COEF(0x35, 0, 1<<14),
- WRITE_COEF(0x06, 0x2100),
- WRITE_COEF(0x1a, 0x0021),
- WRITE_COEF(0x26, 0x008c),
- {}
- };
- static const struct coef_fw coef0288[] = {
- UPDATE_COEF(0x4f, 0x00c0, 0),
- UPDATE_COEF(0x50, 0x2000, 0),
- UPDATE_COEF(0x56, 0x0006, 0),
- UPDATE_COEF(0x4f, 0xfcc0, 0xc400),
- UPDATE_COEF(0x66, 0x0008, 0x0008),
- UPDATE_COEF(0x67, 0x2000, 0x2000),
- {}
- };
- static const struct coef_fw coef0292[] = {
- WRITE_COEF(0x19, 0xa208),
- WRITE_COEF(0x2e, 0xacf0),
- {}
- };
- static const struct coef_fw coef0293[] = {
- UPDATE_COEFEX(0x57, 0x05, 0, 1<<15|1<<13), /* SET charge pump by verb */
- UPDATE_COEFEX(0x57, 0x03, 1<<10, 0), /* SET EN_OSW to 0 */
- UPDATE_COEF(0x1a, 1<<3, 0), /* Combo JD gating without LINE1-VREFO */
- {}
- };
- static const struct coef_fw coef0688[] = {
- WRITE_COEF(0xb7, 0x802b),
- WRITE_COEF(0xb5, 0x1040),
- UPDATE_COEF(0xc3, 0, 1<<12),
- {}
- };
- static const struct coef_fw coef0225[] = {
- UPDATE_COEFEX(0x57, 0x05, 1<<14, 1<<14),
- UPDATE_COEF(0x4a, 3<<4, 2<<4),
- UPDATE_COEF(0x63, 3<<14, 0),
- {}
- };
- static const struct coef_fw coef0274[] = {
- UPDATE_COEFEX(0x57, 0x05, 0x4000, 0x4000),
- UPDATE_COEF(0x4a, 0x0010, 0),
- UPDATE_COEF(0x6b, 0xf000, 0),
- {}
- };
-
- switch (codec->core.vendor_id) {
- case 0x10ec0255:
- alc_write_coef_idx(codec, 0x45, 0xc489);
- snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
- alc_process_coef_fw(codec, coef0255);
- snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
- break;
- case 0x10ec0230:
- case 0x10ec0236:
- case 0x10ec0256:
- case 0x19e58326:
- alc_write_coef_idx(codec, 0x45, 0xc489);
- snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
- alc_process_coef_fw(codec, coef0256);
- snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
- break;
- case 0x10ec0234:
- case 0x10ec0274:
- case 0x10ec0294:
- alc_write_coef_idx(codec, 0x45, 0x4689);
- snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
- alc_process_coef_fw(codec, coef0274);
- snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
- break;
- case 0x10ec0233:
- case 0x10ec0283:
- alc_write_coef_idx(codec, 0x45, 0xc429);
- snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
- alc_process_coef_fw(codec, coef0233);
- snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
- break;
- case 0x10ec0286:
- case 0x10ec0288:
- case 0x10ec0298:
- snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
- alc_process_coef_fw(codec, coef0288);
- snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
- break;
- case 0x10ec0292:
- snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
- alc_process_coef_fw(codec, coef0292);
- break;
- case 0x10ec0293:
- /* Set to TRS mode */
- alc_write_coef_idx(codec, 0x45, 0xc429);
- snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
- alc_process_coef_fw(codec, coef0293);
- snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
- break;
- case 0x10ec0867:
- alc_update_coefex_idx(codec, 0x57, 0x5, 0, 1<<14);
- fallthrough;
- case 0x10ec0221:
- case 0x10ec0662:
- snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
- snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
- break;
- case 0x10ec0668:
- alc_write_coef_idx(codec, 0x11, 0x0001);
- snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
- alc_process_coef_fw(codec, coef0688);
- snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
- break;
- case 0x10ec0215:
- case 0x10ec0225:
- case 0x10ec0285:
- case 0x10ec0295:
- case 0x10ec0289:
- case 0x10ec0299:
- alc_process_coef_fw(codec, alc225_pre_hsmode);
- alc_update_coef_idx(codec, 0x45, 0x3f<<10, 0x31<<10);
- snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
- alc_process_coef_fw(codec, coef0225);
- snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
- break;
- }
- codec_dbg(codec, "Headset jack set to mic-in mode.\n");
-}
-
-static void alc_headset_mode_default(struct hda_codec *codec)
-{
- static const struct coef_fw coef0225[] = {
- UPDATE_COEF(0x45, 0x3f<<10, 0x30<<10),
- UPDATE_COEF(0x45, 0x3f<<10, 0x31<<10),
- UPDATE_COEF(0x49, 3<<8, 0<<8),
- UPDATE_COEF(0x4a, 3<<4, 3<<4),
- UPDATE_COEF(0x63, 3<<14, 0),
- UPDATE_COEF(0x67, 0xf000, 0x3000),
- {}
- };
- static const struct coef_fw coef0255[] = {
- WRITE_COEF(0x45, 0xc089),
- WRITE_COEF(0x45, 0xc489),
- WRITE_COEFEX(0x57, 0x03, 0x8ea6),
- WRITE_COEF(0x49, 0x0049),
- {}
- };
- static const struct coef_fw coef0256[] = {
- WRITE_COEF(0x45, 0xc489),
- WRITE_COEFEX(0x57, 0x03, 0x0da3),
- WRITE_COEF(0x49, 0x0049),
- UPDATE_COEFEX(0x57, 0x05, 1<<14, 0), /* Direct Drive HP Amp control(Set to verb control)*/
- WRITE_COEF(0x06, 0x6100),
- {}
- };
- static const struct coef_fw coef0233[] = {
- WRITE_COEF(0x06, 0x2100),
- WRITE_COEF(0x32, 0x4ea3),
- {}
- };
- static const struct coef_fw coef0288[] = {
- UPDATE_COEF(0x4f, 0xfcc0, 0xc400), /* Set to TRS type */
- UPDATE_COEF(0x50, 0x2000, 0x2000),
- UPDATE_COEF(0x56, 0x0006, 0x0006),
- UPDATE_COEF(0x66, 0x0008, 0),
- UPDATE_COEF(0x67, 0x2000, 0),
- {}
- };
- static const struct coef_fw coef0292[] = {
- WRITE_COEF(0x76, 0x000e),
- WRITE_COEF(0x6c, 0x2400),
- WRITE_COEF(0x6b, 0xc429),
- WRITE_COEF(0x18, 0x7308),
- {}
- };
- static const struct coef_fw coef0293[] = {
- UPDATE_COEF(0x4a, 0x000f, 0x000e), /* Combo Jack auto detect */
- WRITE_COEF(0x45, 0xC429), /* Set to TRS type */
- UPDATE_COEF(0x1a, 1<<3, 0), /* Combo JD gating without LINE1-VREFO */
- {}
- };
- static const struct coef_fw coef0688[] = {
- WRITE_COEF(0x11, 0x0041),
- WRITE_COEF(0x15, 0x0d40),
- WRITE_COEF(0xb7, 0x802b),
- {}
- };
- static const struct coef_fw coef0274[] = {
- WRITE_COEF(0x45, 0x4289),
- UPDATE_COEF(0x4a, 0x0010, 0x0010),
- UPDATE_COEF(0x6b, 0x0f00, 0),
- UPDATE_COEF(0x49, 0x0300, 0x0300),
- {}
- };
-
- switch (codec->core.vendor_id) {
- case 0x10ec0215:
- case 0x10ec0225:
- case 0x10ec0285:
- case 0x10ec0295:
- case 0x10ec0289:
- case 0x10ec0299:
- alc_process_coef_fw(codec, alc225_pre_hsmode);
- alc_process_coef_fw(codec, coef0225);
- alc_hp_enable_unmute(codec, 75);
- break;
- case 0x10ec0255:
- alc_process_coef_fw(codec, coef0255);
- break;
- case 0x10ec0230:
- case 0x10ec0236:
- case 0x10ec0256:
- case 0x19e58326:
- alc_write_coef_idx(codec, 0x1b, 0x0e4b);
- alc_write_coef_idx(codec, 0x45, 0xc089);
- msleep(50);
- alc_process_coef_fw(codec, coef0256);
- alc_hp_enable_unmute(codec, 75);
- break;
- case 0x10ec0234:
- case 0x10ec0274:
- case 0x10ec0294:
- alc_process_coef_fw(codec, coef0274);
- break;
- case 0x10ec0233:
- case 0x10ec0283:
- alc_process_coef_fw(codec, coef0233);
- break;
- case 0x10ec0286:
- case 0x10ec0288:
- case 0x10ec0298:
- alc_process_coef_fw(codec, coef0288);
- break;
- case 0x10ec0292:
- alc_process_coef_fw(codec, coef0292);
- break;
- case 0x10ec0293:
- alc_process_coef_fw(codec, coef0293);
- break;
- case 0x10ec0668:
- alc_process_coef_fw(codec, coef0688);
- break;
- case 0x10ec0867:
- alc_update_coefex_idx(codec, 0x57, 0x5, 1<<14, 0);
- break;
- }
- codec_dbg(codec, "Headset jack set to headphone (default) mode.\n");
-}
-
-/* Iphone type */
-static void alc_headset_mode_ctia(struct hda_codec *codec)
-{
- int val;
-
- static const struct coef_fw coef0255[] = {
- WRITE_COEF(0x45, 0xd489), /* Set to CTIA type */
- WRITE_COEF(0x1b, 0x0c2b),
- WRITE_COEFEX(0x57, 0x03, 0x8ea6),
- {}
- };
- static const struct coef_fw coef0256[] = {
- WRITE_COEF(0x45, 0xd489), /* Set to CTIA type */
- WRITE_COEF(0x1b, 0x0e6b),
- {}
- };
- static const struct coef_fw coef0233[] = {
- WRITE_COEF(0x45, 0xd429),
- WRITE_COEF(0x1b, 0x0c2b),
- WRITE_COEF(0x32, 0x4ea3),
- {}
- };
- static const struct coef_fw coef0288[] = {
- UPDATE_COEF(0x50, 0x2000, 0x2000),
- UPDATE_COEF(0x56, 0x0006, 0x0006),
- UPDATE_COEF(0x66, 0x0008, 0),
- UPDATE_COEF(0x67, 0x2000, 0),
- {}
- };
- static const struct coef_fw coef0292[] = {
- WRITE_COEF(0x6b, 0xd429),
- WRITE_COEF(0x76, 0x0008),
- WRITE_COEF(0x18, 0x7388),
- {}
- };
- static const struct coef_fw coef0293[] = {
- WRITE_COEF(0x45, 0xd429), /* Set to ctia type */
- UPDATE_COEF(0x10, 7<<8, 7<<8), /* SET Line1 JD to 1 */
- {}
- };
- static const struct coef_fw coef0688[] = {
- WRITE_COEF(0x11, 0x0001),
- WRITE_COEF(0x15, 0x0d60),
- WRITE_COEF(0xc3, 0x0000),
- {}
- };
- static const struct coef_fw coef0225_1[] = {
- UPDATE_COEF(0x45, 0x3f<<10, 0x35<<10),
- UPDATE_COEF(0x63, 3<<14, 2<<14),
- {}
- };
- static const struct coef_fw coef0225_2[] = {
- UPDATE_COEF(0x45, 0x3f<<10, 0x35<<10),
- UPDATE_COEF(0x63, 3<<14, 1<<14),
- {}
- };
-
- switch (codec->core.vendor_id) {
- case 0x10ec0255:
- alc_process_coef_fw(codec, coef0255);
- break;
- case 0x10ec0230:
- case 0x10ec0236:
- case 0x10ec0256:
- case 0x19e58326:
- alc_process_coef_fw(codec, coef0256);
- alc_hp_enable_unmute(codec, 75);
- break;
- case 0x10ec0234:
- case 0x10ec0274:
- case 0x10ec0294:
- alc_write_coef_idx(codec, 0x45, 0xd689);
- break;
- case 0x10ec0233:
- case 0x10ec0283:
- alc_process_coef_fw(codec, coef0233);
- break;
- case 0x10ec0298:
- val = alc_read_coef_idx(codec, 0x50);
- if (val & (1 << 12)) {
- alc_update_coef_idx(codec, 0x8e, 0x0070, 0x0020);
- alc_update_coef_idx(codec, 0x4f, 0xfcc0, 0xd400);
- msleep(300);
- } else {
- alc_update_coef_idx(codec, 0x8e, 0x0070, 0x0010);
- alc_update_coef_idx(codec, 0x4f, 0xfcc0, 0xd400);
- msleep(300);
- }
- break;
- case 0x10ec0286:
- case 0x10ec0288:
- alc_update_coef_idx(codec, 0x4f, 0xfcc0, 0xd400);
- msleep(300);
- alc_process_coef_fw(codec, coef0288);
- break;
- case 0x10ec0292:
- alc_process_coef_fw(codec, coef0292);
- break;
- case 0x10ec0293:
- alc_process_coef_fw(codec, coef0293);
- break;
- case 0x10ec0668:
- alc_process_coef_fw(codec, coef0688);
- break;
- case 0x10ec0215:
- case 0x10ec0225:
- case 0x10ec0285:
- case 0x10ec0295:
- case 0x10ec0289:
- case 0x10ec0299:
- val = alc_read_coef_idx(codec, 0x45);
- if (val & (1 << 9))
- alc_process_coef_fw(codec, coef0225_2);
- else
- alc_process_coef_fw(codec, coef0225_1);
- alc_hp_enable_unmute(codec, 75);
- break;
- case 0x10ec0867:
- alc_update_coefex_idx(codec, 0x57, 0x5, 1<<14, 0);
- break;
- }
- codec_dbg(codec, "Headset jack set to iPhone-style headset mode.\n");
-}
-
-/* Nokia type */
-static void alc_headset_mode_omtp(struct hda_codec *codec)
-{
- static const struct coef_fw coef0255[] = {
- WRITE_COEF(0x45, 0xe489), /* Set to OMTP Type */
- WRITE_COEF(0x1b, 0x0c2b),
- WRITE_COEFEX(0x57, 0x03, 0x8ea6),
- {}
- };
- static const struct coef_fw coef0256[] = {
- WRITE_COEF(0x45, 0xe489), /* Set to OMTP Type */
- WRITE_COEF(0x1b, 0x0e6b),
- {}
- };
- static const struct coef_fw coef0233[] = {
- WRITE_COEF(0x45, 0xe429),
- WRITE_COEF(0x1b, 0x0c2b),
- WRITE_COEF(0x32, 0x4ea3),
- {}
- };
- static const struct coef_fw coef0288[] = {
- UPDATE_COEF(0x50, 0x2000, 0x2000),
- UPDATE_COEF(0x56, 0x0006, 0x0006),
- UPDATE_COEF(0x66, 0x0008, 0),
- UPDATE_COEF(0x67, 0x2000, 0),
- {}
- };
- static const struct coef_fw coef0292[] = {
- WRITE_COEF(0x6b, 0xe429),
- WRITE_COEF(0x76, 0x0008),
- WRITE_COEF(0x18, 0x7388),
- {}
- };
- static const struct coef_fw coef0293[] = {
- WRITE_COEF(0x45, 0xe429), /* Set to omtp type */
- UPDATE_COEF(0x10, 7<<8, 7<<8), /* SET Line1 JD to 1 */
- {}
- };
- static const struct coef_fw coef0688[] = {
- WRITE_COEF(0x11, 0x0001),
- WRITE_COEF(0x15, 0x0d50),
- WRITE_COEF(0xc3, 0x0000),
- {}
- };
- static const struct coef_fw coef0225[] = {
- UPDATE_COEF(0x45, 0x3f<<10, 0x39<<10),
- UPDATE_COEF(0x63, 3<<14, 2<<14),
- {}
- };
-
- switch (codec->core.vendor_id) {
- case 0x10ec0255:
- alc_process_coef_fw(codec, coef0255);
- break;
- case 0x10ec0230:
- case 0x10ec0236:
- case 0x10ec0256:
- case 0x19e58326:
- alc_process_coef_fw(codec, coef0256);
- alc_hp_enable_unmute(codec, 75);
- break;
- case 0x10ec0234:
- case 0x10ec0274:
- case 0x10ec0294:
- alc_write_coef_idx(codec, 0x45, 0xe689);
- break;
- case 0x10ec0233:
- case 0x10ec0283:
- alc_process_coef_fw(codec, coef0233);
- break;
- case 0x10ec0298:
- alc_update_coef_idx(codec, 0x8e, 0x0070, 0x0010);/* Headset output enable */
- alc_update_coef_idx(codec, 0x4f, 0xfcc0, 0xe400);
- msleep(300);
- break;
- case 0x10ec0286:
- case 0x10ec0288:
- alc_update_coef_idx(codec, 0x4f, 0xfcc0, 0xe400);
- msleep(300);
- alc_process_coef_fw(codec, coef0288);
- break;
- case 0x10ec0292:
- alc_process_coef_fw(codec, coef0292);
- break;
- case 0x10ec0293:
- alc_process_coef_fw(codec, coef0293);
- break;
- case 0x10ec0668:
- alc_process_coef_fw(codec, coef0688);
- break;
- case 0x10ec0215:
- case 0x10ec0225:
- case 0x10ec0285:
- case 0x10ec0295:
- case 0x10ec0289:
- case 0x10ec0299:
- alc_process_coef_fw(codec, coef0225);
- alc_hp_enable_unmute(codec, 75);
- break;
- }
- codec_dbg(codec, "Headset jack set to Nokia-style headset mode.\n");
-}
-
-static void alc_determine_headset_type(struct hda_codec *codec)
-{
- int val;
- bool is_ctia = false;
- struct alc_spec *spec = codec->spec;
- static const struct coef_fw coef0255[] = {
- WRITE_COEF(0x45, 0xd089), /* combo jack auto switch control(Check type)*/
- WRITE_COEF(0x49, 0x0149), /* combo jack auto switch control(Vref
- conteol) */
- {}
- };
- static const struct coef_fw coef0288[] = {
- UPDATE_COEF(0x4f, 0xfcc0, 0xd400), /* Check Type */
- {}
- };
- static const struct coef_fw coef0298[] = {
- UPDATE_COEF(0x50, 0x2000, 0x2000),
- UPDATE_COEF(0x56, 0x0006, 0x0006),
- UPDATE_COEF(0x66, 0x0008, 0),
- UPDATE_COEF(0x67, 0x2000, 0),
- UPDATE_COEF(0x19, 0x1300, 0x1300),
- {}
- };
- static const struct coef_fw coef0293[] = {
- UPDATE_COEF(0x4a, 0x000f, 0x0008), /* Combo Jack auto detect */
- WRITE_COEF(0x45, 0xD429), /* Set to ctia type */
- {}
- };
- static const struct coef_fw coef0688[] = {
- WRITE_COEF(0x11, 0x0001),
- WRITE_COEF(0xb7, 0x802b),
- WRITE_COEF(0x15, 0x0d60),
- WRITE_COEF(0xc3, 0x0c00),
- {}
- };
- static const struct coef_fw coef0274[] = {
- UPDATE_COEF(0x4a, 0x0010, 0),
- UPDATE_COEF(0x4a, 0x8000, 0),
- WRITE_COEF(0x45, 0xd289),
- UPDATE_COEF(0x49, 0x0300, 0x0300),
- {}
- };
-
- if (spec->no_internal_mic_pin) {
- alc_update_coef_idx(codec, 0x45, 0xf<<12 | 1<<10, 5<<12);
- return;
- }
-
- switch (codec->core.vendor_id) {
- case 0x10ec0255:
- alc_process_coef_fw(codec, coef0255);
- msleep(300);
- val = alc_read_coef_idx(codec, 0x46);
- is_ctia = (val & 0x0070) == 0x0070;
- break;
- case 0x10ec0230:
- case 0x10ec0236:
- case 0x10ec0256:
- case 0x19e58326:
- alc_write_coef_idx(codec, 0x1b, 0x0e4b);
- alc_write_coef_idx(codec, 0x06, 0x6104);
- alc_write_coefex_idx(codec, 0x57, 0x3, 0x09a3);
-
- alc_process_coef_fw(codec, coef0255);
- msleep(300);
- val = alc_read_coef_idx(codec, 0x46);
- is_ctia = (val & 0x0070) == 0x0070;
- if (!is_ctia) {
- alc_write_coef_idx(codec, 0x45, 0xe089);
- msleep(100);
- val = alc_read_coef_idx(codec, 0x46);
- if ((val & 0x0070) == 0x0070)
- is_ctia = false;
- else
- is_ctia = true;
- }
- alc_write_coefex_idx(codec, 0x57, 0x3, 0x0da3);
- alc_update_coefex_idx(codec, 0x57, 0x5, 1<<14, 0);
- break;
- case 0x10ec0234:
- case 0x10ec0274:
- case 0x10ec0294:
- alc_process_coef_fw(codec, coef0274);
- msleep(850);
- val = alc_read_coef_idx(codec, 0x46);
- is_ctia = (val & 0x00f0) == 0x00f0;
- break;
- case 0x10ec0233:
- case 0x10ec0283:
- alc_write_coef_idx(codec, 0x45, 0xd029);
- msleep(300);
- val = alc_read_coef_idx(codec, 0x46);
- is_ctia = (val & 0x0070) == 0x0070;
- break;
- case 0x10ec0298:
- snd_hda_codec_write(codec, 0x21, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
- msleep(100);
- snd_hda_codec_write(codec, 0x21, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
- msleep(200);
-
- val = alc_read_coef_idx(codec, 0x50);
- if (val & (1 << 12)) {
- alc_update_coef_idx(codec, 0x8e, 0x0070, 0x0020);
- alc_process_coef_fw(codec, coef0288);
- msleep(350);
- val = alc_read_coef_idx(codec, 0x50);
- is_ctia = (val & 0x0070) == 0x0070;
- } else {
- alc_update_coef_idx(codec, 0x8e, 0x0070, 0x0010);
- alc_process_coef_fw(codec, coef0288);
- msleep(350);
- val = alc_read_coef_idx(codec, 0x50);
- is_ctia = (val & 0x0070) == 0x0070;
- }
- alc_process_coef_fw(codec, coef0298);
- snd_hda_codec_write(codec, 0x21, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP);
- msleep(75);
- snd_hda_codec_write(codec, 0x21, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
- break;
- case 0x10ec0286:
- case 0x10ec0288:
- alc_process_coef_fw(codec, coef0288);
- msleep(350);
- val = alc_read_coef_idx(codec, 0x50);
- is_ctia = (val & 0x0070) == 0x0070;
- break;
- case 0x10ec0292:
- alc_write_coef_idx(codec, 0x6b, 0xd429);
- msleep(300);
- val = alc_read_coef_idx(codec, 0x6c);
- is_ctia = (val & 0x001c) == 0x001c;
- break;
- case 0x10ec0293:
- alc_process_coef_fw(codec, coef0293);
- msleep(300);
- val = alc_read_coef_idx(codec, 0x46);
- is_ctia = (val & 0x0070) == 0x0070;
- break;
- case 0x10ec0668:
- alc_process_coef_fw(codec, coef0688);
- msleep(300);
- val = alc_read_coef_idx(codec, 0xbe);
- is_ctia = (val & 0x1c02) == 0x1c02;
- break;
- case 0x10ec0215:
- case 0x10ec0225:
- case 0x10ec0285:
- case 0x10ec0295:
- case 0x10ec0289:
- case 0x10ec0299:
- alc_process_coef_fw(codec, alc225_pre_hsmode);
- alc_update_coef_idx(codec, 0x67, 0xf000, 0x1000);
- val = alc_read_coef_idx(codec, 0x45);
- if (val & (1 << 9)) {
- alc_update_coef_idx(codec, 0x45, 0x3f<<10, 0x34<<10);
- alc_update_coef_idx(codec, 0x49, 3<<8, 2<<8);
- msleep(800);
- val = alc_read_coef_idx(codec, 0x46);
- is_ctia = (val & 0x00f0) == 0x00f0;
- } else {
- alc_update_coef_idx(codec, 0x45, 0x3f<<10, 0x34<<10);
- alc_update_coef_idx(codec, 0x49, 3<<8, 1<<8);
- msleep(800);
- val = alc_read_coef_idx(codec, 0x46);
- is_ctia = (val & 0x00f0) == 0x00f0;
- }
- if (!is_ctia) {
- alc_update_coef_idx(codec, 0x45, 0x3f<<10, 0x38<<10);
- alc_update_coef_idx(codec, 0x49, 3<<8, 1<<8);
- msleep(100);
- val = alc_read_coef_idx(codec, 0x46);
- if ((val & 0x00f0) == 0x00f0)
- is_ctia = false;
- else
- is_ctia = true;
- }
- alc_update_coef_idx(codec, 0x4a, 7<<6, 7<<6);
- alc_update_coef_idx(codec, 0x4a, 3<<4, 3<<4);
- alc_update_coef_idx(codec, 0x67, 0xf000, 0x3000);
- break;
- case 0x10ec0867:
- is_ctia = true;
- break;
- }
-
- codec_dbg(codec, "Headset jack detected iPhone-style headset: %s\n",
- str_yes_no(is_ctia));
- spec->current_headset_type = is_ctia ? ALC_HEADSET_TYPE_CTIA : ALC_HEADSET_TYPE_OMTP;
-}
-
-static void alc_update_headset_mode(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- hda_nid_t mux_pin = spec->gen.imux_pins[spec->gen.cur_mux[0]];
- hda_nid_t hp_pin = alc_get_hp_pin(spec);
-
- int new_headset_mode;
-
- if (!snd_hda_jack_detect(codec, hp_pin))
- new_headset_mode = ALC_HEADSET_MODE_UNPLUGGED;
- else if (mux_pin == spec->headset_mic_pin)
- new_headset_mode = ALC_HEADSET_MODE_HEADSET;
- else if (mux_pin == spec->headphone_mic_pin)
- new_headset_mode = ALC_HEADSET_MODE_MIC;
- else
- new_headset_mode = ALC_HEADSET_MODE_HEADPHONE;
-
- if (new_headset_mode == spec->current_headset_mode) {
- snd_hda_gen_update_outputs(codec);
- return;
- }
-
- switch (new_headset_mode) {
- case ALC_HEADSET_MODE_UNPLUGGED:
- alc_headset_mode_unplugged(codec);
- spec->current_headset_mode = ALC_HEADSET_MODE_UNKNOWN;
- spec->current_headset_type = ALC_HEADSET_TYPE_UNKNOWN;
- spec->gen.hp_jack_present = false;
- break;
- case ALC_HEADSET_MODE_HEADSET:
- if (spec->current_headset_type == ALC_HEADSET_TYPE_UNKNOWN)
- alc_determine_headset_type(codec);
- if (spec->current_headset_type == ALC_HEADSET_TYPE_CTIA)
- alc_headset_mode_ctia(codec);
- else if (spec->current_headset_type == ALC_HEADSET_TYPE_OMTP)
- alc_headset_mode_omtp(codec);
- spec->gen.hp_jack_present = true;
- break;
- case ALC_HEADSET_MODE_MIC:
- alc_headset_mode_mic_in(codec, hp_pin, spec->headphone_mic_pin);
- spec->gen.hp_jack_present = false;
- break;
- case ALC_HEADSET_MODE_HEADPHONE:
- alc_headset_mode_default(codec);
- spec->gen.hp_jack_present = true;
- break;
- }
- if (new_headset_mode != ALC_HEADSET_MODE_MIC) {
- snd_hda_set_pin_ctl_cache(codec, hp_pin,
- AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN);
- if (spec->headphone_mic_pin && spec->headphone_mic_pin != hp_pin)
- snd_hda_set_pin_ctl_cache(codec, spec->headphone_mic_pin,
- PIN_VREFHIZ);
- }
- spec->current_headset_mode = new_headset_mode;
-
- snd_hda_gen_update_outputs(codec);
-}
-
-static void alc_update_headset_mode_hook(struct hda_codec *codec,
- struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- alc_update_headset_mode(codec);
-}
-
-static void alc_update_headset_jack_cb(struct hda_codec *codec,
- struct hda_jack_callback *jack)
-{
- snd_hda_gen_hp_automute(codec, jack);
- alc_update_headset_mode(codec);
-}
-
-static void alc_probe_headset_mode(struct hda_codec *codec)
-{
- int i;
- struct alc_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->gen.autocfg;
-
- /* Find mic pins */
- for (i = 0; i < cfg->num_inputs; i++) {
- if (cfg->inputs[i].is_headset_mic && !spec->headset_mic_pin)
- spec->headset_mic_pin = cfg->inputs[i].pin;
- if (cfg->inputs[i].is_headphone_mic && !spec->headphone_mic_pin)
- spec->headphone_mic_pin = cfg->inputs[i].pin;
- }
-
- WARN_ON(spec->gen.cap_sync_hook);
- spec->gen.cap_sync_hook = alc_update_headset_mode_hook;
- spec->gen.automute_hook = alc_update_headset_mode;
- spec->gen.hp_automute_hook = alc_update_headset_jack_cb;
-}
-
-static void alc_fixup_headset_mode(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- spec->parse_flags |= HDA_PINCFG_HEADSET_MIC | HDA_PINCFG_HEADPHONE_MIC;
- break;
- case HDA_FIXUP_ACT_PROBE:
- alc_probe_headset_mode(codec);
- break;
- case HDA_FIXUP_ACT_INIT:
- if (is_s3_resume(codec) || is_s4_resume(codec)) {
- spec->current_headset_mode = ALC_HEADSET_MODE_UNKNOWN;
- spec->current_headset_type = ALC_HEADSET_TYPE_UNKNOWN;
- }
- alc_update_headset_mode(codec);
- break;
- }
-}
-
-static void alc_fixup_headset_mode_no_hp_mic(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- struct alc_spec *spec = codec->spec;
- spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
- }
- else
- alc_fixup_headset_mode(codec, fix, action);
-}
-
-static void alc255_set_default_jack_type(struct hda_codec *codec)
-{
- /* Set to iphone type */
- static const struct coef_fw alc255fw[] = {
- WRITE_COEF(0x1b, 0x880b),
- WRITE_COEF(0x45, 0xd089),
- WRITE_COEF(0x1b, 0x080b),
- WRITE_COEF(0x46, 0x0004),
- WRITE_COEF(0x1b, 0x0c0b),
- {}
- };
- static const struct coef_fw alc256fw[] = {
- WRITE_COEF(0x1b, 0x884b),
- WRITE_COEF(0x45, 0xd089),
- WRITE_COEF(0x1b, 0x084b),
- WRITE_COEF(0x46, 0x0004),
- WRITE_COEF(0x1b, 0x0c4b),
- {}
- };
- switch (codec->core.vendor_id) {
- case 0x10ec0255:
- alc_process_coef_fw(codec, alc255fw);
- break;
- case 0x10ec0230:
- case 0x10ec0236:
- case 0x10ec0256:
- case 0x19e58326:
- alc_process_coef_fw(codec, alc256fw);
- break;
- }
- msleep(30);
-}
-
-static void alc_fixup_headset_mode_alc255(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- alc255_set_default_jack_type(codec);
- }
- alc_fixup_headset_mode(codec, fix, action);
-}
-
-static void alc_fixup_headset_mode_alc255_no_hp_mic(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- struct alc_spec *spec = codec->spec;
- spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
- alc255_set_default_jack_type(codec);
- }
- else
- alc_fixup_headset_mode(codec, fix, action);
-}
-
-static void alc288_update_headset_jack_cb(struct hda_codec *codec,
- struct hda_jack_callback *jack)
-{
- struct alc_spec *spec = codec->spec;
-
- alc_update_headset_jack_cb(codec, jack);
- /* Headset Mic enable or disable, only for Dell Dino */
- alc_update_gpio_data(codec, 0x40, spec->gen.hp_jack_present);
-}
-
-static void alc_fixup_headset_mode_dell_alc288(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- alc_fixup_headset_mode(codec, fix, action);
- if (action == HDA_FIXUP_ACT_PROBE) {
- struct alc_spec *spec = codec->spec;
- /* toggled via hp_automute_hook */
- spec->gpio_mask |= 0x40;
- spec->gpio_dir |= 0x40;
- spec->gen.hp_automute_hook = alc288_update_headset_jack_cb;
- }
-}
-
-static void alc_fixup_auto_mute_via_amp(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- struct alc_spec *spec = codec->spec;
- spec->gen.auto_mute_via_amp = 1;
- }
-}
-
-static void alc_fixup_no_shutup(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- struct alc_spec *spec = codec->spec;
- spec->no_shutup_pins = 1;
- }
-}
-
-static void alc_fixup_disable_aamix(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- struct alc_spec *spec = codec->spec;
- /* Disable AA-loopback as it causes white noise */
- spec->gen.mixer_nid = 0;
- }
-}
-
-/* fixup for Thinkpad docks: add dock pins, avoid HP parser fixup */
-static void alc_fixup_tpt440_dock(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- static const struct hda_pintbl pincfgs[] = {
- { 0x16, 0x21211010 }, /* dock headphone */
- { 0x19, 0x21a11010 }, /* dock mic */
- { }
- };
- struct alc_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
- codec->power_save_node = 0; /* avoid click noises */
- snd_hda_apply_pincfgs(codec, pincfgs);
- }
-}
-
-static void alc_fixup_tpt470_dock(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- static const struct hda_pintbl pincfgs[] = {
- { 0x17, 0x21211010 }, /* dock headphone */
- { 0x19, 0x21a11010 }, /* dock mic */
- { }
- };
- struct alc_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
- snd_hda_apply_pincfgs(codec, pincfgs);
- } else if (action == HDA_FIXUP_ACT_INIT) {
- /* Enable DOCK device */
- snd_hda_codec_write(codec, 0x17, 0,
- AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, 0);
- /* Enable DOCK device */
- snd_hda_codec_write(codec, 0x19, 0,
- AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, 0);
- }
-}
-
-static void alc_fixup_tpt470_dacs(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- /* Assure the speaker pin to be coupled with DAC NID 0x03; otherwise
- * the speaker output becomes too low by some reason on Thinkpads with
- * ALC298 codec
- */
- static const hda_nid_t preferred_pairs[] = {
- 0x14, 0x03, 0x17, 0x02, 0x21, 0x02,
- 0
- };
- struct alc_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE)
- spec->gen.preferred_dacs = preferred_pairs;
-}
-
-static void alc295_fixup_asus_dacs(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- static const hda_nid_t preferred_pairs[] = {
- 0x17, 0x02, 0x21, 0x03, 0
- };
- struct alc_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE)
- spec->gen.preferred_dacs = preferred_pairs;
-}
-
-static void alc_shutup_dell_xps13(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- int hp_pin = alc_get_hp_pin(spec);
-
- /* Prevent pop noises when headphones are plugged in */
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
- msleep(20);
-}
-
-static void alc_fixup_dell_xps13(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
- struct hda_input_mux *imux = &spec->gen.input_mux;
- int i;
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- /* mic pin 0x19 must be initialized with Vref Hi-Z, otherwise
- * it causes a click noise at start up
- */
- snd_hda_codec_set_pin_target(codec, 0x19, PIN_VREFHIZ);
- spec->shutup = alc_shutup_dell_xps13;
- break;
- case HDA_FIXUP_ACT_PROBE:
- /* Make the internal mic the default input source. */
- for (i = 0; i < imux->num_items; i++) {
- if (spec->gen.imux_pins[i] == 0x12) {
- spec->gen.cur_mux[0] = i;
- break;
- }
- }
- break;
- }
-}
-
-static void alc_fixup_headset_mode_alc662(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
- spec->gen.hp_mic = 1; /* Mic-in is same pin as headphone */
-
- /* Disable boost for mic-in permanently. (This code is only called
- from quirks that guarantee that the headphone is at NID 0x1b.) */
- snd_hda_codec_write(codec, 0x1b, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000);
- snd_hda_override_wcaps(codec, 0x1b, get_wcaps(codec, 0x1b) & ~AC_WCAP_IN_AMP);
- } else
- alc_fixup_headset_mode(codec, fix, action);
-}
-
-static void alc_fixup_headset_mode_alc668(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- alc_write_coef_idx(codec, 0xc4, 0x8000);
- alc_update_coef_idx(codec, 0xc2, ~0xfe, 0);
- snd_hda_set_pin_ctl_cache(codec, 0x18, 0);
- }
- alc_fixup_headset_mode(codec, fix, action);
-}
-
-/* Returns the nid of the external mic input pin, or 0 if it cannot be found. */
-static int find_ext_mic_pin(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->gen.autocfg;
- hda_nid_t nid;
- unsigned int defcfg;
- int i;
-
- for (i = 0; i < cfg->num_inputs; i++) {
- if (cfg->inputs[i].type != AUTO_PIN_MIC)
- continue;
- nid = cfg->inputs[i].pin;
- defcfg = snd_hda_codec_get_pincfg(codec, nid);
- if (snd_hda_get_input_pin_attr(defcfg) == INPUT_PIN_ATTR_INT)
- continue;
- return nid;
- }
-
- return 0;
-}
-
-static void alc271_hp_gate_mic_jack(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- struct alc_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PROBE) {
- int mic_pin = find_ext_mic_pin(codec);
- int hp_pin = alc_get_hp_pin(spec);
-
- if (snd_BUG_ON(!mic_pin || !hp_pin))
- return;
- snd_hda_jack_set_gating_jack(codec, mic_pin, hp_pin);
- }
-}
-
-static void alc269_fixup_limit_int_mic_boost(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- struct alc_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->gen.autocfg;
- int i;
-
- /* The mic boosts on level 2 and 3 are too noisy
- on the internal mic input.
- Therefore limit the boost to 0 or 1. */
-
- if (action != HDA_FIXUP_ACT_PROBE)
- return;
-
- for (i = 0; i < cfg->num_inputs; i++) {
- hda_nid_t nid = cfg->inputs[i].pin;
- unsigned int defcfg;
- if (cfg->inputs[i].type != AUTO_PIN_MIC)
- continue;
- defcfg = snd_hda_codec_get_pincfg(codec, nid);
- if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
- continue;
-
- snd_hda_override_amp_caps(codec, nid, HDA_INPUT,
- (0x00 << AC_AMPCAP_OFFSET_SHIFT) |
- (0x01 << AC_AMPCAP_NUM_STEPS_SHIFT) |
- (0x2f << AC_AMPCAP_STEP_SIZE_SHIFT) |
- (0 << AC_AMPCAP_MUTE_SHIFT));
- }
-}
-
-static void alc283_hp_automute_hook(struct hda_codec *codec,
- struct hda_jack_callback *jack)
-{
- struct alc_spec *spec = codec->spec;
- int vref;
-
- msleep(200);
- snd_hda_gen_hp_automute(codec, jack);
-
- vref = spec->gen.hp_jack_present ? PIN_VREF80 : 0;
-
- msleep(600);
- snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
- vref);
-}
-
-static void alc283_fixup_chromebook(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- snd_hda_override_wcaps(codec, 0x03, 0);
- /* Disable AA-loopback as it causes white noise */
- spec->gen.mixer_nid = 0;
- break;
- case HDA_FIXUP_ACT_INIT:
- /* MIC2-VREF control */
- /* Set to manual mode */
- alc_update_coef_idx(codec, 0x06, 0x000c, 0);
- /* Enable Line1 input control by verb */
- alc_update_coef_idx(codec, 0x1a, 0, 1 << 4);
- break;
- }
-}
-
-static void alc283_fixup_sense_combo_jack(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- spec->gen.hp_automute_hook = alc283_hp_automute_hook;
- break;
- case HDA_FIXUP_ACT_INIT:
- /* MIC2-VREF control */
- /* Set to manual mode */
- alc_update_coef_idx(codec, 0x06, 0x000c, 0);
- break;
- }
-}
-
-/* mute tablet speaker pin (0x14) via dock plugging in addition */
-static void asus_tx300_automute(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- snd_hda_gen_update_outputs(codec);
- if (snd_hda_jack_detect(codec, 0x1b))
- spec->gen.mute_bits |= (1ULL << 0x14);
-}
-
-static void alc282_fixup_asus_tx300(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
- static const struct hda_pintbl dock_pins[] = {
- { 0x1b, 0x21114000 }, /* dock speaker pin */
- {}
- };
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- spec->init_amp = ALC_INIT_DEFAULT;
- /* TX300 needs to set up GPIO2 for the speaker amp */
- alc_setup_gpio(codec, 0x04);
- snd_hda_apply_pincfgs(codec, dock_pins);
- spec->gen.auto_mute_via_amp = 1;
- spec->gen.automute_hook = asus_tx300_automute;
- snd_hda_jack_detect_enable_callback(codec, 0x1b,
- snd_hda_gen_hp_automute);
- break;
- case HDA_FIXUP_ACT_PROBE:
- spec->init_amp = ALC_INIT_DEFAULT;
- break;
- case HDA_FIXUP_ACT_BUILD:
- /* this is a bit tricky; give more sane names for the main
- * (tablet) speaker and the dock speaker, respectively
- */
- rename_ctl(codec, "Speaker Playback Switch",
- "Dock Speaker Playback Switch");
- rename_ctl(codec, "Bass Speaker Playback Switch",
- "Speaker Playback Switch");
- break;
- }
-}
-
-static void alc290_fixup_mono_speakers(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- /* DAC node 0x03 is giving mono output. We therefore want to
- make sure 0x14 (front speaker) and 0x15 (headphones) use the
- stereo DAC, while leaving 0x17 (bass speaker) for node 0x03. */
- static const hda_nid_t conn1[] = { 0x0c };
- snd_hda_override_conn_list(codec, 0x14, ARRAY_SIZE(conn1), conn1);
- snd_hda_override_conn_list(codec, 0x15, ARRAY_SIZE(conn1), conn1);
- }
-}
-
-static void alc298_fixup_speaker_volume(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- /* The speaker is routed to the Node 0x06 by a mistake, as a result
- we can't adjust the speaker's volume since this node does not has
- Amp-out capability. we change the speaker's route to:
- Node 0x02 (Audio Output) -> Node 0x0c (Audio Mixer) -> Node 0x17 (
- Pin Complex), since Node 0x02 has Amp-out caps, we can adjust
- speaker's volume now. */
-
- static const hda_nid_t conn1[] = { 0x0c };
- snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn1), conn1);
- }
-}
-
-/* disable DAC3 (0x06) selection on NID 0x17 as it has no volume amp control */
-static void alc295_fixup_disable_dac3(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- static const hda_nid_t conn[] = { 0x02, 0x03 };
- snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn);
- }
-}
-
-/* force NID 0x17 (Bass Speaker) to DAC1 to share it with the main speaker */
-static void alc285_fixup_speaker2_to_dac1(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- static const hda_nid_t conn[] = { 0x02 };
- snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn);
- }
-}
-
-/* disable DAC3 (0x06) selection on NID 0x15 - share Speaker/Bass Speaker DAC 0x03 */
-static void alc294_fixup_bass_speaker_15(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- static const hda_nid_t conn[] = { 0x02, 0x03 };
- snd_hda_override_conn_list(codec, 0x15, ARRAY_SIZE(conn), conn);
- }
-}
-
-/* Hook to update amp GPIO4 for automute */
-static void alc280_hp_gpio4_automute_hook(struct hda_codec *codec,
- struct hda_jack_callback *jack)
-{
- struct alc_spec *spec = codec->spec;
-
- snd_hda_gen_hp_automute(codec, jack);
- /* mute_led_polarity is set to 0, so we pass inverted value here */
- alc_update_gpio_led(codec, 0x10, spec->mute_led_polarity,
- !spec->gen.hp_jack_present);
-}
-
-/* Manage GPIOs for HP EliteBook Folio 9480m.
- *
- * GPIO4 is the headphone amplifier power control
- * GPIO3 is the audio output mute indicator LED
- */
-
-static void alc280_fixup_hp_9480m(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- struct alc_spec *spec = codec->spec;
-
- alc_fixup_hp_gpio_led(codec, action, 0x08, 0);
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- /* amp at GPIO4; toggled via alc280_hp_gpio4_automute_hook() */
- spec->gpio_mask |= 0x10;
- spec->gpio_dir |= 0x10;
- spec->gen.hp_automute_hook = alc280_hp_gpio4_automute_hook;
- }
-}
-
-static void alc275_fixup_gpio4_off(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- struct alc_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->gpio_mask |= 0x04;
- spec->gpio_dir |= 0x04;
- /* set data bit low */
- }
-}
-
-/* Quirk for Thinkpad X1 7th and 8th Gen
- * The following fixed routing needed
- * DAC1 (NID 0x02) -> Speaker (NID 0x14); some eq applied secretly
- * DAC2 (NID 0x03) -> Bass (NID 0x17) & Headphone (NID 0x21); sharing a DAC
- * DAC3 (NID 0x06) -> Unused, due to the lack of volume amp
- */
-static void alc285_fixup_thinkpad_x1_gen7(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- static const hda_nid_t conn[] = { 0x02, 0x03 }; /* exclude 0x06 */
- static const hda_nid_t preferred_pairs[] = {
- 0x14, 0x02, 0x17, 0x03, 0x21, 0x03, 0
- };
- struct alc_spec *spec = codec->spec;
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn);
- spec->gen.preferred_dacs = preferred_pairs;
- break;
- case HDA_FIXUP_ACT_BUILD:
- /* The generic parser creates somewhat unintuitive volume ctls
- * with the fixed routing above, and the shared DAC2 may be
- * confusing for PA.
- * Rename those to unique names so that PA doesn't touch them
- * and use only Master volume.
- */
- rename_ctl(codec, "Front Playback Volume", "DAC1 Playback Volume");
- rename_ctl(codec, "Bass Speaker Playback Volume", "DAC2 Playback Volume");
- break;
- }
-}
-
-static void alc233_alc662_fixup_lenovo_dual_codecs(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- alc_fixup_dual_codecs(codec, fix, action);
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- /* override card longname to provide a unique UCM profile */
- strcpy(codec->card->longname, "HDAudio-Lenovo-DualCodecs");
- break;
- case HDA_FIXUP_ACT_BUILD:
- /* rename Capture controls depending on the codec */
- rename_ctl(codec, "Capture Volume",
- codec->addr == 0 ?
- "Rear-Panel Capture Volume" :
- "Front-Panel Capture Volume");
- rename_ctl(codec, "Capture Switch",
- codec->addr == 0 ?
- "Rear-Panel Capture Switch" :
- "Front-Panel Capture Switch");
- break;
- }
-}
-
-static void alc225_fixup_s3_pop_noise(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action != HDA_FIXUP_ACT_PRE_PROBE)
- return;
-
- codec->power_save_node = 1;
-}
-
-/* Forcibly assign NID 0x03 to HP/LO while NID 0x02 to SPK for EQ */
-static void alc274_fixup_bind_dacs(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
- static const hda_nid_t preferred_pairs[] = {
- 0x21, 0x03, 0x1b, 0x03, 0x16, 0x02,
- 0
- };
-
- if (action != HDA_FIXUP_ACT_PRE_PROBE)
- return;
-
- spec->gen.preferred_dacs = preferred_pairs;
- spec->gen.auto_mute_via_amp = 1;
- codec->power_save_node = 0;
-}
-
-/* avoid DAC 0x06 for speaker switch 0x17; it has no volume control */
-static void alc274_fixup_hp_aio_bind_dacs(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- static const hda_nid_t conn[] = { 0x02, 0x03 }; /* exclude 0x06 */
- /* The speaker is routed to the Node 0x06 by a mistake, thus the
- * speaker's volume can't be adjusted since the node doesn't have
- * Amp-out capability. Assure the speaker and lineout pin to be
- * coupled with DAC NID 0x02.
- */
- static const hda_nid_t preferred_pairs[] = {
- 0x16, 0x02, 0x17, 0x02, 0x21, 0x03, 0
- };
- struct alc_spec *spec = codec->spec;
-
- snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn);
- spec->gen.preferred_dacs = preferred_pairs;
-}
-
-/* avoid DAC 0x06 for bass speaker 0x17; it has no volume control */
-static void alc289_fixup_asus_ga401(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- static const hda_nid_t preferred_pairs[] = {
- 0x14, 0x02, 0x17, 0x02, 0x21, 0x03, 0
- };
- struct alc_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE)
- spec->gen.preferred_dacs = preferred_pairs;
-}
-
-/* The DAC of NID 0x3 will introduce click/pop noise on headphones, so invalidate it */
-static void alc285_fixup_invalidate_dacs(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action != HDA_FIXUP_ACT_PRE_PROBE)
- return;
-
- snd_hda_override_wcaps(codec, 0x03, 0);
-}
-
-static void alc_combo_jack_hp_jd_restart(struct hda_codec *codec)
-{
- switch (codec->core.vendor_id) {
- case 0x10ec0274:
- case 0x10ec0294:
- case 0x10ec0225:
- case 0x10ec0295:
- case 0x10ec0299:
- alc_update_coef_idx(codec, 0x4a, 0x8000, 1 << 15); /* Reset HP JD */
- alc_update_coef_idx(codec, 0x4a, 0x8000, 0 << 15);
- break;
- case 0x10ec0230:
- case 0x10ec0235:
- case 0x10ec0236:
- case 0x10ec0255:
- case 0x10ec0256:
- case 0x10ec0257:
- case 0x19e58326:
- alc_update_coef_idx(codec, 0x1b, 0x8000, 1 << 15); /* Reset HP JD */
- alc_update_coef_idx(codec, 0x1b, 0x8000, 0 << 15);
- break;
- }
-}
-
-static void alc295_fixup_chromebook(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- spec->ultra_low_power = true;
- break;
- case HDA_FIXUP_ACT_INIT:
- alc_combo_jack_hp_jd_restart(codec);
- break;
- }
-}
-
-static void alc256_fixup_chromebook(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- if (codec->core.subsystem_id == 0x10280d76)
- spec->gen.suppress_auto_mute = 0;
- else
- spec->gen.suppress_auto_mute = 1;
- spec->gen.suppress_auto_mic = 1;
- spec->en_3kpull_low = false;
- break;
- }
-}
-
-static void alc_fixup_disable_mic_vref(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_PRE_PROBE)
- snd_hda_codec_set_pin_target(codec, 0x19, PIN_VREFHIZ);
-}
-
-
-static void alc294_gx502_toggle_output(struct hda_codec *codec,
- struct hda_jack_callback *cb)
-{
- /* The Windows driver sets the codec up in a very different way where
- * it appears to leave 0x10 = 0x8a20 set. For Linux we need to toggle it
- */
- if (snd_hda_jack_detect_state(codec, 0x21) == HDA_JACK_PRESENT)
- alc_write_coef_idx(codec, 0x10, 0x8a20);
- else
- alc_write_coef_idx(codec, 0x10, 0x0a20);
-}
-
-static void alc294_fixup_gx502_hp(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- /* Pin 0x21: headphones/headset mic */
- if (!is_jack_detectable(codec, 0x21))
- return;
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- snd_hda_jack_detect_enable_callback(codec, 0x21,
- alc294_gx502_toggle_output);
- break;
- case HDA_FIXUP_ACT_INIT:
- /* Make sure to start in a correct state, i.e. if
- * headphones have been plugged in before powering up the system
- */
- alc294_gx502_toggle_output(codec, NULL);
- break;
- }
-}
-
-static void alc294_gu502_toggle_output(struct hda_codec *codec,
- struct hda_jack_callback *cb)
-{
- /* Windows sets 0x10 to 0x8420 for Node 0x20 which is
- * responsible from changes between speakers and headphones
- */
- if (snd_hda_jack_detect_state(codec, 0x21) == HDA_JACK_PRESENT)
- alc_write_coef_idx(codec, 0x10, 0x8420);
- else
- alc_write_coef_idx(codec, 0x10, 0x0a20);
-}
-
-static void alc294_fixup_gu502_hp(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (!is_jack_detectable(codec, 0x21))
- return;
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- snd_hda_jack_detect_enable_callback(codec, 0x21,
- alc294_gu502_toggle_output);
- break;
- case HDA_FIXUP_ACT_INIT:
- alc294_gu502_toggle_output(codec, NULL);
- break;
- }
-}
-
-static void alc285_fixup_hp_gpio_amp_init(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action != HDA_FIXUP_ACT_INIT)
- return;
-
- msleep(100);
- alc_write_coef_idx(codec, 0x65, 0x0);
-}
-
-static void alc274_fixup_hp_headset_mic(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- switch (action) {
- case HDA_FIXUP_ACT_INIT:
- alc_combo_jack_hp_jd_restart(codec);
- break;
- }
-}
-
-static void alc_fixup_no_int_mic(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- /* Mic RING SLEEVE swap for combo jack */
- alc_update_coef_idx(codec, 0x45, 0xf<<12 | 1<<10, 5<<12);
- spec->no_internal_mic_pin = true;
- break;
- case HDA_FIXUP_ACT_INIT:
- alc_combo_jack_hp_jd_restart(codec);
- break;
- }
-}
-
-/* GPIO1 = amplifier on/off
- * GPIO3 = mic mute LED
- */
-static void alc285_fixup_hp_spectre_x360_eb1(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- static const hda_nid_t conn[] = { 0x02 };
-
- struct alc_spec *spec = codec->spec;
- static const struct hda_pintbl pincfgs[] = {
- { 0x14, 0x90170110 }, /* front/high speakers */
- { 0x17, 0x90170130 }, /* back/bass speakers */
- { }
- };
-
- //enable micmute led
- alc_fixup_hp_gpio_led(codec, action, 0x00, 0x04);
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- spec->micmute_led_polarity = 1;
- /* needed for amp of back speakers */
- spec->gpio_mask |= 0x01;
- spec->gpio_dir |= 0x01;
- snd_hda_apply_pincfgs(codec, pincfgs);
- /* share DAC to have unified volume control */
- snd_hda_override_conn_list(codec, 0x14, ARRAY_SIZE(conn), conn);
- snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn);
- break;
- case HDA_FIXUP_ACT_INIT:
- /* need to toggle GPIO to enable the amp of back speakers */
- alc_update_gpio_data(codec, 0x01, true);
- msleep(100);
- alc_update_gpio_data(codec, 0x01, false);
- break;
- }
-}
-
-/* GPIO1 = amplifier on/off */
-static void alc285_fixup_hp_spectre_x360_df1(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- struct alc_spec *spec = codec->spec;
- static const hda_nid_t conn[] = { 0x02 };
- static const struct hda_pintbl pincfgs[] = {
- { 0x14, 0x90170110 }, /* front/high speakers */
- { 0x17, 0x90170130 }, /* back/bass speakers */
- { }
- };
-
- // enable mute led
- alc285_fixup_hp_mute_led_coefbit(codec, fix, action);
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- /* needed for amp of back speakers */
- spec->gpio_mask |= 0x01;
- spec->gpio_dir |= 0x01;
- snd_hda_apply_pincfgs(codec, pincfgs);
- /* share DAC to have unified volume control */
- snd_hda_override_conn_list(codec, 0x14, ARRAY_SIZE(conn), conn);
- snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn);
- break;
- case HDA_FIXUP_ACT_INIT:
- /* need to toggle GPIO to enable the amp of back speakers */
- alc_update_gpio_data(codec, 0x01, true);
- msleep(100);
- alc_update_gpio_data(codec, 0x01, false);
- break;
- }
-}
-
-static void alc285_fixup_hp_spectre_x360(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- static const hda_nid_t conn[] = { 0x02 };
- static const struct hda_pintbl pincfgs[] = {
- { 0x14, 0x90170110 }, /* rear speaker */
- { }
- };
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- snd_hda_apply_pincfgs(codec, pincfgs);
- /* force front speaker to DAC1 */
- snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn);
- break;
- }
-}
-
-static void alc285_fixup_hp_envy_x360(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- static const struct coef_fw coefs[] = {
- WRITE_COEF(0x08, 0x6a0c), WRITE_COEF(0x0d, 0xa023),
- WRITE_COEF(0x10, 0x0320), WRITE_COEF(0x1a, 0x8c03),
- WRITE_COEF(0x25, 0x1800), WRITE_COEF(0x26, 0x003a),
- WRITE_COEF(0x28, 0x1dfe), WRITE_COEF(0x29, 0xb014),
- WRITE_COEF(0x2b, 0x1dfe), WRITE_COEF(0x37, 0xfe15),
- WRITE_COEF(0x38, 0x7909), WRITE_COEF(0x45, 0xd489),
- WRITE_COEF(0x46, 0x00f4), WRITE_COEF(0x4a, 0x21e0),
- WRITE_COEF(0x66, 0x03f0), WRITE_COEF(0x67, 0x1000),
- WRITE_COEF(0x6e, 0x1005), { }
- };
-
- static const struct hda_pintbl pincfgs[] = {
- { 0x12, 0xb7a60130 }, /* Internal microphone*/
- { 0x14, 0x90170150 }, /* B&O soundbar speakers */
- { 0x17, 0x90170153 }, /* Side speakers */
- { 0x19, 0x03a11040 }, /* Headset microphone */
- { }
- };
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- snd_hda_apply_pincfgs(codec, pincfgs);
-
- /* Fixes volume control problem for side speakers */
- alc295_fixup_disable_dac3(codec, fix, action);
-
- /* Fixes no sound from headset speaker */
- snd_hda_codec_amp_stereo(codec, 0x21, HDA_OUTPUT, 0, -1, 0);
-
- /* Auto-enable headset mic when plugged */
- snd_hda_jack_set_gating_jack(codec, 0x19, 0x21);
-
- /* Headset mic volume enhancement */
- snd_hda_codec_set_pin_target(codec, 0x19, PIN_VREF50);
- break;
- case HDA_FIXUP_ACT_INIT:
- alc_process_coef_fw(codec, coefs);
- break;
- case HDA_FIXUP_ACT_BUILD:
- rename_ctl(codec, "Bass Speaker Playback Volume",
- "B&O-Tuned Playback Volume");
- rename_ctl(codec, "Front Playback Switch",
- "B&O Soundbar Playback Switch");
- rename_ctl(codec, "Bass Speaker Playback Switch",
- "Side Speaker Playback Switch");
- break;
- }
-}
-
-static void alc285_fixup_hp_beep(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- codec->beep_just_power_on = true;
- } else if (action == HDA_FIXUP_ACT_INIT) {
-#ifdef CONFIG_SND_HDA_INPUT_BEEP
- /*
- * Just enable loopback to internal speaker and headphone jack.
- * Disable amplification to get about the same beep volume as
- * was on pure BIOS setup before loading the driver.
- */
- alc_update_coef_idx(codec, 0x36, 0x7070, BIT(13));
-
- snd_hda_enable_beep_device(codec, 1);
-
-#if !IS_ENABLED(CONFIG_INPUT_PCSPKR)
- dev_warn_once(hda_codec_dev(codec),
- "enable CONFIG_INPUT_PCSPKR to get PC beeps\n");
-#endif
-#endif
- }
-}
-
-/* for hda_fixup_thinkpad_acpi() */
-#include "thinkpad_helper.c"
-
-static void alc_fixup_thinkpad_acpi(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- alc_fixup_no_shutup(codec, fix, action); /* reduce click noise */
- hda_fixup_thinkpad_acpi(codec, fix, action);
-}
-
-/* for hda_fixup_ideapad_acpi() */
-#include "ideapad_hotkey_led_helper.c"
-
-static void alc_fixup_ideapad_acpi(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- hda_fixup_ideapad_acpi(codec, fix, action);
-}
-
-/* Fixup for Lenovo Legion 15IMHg05 speaker output on headset removal. */
-static void alc287_fixup_legion_15imhg05_speakers(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- struct alc_spec *spec = codec->spec;
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- spec->gen.suppress_auto_mute = 1;
- break;
- }
-}
-
-static void comp_acpi_device_notify(acpi_handle handle, u32 event, void *data)
-{
- struct hda_codec *cdc = data;
- struct alc_spec *spec = cdc->spec;
-
- codec_info(cdc, "ACPI Notification %d\n", event);
-
- hda_component_acpi_device_notify(&spec->comps, handle, event, data);
-}
-
-static int comp_bind(struct device *dev)
-{
- struct hda_codec *cdc = dev_to_hda_codec(dev);
- struct alc_spec *spec = cdc->spec;
- int ret;
-
- ret = hda_component_manager_bind(cdc, &spec->comps);
- if (ret)
- return ret;
-
- return hda_component_manager_bind_acpi_notifications(cdc,
- &spec->comps,
- comp_acpi_device_notify, cdc);
-}
-
-static void comp_unbind(struct device *dev)
-{
- struct hda_codec *cdc = dev_to_hda_codec(dev);
- struct alc_spec *spec = cdc->spec;
-
- hda_component_manager_unbind_acpi_notifications(cdc, &spec->comps, comp_acpi_device_notify);
- hda_component_manager_unbind(cdc, &spec->comps);
-}
-
-static const struct component_master_ops comp_master_ops = {
- .bind = comp_bind,
- .unbind = comp_unbind,
-};
-
-static void comp_generic_playback_hook(struct hda_pcm_stream *hinfo, struct hda_codec *cdc,
- struct snd_pcm_substream *sub, int action)
-{
- struct alc_spec *spec = cdc->spec;
-
- hda_component_manager_playback_hook(&spec->comps, action);
-}
-
-static void comp_generic_fixup(struct hda_codec *cdc, int action, const char *bus,
- const char *hid, const char *match_str, int count)
-{
- struct alc_spec *spec = cdc->spec;
- int ret;
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- ret = hda_component_manager_init(cdc, &spec->comps, count, bus, hid,
- match_str, &comp_master_ops);
- if (ret)
- return;
-
- spec->gen.pcm_playback_hook = comp_generic_playback_hook;
- break;
- case HDA_FIXUP_ACT_FREE:
- hda_component_manager_free(&spec->comps, &comp_master_ops);
- break;
- }
-}
-
-static void find_cirrus_companion_amps(struct hda_codec *cdc)
-{
- struct device *dev = hda_codec_dev(cdc);
- struct acpi_device *adev;
- struct fwnode_handle *fwnode __free(fwnode_handle) = NULL;
- const char *bus = NULL;
- static const struct {
- const char *hid;
- const char *name;
- } acpi_ids[] = {{ "CSC3554", "cs35l54-hda" },
- { "CSC3556", "cs35l56-hda" },
- { "CSC3557", "cs35l57-hda" }};
- char *match;
- int i, count = 0, count_devindex = 0;
-
- for (i = 0; i < ARRAY_SIZE(acpi_ids); ++i) {
- adev = acpi_dev_get_first_match_dev(acpi_ids[i].hid, NULL, -1);
- if (adev)
- break;
- }
- if (!adev) {
- codec_dbg(cdc, "Did not find ACPI entry for a Cirrus Amp\n");
- return;
- }
-
- count = i2c_acpi_client_count(adev);
- if (count > 0) {
- bus = "i2c";
- } else {
- count = acpi_spi_count_resources(adev);
- if (count > 0)
- bus = "spi";
- }
-
- fwnode = fwnode_handle_get(acpi_fwnode_handle(adev));
- acpi_dev_put(adev);
-
- if (!bus) {
- codec_err(cdc, "Did not find any buses for %s\n", acpi_ids[i].hid);
- return;
- }
-
- if (!fwnode) {
- codec_err(cdc, "Could not get fwnode for %s\n", acpi_ids[i].hid);
- return;
- }
-
- /*
- * When available the cirrus,dev-index property is an accurate
- * count of the amps in a system and is used in preference to
- * the count of bus devices that can contain additional address
- * alias entries.
- */
- count_devindex = fwnode_property_count_u32(fwnode, "cirrus,dev-index");
- if (count_devindex > 0)
- count = count_devindex;
-
- match = devm_kasprintf(dev, GFP_KERNEL, "-%%s:00-%s.%%d", acpi_ids[i].name);
- if (!match)
- return;
- codec_info(cdc, "Found %d %s on %s (%s)\n", count, acpi_ids[i].hid, bus, match);
- comp_generic_fixup(cdc, HDA_FIXUP_ACT_PRE_PROBE, bus, acpi_ids[i].hid, match, count);
-}
-
-static void cs35l41_fixup_i2c_two(struct hda_codec *cdc, const struct hda_fixup *fix, int action)
-{
- comp_generic_fixup(cdc, action, "i2c", "CSC3551", "-%s:00-cs35l41-hda.%d", 2);
-}
-
-static void cs35l41_fixup_i2c_four(struct hda_codec *cdc, const struct hda_fixup *fix, int action)
-{
- comp_generic_fixup(cdc, action, "i2c", "CSC3551", "-%s:00-cs35l41-hda.%d", 4);
-}
-
-static void cs35l41_fixup_spi_two(struct hda_codec *codec, const struct hda_fixup *fix, int action)
-{
- comp_generic_fixup(codec, action, "spi", "CSC3551", "-%s:00-cs35l41-hda.%d", 2);
-}
-
-static void cs35l41_fixup_spi_four(struct hda_codec *codec, const struct hda_fixup *fix, int action)
-{
- comp_generic_fixup(codec, action, "spi", "CSC3551", "-%s:00-cs35l41-hda.%d", 4);
-}
-
-static void alc287_fixup_legion_16achg6_speakers(struct hda_codec *cdc, const struct hda_fixup *fix,
- int action)
-{
- comp_generic_fixup(cdc, action, "i2c", "CLSA0100", "-%s:00-cs35l41-hda.%d", 2);
-}
-
-static void alc287_fixup_legion_16ithg6_speakers(struct hda_codec *cdc, const struct hda_fixup *fix,
- int action)
-{
- comp_generic_fixup(cdc, action, "i2c", "CLSA0101", "-%s:00-cs35l41-hda.%d", 2);
-}
-
-static void alc285_fixup_asus_ga403u(struct hda_codec *cdc, const struct hda_fixup *fix, int action)
-{
- /*
- * The same SSID has been re-used in different hardware, they have
- * different codecs and the newer GA403U has a ALC285.
- */
- if (cdc->core.vendor_id != 0x10ec0285)
- alc_fixup_inv_dmic(cdc, fix, action);
-}
-
-static void tas2781_fixup_i2c(struct hda_codec *cdc,
- const struct hda_fixup *fix, int action)
-{
- comp_generic_fixup(cdc, action, "i2c", "TIAS2781", "-%s:00", 1);
-}
-
-static void tas2781_fixup_spi(struct hda_codec *cdc, const struct hda_fixup *fix, int action)
-{
- comp_generic_fixup(cdc, action, "spi", "TXNW2781", "-%s:00-tas2781-hda.%d", 2);
-}
-
-static void yoga7_14arb7_fixup_i2c(struct hda_codec *cdc,
- const struct hda_fixup *fix, int action)
-{
- comp_generic_fixup(cdc, action, "i2c", "INT8866", "-%s:00", 1);
-}
-
-static void alc256_fixup_acer_sfg16_micmute_led(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- alc_fixup_hp_gpio_led(codec, action, 0, 0x04);
-}
-
-
-/* for alc295_fixup_hp_top_speakers */
-#include "hp_x360_helper.c"
-
-/* for alc285_fixup_ideapad_s740_coef() */
-#include "ideapad_s740_helper.c"
-
-static const struct coef_fw alc256_fixup_set_coef_defaults_coefs[] = {
- WRITE_COEF(0x10, 0x0020), WRITE_COEF(0x24, 0x0000),
- WRITE_COEF(0x26, 0x0000), WRITE_COEF(0x29, 0x3000),
- WRITE_COEF(0x37, 0xfe05), WRITE_COEF(0x45, 0x5089),
- {}
-};
-
-static void alc256_fixup_set_coef_defaults(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- /*
- * A certain other OS sets these coeffs to different values. On at least
- * one TongFang barebone these settings might survive even a cold
- * reboot. So to restore a clean slate the values are explicitly reset
- * to default here. Without this, the external microphone is always in a
- * plugged-in state, while the internal microphone is always in an
- * unplugged state, breaking the ability to use the internal microphone.
- */
- alc_process_coef_fw(codec, alc256_fixup_set_coef_defaults_coefs);
-}
-
-static const struct coef_fw alc233_fixup_no_audio_jack_coefs[] = {
- WRITE_COEF(0x1a, 0x9003), WRITE_COEF(0x1b, 0x0e2b), WRITE_COEF(0x37, 0xfe06),
- WRITE_COEF(0x38, 0x4981), WRITE_COEF(0x45, 0xd489), WRITE_COEF(0x46, 0x0074),
- WRITE_COEF(0x49, 0x0149),
- {}
-};
-
-static void alc233_fixup_no_audio_jack(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- /*
- * The audio jack input and output is not detected on the ASRock NUC Box
- * 1100 series when cold booting without this fix. Warm rebooting from a
- * certain other OS makes the audio functional, as COEF settings are
- * preserved in this case. This fix sets these altered COEF values as
- * the default.
- */
- alc_process_coef_fw(codec, alc233_fixup_no_audio_jack_coefs);
-}
-
-static void alc256_fixup_mic_no_presence_and_resume(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- /*
- * The Clevo NJ51CU comes either with the ALC293 or the ALC256 codec,
- * but uses the 0x8686 subproduct id in both cases. The ALC256 codec
- * needs an additional quirk for sound working after suspend and resume.
- */
- if (codec->core.vendor_id == 0x10ec0256) {
- alc_update_coef_idx(codec, 0x10, 1<<9, 0);
- snd_hda_codec_set_pincfg(codec, 0x19, 0x04a11120);
- } else {
- snd_hda_codec_set_pincfg(codec, 0x1a, 0x04a1113c);
- }
-}
-
-static void alc256_decrease_headphone_amp_val(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- u32 caps;
- u8 nsteps, offs;
-
- if (action != HDA_FIXUP_ACT_PRE_PROBE)
- return;
-
- caps = query_amp_caps(codec, 0x3, HDA_OUTPUT);
- nsteps = ((caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT) - 10;
- offs = ((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT) - 10;
- caps &= ~AC_AMPCAP_NUM_STEPS & ~AC_AMPCAP_OFFSET;
- caps |= (nsteps << AC_AMPCAP_NUM_STEPS_SHIFT) | (offs << AC_AMPCAP_OFFSET_SHIFT);
-
- if (snd_hda_override_amp_caps(codec, 0x3, HDA_OUTPUT, caps))
- codec_warn(codec, "failed to override amp caps for NID 0x3\n");
-}
-
-static void alc_fixup_dell4_mic_no_presence_quiet(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- struct alc_spec *spec = codec->spec;
- struct hda_input_mux *imux = &spec->gen.input_mux;
- int i;
-
- alc269_fixup_limit_int_mic_boost(codec, fix, action);
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- /**
- * Set the vref of pin 0x19 (Headset Mic) and pin 0x1b (Headphone Mic)
- * to Hi-Z to avoid pop noises at startup and when plugging and
- * unplugging headphones.
- */
- snd_hda_codec_set_pin_target(codec, 0x19, PIN_VREFHIZ);
- snd_hda_codec_set_pin_target(codec, 0x1b, PIN_VREFHIZ);
- break;
- case HDA_FIXUP_ACT_PROBE:
- /**
- * Make the internal mic (0x12) the default input source to
- * prevent pop noises on cold boot.
- */
- for (i = 0; i < imux->num_items; i++) {
- if (spec->gen.imux_pins[i] == 0x12) {
- spec->gen.cur_mux[0] = i;
- break;
- }
- }
- break;
- }
-}
-
-static void alc287_fixup_yoga9_14iap7_bass_spk_pin(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- /*
- * The Pin Complex 0x17 for the bass speakers is wrongly reported as
- * unconnected.
- */
- static const struct hda_pintbl pincfgs[] = {
- { 0x17, 0x90170121 },
- { }
- };
- /*
- * Avoid DAC 0x06 and 0x08, as they have no volume controls.
- * DAC 0x02 and 0x03 would be fine.
- */
- static const hda_nid_t conn[] = { 0x02, 0x03 };
- /*
- * Prefer both speakerbar (0x14) and bass speakers (0x17) connected to DAC 0x02.
- * Headphones (0x21) are connected to DAC 0x03.
- */
- static const hda_nid_t preferred_pairs[] = {
- 0x14, 0x02,
- 0x17, 0x02,
- 0x21, 0x03,
- 0
- };
- struct alc_spec *spec = codec->spec;
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- snd_hda_apply_pincfgs(codec, pincfgs);
- snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn);
- spec->gen.preferred_dacs = preferred_pairs;
- break;
- }
-}
-
-static void alc295_fixup_dell_inspiron_top_speakers(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- static const struct hda_pintbl pincfgs[] = {
- { 0x14, 0x90170151 },
- { 0x17, 0x90170150 },
- { }
- };
- static const hda_nid_t conn[] = { 0x02, 0x03 };
- static const hda_nid_t preferred_pairs[] = {
- 0x14, 0x02,
- 0x17, 0x03,
- 0x21, 0x02,
- 0
- };
- struct alc_spec *spec = codec->spec;
-
- alc_fixup_no_shutup(codec, fix, action);
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- snd_hda_apply_pincfgs(codec, pincfgs);
- snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn);
- spec->gen.preferred_dacs = preferred_pairs;
- break;
- }
-}
-
-/* Forcibly assign NID 0x03 to HP while NID 0x02 to SPK */
-static void alc287_fixup_bind_dacs(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
- static const hda_nid_t conn[] = { 0x02, 0x03 }; /* exclude 0x06 */
- static const hda_nid_t preferred_pairs[] = {
- 0x17, 0x02, 0x21, 0x03, 0
- };
-
- if (action != HDA_FIXUP_ACT_PRE_PROBE)
- return;
-
- snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn);
- spec->gen.preferred_dacs = preferred_pairs;
- spec->gen.auto_mute_via_amp = 1;
- if (spec->gen.autocfg.speaker_pins[0] != 0x14) {
- snd_hda_codec_write_cache(codec, 0x14, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
- 0x0); /* Make sure 0x14 was disable */
- }
-}
-/* Fix none verb table of Headset Mic pin */
-static void alc_fixup_headset_mic(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
- static const struct hda_pintbl pincfgs[] = {
- { 0x19, 0x03a1103c },
- { }
- };
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- snd_hda_apply_pincfgs(codec, pincfgs);
- alc_update_coef_idx(codec, 0x45, 0xf<<12 | 1<<10, 5<<12);
- spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
- break;
- }
-}
-
-static void alc245_fixup_hp_spectre_x360_eu0xxx(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- /*
- * The Pin Complex 0x14 for the treble speakers is wrongly reported as
- * unconnected.
- * The Pin Complex 0x17 for the bass speakers has the lowest association
- * and sequence values so shift it up a bit to squeeze 0x14 in.
- */
- static const struct hda_pintbl pincfgs[] = {
- { 0x14, 0x90170110 }, // top/treble
- { 0x17, 0x90170111 }, // bottom/bass
- { }
- };
-
- /*
- * Force DAC 0x02 for the bass speakers 0x17.
- */
- static const hda_nid_t conn[] = { 0x02 };
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- snd_hda_apply_pincfgs(codec, pincfgs);
- snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn);
- break;
- }
-
- cs35l41_fixup_i2c_two(codec, fix, action);
- alc245_fixup_hp_mute_led_coefbit(codec, fix, action);
- alc245_fixup_hp_gpio_led(codec, fix, action);
-}
-
-/* some changes for Spectre x360 16, 2024 model */
-static void alc245_fixup_hp_spectre_x360_16_aa0xxx(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- /*
- * The Pin Complex 0x14 for the treble speakers is wrongly reported as
- * unconnected.
- * The Pin Complex 0x17 for the bass speakers has the lowest association
- * and sequence values so shift it up a bit to squeeze 0x14 in.
- */
- struct alc_spec *spec = codec->spec;
- static const struct hda_pintbl pincfgs[] = {
- { 0x14, 0x90170110 }, // top/treble
- { 0x17, 0x90170111 }, // bottom/bass
- { }
- };
-
- /*
- * Force DAC 0x02 for the bass speakers 0x17.
- */
- static const hda_nid_t conn[] = { 0x02 };
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- /* needed for amp of back speakers */
- spec->gpio_mask |= 0x01;
- spec->gpio_dir |= 0x01;
- snd_hda_apply_pincfgs(codec, pincfgs);
- snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn);
- break;
- case HDA_FIXUP_ACT_INIT:
- /* need to toggle GPIO to enable the amp of back speakers */
- alc_update_gpio_data(codec, 0x01, true);
- msleep(100);
- alc_update_gpio_data(codec, 0x01, false);
- break;
- }
-
- cs35l41_fixup_i2c_two(codec, fix, action);
- alc245_fixup_hp_mute_led_coefbit(codec, fix, action);
- alc245_fixup_hp_gpio_led(codec, fix, action);
-}
-
-static void alc245_fixup_hp_zbook_firefly_g12a(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
- static const hda_nid_t conn[] = { 0x02 };
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- spec->gen.auto_mute_via_amp = 1;
- snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn);
- break;
- }
-
- cs35l41_fixup_i2c_two(codec, fix, action);
- alc245_fixup_hp_mute_led_coefbit(codec, fix, action);
- alc285_fixup_hp_coef_micmute_led(codec, fix, action);
-}
-
-/*
- * ALC287 PCM hooks
- */
-static void alc287_alc1318_playback_pcm_hook(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream,
- int action)
-{
- switch (action) {
- case HDA_GEN_PCM_ACT_OPEN:
- alc_write_coefex_idx(codec, 0x5a, 0x00, 0x954f); /* write gpio3 to high */
- break;
- case HDA_GEN_PCM_ACT_CLOSE:
- alc_write_coefex_idx(codec, 0x5a, 0x00, 0x554f); /* write gpio3 as default value */
- break;
- }
-}
-
-static void alc287_s4_power_gpio3_default(struct hda_codec *codec)
-{
- if (is_s4_suspend(codec)) {
- alc_write_coefex_idx(codec, 0x5a, 0x00, 0x554f); /* write gpio3 as default value */
- }
-}
-
-static void alc287_fixup_lenovo_thinkpad_with_alc1318(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
- static const struct coef_fw coefs[] = {
- WRITE_COEF(0x24, 0x0013), WRITE_COEF(0x25, 0x0000), WRITE_COEF(0x26, 0xC300),
- WRITE_COEF(0x28, 0x0001), WRITE_COEF(0x29, 0xb023),
- WRITE_COEF(0x24, 0x0013), WRITE_COEF(0x25, 0x0000), WRITE_COEF(0x26, 0xC301),
- WRITE_COEF(0x28, 0x0001), WRITE_COEF(0x29, 0xb023),
- };
-
- if (action != HDA_FIXUP_ACT_PRE_PROBE)
- return;
- alc_update_coef_idx(codec, 0x10, 1<<11, 1<<11);
- alc_process_coef_fw(codec, coefs);
- spec->power_hook = alc287_s4_power_gpio3_default;
- spec->gen.pcm_playback_hook = alc287_alc1318_playback_pcm_hook;
-}
-
-/*
- * Clear COEF 0x0d (PCBEEP passthrough) bit 0x40 where BIOS sets it wrongly
- * at PM resume
- */
-static void alc283_fixup_dell_hp_resume(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_INIT)
- alc_write_coef_idx(codec, 0xd, 0x2800);
-}
-
-enum {
- ALC269_FIXUP_GPIO2,
- ALC269_FIXUP_SONY_VAIO,
- ALC275_FIXUP_SONY_VAIO_GPIO2,
- ALC269_FIXUP_DELL_M101Z,
- ALC269_FIXUP_SKU_IGNORE,
- ALC269_FIXUP_ASUS_G73JW,
- ALC269_FIXUP_ASUS_N7601ZM_PINS,
- ALC269_FIXUP_ASUS_N7601ZM,
- ALC269_FIXUP_LENOVO_EAPD,
- ALC275_FIXUP_SONY_HWEQ,
- ALC275_FIXUP_SONY_DISABLE_AAMIX,
- ALC271_FIXUP_DMIC,
- ALC269_FIXUP_PCM_44K,
- ALC269_FIXUP_STEREO_DMIC,
- ALC269_FIXUP_HEADSET_MIC,
- ALC269_FIXUP_QUANTA_MUTE,
- ALC269_FIXUP_LIFEBOOK,
- ALC269_FIXUP_LIFEBOOK_EXTMIC,
- ALC269_FIXUP_LIFEBOOK_HP_PIN,
- ALC269_FIXUP_LIFEBOOK_NO_HP_TO_LINEOUT,
- ALC255_FIXUP_LIFEBOOK_U7x7_HEADSET_MIC,
- ALC269_FIXUP_AMIC,
- ALC269_FIXUP_DMIC,
- ALC269VB_FIXUP_AMIC,
- ALC269VB_FIXUP_DMIC,
- ALC269_FIXUP_HP_MUTE_LED,
- ALC269_FIXUP_HP_MUTE_LED_MIC1,
- ALC269_FIXUP_HP_MUTE_LED_MIC2,
- ALC269_FIXUP_HP_MUTE_LED_MIC3,
- ALC269_FIXUP_HP_GPIO_LED,
- ALC269_FIXUP_HP_GPIO_MIC1_LED,
- ALC269_FIXUP_HP_LINE1_MIC1_LED,
- ALC269_FIXUP_INV_DMIC,
- ALC269_FIXUP_LENOVO_DOCK,
- ALC269_FIXUP_LENOVO_DOCK_LIMIT_BOOST,
- ALC269_FIXUP_NO_SHUTUP,
- ALC286_FIXUP_SONY_MIC_NO_PRESENCE,
- ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT,
- ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
- ALC269_FIXUP_DELL1_LIMIT_INT_MIC_BOOST,
- ALC269_FIXUP_DELL2_MIC_NO_PRESENCE,
- ALC269_FIXUP_DELL3_MIC_NO_PRESENCE,
- ALC269_FIXUP_DELL4_MIC_NO_PRESENCE,
- ALC269_FIXUP_DELL4_MIC_NO_PRESENCE_QUIET,
- ALC269_FIXUP_HEADSET_MODE,
- ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC,
- ALC269_FIXUP_ASPIRE_HEADSET_MIC,
- ALC269_FIXUP_ASUS_X101_FUNC,
- ALC269_FIXUP_ASUS_X101_VERB,
- ALC269_FIXUP_ASUS_X101,
- ALC271_FIXUP_AMIC_MIC2,
- ALC271_FIXUP_HP_GATE_MIC_JACK,
- ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572,
- ALC269_FIXUP_ACER_AC700,
- ALC269_FIXUP_LIMIT_INT_MIC_BOOST,
- ALC269VB_FIXUP_ASUS_ZENBOOK,
- ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A,
- ALC269VB_FIXUP_ASUS_MIC_NO_PRESENCE,
- ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED,
- ALC269VB_FIXUP_ORDISSIMO_EVE2,
- ALC283_FIXUP_CHROME_BOOK,
- ALC283_FIXUP_SENSE_COMBO_JACK,
- ALC282_FIXUP_ASUS_TX300,
- ALC283_FIXUP_INT_MIC,
- ALC290_FIXUP_MONO_SPEAKERS,
- ALC290_FIXUP_MONO_SPEAKERS_HSJACK,
- ALC290_FIXUP_SUBWOOFER,
- ALC290_FIXUP_SUBWOOFER_HSJACK,
- ALC295_FIXUP_HP_MUTE_LED_COEFBIT11,
- ALC269_FIXUP_THINKPAD_ACPI,
- ALC269_FIXUP_LENOVO_XPAD_ACPI,
- ALC269_FIXUP_DMIC_THINKPAD_ACPI,
- ALC269VB_FIXUP_INFINIX_ZERO_BOOK_13,
- ALC269VC_FIXUP_INFINIX_Y4_MAX,
- ALC269VB_FIXUP_CHUWI_COREBOOK_XPRO,
- ALC255_FIXUP_ACER_MIC_NO_PRESENCE,
- ALC255_FIXUP_ASUS_MIC_NO_PRESENCE,
- ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
- ALC255_FIXUP_DELL1_LIMIT_INT_MIC_BOOST,
- ALC255_FIXUP_DELL2_MIC_NO_PRESENCE,
- ALC255_FIXUP_HEADSET_MODE,
- ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC,
- ALC293_FIXUP_DELL1_MIC_NO_PRESENCE,
- ALC292_FIXUP_TPT440_DOCK,
- ALC292_FIXUP_TPT440,
- ALC283_FIXUP_HEADSET_MIC,
- ALC255_FIXUP_MIC_MUTE_LED,
- ALC282_FIXUP_ASPIRE_V5_PINS,
- ALC269VB_FIXUP_ASPIRE_E1_COEF,
- ALC280_FIXUP_HP_GPIO4,
- ALC286_FIXUP_HP_GPIO_LED,
- ALC280_FIXUP_HP_GPIO2_MIC_HOTKEY,
- ALC280_FIXUP_HP_DOCK_PINS,
- ALC269_FIXUP_HP_DOCK_GPIO_MIC1_LED,
- ALC280_FIXUP_HP_9480M,
- ALC245_FIXUP_HP_X360_AMP,
- ALC285_FIXUP_HP_SPECTRE_X360_EB1,
- ALC285_FIXUP_HP_SPECTRE_X360_DF1,
- ALC285_FIXUP_HP_ENVY_X360,
- ALC288_FIXUP_DELL_HEADSET_MODE,
- ALC288_FIXUP_DELL1_MIC_NO_PRESENCE,
- ALC288_FIXUP_DELL_XPS_13,
- ALC288_FIXUP_DISABLE_AAMIX,
- ALC292_FIXUP_DELL_E7X_AAMIX,
- ALC292_FIXUP_DELL_E7X,
- ALC292_FIXUP_DISABLE_AAMIX,
- ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK,
- ALC298_FIXUP_ALIENWARE_MIC_NO_PRESENCE,
- ALC298_FIXUP_DELL1_MIC_NO_PRESENCE,
- ALC298_FIXUP_DELL_AIO_MIC_NO_PRESENCE,
- ALC275_FIXUP_DELL_XPS,
- ALC293_FIXUP_LENOVO_SPK_NOISE,
- ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY,
- ALC233_FIXUP_LENOVO_L2MH_LOW_ENLED,
- ALC255_FIXUP_DELL_SPK_NOISE,
- ALC225_FIXUP_DISABLE_MIC_VREF,
- ALC225_FIXUP_DELL1_MIC_NO_PRESENCE,
- ALC295_FIXUP_DISABLE_DAC3,
- ALC285_FIXUP_SPEAKER2_TO_DAC1,
- ALC285_FIXUP_ASUS_SPEAKER2_TO_DAC1,
- ALC285_FIXUP_ASUS_HEADSET_MIC,
- ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS,
- ALC285_FIXUP_ASUS_I2C_SPEAKER2_TO_DAC1,
- ALC285_FIXUP_ASUS_I2C_HEADSET_MIC,
- ALC280_FIXUP_HP_HEADSET_MIC,
- ALC221_FIXUP_HP_FRONT_MIC,
- ALC292_FIXUP_TPT460,
- ALC298_FIXUP_SPK_VOLUME,
- ALC298_FIXUP_LENOVO_SPK_VOLUME,
- ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER,
- ALC269_FIXUP_ATIV_BOOK_8,
- ALC221_FIXUP_HP_288PRO_MIC_NO_PRESENCE,
- ALC221_FIXUP_HP_MIC_NO_PRESENCE,
- ALC256_FIXUP_ASUS_HEADSET_MODE,
- ALC256_FIXUP_ASUS_MIC,
- ALC256_FIXUP_ASUS_AIO_GPIO2,
- ALC233_FIXUP_ASUS_MIC_NO_PRESENCE,
- ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE,
- ALC233_FIXUP_LENOVO_MULTI_CODECS,
- ALC233_FIXUP_ACER_HEADSET_MIC,
- ALC294_FIXUP_LENOVO_MIC_LOCATION,
- ALC225_FIXUP_DELL_WYSE_MIC_NO_PRESENCE,
- ALC225_FIXUP_S3_POP_NOISE,
- ALC700_FIXUP_INTEL_REFERENCE,
- ALC274_FIXUP_DELL_BIND_DACS,
- ALC274_FIXUP_DELL_AIO_LINEOUT_VERB,
- ALC298_FIXUP_TPT470_DOCK_FIX,
- ALC298_FIXUP_TPT470_DOCK,
- ALC255_FIXUP_DUMMY_LINEOUT_VERB,
- ALC255_FIXUP_DELL_HEADSET_MIC,
- ALC256_FIXUP_HUAWEI_MACH_WX9_PINS,
- ALC298_FIXUP_HUAWEI_MBX_STEREO,
- ALC295_FIXUP_HP_X360,
- ALC221_FIXUP_HP_HEADSET_MIC,
- ALC285_FIXUP_LENOVO_HEADPHONE_NOISE,
- ALC295_FIXUP_HP_AUTO_MUTE,
- ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE,
- ALC294_FIXUP_ASUS_MIC,
- ALC294_FIXUP_ASUS_HEADSET_MIC,
- ALC294_FIXUP_ASUS_SPK,
- ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE,
- ALC285_FIXUP_LENOVO_PC_BEEP_IN_NOISE,
- ALC255_FIXUP_ACER_HEADSET_MIC,
- ALC295_FIXUP_CHROME_BOOK,
- ALC225_FIXUP_HEADSET_JACK,
- ALC225_FIXUP_DELL_WYSE_AIO_MIC_NO_PRESENCE,
- ALC225_FIXUP_WYSE_AUTO_MUTE,
- ALC225_FIXUP_WYSE_DISABLE_MIC_VREF,
- ALC286_FIXUP_ACER_AIO_HEADSET_MIC,
- ALC256_FIXUP_ASUS_HEADSET_MIC,
- ALC256_FIXUP_ASUS_MIC_NO_PRESENCE,
- ALC255_FIXUP_PREDATOR_SUBWOOFER,
- ALC299_FIXUP_PREDATOR_SPK,
- ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE,
- ALC289_FIXUP_DELL_SPK1,
- ALC289_FIXUP_DELL_SPK2,
- ALC289_FIXUP_DUAL_SPK,
- ALC289_FIXUP_RTK_AMP_DUAL_SPK,
- ALC294_FIXUP_SPK2_TO_DAC1,
- ALC294_FIXUP_ASUS_DUAL_SPK,
- ALC285_FIXUP_THINKPAD_X1_GEN7,
- ALC285_FIXUP_THINKPAD_HEADSET_JACK,
- ALC294_FIXUP_ASUS_ALLY,
- ALC294_FIXUP_ASUS_ALLY_PINS,
- ALC294_FIXUP_ASUS_ALLY_VERBS,
- ALC294_FIXUP_ASUS_ALLY_SPEAKER,
- ALC294_FIXUP_ASUS_HPE,
- ALC294_FIXUP_ASUS_COEF_1B,
- ALC294_FIXUP_ASUS_GX502_HP,
- ALC294_FIXUP_ASUS_GX502_PINS,
- ALC294_FIXUP_ASUS_GX502_VERBS,
- ALC294_FIXUP_ASUS_GU502_HP,
- ALC294_FIXUP_ASUS_GU502_PINS,
- ALC294_FIXUP_ASUS_GU502_VERBS,
- ALC294_FIXUP_ASUS_G513_PINS,
- ALC285_FIXUP_ASUS_G533Z_PINS,
- ALC285_FIXUP_HP_GPIO_LED,
- ALC285_FIXUP_HP_MUTE_LED,
- ALC285_FIXUP_HP_SPECTRE_X360_MUTE_LED,
- ALC285_FIXUP_HP_BEEP_MICMUTE_LED,
- ALC236_FIXUP_HP_MUTE_LED_COEFBIT2,
- ALC236_FIXUP_HP_GPIO_LED,
- ALC236_FIXUP_HP_MUTE_LED,
- ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF,
- ALC236_FIXUP_LENOVO_INV_DMIC,
- ALC298_FIXUP_SAMSUNG_AMP,
- ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS,
- ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS,
- ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET,
- ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET,
- ALC295_FIXUP_ASUS_MIC_NO_PRESENCE,
- ALC269VC_FIXUP_ACER_VCOPPERBOX_PINS,
- ALC269VC_FIXUP_ACER_HEADSET_MIC,
- ALC269VC_FIXUP_ACER_MIC_NO_PRESENCE,
- ALC289_FIXUP_ASUS_GA401,
- ALC289_FIXUP_ASUS_GA502,
- ALC256_FIXUP_ACER_MIC_NO_PRESENCE,
- ALC285_FIXUP_HP_GPIO_AMP_INIT,
- ALC269_FIXUP_CZC_B20,
- ALC269_FIXUP_CZC_TMI,
- ALC269_FIXUP_CZC_L101,
- ALC269_FIXUP_LEMOTE_A1802,
- ALC269_FIXUP_LEMOTE_A190X,
- ALC256_FIXUP_INTEL_NUC8_RUGGED,
- ALC233_FIXUP_INTEL_NUC8_DMIC,
- ALC233_FIXUP_INTEL_NUC8_BOOST,
- ALC256_FIXUP_INTEL_NUC10,
- ALC255_FIXUP_XIAOMI_HEADSET_MIC,
- ALC274_FIXUP_HP_MIC,
- ALC274_FIXUP_HP_HEADSET_MIC,
- ALC274_FIXUP_HP_ENVY_GPIO,
- ALC274_FIXUP_ASUS_ZEN_AIO_27,
- ALC256_FIXUP_ASUS_HPE,
- ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK,
- ALC287_FIXUP_HP_GPIO_LED,
- ALC256_FIXUP_HP_HEADSET_MIC,
- ALC245_FIXUP_HP_GPIO_LED,
- ALC236_FIXUP_DELL_AIO_HEADSET_MIC,
- ALC282_FIXUP_ACER_DISABLE_LINEOUT,
- ALC255_FIXUP_ACER_LIMIT_INT_MIC_BOOST,
- ALC256_FIXUP_ACER_HEADSET_MIC,
- ALC285_FIXUP_IDEAPAD_S740_COEF,
- ALC285_FIXUP_HP_LIMIT_INT_MIC_BOOST,
- ALC295_FIXUP_ASUS_DACS,
- ALC295_FIXUP_HP_OMEN,
- ALC285_FIXUP_HP_SPECTRE_X360,
- ALC287_FIXUP_IDEAPAD_BASS_SPK_AMP,
- ALC623_FIXUP_LENOVO_THINKSTATION_P340,
- ALC255_FIXUP_ACER_HEADPHONE_AND_MIC,
- ALC236_FIXUP_HP_LIMIT_INT_MIC_BOOST,
- ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS,
- ALC287_FIXUP_LEGION_15IMHG05_AUTOMUTE,
- ALC287_FIXUP_YOGA7_14ITL_SPEAKERS,
- ALC298_FIXUP_LENOVO_C940_DUET7,
- ALC287_FIXUP_13S_GEN2_SPEAKERS,
- ALC256_FIXUP_SET_COEF_DEFAULTS,
- ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE,
- ALC233_FIXUP_NO_AUDIO_JACK,
- ALC256_FIXUP_MIC_NO_PRESENCE_AND_RESUME,
- ALC285_FIXUP_LEGION_Y9000X_SPEAKERS,
- ALC285_FIXUP_LEGION_Y9000X_AUTOMUTE,
- ALC287_FIXUP_LEGION_16ACHG6,
- ALC287_FIXUP_CS35L41_I2C_2,
- ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED,
- ALC287_FIXUP_CS35L41_I2C_4,
- ALC245_FIXUP_CS35L41_SPI_2,
- ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED,
- ALC245_FIXUP_CS35L41_SPI_4,
- ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED,
- ALC285_FIXUP_HP_SPEAKERS_MICMUTE_LED,
- ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE,
- ALC287_FIXUP_LEGION_16ITHG6,
- ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK,
- ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN,
- ALC287_FIXUP_YOGA9_14IMH9_BASS_SPK_PIN,
- ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS,
- ALC236_FIXUP_DELL_DUAL_CODECS,
- ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI,
- ALC287_FIXUP_TAS2781_I2C,
- ALC245_FIXUP_TAS2781_SPI_2,
- ALC287_FIXUP_YOGA7_14ARB7_I2C,
- ALC245_FIXUP_HP_MUTE_LED_COEFBIT,
- ALC245_FIXUP_HP_MUTE_LED_V1_COEFBIT,
- ALC245_FIXUP_HP_X360_MUTE_LEDS,
- ALC287_FIXUP_THINKPAD_I2S_SPK,
- ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD,
- ALC2XX_FIXUP_HEADSET_MIC,
- ALC289_FIXUP_DELL_CS35L41_SPI_2,
- ALC294_FIXUP_CS35L41_I2C_2,
- ALC256_FIXUP_ACER_SFG16_MICMUTE_LED,
- ALC256_FIXUP_HEADPHONE_AMP_VOL,
- ALC245_FIXUP_HP_SPECTRE_X360_EU0XXX,
- ALC245_FIXUP_HP_SPECTRE_X360_16_AA0XXX,
- ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A,
- ALC285_FIXUP_ASUS_GA403U,
- ALC285_FIXUP_ASUS_GA403U_HEADSET_MIC,
- ALC285_FIXUP_ASUS_GA403U_I2C_SPEAKER2_TO_DAC1,
- ALC285_FIXUP_ASUS_GU605_SPI_2_HEADSET_MIC,
- ALC285_FIXUP_ASUS_GU605_SPI_SPEAKER2_TO_DAC1,
- ALC287_FIXUP_LENOVO_THKPAD_WH_ALC1318,
- ALC256_FIXUP_CHROME_BOOK,
- ALC245_FIXUP_CLEVO_NOISY_MIC,
- ALC269_FIXUP_VAIO_VJFH52_MIC_NO_PRESENCE,
- ALC233_FIXUP_MEDION_MTL_SPK,
- ALC294_FIXUP_BASS_SPEAKER_15,
- ALC283_FIXUP_DELL_HP_RESUME,
- ALC294_FIXUP_ASUS_CS35L41_SPI_2,
- ALC274_FIXUP_HP_AIO_BIND_DACS,
- ALC287_FIXUP_PREDATOR_SPK_CS35L41_I2C_2,
- ALC285_FIXUP_ASUS_GA605K_HEADSET_MIC,
- ALC285_FIXUP_ASUS_GA605K_I2C_SPEAKER2_TO_DAC1,
- ALC269_FIXUP_POSITIVO_P15X_HEADSET_MIC,
-};
-
-/* A special fixup for Lenovo C940 and Yoga Duet 7;
- * both have the very same PCI SSID, and we need to apply different fixups
- * depending on the codec ID
- */
-static void alc298_fixup_lenovo_c940_duet7(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- int id;
-
- if (codec->core.vendor_id == 0x10ec0298)
- id = ALC298_FIXUP_LENOVO_SPK_VOLUME; /* C940 */
- else
- id = ALC287_FIXUP_YOGA7_14ITL_SPEAKERS; /* Duet 7 */
- __snd_hda_apply_fixup(codec, id, action, 0);
-}
-
-static const struct hda_fixup alc269_fixups[] = {
- [ALC269_FIXUP_GPIO2] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_gpio2,
- },
- [ALC269_FIXUP_SONY_VAIO] = {
- .type = HDA_FIXUP_PINCTLS,
- .v.pins = (const struct hda_pintbl[]) {
- {0x19, PIN_VREFGRD},
- {}
- }
- },
- [ALC275_FIXUP_SONY_VAIO_GPIO2] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc275_fixup_gpio4_off,
- .chained = true,
- .chain_id = ALC269_FIXUP_SONY_VAIO
- },
- [ALC269_FIXUP_DELL_M101Z] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- /* Enables internal speaker */
- {0x20, AC_VERB_SET_COEF_INDEX, 13},
- {0x20, AC_VERB_SET_PROC_COEF, 0x4040},
- {}
- }
- },
- [ALC269_FIXUP_SKU_IGNORE] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_sku_ignore,
- },
- [ALC269_FIXUP_ASUS_G73JW] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x17, 0x99130111 }, /* subwoofer */
- { }
- }
- },
- [ALC269_FIXUP_ASUS_N7601ZM_PINS] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x03A11050 },
- { 0x1a, 0x03A11C30 },
- { 0x21, 0x03211420 },
- { }
- }
- },
- [ALC269_FIXUP_ASUS_N7601ZM] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- {0x20, AC_VERB_SET_COEF_INDEX, 0x62},
- {0x20, AC_VERB_SET_PROC_COEF, 0xa007},
- {0x20, AC_VERB_SET_COEF_INDEX, 0x10},
- {0x20, AC_VERB_SET_PROC_COEF, 0x8420},
- {0x20, AC_VERB_SET_COEF_INDEX, 0x0f},
- {0x20, AC_VERB_SET_PROC_COEF, 0x7774},
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_ASUS_N7601ZM_PINS,
- },
- [ALC269_FIXUP_LENOVO_EAPD] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
- {}
- }
- },
- [ALC275_FIXUP_SONY_HWEQ] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc269_fixup_hweq,
- .chained = true,
- .chain_id = ALC275_FIXUP_SONY_VAIO_GPIO2
- },
- [ALC275_FIXUP_SONY_DISABLE_AAMIX] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_disable_aamix,
- .chained = true,
- .chain_id = ALC269_FIXUP_SONY_VAIO
- },
- [ALC271_FIXUP_DMIC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc271_fixup_dmic,
- },
- [ALC269_FIXUP_PCM_44K] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc269_fixup_pcm_44k,
- .chained = true,
- .chain_id = ALC269_FIXUP_QUANTA_MUTE
- },
- [ALC269_FIXUP_STEREO_DMIC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc269_fixup_stereo_dmic,
- },
- [ALC269_FIXUP_HEADSET_MIC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc269_fixup_headset_mic,
- },
- [ALC269_FIXUP_QUANTA_MUTE] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc269_fixup_quanta_mute,
- },
- [ALC269_FIXUP_LIFEBOOK] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1a, 0x2101103f }, /* dock line-out */
- { 0x1b, 0x23a11040 }, /* dock mic-in */
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_QUANTA_MUTE
- },
- [ALC269_FIXUP_LIFEBOOK_EXTMIC] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x01a1903c }, /* headset mic, with jack detect */
- { }
- },
- },
- [ALC269_FIXUP_LIFEBOOK_HP_PIN] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x21, 0x0221102f }, /* HP out */
- { }
- },
- },
- [ALC269_FIXUP_LIFEBOOK_NO_HP_TO_LINEOUT] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc269_fixup_pincfg_no_hp_to_lineout,
- },
- [ALC255_FIXUP_LIFEBOOK_U7x7_HEADSET_MIC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc269_fixup_pincfg_U7x7_headset_mic,
- },
- [ALC269VB_FIXUP_INFINIX_ZERO_BOOK_13] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x14, 0x90170151 }, /* use as internal speaker (LFE) */
- { 0x1b, 0x90170152 }, /* use as internal speaker (back) */
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
- },
- [ALC269VC_FIXUP_INFINIX_Y4_MAX] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1b, 0x90170150 }, /* use as internal speaker */
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
- },
- [ALC269VB_FIXUP_CHUWI_COREBOOK_XPRO] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x18, 0x03a19020 }, /* headset mic */
- { 0x1b, 0x90170150 }, /* speaker */
- { }
- },
- },
- [ALC269_FIXUP_AMIC] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x14, 0x99130110 }, /* speaker */
- { 0x15, 0x0121401f }, /* HP out */
- { 0x18, 0x01a19c20 }, /* mic */
- { 0x19, 0x99a3092f }, /* int-mic */
- { }
- },
- },
- [ALC269_FIXUP_DMIC] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x12, 0x99a3092f }, /* int-mic */
- { 0x14, 0x99130110 }, /* speaker */
- { 0x15, 0x0121401f }, /* HP out */
- { 0x18, 0x01a19c20 }, /* mic */
- { }
- },
- },
- [ALC269VB_FIXUP_AMIC] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x14, 0x99130110 }, /* speaker */
- { 0x18, 0x01a19c20 }, /* mic */
- { 0x19, 0x99a3092f }, /* int-mic */
- { 0x21, 0x0121401f }, /* HP out */
- { }
- },
- },
- [ALC269VB_FIXUP_DMIC] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x12, 0x99a3092f }, /* int-mic */
- { 0x14, 0x99130110 }, /* speaker */
- { 0x18, 0x01a19c20 }, /* mic */
- { 0x21, 0x0121401f }, /* HP out */
- { }
- },
- },
- [ALC269_FIXUP_HP_MUTE_LED] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc269_fixup_hp_mute_led,
- },
- [ALC269_FIXUP_HP_MUTE_LED_MIC1] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc269_fixup_hp_mute_led_mic1,
- },
- [ALC269_FIXUP_HP_MUTE_LED_MIC2] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc269_fixup_hp_mute_led_mic2,
- },
- [ALC269_FIXUP_HP_MUTE_LED_MIC3] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc269_fixup_hp_mute_led_mic3,
- .chained = true,
- .chain_id = ALC295_FIXUP_HP_AUTO_MUTE
- },
- [ALC269_FIXUP_HP_GPIO_LED] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc269_fixup_hp_gpio_led,
- },
- [ALC269_FIXUP_HP_GPIO_MIC1_LED] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc269_fixup_hp_gpio_mic1_led,
- },
- [ALC269_FIXUP_HP_LINE1_MIC1_LED] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc269_fixup_hp_line1_mic1_led,
- },
- [ALC269_FIXUP_INV_DMIC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_inv_dmic,
- },
- [ALC269_FIXUP_NO_SHUTUP] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_no_shutup,
- },
- [ALC269_FIXUP_LENOVO_DOCK] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x23a11040 }, /* dock mic */
- { 0x1b, 0x2121103f }, /* dock headphone */
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT
- },
- [ALC269_FIXUP_LENOVO_DOCK_LIMIT_BOOST] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc269_fixup_limit_int_mic_boost,
- .chained = true,
- .chain_id = ALC269_FIXUP_LENOVO_DOCK,
- },
- [ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc269_fixup_pincfg_no_hp_to_lineout,
- .chained = true,
- .chain_id = ALC269_FIXUP_THINKPAD_ACPI,
- },
- [ALC269_FIXUP_DELL1_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
- { 0x1a, 0x01a1913d }, /* use as headphone mic, without its own jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MODE
- },
- [ALC269_FIXUP_DELL1_LIMIT_INT_MIC_BOOST] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc269_fixup_limit_int_mic_boost,
- .chained = true,
- .chain_id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE
- },
- [ALC269_FIXUP_DELL2_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x16, 0x21014020 }, /* dock line out */
- { 0x19, 0x21a19030 }, /* dock mic */
- { 0x1a, 0x01a1913c }, /* use as headset mic, without its own jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
- },
- [ALC269_FIXUP_DELL3_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1a, 0x01a1913c }, /* use as headset mic, without its own jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
- },
- [ALC269_FIXUP_DELL4_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
- { 0x1b, 0x01a1913d }, /* use as headphone mic, without its own jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MODE
- },
- [ALC269_FIXUP_HEADSET_MODE] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_headset_mode,
- .chained = true,
- .chain_id = ALC255_FIXUP_MIC_MUTE_LED
- },
- [ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_headset_mode_no_hp_mic,
- },
- [ALC269_FIXUP_ASPIRE_HEADSET_MIC] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x01a1913c }, /* headset mic w/o jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MODE,
- },
- [ALC286_FIXUP_SONY_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x18, 0x01a1913c }, /* use as headset mic, without its own jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MIC
- },
- [ALC256_FIXUP_HUAWEI_MACH_WX9_PINS] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- {0x12, 0x90a60130},
- {0x13, 0x40000000},
- {0x14, 0x90170110},
- {0x18, 0x411111f0},
- {0x19, 0x04a11040},
- {0x1a, 0x411111f0},
- {0x1b, 0x90170112},
- {0x1d, 0x40759a05},
- {0x1e, 0x411111f0},
- {0x21, 0x04211020},
- { }
- },
- .chained = true,
- .chain_id = ALC255_FIXUP_MIC_MUTE_LED
- },
- [ALC298_FIXUP_HUAWEI_MBX_STEREO] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc298_fixup_huawei_mbx_stereo,
- .chained = true,
- .chain_id = ALC255_FIXUP_MIC_MUTE_LED
- },
- [ALC269_FIXUP_ASUS_X101_FUNC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc269_fixup_x101_headset_mic,
- },
- [ALC269_FIXUP_ASUS_X101_VERB] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
- {0x20, AC_VERB_SET_COEF_INDEX, 0x08},
- {0x20, AC_VERB_SET_PROC_COEF, 0x0310},
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_ASUS_X101_FUNC
- },
- [ALC269_FIXUP_ASUS_X101] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x18, 0x04a1182c }, /* Headset mic */
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_ASUS_X101_VERB
- },
- [ALC271_FIXUP_AMIC_MIC2] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x14, 0x99130110 }, /* speaker */
- { 0x19, 0x01a19c20 }, /* mic */
- { 0x1b, 0x99a7012f }, /* int-mic */
- { 0x21, 0x0121401f }, /* HP out */
- { }
- },
- },
- [ALC271_FIXUP_HP_GATE_MIC_JACK] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc271_hp_gate_mic_jack,
- .chained = true,
- .chain_id = ALC271_FIXUP_AMIC_MIC2,
- },
- [ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc269_fixup_limit_int_mic_boost,
- .chained = true,
- .chain_id = ALC271_FIXUP_HP_GATE_MIC_JACK,
- },
- [ALC269_FIXUP_ACER_AC700] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x12, 0x99a3092f }, /* int-mic */
- { 0x14, 0x99130110 }, /* speaker */
- { 0x18, 0x03a11c20 }, /* mic */
- { 0x1e, 0x0346101e }, /* SPDIF1 */
- { 0x21, 0x0321101f }, /* HP out */
- { }
- },
- .chained = true,
- .chain_id = ALC271_FIXUP_DMIC,
- },
- [ALC269_FIXUP_LIMIT_INT_MIC_BOOST] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc269_fixup_limit_int_mic_boost,
- .chained = true,
- .chain_id = ALC269_FIXUP_THINKPAD_ACPI,
- },
- [ALC269VB_FIXUP_ASUS_ZENBOOK] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc269_fixup_limit_int_mic_boost,
- .chained = true,
- .chain_id = ALC269VB_FIXUP_DMIC,
- },
- [ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- /* class-D output amp +5dB */
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x12 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x2800 },
- {}
- },
- .chained = true,
- .chain_id = ALC269VB_FIXUP_ASUS_ZENBOOK,
- },
- [ALC269VB_FIXUP_ASUS_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x18, 0x01a110f0 }, /* use as headset mic */
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MIC
- },
- [ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc269_fixup_limit_int_mic_boost,
- .chained = true,
- .chain_id = ALC269_FIXUP_HP_MUTE_LED_MIC1,
- },
- [ALC269VB_FIXUP_ORDISSIMO_EVE2] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x12, 0x99a3092f }, /* int-mic */
- { 0x18, 0x03a11d20 }, /* mic */
- { 0x19, 0x411111f0 }, /* Unused bogus pin */
- { }
- },
- },
- [ALC283_FIXUP_CHROME_BOOK] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc283_fixup_chromebook,
- },
- [ALC283_FIXUP_SENSE_COMBO_JACK] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc283_fixup_sense_combo_jack,
- .chained = true,
- .chain_id = ALC283_FIXUP_CHROME_BOOK,
- },
- [ALC282_FIXUP_ASUS_TX300] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc282_fixup_asus_tx300,
- },
- [ALC283_FIXUP_INT_MIC] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- {0x20, AC_VERB_SET_COEF_INDEX, 0x1a},
- {0x20, AC_VERB_SET_PROC_COEF, 0x0011},
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
- },
- [ALC290_FIXUP_SUBWOOFER_HSJACK] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x17, 0x90170112 }, /* subwoofer */
- { }
- },
- .chained = true,
- .chain_id = ALC290_FIXUP_MONO_SPEAKERS_HSJACK,
- },
- [ALC290_FIXUP_SUBWOOFER] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x17, 0x90170112 }, /* subwoofer */
- { }
- },
- .chained = true,
- .chain_id = ALC290_FIXUP_MONO_SPEAKERS,
- },
- [ALC290_FIXUP_MONO_SPEAKERS] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc290_fixup_mono_speakers,
- },
- [ALC290_FIXUP_MONO_SPEAKERS_HSJACK] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc290_fixup_mono_speakers,
- .chained = true,
- .chain_id = ALC269_FIXUP_DELL3_MIC_NO_PRESENCE,
- },
- [ALC269_FIXUP_THINKPAD_ACPI] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_thinkpad_acpi,
- .chained = true,
- .chain_id = ALC269_FIXUP_SKU_IGNORE,
- },
- [ALC269_FIXUP_LENOVO_XPAD_ACPI] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_ideapad_acpi,
- .chained = true,
- .chain_id = ALC269_FIXUP_THINKPAD_ACPI,
- },
- [ALC269_FIXUP_DMIC_THINKPAD_ACPI] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_inv_dmic,
- .chained = true,
- .chain_id = ALC269_FIXUP_THINKPAD_ACPI,
- },
- [ALC255_FIXUP_ACER_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC255_FIXUP_HEADSET_MODE
- },
- [ALC255_FIXUP_ASUS_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC255_FIXUP_HEADSET_MODE
- },
- [ALC255_FIXUP_DELL1_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
- { 0x1a, 0x01a1913d }, /* use as headphone mic, without its own jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC255_FIXUP_HEADSET_MODE
- },
- [ALC255_FIXUP_DELL1_LIMIT_INT_MIC_BOOST] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc269_fixup_limit_int_mic_boost,
- .chained = true,
- .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
- },
- [ALC255_FIXUP_DELL2_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC
- },
- [ALC255_FIXUP_HEADSET_MODE] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_headset_mode_alc255,
- .chained = true,
- .chain_id = ALC255_FIXUP_MIC_MUTE_LED
- },
- [ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_headset_mode_alc255_no_hp_mic,
- },
- [ALC293_FIXUP_DELL1_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x18, 0x01a1913d }, /* use as headphone mic, without its own jack detect */
- { 0x1a, 0x01a1913c }, /* use as headset mic, without its own jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MODE
- },
- [ALC292_FIXUP_TPT440_DOCK] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_tpt440_dock,
- .chained = true,
- .chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
- },
- [ALC292_FIXUP_TPT440] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_disable_aamix,
- .chained = true,
- .chain_id = ALC292_FIXUP_TPT440_DOCK,
- },
- [ALC283_FIXUP_HEADSET_MIC] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x04a110f0 },
- { },
- },
- },
- [ALC255_FIXUP_MIC_MUTE_LED] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_micmute_led,
- },
- [ALC282_FIXUP_ASPIRE_V5_PINS] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x12, 0x90a60130 },
- { 0x14, 0x90170110 },
- { 0x17, 0x40000008 },
- { 0x18, 0x411111f0 },
- { 0x19, 0x01a1913c },
- { 0x1a, 0x411111f0 },
- { 0x1b, 0x411111f0 },
- { 0x1d, 0x40f89b2d },
- { 0x1e, 0x411111f0 },
- { 0x21, 0x0321101f },
- { },
- },
- },
- [ALC269VB_FIXUP_ASPIRE_E1_COEF] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc269vb_fixup_aspire_e1_coef,
- },
- [ALC280_FIXUP_HP_GPIO4] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc280_fixup_hp_gpio4,
- },
- [ALC286_FIXUP_HP_GPIO_LED] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc286_fixup_hp_gpio_led,
- },
- [ALC280_FIXUP_HP_GPIO2_MIC_HOTKEY] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc280_fixup_hp_gpio2_mic_hotkey,
- },
- [ALC280_FIXUP_HP_DOCK_PINS] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1b, 0x21011020 }, /* line-out */
- { 0x1a, 0x01a1903c }, /* headset mic */
- { 0x18, 0x2181103f }, /* line-in */
- { },
- },
- .chained = true,
- .chain_id = ALC280_FIXUP_HP_GPIO4
- },
- [ALC269_FIXUP_HP_DOCK_GPIO_MIC1_LED] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1b, 0x21011020 }, /* line-out */
- { 0x18, 0x2181103f }, /* line-in */
- { },
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_HP_GPIO_MIC1_LED
- },
- [ALC280_FIXUP_HP_9480M] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc280_fixup_hp_9480m,
- },
- [ALC245_FIXUP_HP_X360_AMP] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc245_fixup_hp_x360_amp,
- .chained = true,
- .chain_id = ALC245_FIXUP_HP_GPIO_LED
- },
- [ALC288_FIXUP_DELL_HEADSET_MODE] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_headset_mode_dell_alc288,
- .chained = true,
- .chain_id = ALC255_FIXUP_MIC_MUTE_LED
- },
- [ALC288_FIXUP_DELL1_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x18, 0x01a1913c }, /* use as headset mic, without its own jack detect */
- { 0x1a, 0x01a1913d }, /* use as headphone mic, without its own jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC288_FIXUP_DELL_HEADSET_MODE
- },
- [ALC288_FIXUP_DISABLE_AAMIX] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_disable_aamix,
- .chained = true,
- .chain_id = ALC288_FIXUP_DELL1_MIC_NO_PRESENCE
- },
- [ALC288_FIXUP_DELL_XPS_13] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_dell_xps13,
- .chained = true,
- .chain_id = ALC288_FIXUP_DISABLE_AAMIX
- },
- [ALC292_FIXUP_DISABLE_AAMIX] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_disable_aamix,
- .chained = true,
- .chain_id = ALC269_FIXUP_DELL2_MIC_NO_PRESENCE
- },
- [ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_disable_aamix,
- .chained = true,
- .chain_id = ALC293_FIXUP_DELL1_MIC_NO_PRESENCE
- },
- [ALC292_FIXUP_DELL_E7X_AAMIX] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_dell_xps13,
- .chained = true,
- .chain_id = ALC292_FIXUP_DISABLE_AAMIX
- },
- [ALC292_FIXUP_DELL_E7X] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_micmute_led,
- /* micmute fixup must be applied at last */
- .chained_before = true,
- .chain_id = ALC292_FIXUP_DELL_E7X_AAMIX,
- },
- [ALC298_FIXUP_ALIENWARE_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x18, 0x01a1913c }, /* headset mic w/o jack detect */
- { }
- },
- .chained_before = true,
- .chain_id = ALC269_FIXUP_HEADSET_MODE,
- },
- [ALC298_FIXUP_DELL1_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x18, 0x01a1913c }, /* use as headset mic, without its own jack detect */
- { 0x1a, 0x01a1913d }, /* use as headphone mic, without its own jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MODE
- },
- [ALC298_FIXUP_DELL_AIO_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x18, 0x01a1913c }, /* use as headset mic, without its own jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MODE
- },
- [ALC275_FIXUP_DELL_XPS] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- /* Enables internal speaker */
- {0x20, AC_VERB_SET_COEF_INDEX, 0x1f},
- {0x20, AC_VERB_SET_PROC_COEF, 0x00c0},
- {0x20, AC_VERB_SET_COEF_INDEX, 0x30},
- {0x20, AC_VERB_SET_PROC_COEF, 0x00b1},
- {}
- }
- },
- [ALC293_FIXUP_LENOVO_SPK_NOISE] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_disable_aamix,
- .chained = true,
- .chain_id = ALC269_FIXUP_THINKPAD_ACPI
- },
- [ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc233_fixup_lenovo_line2_mic_hotkey,
- },
- [ALC233_FIXUP_LENOVO_L2MH_LOW_ENLED] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc233_fixup_lenovo_low_en_micmute_led,
- },
- [ALC233_FIXUP_INTEL_NUC8_DMIC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_inv_dmic,
- .chained = true,
- .chain_id = ALC233_FIXUP_INTEL_NUC8_BOOST,
- },
- [ALC233_FIXUP_INTEL_NUC8_BOOST] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc269_fixup_limit_int_mic_boost
- },
- [ALC255_FIXUP_DELL_SPK_NOISE] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_disable_aamix,
- .chained = true,
- .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
- },
- [ALC225_FIXUP_DISABLE_MIC_VREF] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_disable_mic_vref,
- .chained = true,
- .chain_id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE
- },
- [ALC225_FIXUP_DELL1_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- /* Disable pass-through path for FRONT 14h */
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x36 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x57d7 },
- {}
- },
- .chained = true,
- .chain_id = ALC225_FIXUP_DISABLE_MIC_VREF
- },
- [ALC280_FIXUP_HP_HEADSET_MIC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_disable_aamix,
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MIC,
- },
- [ALC221_FIXUP_HP_FRONT_MIC] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x02a19020 }, /* Front Mic */
- { }
- },
- },
- [ALC292_FIXUP_TPT460] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_tpt440_dock,
- .chained = true,
- .chain_id = ALC293_FIXUP_LENOVO_SPK_NOISE,
- },
- [ALC298_FIXUP_SPK_VOLUME] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc298_fixup_speaker_volume,
- .chained = true,
- .chain_id = ALC298_FIXUP_DELL_AIO_MIC_NO_PRESENCE,
- },
- [ALC298_FIXUP_LENOVO_SPK_VOLUME] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc298_fixup_speaker_volume,
- },
- [ALC295_FIXUP_DISABLE_DAC3] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc295_fixup_disable_dac3,
- },
- [ALC285_FIXUP_SPEAKER2_TO_DAC1] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc285_fixup_speaker2_to_dac1,
- .chained = true,
- .chain_id = ALC269_FIXUP_THINKPAD_ACPI
- },
- [ALC285_FIXUP_ASUS_SPEAKER2_TO_DAC1] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc285_fixup_speaker2_to_dac1,
- .chained = true,
- .chain_id = ALC245_FIXUP_CS35L41_SPI_2
- },
- [ALC285_FIXUP_ASUS_HEADSET_MIC] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x03a11050 },
- { 0x1b, 0x03a11c30 },
- { }
- },
- .chained = true,
- .chain_id = ALC285_FIXUP_ASUS_SPEAKER2_TO_DAC1
- },
- [ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x14, 0x90170120 },
- { }
- },
- .chained = true,
- .chain_id = ALC285_FIXUP_ASUS_HEADSET_MIC
- },
- [ALC285_FIXUP_ASUS_I2C_SPEAKER2_TO_DAC1] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc285_fixup_speaker2_to_dac1,
- .chained = true,
- .chain_id = ALC287_FIXUP_CS35L41_I2C_2
- },
- [ALC285_FIXUP_ASUS_I2C_HEADSET_MIC] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x03a11050 },
- { 0x1b, 0x03a11c30 },
- { }
- },
- .chained = true,
- .chain_id = ALC285_FIXUP_ASUS_I2C_SPEAKER2_TO_DAC1
- },
- [ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1b, 0x90170151 },
- { }
- },
- .chained = true,
- .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
- },
- [ALC269_FIXUP_ATIV_BOOK_8] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_auto_mute_via_amp,
- .chained = true,
- .chain_id = ALC269_FIXUP_NO_SHUTUP
- },
- [ALC221_FIXUP_HP_288PRO_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
- { 0x1a, 0x01813030 }, /* use as headphone mic, without its own jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MODE
- },
- [ALC221_FIXUP_HP_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x18, 0x01a1913c }, /* use as headset mic, without its own jack detect */
- { 0x1a, 0x01a1913d }, /* use as headphone mic, without its own jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MODE
- },
- [ALC256_FIXUP_ASUS_HEADSET_MODE] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_headset_mode,
- },
- [ALC256_FIXUP_ASUS_MIC] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x13, 0x90a60160 }, /* use as internal mic */
- { 0x19, 0x04a11120 }, /* use as headset mic, without its own jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC256_FIXUP_ASUS_HEADSET_MODE
- },
- [ALC256_FIXUP_ASUS_AIO_GPIO2] = {
- .type = HDA_FIXUP_FUNC,
- /* Set up GPIO2 for the speaker amp */
- .v.func = alc_fixup_gpio4,
- },
- [ALC233_FIXUP_ASUS_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MIC
- },
- [ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- /* Enables internal speaker */
- {0x20, AC_VERB_SET_COEF_INDEX, 0x40},
- {0x20, AC_VERB_SET_PROC_COEF, 0x8800},
- {}
- },
- .chained = true,
- .chain_id = ALC233_FIXUP_ASUS_MIC_NO_PRESENCE
- },
- [ALC233_FIXUP_LENOVO_MULTI_CODECS] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc233_alc662_fixup_lenovo_dual_codecs,
- .chained = true,
- .chain_id = ALC269_FIXUP_GPIO2
- },
- [ALC233_FIXUP_ACER_HEADSET_MIC] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x45 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x5089 },
- { }
- },
- .chained = true,
- .chain_id = ALC233_FIXUP_ASUS_MIC_NO_PRESENCE
- },
- [ALC294_FIXUP_LENOVO_MIC_LOCATION] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- /* Change the mic location from front to right, otherwise there are
- two front mics with the same name, pulseaudio can't handle them.
- This is just a temporary workaround, after applying this fixup,
- there will be one "Front Mic" and one "Mic" in this machine.
- */
- { 0x1a, 0x04a19040 },
- { }
- },
- },
- [ALC225_FIXUP_DELL_WYSE_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x16, 0x0101102f }, /* Rear Headset HP */
- { 0x19, 0x02a1913c }, /* use as Front headset mic, without its own jack detect */
- { 0x1a, 0x01a19030 }, /* Rear Headset MIC */
- { 0x1b, 0x02011020 },
- { }
- },
- .chained = true,
- .chain_id = ALC225_FIXUP_S3_POP_NOISE
- },
- [ALC225_FIXUP_S3_POP_NOISE] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc225_fixup_s3_pop_noise,
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
- },
- [ALC700_FIXUP_INTEL_REFERENCE] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- /* Enables internal speaker */
- {0x20, AC_VERB_SET_COEF_INDEX, 0x45},
- {0x20, AC_VERB_SET_PROC_COEF, 0x5289},
- {0x20, AC_VERB_SET_COEF_INDEX, 0x4A},
- {0x20, AC_VERB_SET_PROC_COEF, 0x001b},
- {0x58, AC_VERB_SET_COEF_INDEX, 0x00},
- {0x58, AC_VERB_SET_PROC_COEF, 0x3888},
- {0x20, AC_VERB_SET_COEF_INDEX, 0x6f},
- {0x20, AC_VERB_SET_PROC_COEF, 0x2c0b},
- {}
- }
- },
- [ALC274_FIXUP_DELL_BIND_DACS] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc274_fixup_bind_dacs,
- .chained = true,
- .chain_id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE
- },
- [ALC274_FIXUP_DELL_AIO_LINEOUT_VERB] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1b, 0x0401102f },
- { }
- },
- .chained = true,
- .chain_id = ALC274_FIXUP_DELL_BIND_DACS
- },
- [ALC298_FIXUP_TPT470_DOCK_FIX] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_tpt470_dock,
- .chained = true,
- .chain_id = ALC293_FIXUP_LENOVO_SPK_NOISE
- },
- [ALC298_FIXUP_TPT470_DOCK] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_tpt470_dacs,
- .chained = true,
- .chain_id = ALC298_FIXUP_TPT470_DOCK_FIX
- },
- [ALC255_FIXUP_DUMMY_LINEOUT_VERB] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x14, 0x0201101f },
- { }
- },
- .chained = true,
- .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
- },
- [ALC255_FIXUP_DELL_HEADSET_MIC] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MIC
- },
- [ALC295_FIXUP_HP_X360] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc295_fixup_hp_top_speakers,
- .chained = true,
- .chain_id = ALC269_FIXUP_HP_MUTE_LED_MIC3
- },
- [ALC221_FIXUP_HP_HEADSET_MIC] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x0181313f},
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MIC
- },
- [ALC285_FIXUP_LENOVO_HEADPHONE_NOISE] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc285_fixup_invalidate_dacs,
- .chained = true,
- .chain_id = ALC269_FIXUP_THINKPAD_ACPI
- },
- [ALC295_FIXUP_HP_AUTO_MUTE] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_auto_mute_via_amp,
- },
- [ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x18, 0x01a1913c }, /* use as headset mic, without its own jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MIC
- },
- [ALC294_FIXUP_ASUS_MIC] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x13, 0x90a60160 }, /* use as internal mic */
- { 0x19, 0x04a11120 }, /* use as headset mic, without its own jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MIC
- },
- [ALC294_FIXUP_ASUS_HEADSET_MIC] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x01a1103c }, /* use as headset mic */
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MIC
- },
- [ALC294_FIXUP_ASUS_SPK] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- /* Set EAPD high */
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x40 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x8800 },
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x0f },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x7774 },
- { }
- },
- .chained = true,
- .chain_id = ALC294_FIXUP_ASUS_HEADSET_MIC
- },
- [ALC295_FIXUP_CHROME_BOOK] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc295_fixup_chromebook,
- .chained = true,
- .chain_id = ALC225_FIXUP_HEADSET_JACK
- },
- [ALC225_FIXUP_HEADSET_JACK] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_headset_jack,
- },
- [ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1a, 0x01a1913c }, /* use as headset mic, without its own jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
- },
- [ALC285_FIXUP_LENOVO_PC_BEEP_IN_NOISE] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- /* Disable PCBEEP-IN passthrough */
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x36 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x57d7 },
- { }
- },
- .chained = true,
- .chain_id = ALC285_FIXUP_LENOVO_HEADPHONE_NOISE
- },
- [ALC255_FIXUP_ACER_HEADSET_MIC] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x03a11130 },
- { 0x1a, 0x90a60140 }, /* use as internal mic */
- { }
- },
- .chained = true,
- .chain_id = ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC
- },
- [ALC225_FIXUP_DELL_WYSE_AIO_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x16, 0x01011020 }, /* Rear Line out */
- { 0x19, 0x01a1913c }, /* use as Front headset mic, without its own jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC225_FIXUP_WYSE_AUTO_MUTE
- },
- [ALC225_FIXUP_WYSE_AUTO_MUTE] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_auto_mute_via_amp,
- .chained = true,
- .chain_id = ALC225_FIXUP_WYSE_DISABLE_MIC_VREF
- },
- [ALC225_FIXUP_WYSE_DISABLE_MIC_VREF] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_disable_mic_vref,
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
- },
- [ALC286_FIXUP_ACER_AIO_HEADSET_MIC] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x4f },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x5029 },
- { }
- },
- .chained = true,
- .chain_id = ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE
- },
- [ALC256_FIXUP_ASUS_HEADSET_MIC] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x03a11020 }, /* headset mic with jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC256_FIXUP_ASUS_HEADSET_MODE
- },
- [ALC256_FIXUP_ASUS_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x04a11120 }, /* use as headset mic, without its own jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC256_FIXUP_ASUS_HEADSET_MODE
- },
- [ALC255_FIXUP_PREDATOR_SUBWOOFER] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x17, 0x90170151 }, /* use as internal speaker (LFE) */
- { 0x1b, 0x90170152 } /* use as internal speaker (back) */
- }
- },
- [ALC299_FIXUP_PREDATOR_SPK] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x21, 0x90170150 }, /* use as headset mic, without its own jack detect */
- { }
- }
- },
- [ALC287_FIXUP_PREDATOR_SPK_CS35L41_I2C_2] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cs35l41_fixup_i2c_two,
- .chained = true,
- .chain_id = ALC255_FIXUP_PREDATOR_SUBWOOFER
- },
- [ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x04a11040 },
- { 0x21, 0x04211020 },
- { }
- },
- .chained = true,
- .chain_id = ALC256_FIXUP_ASUS_HEADSET_MODE
- },
- [ALC289_FIXUP_DELL_SPK1] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x14, 0x90170140 },
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_DELL4_MIC_NO_PRESENCE
- },
- [ALC289_FIXUP_DELL_SPK2] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x17, 0x90170130 }, /* bass spk */
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_DELL4_MIC_NO_PRESENCE
- },
- [ALC289_FIXUP_DUAL_SPK] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc285_fixup_speaker2_to_dac1,
- .chained = true,
- .chain_id = ALC289_FIXUP_DELL_SPK2
- },
- [ALC289_FIXUP_RTK_AMP_DUAL_SPK] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc285_fixup_speaker2_to_dac1,
- .chained = true,
- .chain_id = ALC289_FIXUP_DELL_SPK1
- },
- [ALC294_FIXUP_SPK2_TO_DAC1] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc285_fixup_speaker2_to_dac1,
- .chained = true,
- .chain_id = ALC294_FIXUP_ASUS_HEADSET_MIC
- },
- [ALC294_FIXUP_ASUS_DUAL_SPK] = {
- .type = HDA_FIXUP_FUNC,
- /* The GPIO must be pulled to initialize the AMP */
- .v.func = alc_fixup_gpio4,
- .chained = true,
- .chain_id = ALC294_FIXUP_SPK2_TO_DAC1
- },
- [ALC294_FIXUP_ASUS_ALLY] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cs35l41_fixup_i2c_two,
- .chained = true,
- .chain_id = ALC294_FIXUP_ASUS_ALLY_PINS
- },
- [ALC294_FIXUP_ASUS_ALLY_PINS] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x03a11050 },
- { 0x1a, 0x03a11c30 },
- { 0x21, 0x03211420 },
- { }
- },
- .chained = true,
- .chain_id = ALC294_FIXUP_ASUS_ALLY_VERBS
- },
- [ALC294_FIXUP_ASUS_ALLY_VERBS] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x45 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x5089 },
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x46 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0004 },
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x47 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xa47a },
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x49 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0049},
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x4a },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x201b },
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x6b },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x4278},
- { }
- },
- .chained = true,
- .chain_id = ALC294_FIXUP_ASUS_ALLY_SPEAKER
- },
- [ALC294_FIXUP_ASUS_ALLY_SPEAKER] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc285_fixup_speaker2_to_dac1,
- },
- [ALC285_FIXUP_THINKPAD_X1_GEN7] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc285_fixup_thinkpad_x1_gen7,
- .chained = true,
- .chain_id = ALC269_FIXUP_THINKPAD_ACPI
- },
- [ALC285_FIXUP_THINKPAD_HEADSET_JACK] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_headset_jack,
- .chained = true,
- .chain_id = ALC285_FIXUP_THINKPAD_X1_GEN7
- },
- [ALC294_FIXUP_ASUS_HPE] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- /* Set EAPD high */
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x0f },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x7774 },
- { }
- },
- .chained = true,
- .chain_id = ALC294_FIXUP_ASUS_HEADSET_MIC
- },
- [ALC294_FIXUP_ASUS_GX502_PINS] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x03a11050 }, /* front HP mic */
- { 0x1a, 0x01a11830 }, /* rear external mic */
- { 0x21, 0x03211020 }, /* front HP out */
- { }
- },
- .chained = true,
- .chain_id = ALC294_FIXUP_ASUS_GX502_VERBS
- },
- [ALC294_FIXUP_ASUS_GX502_VERBS] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- /* set 0x15 to HP-OUT ctrl */
- { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
- /* unmute the 0x15 amp */
- { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
- { }
- },
- .chained = true,
- .chain_id = ALC294_FIXUP_ASUS_GX502_HP
- },
- [ALC294_FIXUP_ASUS_GX502_HP] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc294_fixup_gx502_hp,
- },
- [ALC294_FIXUP_ASUS_GU502_PINS] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x01a11050 }, /* rear HP mic */
- { 0x1a, 0x01a11830 }, /* rear external mic */
- { 0x21, 0x012110f0 }, /* rear HP out */
- { }
- },
- .chained = true,
- .chain_id = ALC294_FIXUP_ASUS_GU502_VERBS
- },
- [ALC294_FIXUP_ASUS_GU502_VERBS] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- /* set 0x15 to HP-OUT ctrl */
- { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
- /* unmute the 0x15 amp */
- { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
- /* set 0x1b to HP-OUT */
- { 0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
- { }
- },
- .chained = true,
- .chain_id = ALC294_FIXUP_ASUS_GU502_HP
- },
- [ALC294_FIXUP_ASUS_GU502_HP] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc294_fixup_gu502_hp,
- },
- [ALC294_FIXUP_ASUS_G513_PINS] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x03a11050 }, /* front HP mic */
- { 0x1a, 0x03a11c30 }, /* rear external mic */
- { 0x21, 0x03211420 }, /* front HP out */
- { }
- },
- },
- [ALC285_FIXUP_ASUS_G533Z_PINS] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x14, 0x90170152 }, /* Speaker Surround Playback Switch */
- { 0x19, 0x03a19020 }, /* Mic Boost Volume */
- { 0x1a, 0x03a11c30 }, /* Mic Boost Volume */
- { 0x1e, 0x90170151 }, /* Rear jack, IN OUT EAPD Detect */
- { 0x21, 0x03211420 },
- { }
- },
- },
- [ALC294_FIXUP_ASUS_COEF_1B] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- /* Set bit 10 to correct noisy output after reboot from
- * Windows 10 (due to pop noise reduction?)
- */
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x1b },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x4e4b },
- { }
- },
- .chained = true,
- .chain_id = ALC289_FIXUP_ASUS_GA401,
- },
- [ALC285_FIXUP_HP_GPIO_LED] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc285_fixup_hp_gpio_led,
- },
- [ALC285_FIXUP_HP_MUTE_LED] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc285_fixup_hp_mute_led,
- },
- [ALC285_FIXUP_HP_SPECTRE_X360_MUTE_LED] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc285_fixup_hp_spectre_x360_mute_led,
- },
- [ALC285_FIXUP_HP_BEEP_MICMUTE_LED] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc285_fixup_hp_beep,
- .chained = true,
- .chain_id = ALC285_FIXUP_HP_MUTE_LED,
- },
- [ALC236_FIXUP_HP_MUTE_LED_COEFBIT2] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc236_fixup_hp_mute_led_coefbit2,
- },
- [ALC236_FIXUP_HP_GPIO_LED] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc236_fixup_hp_gpio_led,
- },
- [ALC236_FIXUP_HP_MUTE_LED] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc236_fixup_hp_mute_led,
- },
- [ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc236_fixup_hp_mute_led_micmute_vref,
- },
- [ALC236_FIXUP_LENOVO_INV_DMIC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_inv_dmic,
- .chained = true,
- .chain_id = ALC283_FIXUP_INT_MIC,
- },
- [ALC295_FIXUP_HP_MUTE_LED_COEFBIT11] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc295_fixup_hp_mute_led_coefbit11,
- },
- [ALC298_FIXUP_SAMSUNG_AMP] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc298_fixup_samsung_amp,
- .chained = true,
- .chain_id = ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET
- },
- [ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc298_fixup_samsung_amp_v2_2_amps
- },
- [ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc298_fixup_samsung_amp_v2_4_amps
- },
- [ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc5 },
- { }
- },
- },
- [ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x08},
- { 0x20, AC_VERB_SET_PROC_COEF, 0x2fcf},
- { }
- },
- },
- [ALC295_FIXUP_ASUS_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MODE
- },
- [ALC269VC_FIXUP_ACER_VCOPPERBOX_PINS] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x14, 0x90100120 }, /* use as internal speaker */
- { 0x18, 0x02a111f0 }, /* use as headset mic, without its own jack detect */
- { 0x1a, 0x01011020 }, /* use as line out */
- { },
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MIC
- },
- [ALC269VC_FIXUP_ACER_HEADSET_MIC] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x18, 0x02a11030 }, /* use as headset mic */
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MIC
- },
- [ALC269VC_FIXUP_ACER_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x18, 0x01a11130 }, /* use as headset mic, without its own jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MIC
- },
- [ALC289_FIXUP_ASUS_GA401] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc289_fixup_asus_ga401,
- .chained = true,
- .chain_id = ALC289_FIXUP_ASUS_GA502,
- },
- [ALC289_FIXUP_ASUS_GA502] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x03a11020 }, /* headset mic with jack detect */
- { }
- },
- },
- [ALC256_FIXUP_ACER_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x02a11120 }, /* use as headset mic, without its own jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC256_FIXUP_ASUS_HEADSET_MODE
- },
- [ALC285_FIXUP_HP_GPIO_AMP_INIT] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc285_fixup_hp_gpio_amp_init,
- .chained = true,
- .chain_id = ALC285_FIXUP_HP_GPIO_LED
- },
- [ALC269_FIXUP_CZC_B20] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x12, 0x411111f0 },
- { 0x14, 0x90170110 }, /* speaker */
- { 0x15, 0x032f1020 }, /* HP out */
- { 0x17, 0x411111f0 },
- { 0x18, 0x03ab1040 }, /* mic */
- { 0x19, 0xb7a7013f },
- { 0x1a, 0x0181305f },
- { 0x1b, 0x411111f0 },
- { 0x1d, 0x411111f0 },
- { 0x1e, 0x411111f0 },
- { }
- },
- .chain_id = ALC269_FIXUP_DMIC,
- },
- [ALC269_FIXUP_CZC_TMI] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x12, 0x4000c000 },
- { 0x14, 0x90170110 }, /* speaker */
- { 0x15, 0x0421401f }, /* HP out */
- { 0x17, 0x411111f0 },
- { 0x18, 0x04a19020 }, /* mic */
- { 0x19, 0x411111f0 },
- { 0x1a, 0x411111f0 },
- { 0x1b, 0x411111f0 },
- { 0x1d, 0x40448505 },
- { 0x1e, 0x411111f0 },
- { 0x20, 0x8000ffff },
- { }
- },
- .chain_id = ALC269_FIXUP_DMIC,
- },
- [ALC269_FIXUP_CZC_L101] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x12, 0x40000000 },
- { 0x14, 0x01014010 }, /* speaker */
- { 0x15, 0x411111f0 }, /* HP out */
- { 0x16, 0x411111f0 },
- { 0x18, 0x01a19020 }, /* mic */
- { 0x19, 0x02a19021 },
- { 0x1a, 0x0181302f },
- { 0x1b, 0x0221401f },
- { 0x1c, 0x411111f0 },
- { 0x1d, 0x4044c601 },
- { 0x1e, 0x411111f0 },
- { }
- },
- .chain_id = ALC269_FIXUP_DMIC,
- },
- [ALC269_FIXUP_LEMOTE_A1802] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x12, 0x40000000 },
- { 0x14, 0x90170110 }, /* speaker */
- { 0x17, 0x411111f0 },
- { 0x18, 0x03a19040 }, /* mic1 */
- { 0x19, 0x90a70130 }, /* mic2 */
- { 0x1a, 0x411111f0 },
- { 0x1b, 0x411111f0 },
- { 0x1d, 0x40489d2d },
- { 0x1e, 0x411111f0 },
- { 0x20, 0x0003ffff },
- { 0x21, 0x03214020 },
- { }
- },
- .chain_id = ALC269_FIXUP_DMIC,
- },
- [ALC269_FIXUP_LEMOTE_A190X] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x14, 0x99130110 }, /* speaker */
- { 0x15, 0x0121401f }, /* HP out */
- { 0x18, 0x01a19c20 }, /* rear mic */
- { 0x19, 0x99a3092f }, /* front mic */
- { 0x1b, 0x0201401f }, /* front lineout */
- { }
- },
- .chain_id = ALC269_FIXUP_DMIC,
- },
- [ALC256_FIXUP_INTEL_NUC8_RUGGED] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1b, 0x01a1913c }, /* use as headset mic, without its own jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MODE
- },
- [ALC256_FIXUP_INTEL_NUC10] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MODE
- },
- [ALC255_FIXUP_XIAOMI_HEADSET_MIC] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x45 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x5089 },
- { }
- },
- .chained = true,
- .chain_id = ALC289_FIXUP_ASUS_GA502
- },
- [ALC274_FIXUP_HP_MIC] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x45 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x5089 },
- { }
- },
- },
- [ALC274_FIXUP_HP_HEADSET_MIC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc274_fixup_hp_headset_mic,
- .chained = true,
- .chain_id = ALC274_FIXUP_HP_MIC
- },
- [ALC274_FIXUP_HP_ENVY_GPIO] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc274_fixup_hp_envy_gpio,
- },
- [ALC274_FIXUP_ASUS_ZEN_AIO_27] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x10 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xc420 },
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x40 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x8800 },
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x49 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0249 },
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x4a },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x202b },
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x62 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xa007 },
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x6b },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x5060 },
- {}
- },
- .chained = true,
- .chain_id = ALC2XX_FIXUP_HEADSET_MIC,
- },
- [ALC256_FIXUP_ASUS_HPE] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- /* Set EAPD high */
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x0f },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x7778 },
- { }
- },
- .chained = true,
- .chain_id = ALC294_FIXUP_ASUS_HEADSET_MIC
- },
- [ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_headset_jack,
- .chained = true,
- .chain_id = ALC269_FIXUP_THINKPAD_ACPI
- },
- [ALC287_FIXUP_HP_GPIO_LED] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc287_fixup_hp_gpio_led,
- },
- [ALC256_FIXUP_HP_HEADSET_MIC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc274_fixup_hp_headset_mic,
- },
- [ALC236_FIXUP_DELL_AIO_HEADSET_MIC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_no_int_mic,
- .chained = true,
- .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
- },
- [ALC282_FIXUP_ACER_DISABLE_LINEOUT] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1b, 0x411111f0 },
- { 0x18, 0x01a1913c }, /* use as headset mic, without its own jack detect */
- { },
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MODE
- },
- [ALC255_FIXUP_ACER_LIMIT_INT_MIC_BOOST] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc269_fixup_limit_int_mic_boost,
- .chained = true,
- .chain_id = ALC255_FIXUP_ACER_MIC_NO_PRESENCE,
- },
- [ALC256_FIXUP_ACER_HEADSET_MIC] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x02a1113c }, /* use as headset mic, without its own jack detect */
- { 0x1a, 0x90a1092f }, /* use as internal mic */
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
- },
- [ALC285_FIXUP_IDEAPAD_S740_COEF] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc285_fixup_ideapad_s740_coef,
- .chained = true,
- .chain_id = ALC269_FIXUP_THINKPAD_ACPI,
- },
- [ALC285_FIXUP_HP_LIMIT_INT_MIC_BOOST] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc269_fixup_limit_int_mic_boost,
- .chained = true,
- .chain_id = ALC285_FIXUP_HP_MUTE_LED,
- },
- [ALC295_FIXUP_ASUS_DACS] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc295_fixup_asus_dacs,
- },
- [ALC295_FIXUP_HP_OMEN] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x12, 0xb7a60130 },
- { 0x13, 0x40000000 },
- { 0x14, 0x411111f0 },
- { 0x16, 0x411111f0 },
- { 0x17, 0x90170110 },
- { 0x18, 0x411111f0 },
- { 0x19, 0x02a11030 },
- { 0x1a, 0x411111f0 },
- { 0x1b, 0x04a19030 },
- { 0x1d, 0x40600001 },
- { 0x1e, 0x411111f0 },
- { 0x21, 0x03211020 },
- {}
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_HP_LINE1_MIC1_LED,
- },
- [ALC285_FIXUP_HP_SPECTRE_X360] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc285_fixup_hp_spectre_x360,
- },
- [ALC285_FIXUP_HP_SPECTRE_X360_EB1] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc285_fixup_hp_spectre_x360_eb1
- },
- [ALC285_FIXUP_HP_SPECTRE_X360_DF1] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc285_fixup_hp_spectre_x360_df1
- },
- [ALC285_FIXUP_HP_ENVY_X360] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc285_fixup_hp_envy_x360,
- .chained = true,
- .chain_id = ALC285_FIXUP_HP_GPIO_AMP_INIT,
- },
- [ALC287_FIXUP_IDEAPAD_BASS_SPK_AMP] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc285_fixup_ideapad_s740_coef,
- .chained = true,
- .chain_id = ALC285_FIXUP_THINKPAD_HEADSET_JACK,
- },
- [ALC623_FIXUP_LENOVO_THINKSTATION_P340] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_no_shutup,
- .chained = true,
- .chain_id = ALC283_FIXUP_HEADSET_MIC,
- },
- [ALC255_FIXUP_ACER_HEADPHONE_AND_MIC] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x21, 0x03211030 }, /* Change the Headphone location to Left */
- { }
- },
- .chained = true,
- .chain_id = ALC255_FIXUP_XIAOMI_HEADSET_MIC
- },
- [ALC236_FIXUP_HP_LIMIT_INT_MIC_BOOST] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc269_fixup_limit_int_mic_boost,
- .chained = true,
- .chain_id = ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF,
- },
- [ALC285_FIXUP_LEGION_Y9000X_SPEAKERS] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc285_fixup_ideapad_s740_coef,
- .chained = true,
- .chain_id = ALC285_FIXUP_LEGION_Y9000X_AUTOMUTE,
- },
- [ALC285_FIXUP_LEGION_Y9000X_AUTOMUTE] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc287_fixup_legion_15imhg05_speakers,
- .chained = true,
- .chain_id = ALC269_FIXUP_THINKPAD_ACPI,
- },
- [ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS] = {
- .type = HDA_FIXUP_VERBS,
- //.v.verbs = legion_15imhg05_coefs,
- .v.verbs = (const struct hda_verb[]) {
- // set left speaker Legion 7i.
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x24 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x41 },
-
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xc },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x1a },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x2 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-
- // set right speaker Legion 7i.
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x24 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x42 },
-
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xc },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x2a },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x2 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
- {}
- },
- .chained = true,
- .chain_id = ALC287_FIXUP_LEGION_15IMHG05_AUTOMUTE,
- },
- [ALC287_FIXUP_LEGION_15IMHG05_AUTOMUTE] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc287_fixup_legion_15imhg05_speakers,
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MODE,
- },
- [ALC287_FIXUP_YOGA7_14ITL_SPEAKERS] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- // set left speaker Yoga 7i.
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x24 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x41 },
-
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xc },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x1a },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x2 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-
- // set right speaker Yoga 7i.
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x24 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x46 },
-
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xc },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x2a },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x2 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
- {}
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MODE,
- },
- [ALC298_FIXUP_LENOVO_C940_DUET7] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc298_fixup_lenovo_c940_duet7,
- },
- [ALC287_FIXUP_13S_GEN2_SPEAKERS] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x24 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x41 },
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x2 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x24 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x42 },
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x2 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
- {}
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MODE,
- },
- [ALC256_FIXUP_SET_COEF_DEFAULTS] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc256_fixup_set_coef_defaults,
- },
- [ALC245_FIXUP_HP_GPIO_LED] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc245_fixup_hp_gpio_led,
- },
- [ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x03a11120 }, /* use as headset mic, without its own jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC,
- },
- [ALC233_FIXUP_NO_AUDIO_JACK] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc233_fixup_no_audio_jack,
- },
- [ALC256_FIXUP_MIC_NO_PRESENCE_AND_RESUME] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc256_fixup_mic_no_presence_and_resume,
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
- },
- [ALC287_FIXUP_LEGION_16ACHG6] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc287_fixup_legion_16achg6_speakers,
- },
- [ALC287_FIXUP_CS35L41_I2C_2] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cs35l41_fixup_i2c_two,
- },
- [ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cs35l41_fixup_i2c_two,
- .chained = true,
- .chain_id = ALC285_FIXUP_HP_MUTE_LED,
- },
- [ALC287_FIXUP_CS35L41_I2C_4] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cs35l41_fixup_i2c_four,
- },
- [ALC245_FIXUP_CS35L41_SPI_2] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cs35l41_fixup_spi_two,
- },
- [ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cs35l41_fixup_spi_two,
- .chained = true,
- .chain_id = ALC285_FIXUP_HP_GPIO_LED,
- },
- [ALC245_FIXUP_CS35L41_SPI_4] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cs35l41_fixup_spi_four,
- },
- [ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cs35l41_fixup_spi_four,
- .chained = true,
- .chain_id = ALC285_FIXUP_HP_GPIO_LED,
- },
- [ALC285_FIXUP_HP_SPEAKERS_MICMUTE_LED] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x19 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x8e11 },
- { }
- },
- .chained = true,
- .chain_id = ALC285_FIXUP_HP_MUTE_LED,
- },
- [ALC269_FIXUP_DELL4_MIC_NO_PRESENCE_QUIET] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_dell4_mic_no_presence_quiet,
- .chained = true,
- .chain_id = ALC269_FIXUP_DELL4_MIC_NO_PRESENCE,
- },
- [ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x02a1112c }, /* use as headset mic, without its own jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
- },
- [ALC287_FIXUP_LEGION_16ITHG6] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc287_fixup_legion_16ithg6_speakers,
- },
- [ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- // enable left speaker
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x24 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x41 },
-
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xc },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x1a },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xf },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x42 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x10 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x40 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x2 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-
- // enable right speaker
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x24 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x46 },
-
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xc },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x2a },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xf },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x46 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x10 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x44 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x2 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
-
- { },
- },
- },
- [ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc287_fixup_yoga9_14iap7_bass_spk_pin,
- .chained = true,
- .chain_id = ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK,
- },
- [ALC287_FIXUP_YOGA9_14IMH9_BASS_SPK_PIN] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc287_fixup_yoga9_14iap7_bass_spk_pin,
- .chained = true,
- .chain_id = ALC287_FIXUP_CS35L41_I2C_2,
- },
- [ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc295_fixup_dell_inspiron_top_speakers,
- .chained = true,
- .chain_id = ALC269_FIXUP_DELL4_MIC_NO_PRESENCE,
- },
- [ALC236_FIXUP_DELL_DUAL_CODECS] = {
- .type = HDA_FIXUP_PINS,
- .v.func = alc1220_fixup_gb_dual_codecs,
- .chained = true,
- .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
- },
- [ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cs35l41_fixup_i2c_two,
- .chained = true,
- .chain_id = ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK,
- },
- [ALC287_FIXUP_TAS2781_I2C] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = tas2781_fixup_i2c,
- .chained = true,
- .chain_id = ALC285_FIXUP_THINKPAD_HEADSET_JACK,
- },
- [ALC245_FIXUP_TAS2781_SPI_2] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = tas2781_fixup_spi,
- .chained = true,
- .chain_id = ALC285_FIXUP_HP_GPIO_LED,
- },
- [ALC287_FIXUP_YOGA7_14ARB7_I2C] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = yoga7_14arb7_fixup_i2c,
- .chained = true,
- .chain_id = ALC285_FIXUP_THINKPAD_HEADSET_JACK,
- },
- [ALC245_FIXUP_HP_MUTE_LED_COEFBIT] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc245_fixup_hp_mute_led_coefbit,
- },
- [ALC245_FIXUP_HP_MUTE_LED_V1_COEFBIT] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc245_fixup_hp_mute_led_v1_coefbit,
- },
- [ALC245_FIXUP_HP_X360_MUTE_LEDS] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc245_fixup_hp_mute_led_coefbit,
- .chained = true,
- .chain_id = ALC245_FIXUP_HP_GPIO_LED
- },
- [ALC287_FIXUP_THINKPAD_I2S_SPK] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc287_fixup_bind_dacs,
- .chained = true,
- .chain_id = ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK,
- },
- [ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc287_fixup_bind_dacs,
- .chained = true,
- .chain_id = ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI,
- },
- [ALC2XX_FIXUP_HEADSET_MIC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_headset_mic,
- },
- [ALC289_FIXUP_DELL_CS35L41_SPI_2] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cs35l41_fixup_spi_two,
- .chained = true,
- .chain_id = ALC289_FIXUP_DUAL_SPK
- },
- [ALC294_FIXUP_CS35L41_I2C_2] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cs35l41_fixup_i2c_two,
- },
- [ALC256_FIXUP_ACER_SFG16_MICMUTE_LED] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc256_fixup_acer_sfg16_micmute_led,
- },
- [ALC256_FIXUP_HEADPHONE_AMP_VOL] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc256_decrease_headphone_amp_val,
- },
- [ALC245_FIXUP_HP_SPECTRE_X360_EU0XXX] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc245_fixup_hp_spectre_x360_eu0xxx,
- },
- [ALC245_FIXUP_HP_SPECTRE_X360_16_AA0XXX] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc245_fixup_hp_spectre_x360_16_aa0xxx,
- },
- [ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc245_fixup_hp_zbook_firefly_g12a,
- },
- [ALC285_FIXUP_ASUS_GA403U] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc285_fixup_asus_ga403u,
- },
- [ALC285_FIXUP_ASUS_GA403U_HEADSET_MIC] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x03a11050 },
- { 0x1b, 0x03a11c30 },
- { }
- },
- .chained = true,
- .chain_id = ALC285_FIXUP_ASUS_GA403U_I2C_SPEAKER2_TO_DAC1
- },
- [ALC285_FIXUP_ASUS_GU605_SPI_SPEAKER2_TO_DAC1] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc285_fixup_speaker2_to_dac1,
- .chained = true,
- .chain_id = ALC285_FIXUP_ASUS_GU605_SPI_2_HEADSET_MIC,
- },
- [ALC285_FIXUP_ASUS_GU605_SPI_2_HEADSET_MIC] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x03a11050 },
- { 0x1b, 0x03a11c30 },
- { }
- },
- },
- [ALC285_FIXUP_ASUS_GA403U_I2C_SPEAKER2_TO_DAC1] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc285_fixup_speaker2_to_dac1,
- .chained = true,
- .chain_id = ALC285_FIXUP_ASUS_GA403U,
- },
- [ALC287_FIXUP_LENOVO_THKPAD_WH_ALC1318] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc287_fixup_lenovo_thinkpad_with_alc1318,
- .chained = true,
- .chain_id = ALC269_FIXUP_THINKPAD_ACPI
- },
- [ALC256_FIXUP_CHROME_BOOK] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc256_fixup_chromebook,
- .chained = true,
- .chain_id = ALC225_FIXUP_HEADSET_JACK
- },
- [ALC245_FIXUP_CLEVO_NOISY_MIC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc269_fixup_limit_int_mic_boost,
- .chained = true,
- .chain_id = ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE,
- },
- [ALC269_FIXUP_VAIO_VJFH52_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x03a1113c }, /* use as headset mic, without its own jack detect */
- { 0x1b, 0x20a11040 }, /* dock mic */
- { }
- },
- .chained = true,
- .chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
- },
- [ALC233_FIXUP_MEDION_MTL_SPK] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1b, 0x90170110 },
- { }
- },
- },
- [ALC294_FIXUP_BASS_SPEAKER_15] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc294_fixup_bass_speaker_15,
- },
- [ALC283_FIXUP_DELL_HP_RESUME] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc283_fixup_dell_hp_resume,
- },
- [ALC294_FIXUP_ASUS_CS35L41_SPI_2] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = cs35l41_fixup_spi_two,
- .chained = true,
- .chain_id = ALC294_FIXUP_ASUS_HEADSET_MIC,
- },
- [ALC274_FIXUP_HP_AIO_BIND_DACS] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc274_fixup_hp_aio_bind_dacs,
- },
- [ALC285_FIXUP_ASUS_GA605K_HEADSET_MIC] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x03a11050 },
- { 0x1b, 0x03a11c30 },
- { }
- },
- .chained = true,
- .chain_id = ALC285_FIXUP_ASUS_GA605K_I2C_SPEAKER2_TO_DAC1
- },
- [ALC285_FIXUP_ASUS_GA605K_I2C_SPEAKER2_TO_DAC1] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc285_fixup_speaker2_to_dac1,
- },
- [ALC269_FIXUP_POSITIVO_P15X_HEADSET_MIC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc269_fixup_limit_int_mic_boost,
- .chained = true,
- .chain_id = ALC269VC_FIXUP_ACER_MIC_NO_PRESENCE,
- },
-};
-
-static const struct hda_quirk alc269_fixup_tbl[] = {
- SND_PCI_QUIRK(0x1025, 0x0283, "Acer TravelMate 8371", ALC269_FIXUP_INV_DMIC),
- SND_PCI_QUIRK(0x1025, 0x029b, "Acer 1810TZ", ALC269_FIXUP_INV_DMIC),
- SND_PCI_QUIRK(0x1025, 0x0349, "Acer AOD260", ALC269_FIXUP_INV_DMIC),
- SND_PCI_QUIRK(0x1025, 0x047c, "Acer AC700", ALC269_FIXUP_ACER_AC700),
- SND_PCI_QUIRK(0x1025, 0x072d, "Acer Aspire V5-571G", ALC269_FIXUP_ASPIRE_HEADSET_MIC),
- SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK),
- SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK),
- SND_PCI_QUIRK(0x1025, 0x0762, "Acer Aspire E1-472", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572),
- SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572),
- SND_PCI_QUIRK(0x1025, 0x079b, "Acer Aspire V5-573G", ALC282_FIXUP_ASPIRE_V5_PINS),
- SND_PCI_QUIRK(0x1025, 0x080d, "Acer Aspire V5-122P", ALC269_FIXUP_ASPIRE_HEADSET_MIC),
- SND_PCI_QUIRK(0x1025, 0x0840, "Acer Aspire E1", ALC269VB_FIXUP_ASPIRE_E1_COEF),
- SND_PCI_QUIRK(0x1025, 0x100c, "Acer Aspire E5-574G", ALC255_FIXUP_ACER_LIMIT_INT_MIC_BOOST),
- SND_PCI_QUIRK(0x1025, 0x101c, "Acer Veriton N2510G", ALC269_FIXUP_LIFEBOOK),
- SND_PCI_QUIRK(0x1025, 0x102b, "Acer Aspire C24-860", ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1025, 0x1065, "Acer Aspire C20-820", ALC269VC_FIXUP_ACER_HEADSET_MIC),
- SND_PCI_QUIRK(0x1025, 0x106d, "Acer Cloudbook 14", ALC283_FIXUP_CHROME_BOOK),
- SND_PCI_QUIRK(0x1025, 0x1094, "Acer Aspire E5-575T", ALC255_FIXUP_ACER_LIMIT_INT_MIC_BOOST),
- SND_PCI_QUIRK(0x1025, 0x1099, "Acer Aspire E5-523G", ALC255_FIXUP_ACER_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1025, 0x110e, "Acer Aspire ES1-432", ALC255_FIXUP_ACER_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1025, 0x1166, "Acer Veriton N4640G", ALC269_FIXUP_LIFEBOOK),
- SND_PCI_QUIRK(0x1025, 0x1167, "Acer Veriton N6640G", ALC269_FIXUP_LIFEBOOK),
- SND_PCI_QUIRK(0x1025, 0x1177, "Acer Predator G9-593", ALC255_FIXUP_PREDATOR_SUBWOOFER),
- SND_PCI_QUIRK(0x1025, 0x1178, "Acer Predator G9-593", ALC255_FIXUP_PREDATOR_SUBWOOFER),
- SND_PCI_QUIRK(0x1025, 0x1246, "Acer Predator Helios 500", ALC299_FIXUP_PREDATOR_SPK),
- SND_PCI_QUIRK(0x1025, 0x1247, "Acer vCopperbox", ALC269VC_FIXUP_ACER_VCOPPERBOX_PINS),
- SND_PCI_QUIRK(0x1025, 0x1248, "Acer Veriton N4660G", ALC269VC_FIXUP_ACER_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1025, 0x1269, "Acer SWIFT SF314-54", ALC256_FIXUP_ACER_HEADSET_MIC),
- SND_PCI_QUIRK(0x1025, 0x126a, "Acer Swift SF114-32", ALC256_FIXUP_ACER_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1025, 0x128f, "Acer Veriton Z6860G", ALC286_FIXUP_ACER_AIO_HEADSET_MIC),
- SND_PCI_QUIRK(0x1025, 0x1290, "Acer Veriton Z4860G", ALC286_FIXUP_ACER_AIO_HEADSET_MIC),
- SND_PCI_QUIRK(0x1025, 0x1291, "Acer Veriton Z4660G", ALC286_FIXUP_ACER_AIO_HEADSET_MIC),
- SND_PCI_QUIRK(0x1025, 0x129c, "Acer SWIFT SF314-55", ALC256_FIXUP_ACER_HEADSET_MIC),
- SND_PCI_QUIRK(0x1025, 0x129d, "Acer SWIFT SF313-51", ALC256_FIXUP_ACER_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1025, 0x1300, "Acer SWIFT SF314-56", ALC256_FIXUP_ACER_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1025, 0x1308, "Acer Aspire Z24-890", ALC286_FIXUP_ACER_AIO_HEADSET_MIC),
- SND_PCI_QUIRK(0x1025, 0x132a, "Acer TravelMate B114-21", ALC233_FIXUP_ACER_HEADSET_MIC),
- SND_PCI_QUIRK(0x1025, 0x1330, "Acer TravelMate X514-51T", ALC255_FIXUP_ACER_HEADSET_MIC),
- SND_PCI_QUIRK(0x1025, 0x1360, "Acer Aspire A115", ALC255_FIXUP_ACER_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1025, 0x141f, "Acer Spin SP513-54N", ALC255_FIXUP_ACER_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1025, 0x142b, "Acer Swift SF314-42", ALC255_FIXUP_ACER_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1025, 0x1430, "Acer TravelMate B311R-31", ALC256_FIXUP_ACER_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1025, 0x1466, "Acer Aspire A515-56", ALC255_FIXUP_ACER_HEADPHONE_AND_MIC),
- SND_PCI_QUIRK(0x1025, 0x1534, "Acer Predator PH315-54", ALC255_FIXUP_ACER_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1025, 0x159c, "Acer Nitro 5 AN515-58", ALC2XX_FIXUP_HEADSET_MIC),
- SND_PCI_QUIRK(0x1025, 0x169a, "Acer Swift SFG16", ALC256_FIXUP_ACER_SFG16_MICMUTE_LED),
- SND_PCI_QUIRK(0x1025, 0x1826, "Acer Helios ZPC", ALC287_FIXUP_PREDATOR_SPK_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x1025, 0x182c, "Acer Helios ZPD", ALC287_FIXUP_PREDATOR_SPK_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x1025, 0x1844, "Acer Helios ZPS", ALC287_FIXUP_PREDATOR_SPK_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
- SND_PCI_QUIRK(0x1028, 0x053c, "Dell Latitude E5430", ALC292_FIXUP_DELL_E7X),
- SND_PCI_QUIRK(0x1028, 0x054b, "Dell XPS one 2710", ALC275_FIXUP_DELL_XPS),
- SND_PCI_QUIRK(0x1028, 0x05bd, "Dell Latitude E6440", ALC292_FIXUP_DELL_E7X),
- SND_PCI_QUIRK(0x1028, 0x05be, "Dell Latitude E6540", ALC292_FIXUP_DELL_E7X),
- SND_PCI_QUIRK(0x1028, 0x05ca, "Dell Latitude E7240", ALC292_FIXUP_DELL_E7X),
- SND_PCI_QUIRK(0x1028, 0x05cb, "Dell Latitude E7440", ALC292_FIXUP_DELL_E7X),
- SND_PCI_QUIRK(0x1028, 0x05da, "Dell Vostro 5460", ALC290_FIXUP_SUBWOOFER),
- SND_PCI_QUIRK(0x1028, 0x05f4, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1028, 0x05f5, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1028, 0x05f6, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1028, 0x0604, "Dell Venue 11 Pro 7130", ALC283_FIXUP_DELL_HP_RESUME),
- SND_PCI_QUIRK(0x1028, 0x0615, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
- SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
- SND_PCI_QUIRK(0x1028, 0x062c, "Dell Latitude E5550", ALC292_FIXUP_DELL_E7X),
- SND_PCI_QUIRK(0x1028, 0x062e, "Dell Latitude E7450", ALC292_FIXUP_DELL_E7X),
- SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS_HSJACK),
- SND_PCI_QUIRK(0x1028, 0x064a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1028, 0x064b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1028, 0x0665, "Dell XPS 13", ALC288_FIXUP_DELL_XPS_13),
- SND_PCI_QUIRK(0x1028, 0x0669, "Dell Optiplex 9020m", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1028, 0x069a, "Dell Vostro 5480", ALC290_FIXUP_SUBWOOFER_HSJACK),
- SND_PCI_QUIRK(0x1028, 0x06c7, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1028, 0x06d9, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1028, 0x06da, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1028, 0x06db, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
- SND_PCI_QUIRK(0x1028, 0x06dd, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
- SND_PCI_QUIRK(0x1028, 0x06de, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
- SND_PCI_QUIRK(0x1028, 0x06df, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
- SND_PCI_QUIRK(0x1028, 0x06e0, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
- SND_PCI_QUIRK(0x1028, 0x0706, "Dell Inspiron 7559", ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER),
- SND_PCI_QUIRK(0x1028, 0x0725, "Dell Inspiron 3162", ALC255_FIXUP_DELL_SPK_NOISE),
- SND_PCI_QUIRK(0x1028, 0x0738, "Dell Precision 5820", ALC269_FIXUP_NO_SHUTUP),
- SND_PCI_QUIRK(0x1028, 0x075c, "Dell XPS 27 7760", ALC298_FIXUP_SPK_VOLUME),
- SND_PCI_QUIRK(0x1028, 0x075d, "Dell AIO", ALC298_FIXUP_SPK_VOLUME),
- SND_PCI_QUIRK(0x1028, 0x0798, "Dell Inspiron 17 7000 Gaming", ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER),
- SND_PCI_QUIRK(0x1028, 0x07b0, "Dell Precision 7520", ALC295_FIXUP_DISABLE_DAC3),
- SND_PCI_QUIRK(0x1028, 0x080c, "Dell WYSE", ALC225_FIXUP_DELL_WYSE_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1028, 0x084b, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB),
- SND_PCI_QUIRK(0x1028, 0x084e, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB),
- SND_PCI_QUIRK(0x1028, 0x0871, "Dell Precision 3630", ALC255_FIXUP_DELL_HEADSET_MIC),
- SND_PCI_QUIRK(0x1028, 0x0872, "Dell Precision 3630", ALC255_FIXUP_DELL_HEADSET_MIC),
- SND_PCI_QUIRK(0x1028, 0x0873, "Dell Precision 3930", ALC255_FIXUP_DUMMY_LINEOUT_VERB),
- SND_PCI_QUIRK(0x1028, 0x0879, "Dell Latitude 5420 Rugged", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1028, 0x08ad, "Dell WYSE AIO", ALC225_FIXUP_DELL_WYSE_AIO_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1028, 0x08ae, "Dell WYSE NB", ALC225_FIXUP_DELL1_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1028, 0x0935, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB),
- SND_PCI_QUIRK(0x1028, 0x097d, "Dell Precision", ALC289_FIXUP_DUAL_SPK),
- SND_PCI_QUIRK(0x1028, 0x097e, "Dell Precision", ALC289_FIXUP_DUAL_SPK),
- SND_PCI_QUIRK(0x1028, 0x098d, "Dell Precision", ALC233_FIXUP_ASUS_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1028, 0x09bf, "Dell Precision", ALC233_FIXUP_ASUS_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1028, 0x0a2e, "Dell", ALC236_FIXUP_DELL_AIO_HEADSET_MIC),
- SND_PCI_QUIRK(0x1028, 0x0a30, "Dell", ALC236_FIXUP_DELL_AIO_HEADSET_MIC),
- SND_PCI_QUIRK(0x1028, 0x0a38, "Dell Latitude 7520", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE_QUIET),
- SND_PCI_QUIRK(0x1028, 0x0a58, "Dell", ALC255_FIXUP_DELL_HEADSET_MIC),
- SND_PCI_QUIRK(0x1028, 0x0a61, "Dell XPS 15 9510", ALC289_FIXUP_DUAL_SPK),
- SND_PCI_QUIRK(0x1028, 0x0a62, "Dell Precision 5560", ALC289_FIXUP_DUAL_SPK),
- SND_PCI_QUIRK(0x1028, 0x0a9d, "Dell Latitude 5430", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1028, 0x0a9e, "Dell Latitude 5430", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1028, 0x0b19, "Dell XPS 15 9520", ALC289_FIXUP_DUAL_SPK),
- SND_PCI_QUIRK(0x1028, 0x0b1a, "Dell Precision 5570", ALC289_FIXUP_DUAL_SPK),
- SND_PCI_QUIRK(0x1028, 0x0b27, "Dell", ALC245_FIXUP_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1028, 0x0b28, "Dell", ALC245_FIXUP_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1028, 0x0b37, "Dell Inspiron 16 Plus 7620 2-in-1", ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS),
- SND_PCI_QUIRK(0x1028, 0x0b71, "Dell Inspiron 16 Plus 7620", ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS),
- SND_PCI_QUIRK(0x1028, 0x0beb, "Dell XPS 15 9530 (2023)", ALC289_FIXUP_DELL_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1028, 0x0c03, "Dell Precision 5340", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1028, 0x0c0b, "Dell Oasis 14 RPL-P", ALC289_FIXUP_RTK_AMP_DUAL_SPK),
- SND_PCI_QUIRK(0x1028, 0x0c0d, "Dell Oasis", ALC289_FIXUP_RTK_AMP_DUAL_SPK),
- SND_PCI_QUIRK(0x1028, 0x0c0e, "Dell Oasis 16", ALC289_FIXUP_RTK_AMP_DUAL_SPK),
- SND_PCI_QUIRK(0x1028, 0x0c19, "Dell Precision 3340", ALC236_FIXUP_DELL_DUAL_CODECS),
- SND_PCI_QUIRK(0x1028, 0x0c1a, "Dell Precision 3340", ALC236_FIXUP_DELL_DUAL_CODECS),
- SND_PCI_QUIRK(0x1028, 0x0c1b, "Dell Precision 3440", ALC236_FIXUP_DELL_DUAL_CODECS),
- SND_PCI_QUIRK(0x1028, 0x0c1c, "Dell Precision 3540", ALC236_FIXUP_DELL_DUAL_CODECS),
- SND_PCI_QUIRK(0x1028, 0x0c1d, "Dell Precision 3440", ALC236_FIXUP_DELL_DUAL_CODECS),
- SND_PCI_QUIRK(0x1028, 0x0c1e, "Dell Precision 3540", ALC236_FIXUP_DELL_DUAL_CODECS),
- SND_PCI_QUIRK(0x1028, 0x0c28, "Dell Inspiron 16 Plus 7630", ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS),
- SND_PCI_QUIRK(0x1028, 0x0c4d, "Dell", ALC287_FIXUP_CS35L41_I2C_4),
- SND_PCI_QUIRK(0x1028, 0x0c94, "Dell Polaris 3 metal", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x1028, 0x0c96, "Dell Polaris 2in1", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x1028, 0x0cbd, "Dell Oasis 13 CS MTL-U", ALC289_FIXUP_DELL_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1028, 0x0cbe, "Dell Oasis 13 2-IN-1 MTL-U", ALC289_FIXUP_DELL_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1028, 0x0cbf, "Dell Oasis 13 Low Weight MTU-L", ALC289_FIXUP_DELL_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1028, 0x0cc0, "Dell Oasis 13", ALC289_FIXUP_RTK_AMP_DUAL_SPK),
- SND_PCI_QUIRK(0x1028, 0x0cc1, "Dell Oasis 14 MTL-H/U", ALC289_FIXUP_DELL_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1028, 0x0cc2, "Dell Oasis 14 2-in-1 MTL-H/U", ALC289_FIXUP_DELL_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1028, 0x0cc3, "Dell Oasis 14 Low Weight MTL-U", ALC289_FIXUP_DELL_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1028, 0x0cc4, "Dell Oasis 16 MTL-H/U", ALC289_FIXUP_DELL_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1028, 0x0cc5, "Dell Oasis 14", ALC289_FIXUP_RTK_AMP_DUAL_SPK),
- SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
- SND_PCI_QUIRK(0x103c, 0x18e6, "HP", ALC269_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x218b, "HP", ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED),
- SND_PCI_QUIRK(0x103c, 0x21f9, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x2210, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x2214, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x221b, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
- SND_PCI_QUIRK(0x103c, 0x221c, "HP EliteBook 755 G2", ALC280_FIXUP_HP_HEADSET_MIC),
- SND_PCI_QUIRK(0x103c, 0x2221, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
- SND_PCI_QUIRK(0x103c, 0x2225, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
- SND_PCI_QUIRK(0x103c, 0x2236, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
- SND_PCI_QUIRK(0x103c, 0x2237, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
- SND_PCI_QUIRK(0x103c, 0x2238, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
- SND_PCI_QUIRK(0x103c, 0x2239, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
- SND_PCI_QUIRK(0x103c, 0x224b, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
- SND_PCI_QUIRK(0x103c, 0x2253, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
- SND_PCI_QUIRK(0x103c, 0x2254, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
- SND_PCI_QUIRK(0x103c, 0x2255, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
- SND_PCI_QUIRK(0x103c, 0x2256, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
- SND_PCI_QUIRK(0x103c, 0x2257, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
- SND_PCI_QUIRK(0x103c, 0x2259, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
- SND_PCI_QUIRK(0x103c, 0x225a, "HP", ALC269_FIXUP_HP_DOCK_GPIO_MIC1_LED),
- SND_PCI_QUIRK(0x103c, 0x225f, "HP", ALC280_FIXUP_HP_GPIO2_MIC_HOTKEY),
- SND_PCI_QUIRK(0x103c, 0x2260, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x2263, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x2264, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x2265, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x2268, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x226a, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x226b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x226e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x2271, "HP", ALC286_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x2272, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
- SND_PCI_QUIRK(0x103c, 0x2272, "HP", ALC280_FIXUP_HP_DOCK_PINS),
- SND_PCI_QUIRK(0x103c, 0x2273, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
- SND_PCI_QUIRK(0x103c, 0x2273, "HP", ALC280_FIXUP_HP_DOCK_PINS),
- SND_PCI_QUIRK(0x103c, 0x2278, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
- SND_PCI_QUIRK(0x103c, 0x227f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x2282, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x228b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x228e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x229e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x22b2, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x22b7, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x22bf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x22c4, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x22c5, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x22c7, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x22c8, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x22cf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x22db, "HP", ALC280_FIXUP_HP_9480M),
- SND_PCI_QUIRK(0x103c, 0x22dc, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
- SND_PCI_QUIRK(0x103c, 0x22fb, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
- SND_PCI_QUIRK(0x103c, 0x2334, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x2335, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x2336, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x2337, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
- SND_PCI_QUIRK(0x103c, 0x2b5e, "HP 288 Pro G2 MT", ALC221_FIXUP_HP_288PRO_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x103c, 0x802e, "HP Z240 SFF", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x103c, 0x802f, "HP Z240", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x103c, 0x8077, "HP", ALC256_FIXUP_HP_HEADSET_MIC),
- SND_PCI_QUIRK(0x103c, 0x8158, "HP", ALC256_FIXUP_HP_HEADSET_MIC),
- SND_PCI_QUIRK(0x103c, 0x820d, "HP Pavilion 15", ALC295_FIXUP_HP_X360),
- SND_PCI_QUIRK(0x103c, 0x8256, "HP", ALC221_FIXUP_HP_FRONT_MIC),
- SND_PCI_QUIRK(0x103c, 0x827e, "HP x360", ALC295_FIXUP_HP_X360),
- SND_PCI_QUIRK(0x103c, 0x827f, "HP x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
- SND_PCI_QUIRK(0x103c, 0x82bf, "HP G3 mini", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x103c, 0x82c0, "HP G3 mini premium", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x103c, 0x83b9, "HP Spectre x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
- SND_PCI_QUIRK(0x103c, 0x841c, "HP Pavilion 15-CK0xx", ALC269_FIXUP_HP_MUTE_LED_MIC3),
- SND_PCI_QUIRK(0x103c, 0x8497, "HP Envy x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
- SND_PCI_QUIRK(0x103c, 0x84a6, "HP 250 G7 Notebook PC", ALC269_FIXUP_HP_LINE1_MIC1_LED),
- SND_PCI_QUIRK(0x103c, 0x84ae, "HP 15-db0403ng", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
- SND_PCI_QUIRK(0x103c, 0x84da, "HP OMEN dc0019-ur", ALC295_FIXUP_HP_OMEN),
- SND_PCI_QUIRK(0x103c, 0x84e7, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3),
- SND_PCI_QUIRK(0x103c, 0x8519, "HP Spectre x360 15-df0xxx", ALC285_FIXUP_HP_SPECTRE_X360),
- SND_PCI_QUIRK(0x103c, 0x8537, "HP ProBook 440 G6", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
- SND_PCI_QUIRK(0x103c, 0x85c6, "HP Pavilion x360 Convertible 14-dy1xxx", ALC295_FIXUP_HP_MUTE_LED_COEFBIT11),
- SND_PCI_QUIRK(0x103c, 0x85de, "HP Envy x360 13-ar0xxx", ALC285_FIXUP_HP_ENVY_X360),
- SND_PCI_QUIRK(0x103c, 0x860f, "HP ZBook 15 G6", ALC285_FIXUP_HP_GPIO_AMP_INIT),
- SND_PCI_QUIRK(0x103c, 0x861f, "HP Elite Dragonfly G1", ALC285_FIXUP_HP_GPIO_AMP_INIT),
- SND_PCI_QUIRK(0x103c, 0x869d, "HP", ALC236_FIXUP_HP_MUTE_LED),
- SND_PCI_QUIRK(0x103c, 0x86c1, "HP Laptop 15-da3001TU", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
- SND_PCI_QUIRK(0x103c, 0x86c7, "HP Envy AiO 32", ALC274_FIXUP_HP_ENVY_GPIO),
- SND_PCI_QUIRK(0x103c, 0x86e7, "HP Spectre x360 15-eb0xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1),
- SND_PCI_QUIRK(0x103c, 0x863e, "HP Spectre x360 15-df1xxx", ALC285_FIXUP_HP_SPECTRE_X360_DF1),
- SND_PCI_QUIRK(0x103c, 0x86e8, "HP Spectre x360 15-eb0xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1),
- SND_PCI_QUIRK(0x103c, 0x86f9, "HP Spectre x360 13-aw0xxx", ALC285_FIXUP_HP_SPECTRE_X360_MUTE_LED),
- SND_PCI_QUIRK(0x103c, 0x8716, "HP Elite Dragonfly G2 Notebook PC", ALC285_FIXUP_HP_GPIO_AMP_INIT),
- SND_PCI_QUIRK(0x103c, 0x8720, "HP EliteBook x360 1040 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_AMP_INIT),
- SND_PCI_QUIRK(0x103c, 0x8724, "HP EliteBook 850 G7", ALC285_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8728, "HP EliteBook 840 G7", ALC285_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8729, "HP", ALC285_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8730, "HP ProBook 445 G7", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
- SND_PCI_QUIRK(0x103c, 0x8735, "HP ProBook 435 G7", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
- SND_PCI_QUIRK(0x103c, 0x8736, "HP", ALC285_FIXUP_HP_GPIO_AMP_INIT),
- SND_PCI_QUIRK(0x103c, 0x8760, "HP EliteBook 8{4,5}5 G7", ALC285_FIXUP_HP_BEEP_MICMUTE_LED),
- SND_PCI_QUIRK(0x103c, 0x876e, "HP ENVY x360 Convertible 13-ay0xxx", ALC245_FIXUP_HP_X360_MUTE_LEDS),
- SND_PCI_QUIRK(0x103c, 0x877a, "HP", ALC285_FIXUP_HP_MUTE_LED),
- SND_PCI_QUIRK(0x103c, 0x877d, "HP", ALC236_FIXUP_HP_MUTE_LED),
- SND_PCI_QUIRK(0x103c, 0x8780, "HP ZBook Fury 17 G7 Mobile Workstation",
- ALC285_FIXUP_HP_GPIO_AMP_INIT),
- SND_PCI_QUIRK(0x103c, 0x8783, "HP ZBook Fury 15 G7 Mobile Workstation",
- ALC285_FIXUP_HP_GPIO_AMP_INIT),
- SND_PCI_QUIRK(0x103c, 0x8786, "HP OMEN 15", ALC285_FIXUP_HP_MUTE_LED),
- SND_PCI_QUIRK(0x103c, 0x8787, "HP OMEN 15", ALC285_FIXUP_HP_MUTE_LED),
- SND_PCI_QUIRK(0x103c, 0x8788, "HP OMEN 15", ALC285_FIXUP_HP_MUTE_LED),
- SND_PCI_QUIRK(0x103c, 0x87b7, "HP Laptop 14-fq0xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
- SND_PCI_QUIRK(0x103c, 0x87c8, "HP", ALC287_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x87d3, "HP Laptop 15-gw0xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
- SND_PCI_QUIRK(0x103c, 0x87df, "HP ProBook 430 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x87e5, "HP ProBook 440 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x87e7, "HP ProBook 450 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x87f1, "HP ProBook 630 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x87f2, "HP ProBook 640 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x87f4, "HP", ALC287_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x87f5, "HP", ALC287_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x87f6, "HP Spectre x360 14", ALC245_FIXUP_HP_X360_AMP),
- SND_PCI_QUIRK(0x103c, 0x87f7, "HP Spectre x360 14", ALC245_FIXUP_HP_X360_AMP),
- SND_PCI_QUIRK(0x103c, 0x87fd, "HP Laptop 14-dq2xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
- SND_PCI_QUIRK(0x103c, 0x87fe, "HP Laptop 15s-fq2xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
- SND_PCI_QUIRK(0x103c, 0x8805, "HP ProBook 650 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x880d, "HP EliteBook 830 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8811, "HP Spectre x360 15-eb1xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1),
- SND_PCI_QUIRK(0x103c, 0x8812, "HP Spectre x360 15-eb1xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1),
- SND_PCI_QUIRK(0x103c, 0x881d, "HP 250 G8 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
- SND_PCI_QUIRK(0x103c, 0x881e, "HP Laptop 15s-du3xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
- SND_PCI_QUIRK(0x103c, 0x8846, "HP EliteBook 850 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8847, "HP EliteBook x360 830 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x884b, "HP EliteBook 840 Aero G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x884c, "HP EliteBook 840 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8862, "HP ProBook 445 G8 Notebook PC", ALC236_FIXUP_HP_LIMIT_INT_MIC_BOOST),
- SND_PCI_QUIRK(0x103c, 0x8863, "HP ProBook 445 G8 Notebook PC", ALC236_FIXUP_HP_LIMIT_INT_MIC_BOOST),
- SND_PCI_QUIRK(0x103c, 0x886d, "HP ZBook Fury 17.3 Inch G8 Mobile Workstation PC", ALC285_FIXUP_HP_GPIO_AMP_INIT),
- SND_PCI_QUIRK(0x103c, 0x8870, "HP ZBook Fury 15.6 Inch G8 Mobile Workstation PC", ALC285_FIXUP_HP_GPIO_AMP_INIT),
- SND_PCI_QUIRK(0x103c, 0x8873, "HP ZBook Studio 15.6 Inch G8 Mobile Workstation PC", ALC285_FIXUP_HP_GPIO_AMP_INIT),
- SND_PCI_QUIRK(0x103c, 0x887a, "HP Laptop 15s-eq2xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
- SND_PCI_QUIRK(0x103c, 0x887c, "HP Laptop 14s-fq1xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
- SND_PCI_QUIRK(0x103c, 0x888a, "HP ENVY x360 Convertible 15-eu0xxx", ALC245_FIXUP_HP_X360_MUTE_LEDS),
- SND_PCI_QUIRK(0x103c, 0x888d, "HP ZBook Power 15.6 inch G8 Mobile Workstation PC", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8895, "HP EliteBook 855 G8 Notebook PC", ALC285_FIXUP_HP_SPEAKERS_MICMUTE_LED),
- SND_PCI_QUIRK(0x103c, 0x8896, "HP EliteBook 855 G8 Notebook PC", ALC285_FIXUP_HP_MUTE_LED),
- SND_PCI_QUIRK(0x103c, 0x8898, "HP EliteBook 845 G8 Notebook PC", ALC285_FIXUP_HP_LIMIT_INT_MIC_BOOST),
- SND_PCI_QUIRK(0x103c, 0x88d0, "HP Pavilion 15-eh1xxx (mainboard 88D0)", ALC287_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x88dd, "HP Pavilion 15z-ec200", ALC285_FIXUP_HP_MUTE_LED),
- SND_PCI_QUIRK(0x103c, 0x8902, "HP OMEN 16", ALC285_FIXUP_HP_MUTE_LED),
- SND_PCI_QUIRK(0x103c, 0x890e, "HP 255 G8 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
- SND_PCI_QUIRK(0x103c, 0x8919, "HP Pavilion Aero Laptop 13-be0xxx", ALC287_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x896d, "HP ZBook Firefly 16 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x896e, "HP EliteBook x360 830 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8971, "HP EliteBook 830 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8972, "HP EliteBook 840 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8973, "HP EliteBook 860 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8974, "HP EliteBook 840 Aero G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8975, "HP EliteBook x360 840 Aero G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x897d, "HP mt440 Mobile Thin Client U74", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8981, "HP Elite Dragonfly G3", ALC245_FIXUP_CS35L41_SPI_4),
- SND_PCI_QUIRK(0x103c, 0x898e, "HP EliteBook 835 G9", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x898f, "HP EliteBook 835 G9", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8991, "HP EliteBook 845 G9", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8992, "HP EliteBook 845 G9", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8994, "HP EliteBook 855 G9", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8995, "HP EliteBook 855 G9", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x89a4, "HP ProBook 440 G9", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x89a6, "HP ProBook 450 G9", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x89aa, "HP EliteBook 630 G9", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x89ac, "HP EliteBook 640 G9", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x89ae, "HP EliteBook 650 G9", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x89c0, "HP ZBook Power 15.6 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x89c3, "Zbook Studio G9", ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x89c6, "Zbook Fury 17 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x89ca, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
- SND_PCI_QUIRK(0x103c, 0x89d3, "HP EliteBook 645 G9 (MB 89D2)", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
- SND_PCI_QUIRK(0x103c, 0x89e7, "HP Elite x2 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8a0f, "HP Pavilion 14-ec1xxx", ALC287_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8a20, "HP Laptop 15s-fq5xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
- SND_PCI_QUIRK(0x103c, 0x8a25, "HP Victus 16-d1xxx (MB 8A25)", ALC245_FIXUP_HP_MUTE_LED_COEFBIT),
- SND_PCI_QUIRK(0x103c, 0x8a28, "HP Envy 13", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8a29, "HP Envy 15", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8a2a, "HP Envy 15", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8a2b, "HP Envy 15", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8a2c, "HP Envy 16", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8a2d, "HP Envy 16", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8a2e, "HP Envy 16", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8a30, "HP Envy 17", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8a31, "HP Envy 15", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8a6e, "HP EDNA 360", ALC287_FIXUP_CS35L41_I2C_4),
- SND_PCI_QUIRK(0x103c, 0x8a74, "HP ProBook 440 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8a78, "HP Dev One", ALC285_FIXUP_HP_LIMIT_INT_MIC_BOOST),
- SND_PCI_QUIRK(0x103c, 0x8aa0, "HP ProBook 440 G9 (MB 8A9E)", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8aa3, "HP ProBook 450 G9 (MB 8AA1)", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8aa8, "HP EliteBook 640 G9 (MB 8AA6)", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8aab, "HP EliteBook 650 G9 (MB 8AA9)", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8ab9, "HP EliteBook 840 G8 (MB 8AB8)", ALC285_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8abb, "HP ZBook Firefly 14 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8ad1, "HP EliteBook 840 14 inch G9 Notebook PC", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8ad2, "HP EliteBook 860 16 inch G9 Notebook PC", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8ad8, "HP 800 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8b0f, "HP Elite mt645 G7 Mobile Thin Client U81", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
- SND_PCI_QUIRK(0x103c, 0x8b2f, "HP 255 15.6 inch G10 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
- SND_PCI_QUIRK(0x103c, 0x8b3a, "HP Envy 15", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8b3f, "HP mt440 Mobile Thin Client U91", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8b42, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8b43, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8b44, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8b45, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8b46, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8b47, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8b59, "HP Elite mt645 G7 Mobile Thin Client U89", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
- SND_PCI_QUIRK(0x103c, 0x8b5d, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
- SND_PCI_QUIRK(0x103c, 0x8b5e, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
- SND_PCI_QUIRK(0x103c, 0x8b5f, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
- SND_PCI_QUIRK(0x103c, 0x8b63, "HP Elite Dragonfly 13.5 inch G4", ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8b65, "HP ProBook 455 15.6 inch G10 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
- SND_PCI_QUIRK(0x103c, 0x8b66, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
- SND_PCI_QUIRK(0x103c, 0x8b70, "HP EliteBook 835 G10", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8b72, "HP EliteBook 845 G10", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8b74, "HP EliteBook 845W G10", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8b77, "HP ElieBook 865 G10", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8b7a, "HP", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8b7d, "HP", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8b87, "HP", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8b8a, "HP", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8b8b, "HP", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8b8d, "HP", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8b8f, "HP", ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8b92, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8b96, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
- SND_PCI_QUIRK(0x103c, 0x8b97, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
- SND_PCI_QUIRK(0x103c, 0x8bb3, "HP Slim OMEN", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8bb4, "HP Slim OMEN", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8bc8, "HP Victus 15-fa1xxx", ALC245_FIXUP_HP_MUTE_LED_COEFBIT),
- SND_PCI_QUIRK(0x103c, 0x8bcd, "HP Omen 16-xd0xxx", ALC245_FIXUP_HP_MUTE_LED_V1_COEFBIT),
- SND_PCI_QUIRK(0x103c, 0x8bdd, "HP Envy 17", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8bde, "HP Envy 17", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8bdf, "HP Envy 15", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8be0, "HP Envy 15", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8be1, "HP Envy 15", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8be2, "HP Envy 15", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8be3, "HP Envy 15", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8be5, "HP Envy 16", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8be6, "HP Envy 16", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8be7, "HP Envy 17", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8be8, "HP Envy 17", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8be9, "HP Envy 15", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8bf0, "HP", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8c15, "HP Spectre x360 2-in-1 Laptop 14-eu0xxx", ALC245_FIXUP_HP_SPECTRE_X360_EU0XXX),
- SND_PCI_QUIRK(0x103c, 0x8c16, "HP Spectre x360 2-in-1 Laptop 16-aa0xxx", ALC245_FIXUP_HP_SPECTRE_X360_16_AA0XXX),
- SND_PCI_QUIRK(0x103c, 0x8c17, "HP Spectre 16", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8c21, "HP Pavilion Plus Laptop 14-ey0XXX", ALC245_FIXUP_HP_X360_MUTE_LEDS),
- SND_PCI_QUIRK(0x103c, 0x8c30, "HP Victus 15-fb1xxx", ALC245_FIXUP_HP_MUTE_LED_COEFBIT),
- SND_PCI_QUIRK(0x103c, 0x8c46, "HP EliteBook 830 G11", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8c47, "HP EliteBook 840 G11", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8c48, "HP EliteBook 860 G11", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8c49, "HP Elite x360 830 2-in-1 G11", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8c4d, "HP Omen", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8c4e, "HP Omen", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8c4f, "HP Envy 15", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8c50, "HP Envy 17", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8c51, "HP Envy 17", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8c52, "HP EliteBook 1040 G11", ALC285_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8c53, "HP Elite x360 1040 2-in-1 G11", ALC285_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8c66, "HP Envy 16", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8c67, "HP Envy 17", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8c68, "HP Envy 17", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8c6a, "HP Envy 16", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8c70, "HP EliteBook 835 G11", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8c71, "HP EliteBook 845 G11", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8c72, "HP EliteBook 865 G11", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8c7b, "HP ProBook 445 G11", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
- SND_PCI_QUIRK(0x103c, 0x8c7c, "HP ProBook 445 G11", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
- SND_PCI_QUIRK(0x103c, 0x8c7d, "HP ProBook 465 G11", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
- SND_PCI_QUIRK(0x103c, 0x8c7e, "HP ProBook 465 G11", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
- SND_PCI_QUIRK(0x103c, 0x8c7f, "HP EliteBook 645 G11", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
- SND_PCI_QUIRK(0x103c, 0x8c80, "HP EliteBook 645 G11", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
- SND_PCI_QUIRK(0x103c, 0x8c81, "HP EliteBook 665 G11", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
- SND_PCI_QUIRK(0x103c, 0x8c89, "HP ProBook 460 G11", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8c8a, "HP EliteBook 630", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8c8c, "HP EliteBook 660", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8c8d, "HP ProBook 440 G11", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8c8e, "HP ProBook 460 G11", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8c90, "HP EliteBook 640", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8c91, "HP EliteBook 660", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8c96, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
- SND_PCI_QUIRK(0x103c, 0x8c97, "HP ZBook", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
- SND_PCI_QUIRK(0x103c, 0x8c9c, "HP Victus 16-s1xxx (MB 8C9C)", ALC245_FIXUP_HP_MUTE_LED_COEFBIT),
- SND_PCI_QUIRK(0x103c, 0x8ca1, "HP ZBook Power", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8ca2, "HP ZBook Power", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8ca4, "HP ZBook Fury", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8ca7, "HP ZBook Fury", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8caf, "HP Elite mt645 G8 Mobile Thin Client", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
- SND_PCI_QUIRK(0x103c, 0x8cbd, "HP Pavilion Aero Laptop 13-bg0xxx", ALC245_FIXUP_HP_X360_MUTE_LEDS),
- SND_PCI_QUIRK(0x103c, 0x8cdd, "HP Spectre", ALC245_FIXUP_HP_SPECTRE_X360_EU0XXX),
- SND_PCI_QUIRK(0x103c, 0x8cde, "HP OmniBook Ultra Flip Laptop 14t", ALC245_FIXUP_HP_SPECTRE_X360_EU0XXX),
- SND_PCI_QUIRK(0x103c, 0x8cdf, "HP SnowWhite", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8ce0, "HP SnowWhite", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8cf5, "HP ZBook Studio 16", ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8d01, "HP ZBook Power 14 G12", ALC285_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8d18, "HP EliteStudio 8 AIO", ALC274_FIXUP_HP_AIO_BIND_DACS),
- SND_PCI_QUIRK(0x103c, 0x8d84, "HP EliteBook X G1i", ALC285_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8d85, "HP EliteBook 14 G12", ALC285_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8d86, "HP Elite X360 14 G12", ALC285_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8d8c, "HP EliteBook 13 G12", ALC285_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8d8d, "HP Elite X360 13 G12", ALC285_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8d8e, "HP EliteBook 14 G12", ALC285_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8d8f, "HP EliteBook 14 G12", ALC285_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8d90, "HP EliteBook 16 G12", ALC285_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8d91, "HP ZBook Firefly 14 G12", ALC285_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8d92, "HP ZBook Firefly 16 G12", ALC285_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8d9b, "HP 17 Turbine OmniBook 7 UMA", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8d9c, "HP 17 Turbine OmniBook 7 DIS", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8d9d, "HP 17 Turbine OmniBook X UMA", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8d9e, "HP 17 Turbine OmniBook X DIS", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8d9f, "HP 14 Cadet (x360)", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8da0, "HP 16 Clipper OmniBook 7(X360)", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8da1, "HP 16 Clipper OmniBook X", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8da7, "HP 14 Enstrom OmniBook X", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8da8, "HP 16 Piston OmniBook X", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8dd4, "HP EliteStudio 8 AIO", ALC274_FIXUP_HP_AIO_BIND_DACS),
- SND_PCI_QUIRK(0x103c, 0x8de8, "HP Gemtree", ALC245_FIXUP_TAS2781_SPI_2),
- SND_PCI_QUIRK(0x103c, 0x8de9, "HP Gemtree", ALC245_FIXUP_TAS2781_SPI_2),
- SND_PCI_QUIRK(0x103c, 0x8dec, "HP EliteBook 640 G12", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8ded, "HP EliteBook 640 G12", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8dee, "HP EliteBook 660 G12", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8def, "HP EliteBook 660 G12", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8df0, "HP EliteBook 630 G12", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8df1, "HP EliteBook 630 G12", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8dfc, "HP EliteBook 645 G12", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8dfe, "HP EliteBook 665 G12", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8e11, "HP Trekker", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8e12, "HP Trekker", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8e13, "HP Trekker", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8e14, "HP ZBook Firefly 14 G12", ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A),
- SND_PCI_QUIRK(0x103c, 0x8e15, "HP ZBook Firefly 14 G12", ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A),
- SND_PCI_QUIRK(0x103c, 0x8e16, "HP ZBook Firefly 14 G12", ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A),
- SND_PCI_QUIRK(0x103c, 0x8e17, "HP ZBook Firefly 14 G12", ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A),
- SND_PCI_QUIRK(0x103c, 0x8e18, "HP ZBook Firefly 14 G12A", ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A),
- SND_PCI_QUIRK(0x103c, 0x8e19, "HP ZBook Firefly 14 G12A", ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A),
- SND_PCI_QUIRK(0x103c, 0x8e1a, "HP ZBook Firefly 14 G12A", ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A),
- SND_PCI_QUIRK(0x103c, 0x8e1b, "HP EliteBook G12", ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A),
- SND_PCI_QUIRK(0x103c, 0x8e1c, "HP EliteBook G12", ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A),
- SND_PCI_QUIRK(0x103c, 0x8e1d, "HP ZBook X Gli 16 G12", ALC236_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8e2c, "HP EliteBook 16 G12", ALC285_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8e36, "HP 14 Enstrom OmniBook X", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8e37, "HP 16 Piston OmniBook X", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8e3a, "HP Agusta", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8e3b, "HP Agusta", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8e60, "HP Trekker ", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8e61, "HP Trekker ", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8e62, "HP Trekker ", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x1043, 0x1032, "ASUS VivoBook X513EA", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1043, 0x1034, "ASUS GU605C", ALC285_FIXUP_ASUS_GU605_SPI_SPEAKER2_TO_DAC1),
- SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
- SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
- SND_PCI_QUIRK(0x1043, 0x1054, "ASUS G614FH/FM/FP", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
- SND_PCI_QUIRK(0x1043, 0x106f, "ASUS VivoBook X515UA", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1043, 0x1074, "ASUS G614PH/PM/PP", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x1043, 0x10a1, "ASUS UX391UA", ALC294_FIXUP_ASUS_SPK),
- SND_PCI_QUIRK(0x1043, 0x10a4, "ASUS TP3407SA", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x1043, 0x10c0, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
- SND_PCI_QUIRK(0x1043, 0x10d0, "ASUS X540LA/X540LJ", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1043, 0x10d3, "ASUS K6500ZC", ALC294_FIXUP_ASUS_SPK),
- SND_PCI_QUIRK(0x1043, 0x1154, "ASUS TP3607SH", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
- SND_PCI_QUIRK(0x1043, 0x1194, "ASUS UM3406KA", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x1043, 0x11c0, "ASUS X556UR", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1043, 0x1204, "ASUS Strix G615JHR_JMR_JPR", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x1043, 0x1214, "ASUS Strix G615LH_LM_LP", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x1043, 0x125e, "ASUS Q524UQK", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1043, 0x1271, "ASUS X430UN", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1043, 0x1290, "ASUS X441SA", ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1043, 0x1294, "ASUS B3405CVA", ALC245_FIXUP_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1043, 0x12a0, "ASUS X441UV", ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1043, 0x12a3, "Asus N7691ZM", ALC269_FIXUP_ASUS_N7601ZM),
- SND_PCI_QUIRK(0x1043, 0x12af, "ASUS UX582ZS", ALC245_FIXUP_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1043, 0x12b4, "ASUS B3405CCA / P3405CCA", ALC294_FIXUP_ASUS_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1043, 0x12e0, "ASUS X541SA", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1043, 0x12f0, "ASUS X541UV", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1043, 0x1313, "Asus K42JZ", ALC269VB_FIXUP_ASUS_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1043, 0x1314, "ASUS GA605K", ALC285_FIXUP_ASUS_GA605K_HEADSET_MIC),
- SND_PCI_QUIRK(0x1043, 0x13b0, "ASUS Z550SA", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_ASUS_ZENBOOK),
- SND_PCI_QUIRK(0x1043, 0x1433, "ASUS GX650PY/PZ/PV/PU/PYV/PZV/PIV/PVV", ALC285_FIXUP_ASUS_I2C_HEADSET_MIC),
- SND_PCI_QUIRK(0x1043, 0x1460, "Asus VivoBook 15", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1043, 0x1463, "Asus GA402X/GA402N", ALC285_FIXUP_ASUS_I2C_HEADSET_MIC),
- SND_PCI_QUIRK(0x1043, 0x1473, "ASUS GU604VI/VC/VE/VG/VJ/VQ/VU/VV/VY/VZ", ALC285_FIXUP_ASUS_HEADSET_MIC),
- SND_PCI_QUIRK(0x1043, 0x1483, "ASUS GU603VQ/VU/VV/VJ/VI", ALC285_FIXUP_ASUS_HEADSET_MIC),
- SND_PCI_QUIRK(0x1043, 0x1493, "ASUS GV601VV/VU/VJ/VQ/VI", ALC285_FIXUP_ASUS_HEADSET_MIC),
- SND_PCI_QUIRK(0x1043, 0x14d3, "ASUS G614JY/JZ/JG", ALC245_FIXUP_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1043, 0x14e3, "ASUS G513PI/PU/PV", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x1043, 0x14f2, "ASUS VivoBook X515JA", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1043, 0x1503, "ASUS G733PY/PZ/PZV/PYV", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A),
- SND_PCI_QUIRK(0x1043, 0x1533, "ASUS GV302XA/XJ/XQ/XU/XV/XI", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x1043, 0x1573, "ASUS GZ301VV/VQ/VU/VJ/VA/VC/VE/VVC/VQC/VUC/VJC/VEC/VCC", ALC285_FIXUP_ASUS_HEADSET_MIC),
- SND_PCI_QUIRK(0x1043, 0x1662, "ASUS GV301QH", ALC294_FIXUP_ASUS_DUAL_SPK),
- SND_PCI_QUIRK(0x1043, 0x1663, "ASUS GU603ZI/ZJ/ZQ/ZU/ZV", ALC285_FIXUP_ASUS_HEADSET_MIC),
- SND_PCI_QUIRK(0x1043, 0x1683, "ASUS UM3402YAR", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS UX3402VA", ALC245_FIXUP_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1043, 0x16b2, "ASUS GU603", ALC289_FIXUP_ASUS_GA401),
- SND_PCI_QUIRK(0x1043, 0x16d3, "ASUS UX5304VA", ALC245_FIXUP_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
- SND_PCI_QUIRK(0x1043, 0x16f3, "ASUS UX7602VI/BZ", ALC245_FIXUP_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1043, 0x1740, "ASUS UX430UA", ALC295_FIXUP_ASUS_DACS),
- SND_PCI_QUIRK(0x1043, 0x17d1, "ASUS UX431FL", ALC294_FIXUP_ASUS_DUAL_SPK),
- SND_PCI_QUIRK(0x1043, 0x17f3, "ROG Ally NR2301L/X", ALC294_FIXUP_ASUS_ALLY),
- SND_PCI_QUIRK(0x1043, 0x1863, "ASUS UX6404VI/VV", ALC245_FIXUP_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1043, 0x1881, "ASUS Zephyrus S/M", ALC294_FIXUP_ASUS_GX502_PINS),
- SND_PCI_QUIRK(0x1043, 0x18b1, "Asus MJ401TA", ALC256_FIXUP_ASUS_HEADSET_MIC),
- SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS UM3504DA", ALC294_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x1043, 0x18f1, "Asus FX505DT", ALC256_FIXUP_ASUS_HEADSET_MIC),
- SND_PCI_QUIRK(0x1043, 0x194e, "ASUS UX563FD", ALC294_FIXUP_ASUS_HPE),
- SND_PCI_QUIRK(0x1043, 0x1970, "ASUS UX550VE", ALC289_FIXUP_ASUS_GA401),
- SND_PCI_QUIRK(0x1043, 0x1982, "ASUS B1400CEPE", ALC256_FIXUP_ASUS_HPE),
- SND_PCI_QUIRK(0x1043, 0x19ce, "ASUS B9450FA", ALC294_FIXUP_ASUS_HPE),
- SND_PCI_QUIRK(0x1043, 0x19e1, "ASUS UX581LV", ALC295_FIXUP_ASUS_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
- SND_PCI_QUIRK(0x1043, 0x1a63, "ASUS UX3405MA", ALC245_FIXUP_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1043, 0x1a83, "ASUS UM5302LA", ALC294_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x1043, 0x1a8f, "ASUS UX582ZS", ALC245_FIXUP_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1043, 0x1b11, "ASUS UX431DA", ALC294_FIXUP_ASUS_COEF_1B),
- SND_PCI_QUIRK(0x1043, 0x1b13, "ASUS U41SV/GA403U", ALC285_FIXUP_ASUS_GA403U_HEADSET_MIC),
- SND_PCI_QUIRK(0x1043, 0x1b93, "ASUS G614JVR/JIR", ALC245_FIXUP_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1043, 0x1bbd, "ASUS Z550MA", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1043, 0x1c03, "ASUS UM3406HA", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x1043, 0x1c23, "Asus X55U", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
- SND_PCI_QUIRK(0x1043, 0x1c33, "ASUS UX5304MA", ALC245_FIXUP_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1043, 0x1c43, "ASUS UX8406MA", ALC245_FIXUP_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1043, 0x1c62, "ASUS GU603", ALC289_FIXUP_ASUS_GA401),
- SND_PCI_QUIRK(0x1043, 0x1c63, "ASUS GU605M", ALC285_FIXUP_ASUS_GU605_SPI_SPEAKER2_TO_DAC1),
- SND_PCI_QUIRK(0x1043, 0x1c80, "ASUS VivoBook TP401", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1043, 0x1c92, "ASUS ROG Strix G15", ALC285_FIXUP_ASUS_G533Z_PINS),
- SND_PCI_QUIRK(0x1043, 0x1c9f, "ASUS G614JU/JV/JI", ALC285_FIXUP_ASUS_HEADSET_MIC),
- SND_PCI_QUIRK(0x1043, 0x1caf, "ASUS G634JY/JZ/JI/JG", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS),
- SND_PCI_QUIRK(0x1043, 0x1ccd, "ASUS X555UB", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1043, 0x1ccf, "ASUS G814JU/JV/JI", ALC245_FIXUP_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1043, 0x1cdf, "ASUS G814JY/JZ/JG", ALC245_FIXUP_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1043, 0x1cef, "ASUS G834JY/JZ/JI/JG", ALC285_FIXUP_ASUS_HEADSET_MIC),
- SND_PCI_QUIRK(0x1043, 0x1d1f, "ASUS G713PI/PU/PV/PVN", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x1043, 0x1d42, "ASUS Zephyrus G14 2022", ALC289_FIXUP_ASUS_GA401),
- SND_PCI_QUIRK(0x1043, 0x1d4e, "ASUS TM420", ALC256_FIXUP_ASUS_HPE),
- SND_PCI_QUIRK(0x1043, 0x1da2, "ASUS UP6502ZA/ZD", ALC245_FIXUP_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1043, 0x1df3, "ASUS UM5606WA", ALC294_FIXUP_BASS_SPEAKER_15),
- SND_PCI_QUIRK(0x1043, 0x1264, "ASUS UM5606KA", ALC294_FIXUP_BASS_SPEAKER_15),
- SND_PCI_QUIRK(0x1043, 0x1e02, "ASUS UX3402ZA", ALC245_FIXUP_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1043, 0x1e11, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA502),
- SND_PCI_QUIRK(0x1043, 0x1e12, "ASUS UM3402", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x1043, 0x1e1f, "ASUS Vivobook 15 X1504VAP", ALC2XX_FIXUP_HEADSET_MIC),
- SND_PCI_QUIRK(0x1043, 0x1e51, "ASUS Zephyrus M15", ALC294_FIXUP_ASUS_GU502_PINS),
- SND_PCI_QUIRK(0x1043, 0x1e5e, "ASUS ROG Strix G513", ALC294_FIXUP_ASUS_G513_PINS),
- SND_PCI_QUIRK(0x1043, 0x1e63, "ASUS H7606W", ALC285_FIXUP_ASUS_GU605_SPI_SPEAKER2_TO_DAC1),
- SND_PCI_QUIRK(0x1043, 0x1e83, "ASUS GA605W", ALC285_FIXUP_ASUS_GU605_SPI_SPEAKER2_TO_DAC1),
- SND_PCI_QUIRK(0x1043, 0x1e8e, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA401),
- SND_PCI_QUIRK(0x1043, 0x1eb3, "ASUS Ally RCLA72", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x1043, 0x1ed3, "ASUS HN7306W", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x1043, 0x1ee2, "ASUS UM6702RA/RC", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x1043, 0x1c52, "ASUS Zephyrus G15 2022", ALC289_FIXUP_ASUS_GA401),
- SND_PCI_QUIRK(0x1043, 0x1f11, "ASUS Zephyrus G14", ALC289_FIXUP_ASUS_GA401),
- SND_PCI_QUIRK(0x1043, 0x1f12, "ASUS UM5302", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x1043, 0x1f1f, "ASUS H7604JI/JV/J3D", ALC245_FIXUP_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1043, 0x1f62, "ASUS UX7602ZM", ALC245_FIXUP_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1043, 0x1f63, "ASUS P5405CSA", ALC245_FIXUP_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1043, 0x1f92, "ASUS ROG Flow X16", ALC289_FIXUP_ASUS_GA401),
- SND_PCI_QUIRK(0x1043, 0x1fb3, "ASUS ROG Flow Z13 GZ302EA", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x1043, 0x3011, "ASUS B5605CVA", ALC245_FIXUP_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1043, 0x3030, "ASUS ZN270IE", ALC256_FIXUP_ASUS_AIO_GPIO2),
- SND_PCI_QUIRK(0x1043, 0x3061, "ASUS B3405CCA", ALC294_FIXUP_ASUS_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1043, 0x3071, "ASUS B5405CCA", ALC294_FIXUP_ASUS_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1043, 0x30c1, "ASUS B3605CCA / P3605CCA", ALC294_FIXUP_ASUS_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1043, 0x30d1, "ASUS B5405CCA", ALC294_FIXUP_ASUS_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1043, 0x30e1, "ASUS B5605CCA", ALC294_FIXUP_ASUS_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1043, 0x31d0, "ASUS Zen AIO 27 Z272SD_A272SD", ALC274_FIXUP_ASUS_ZEN_AIO_27),
- SND_PCI_QUIRK(0x1043, 0x31e1, "ASUS B5605CCA", ALC294_FIXUP_ASUS_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1043, 0x31f1, "ASUS B3605CCA", ALC294_FIXUP_ASUS_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1043, 0x3a20, "ASUS G614JZR", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS),
- SND_PCI_QUIRK(0x1043, 0x3a30, "ASUS G814JVR/JIR", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS),
- SND_PCI_QUIRK(0x1043, 0x3a40, "ASUS G814JZR", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS),
- SND_PCI_QUIRK(0x1043, 0x3a50, "ASUS G834JYR/JZR", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS),
- SND_PCI_QUIRK(0x1043, 0x3a60, "ASUS G634JYR/JZR", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS),
- SND_PCI_QUIRK(0x1043, 0x3d78, "ASUS GA603KH", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x1043, 0x3d88, "ASUS GA603KM", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x1043, 0x3e00, "ASUS G814FH/FM/FP", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x1043, 0x3e20, "ASUS G814PH/PM/PP", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x1043, 0x3e30, "ASUS TP3607SA", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x1043, 0x3ee0, "ASUS Strix G815_JHR_JMR_JPR", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x1043, 0x3ef0, "ASUS Strix G635LR_LW_LX", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x1043, 0x3f00, "ASUS Strix G815LH_LM_LP", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x1043, 0x3f10, "ASUS Strix G835LR_LW_LX", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x1043, 0x3f20, "ASUS Strix G615LR_LW", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x1043, 0x3f30, "ASUS Strix G815LR_LW", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x1043, 0x3fd0, "ASUS B3605CVA", ALC245_FIXUP_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1043, 0x3ff0, "ASUS B5405CVA", ALC245_FIXUP_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
- SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC),
- SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
- SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
- SND_PCI_QUIRK(0x1043, 0x8516, "ASUS X101CH", ALC269_FIXUP_ASUS_X101),
- SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2),
- SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
- SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
- SND_PCI_QUIRK(0x104d, 0x9099, "Sony VAIO S13", ALC275_FIXUP_SONY_DISABLE_AAMIX),
- SND_PCI_QUIRK(0x104d, 0x90b5, "Sony VAIO Pro 11", ALC286_FIXUP_SONY_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x104d, 0x90b6, "Sony VAIO Pro 13", ALC286_FIXUP_SONY_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK),
- SND_PCI_QUIRK(0x10cf, 0x159f, "Lifebook E780", ALC269_FIXUP_LIFEBOOK_NO_HP_TO_LINEOUT),
- SND_PCI_QUIRK(0x10cf, 0x15dc, "Lifebook T731", ALC269_FIXUP_LIFEBOOK_HP_PIN),
- SND_PCI_QUIRK(0x10cf, 0x1629, "Lifebook U7x7", ALC255_FIXUP_LIFEBOOK_U7x7_HEADSET_MIC),
- SND_PCI_QUIRK(0x10cf, 0x1757, "Lifebook E752", ALC269_FIXUP_LIFEBOOK_HP_PIN),
- SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC),
- SND_PCI_QUIRK(0x10ec, 0x10f2, "Intel Reference board", ALC700_FIXUP_INTEL_REFERENCE),
- SND_PCI_QUIRK(0x10ec, 0x118c, "Medion EE4254 MD62100", ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE),
- SND_PCI_QUIRK(0x10ec, 0x119e, "Positivo SU C1400", ALC269_FIXUP_ASPIRE_HEADSET_MIC),
- SND_PCI_QUIRK(0x10ec, 0x11bc, "VAIO VJFE-IL", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
- SND_PCI_QUIRK(0x10ec, 0x1230, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
- SND_PCI_QUIRK(0x10ec, 0x124c, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
- SND_PCI_QUIRK(0x10ec, 0x1252, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
- SND_PCI_QUIRK(0x10ec, 0x1254, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
- SND_PCI_QUIRK(0x10ec, 0x12cc, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
- SND_PCI_QUIRK(0x10ec, 0x12f6, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
- SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-SZ6", ALC269_FIXUP_ASPIRE_HEADSET_MIC),
- SND_PCI_QUIRK(0x144d, 0xc109, "Samsung Ativ book 9 (NP900X3G)", ALC269_FIXUP_INV_DMIC),
- SND_PCI_QUIRK(0x144d, 0xc169, "Samsung Notebook 9 Pen (NP930SBE-K01US)", ALC298_FIXUP_SAMSUNG_AMP),
- SND_PCI_QUIRK(0x144d, 0xc176, "Samsung Notebook 9 Pro (NP930MBE-K04US)", ALC298_FIXUP_SAMSUNG_AMP),
- SND_PCI_QUIRK(0x144d, 0xc189, "Samsung Galaxy Flex Book (NT950QCG-X716)", ALC298_FIXUP_SAMSUNG_AMP),
- SND_PCI_QUIRK(0x144d, 0xc18a, "Samsung Galaxy Book Ion (NP930XCJ-K01US)", ALC298_FIXUP_SAMSUNG_AMP),
- SND_PCI_QUIRK(0x144d, 0xc1a3, "Samsung Galaxy Book Pro (NP935XDB-KC1SE)", ALC298_FIXUP_SAMSUNG_AMP),
- SND_PCI_QUIRK(0x144d, 0xc1a4, "Samsung Galaxy Book Pro 360 (NT935QBD)", ALC298_FIXUP_SAMSUNG_AMP),
- SND_PCI_QUIRK(0x144d, 0xc1a6, "Samsung Galaxy Book Pro 360 (NP930QBD)", ALC298_FIXUP_SAMSUNG_AMP),
- SND_PCI_QUIRK(0x144d, 0xc740, "Samsung Ativ book 8 (NP870Z5G)", ALC269_FIXUP_ATIV_BOOK_8),
- SND_PCI_QUIRK(0x144d, 0xc812, "Samsung Notebook Pen S (NT950SBE-X58)", ALC298_FIXUP_SAMSUNG_AMP),
- SND_PCI_QUIRK(0x144d, 0xc830, "Samsung Galaxy Book Ion (NT950XCJ-X716A)", ALC298_FIXUP_SAMSUNG_AMP),
- SND_PCI_QUIRK(0x144d, 0xc832, "Samsung Galaxy Book Flex Alpha (NP730QCJ)", ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
- SND_PCI_QUIRK(0x144d, 0xca03, "Samsung Galaxy Book2 Pro 360 (NP930QED)", ALC298_FIXUP_SAMSUNG_AMP),
- SND_PCI_QUIRK(0x144d, 0xca06, "Samsung Galaxy Book3 360 (NP730QFG)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
- SND_PCI_QUIRK(0x144d, 0xc868, "Samsung Galaxy Book2 Pro (NP930XED)", ALC298_FIXUP_SAMSUNG_AMP),
- SND_PCI_QUIRK(0x144d, 0xc870, "Samsung Galaxy Book2 Pro (NP950XED)", ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS),
- SND_PCI_QUIRK(0x144d, 0xc872, "Samsung Galaxy Book2 Pro (NP950XEE)", ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS),
- SND_PCI_QUIRK(0x144d, 0xc886, "Samsung Galaxy Book3 Pro (NP964XFG)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
- SND_PCI_QUIRK(0x144d, 0xc1ca, "Samsung Galaxy Book3 Pro 360 (NP960QFG)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
- SND_PCI_QUIRK(0x144d, 0xc1cc, "Samsung Galaxy Book3 Ultra (NT960XFH)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
- SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_HEADSET_MIC),
- SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC),
- SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC),
- SND_PCI_QUIRK(0x152d, 0x1082, "Quanta NL3", ALC269_FIXUP_LIFEBOOK),
- SND_PCI_QUIRK(0x152d, 0x1262, "Huawei NBLB-WAX9N", ALC2XX_FIXUP_HEADSET_MIC),
- SND_PCI_QUIRK(0x1558, 0x0353, "Clevo V35[05]SN[CDE]Q", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x1323, "Clevo N130ZU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x1325, "Clevo N15[01][CW]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x1401, "Clevo L140[CZ]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x1403, "Clevo N140CU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x1404, "Clevo N150CU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x14a1, "Clevo L141MU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x2624, "Clevo L240TU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x28c1, "Clevo V370VND", ALC2XX_FIXUP_HEADSET_MIC),
- SND_PCI_QUIRK(0x1558, 0x4018, "Clevo NV40M[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x4019, "Clevo NV40MZ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x4020, "Clevo NV40MB", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x4041, "Clevo NV4[15]PZ", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x40a1, "Clevo NL40GU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x40c1, "Clevo NL40[CZ]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x40d1, "Clevo NL41DU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x5015, "Clevo NH5[58]H[HJK]Q", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x5017, "Clevo NH7[79]H[HJK]Q", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x50a3, "Clevo NJ51GU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x50b3, "Clevo NK50S[BEZ]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x50b6, "Clevo NK50S5", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x50b8, "Clevo NK50SZ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x50d5, "Clevo NP50D5", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x50e1, "Clevo NH5[58]HPQ", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x50e2, "Clevo NH7[79]HPQ", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x50f0, "Clevo NH50A[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x50f2, "Clevo NH50E[PR]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x50f3, "Clevo NH58DPQ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x50f5, "Clevo NH55EPY", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x50f6, "Clevo NH55DPQ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x5101, "Clevo S510WU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x5157, "Clevo W517GU1", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x51a1, "Clevo NS50MU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x51b1, "Clevo NS50AU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x51b3, "Clevo NS70AU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x5630, "Clevo NP50RNJS", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x70a1, "Clevo NB70T[HJK]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x70b3, "Clevo NK70SB", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x70f2, "Clevo NH79EPY", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x70f3, "Clevo NH77DPQ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x70f4, "Clevo NH77EPY", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x70f6, "Clevo NH77DPQ-Y", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x7716, "Clevo NS50PU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x7717, "Clevo NS70PU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x7718, "Clevo L140PU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x7724, "Clevo L140AU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x8228, "Clevo NR40BU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x8520, "Clevo NH50D[CD]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x8521, "Clevo NH77D[CD]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x8535, "Clevo NH50D[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x8536, "Clevo NH79D[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x8550, "Clevo NH[57][0-9][ER][ACDH]Q", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x8551, "Clevo NH[57][0-9][ER][ACDH]Q", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x8560, "Clevo NH[57][0-9][ER][ACDH]Q", ALC269_FIXUP_HEADSET_MIC),
- SND_PCI_QUIRK(0x1558, 0x8561, "Clevo NH[57][0-9][ER][ACDH]Q", ALC269_FIXUP_HEADSET_MIC),
- SND_PCI_QUIRK(0x1558, 0x8562, "Clevo NH[57][0-9]RZ[Q]", ALC269_FIXUP_DMIC),
- SND_PCI_QUIRK(0x1558, 0x8668, "Clevo NP50B[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x866d, "Clevo NP5[05]PN[HJK]", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x867c, "Clevo NP7[01]PNP", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x867d, "Clevo NP7[01]PN[HJK]", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x8680, "Clevo NJ50LU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x8686, "Clevo NH50[CZ]U", ALC256_FIXUP_MIC_NO_PRESENCE_AND_RESUME),
- SND_PCI_QUIRK(0x1558, 0x8a20, "Clevo NH55DCQ-Y", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x8a51, "Clevo NH70RCQ-Y", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x8d50, "Clevo NH55RCQ-M", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x951d, "Clevo N950T[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x9600, "Clevo N960K[PR]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x961d, "Clevo N960S[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0x971d, "Clevo N970T[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0xa500, "Clevo NL5[03]RU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0xa554, "VAIO VJFH52", ALC269_FIXUP_VAIO_VJFH52_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0xa600, "Clevo NL50NU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0xa650, "Clevo NP[567]0SN[CD]", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0xa671, "Clevo NP70SN[CDE]", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0xa741, "Clevo V54x_6x_TNE", ALC245_FIXUP_CLEVO_NOISY_MIC),
- SND_PCI_QUIRK(0x1558, 0xa763, "Clevo V54x_6x_TU", ALC245_FIXUP_CLEVO_NOISY_MIC),
- SND_PCI_QUIRK(0x1558, 0xb018, "Clevo NP50D[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0xb019, "Clevo NH77D[BE]Q", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0xb022, "Clevo NH77D[DC][QW]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0xc018, "Clevo NP50D[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0xc019, "Clevo NH77D[BE]Q", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1558, 0xc022, "Clevo NH77[DC][QW]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC233_FIXUP_LENOVO_MULTI_CODECS),
- SND_PCI_QUIRK(0x17aa, 0x1048, "ThinkCentre Station", ALC623_FIXUP_LENOVO_THINKSTATION_P340),
- SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
- SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
- SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
- SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE),
- SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE),
- SND_PCI_QUIRK(0x17aa, 0x21f3, "Thinkpad T430", ALC269_FIXUP_LENOVO_DOCK),
- SND_PCI_QUIRK(0x17aa, 0x21f6, "Thinkpad T530", ALC269_FIXUP_LENOVO_DOCK_LIMIT_BOOST),
- SND_PCI_QUIRK(0x17aa, 0x21fa, "Thinkpad X230", ALC269_FIXUP_LENOVO_DOCK),
- SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK),
- SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK),
- SND_PCI_QUIRK(0x17aa, 0x2208, "Thinkpad T431s", ALC269_FIXUP_LENOVO_DOCK),
- SND_PCI_QUIRK(0x17aa, 0x220c, "Thinkpad T440s", ALC292_FIXUP_TPT440),
- SND_PCI_QUIRK(0x17aa, 0x220e, "Thinkpad T440p", ALC292_FIXUP_TPT440_DOCK),
- SND_PCI_QUIRK(0x17aa, 0x2210, "Thinkpad T540p", ALC292_FIXUP_TPT440_DOCK),
- SND_PCI_QUIRK(0x17aa, 0x2211, "Thinkpad W541", ALC292_FIXUP_TPT440_DOCK),
- SND_PCI_QUIRK(0x17aa, 0x2212, "Thinkpad T440", ALC292_FIXUP_TPT440_DOCK),
- SND_PCI_QUIRK(0x17aa, 0x2214, "Thinkpad X240", ALC292_FIXUP_TPT440_DOCK),
- SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
- SND_PCI_QUIRK(0x17aa, 0x2218, "Thinkpad X1 Carbon 2nd", ALC292_FIXUP_TPT440_DOCK),
- SND_PCI_QUIRK(0x17aa, 0x2223, "ThinkPad T550", ALC292_FIXUP_TPT440_DOCK),
- SND_PCI_QUIRK(0x17aa, 0x2226, "ThinkPad X250", ALC292_FIXUP_TPT440_DOCK),
- SND_PCI_QUIRK(0x17aa, 0x222d, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
- SND_PCI_QUIRK(0x17aa, 0x222e, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
- SND_PCI_QUIRK(0x17aa, 0x2231, "Thinkpad T560", ALC292_FIXUP_TPT460),
- SND_PCI_QUIRK(0x17aa, 0x2233, "Thinkpad", ALC292_FIXUP_TPT460),
- SND_PCI_QUIRK(0x17aa, 0x2234, "Thinkpad ICE-1", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x17aa, 0x2245, "Thinkpad T470", ALC298_FIXUP_TPT470_DOCK),
- SND_PCI_QUIRK(0x17aa, 0x2246, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
- SND_PCI_QUIRK(0x17aa, 0x2247, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
- SND_PCI_QUIRK(0x17aa, 0x2249, "Thinkpad", ALC292_FIXUP_TPT460),
- SND_PCI_QUIRK(0x17aa, 0x224b, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
- SND_PCI_QUIRK(0x17aa, 0x224c, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
- SND_PCI_QUIRK(0x17aa, 0x224d, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
- SND_PCI_QUIRK(0x17aa, 0x225d, "Thinkpad T480", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
- SND_PCI_QUIRK(0x17aa, 0x2292, "Thinkpad X1 Carbon 7th", ALC285_FIXUP_THINKPAD_HEADSET_JACK),
- SND_PCI_QUIRK(0x17aa, 0x22be, "Thinkpad X1 Carbon 8th", ALC285_FIXUP_THINKPAD_HEADSET_JACK),
- SND_PCI_QUIRK(0x17aa, 0x22c1, "Thinkpad P1 Gen 3", ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK),
- SND_PCI_QUIRK(0x17aa, 0x22c2, "Thinkpad X1 Extreme Gen 3", ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK),
- SND_PCI_QUIRK(0x17aa, 0x22f1, "Thinkpad", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
- SND_PCI_QUIRK(0x17aa, 0x22f2, "Thinkpad", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
- SND_PCI_QUIRK(0x17aa, 0x22f3, "Thinkpad", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
- SND_PCI_QUIRK(0x17aa, 0x2316, "Thinkpad P1 Gen 6", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
- SND_PCI_QUIRK(0x17aa, 0x2317, "Thinkpad P1 Gen 6", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
- SND_PCI_QUIRK(0x17aa, 0x2318, "Thinkpad Z13 Gen2", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
- SND_PCI_QUIRK(0x17aa, 0x2319, "Thinkpad Z16 Gen2", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
- SND_PCI_QUIRK(0x17aa, 0x231a, "Thinkpad Z16 Gen2", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
- SND_PCI_QUIRK(0x17aa, 0x231e, "Thinkpad", ALC287_FIXUP_LENOVO_THKPAD_WH_ALC1318),
- SND_PCI_QUIRK(0x17aa, 0x231f, "Thinkpad", ALC287_FIXUP_LENOVO_THKPAD_WH_ALC1318),
- SND_PCI_QUIRK(0x17aa, 0x2326, "Hera2", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
- SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
- SND_PCI_QUIRK(0x17aa, 0x310c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
- SND_PCI_QUIRK(0x17aa, 0x3111, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
- SND_PCI_QUIRK(0x17aa, 0x312a, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
- SND_PCI_QUIRK(0x17aa, 0x312f, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
- SND_PCI_QUIRK(0x17aa, 0x313c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
- SND_PCI_QUIRK(0x17aa, 0x3151, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC),
- SND_PCI_QUIRK(0x17aa, 0x3176, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC),
- SND_PCI_QUIRK(0x17aa, 0x3178, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC),
- SND_PCI_QUIRK(0x17aa, 0x31af, "ThinkCentre Station", ALC623_FIXUP_LENOVO_THINKSTATION_P340),
- SND_PCI_QUIRK(0x17aa, 0x334b, "Lenovo ThinkCentre M70 Gen5", ALC283_FIXUP_HEADSET_MIC),
- SND_PCI_QUIRK(0x17aa, 0x3384, "ThinkCentre M90a PRO", ALC233_FIXUP_LENOVO_L2MH_LOW_ENLED),
- SND_PCI_QUIRK(0x17aa, 0x3386, "ThinkCentre M90a Gen6", ALC233_FIXUP_LENOVO_L2MH_LOW_ENLED),
- SND_PCI_QUIRK(0x17aa, 0x3387, "ThinkCentre M70a Gen6", ALC233_FIXUP_LENOVO_L2MH_LOW_ENLED),
- SND_PCI_QUIRK(0x17aa, 0x3801, "Lenovo Yoga9 14IAP7", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
- HDA_CODEC_QUIRK(0x17aa, 0x3802, "DuetITL 2021", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
- SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo Yoga Pro 9 14IRP8", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x17aa, 0x3813, "Legion 7i 15IMHG05", ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS),
- SND_PCI_QUIRK(0x17aa, 0x3818, "Lenovo C940 / Yoga Duet 7", ALC298_FIXUP_LENOVO_C940_DUET7),
- SND_PCI_QUIRK(0x17aa, 0x3819, "Lenovo 13s Gen2 ITL", ALC287_FIXUP_13S_GEN2_SPEAKERS),
- HDA_CODEC_QUIRK(0x17aa, 0x3820, "IdeaPad 330-17IKB 81DM", ALC269_FIXUP_ASPIRE_HEADSET_MIC),
- SND_PCI_QUIRK(0x17aa, 0x3820, "Yoga Duet 7 13ITL6", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
- SND_PCI_QUIRK(0x17aa, 0x3824, "Legion Y9000X 2020", ALC285_FIXUP_LEGION_Y9000X_SPEAKERS),
- SND_PCI_QUIRK(0x17aa, 0x3827, "Ideapad S740", ALC285_FIXUP_IDEAPAD_S740_COEF),
- SND_PCI_QUIRK(0x17aa, 0x3834, "Lenovo IdeaPad Slim 9i 14ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
- SND_PCI_QUIRK(0x17aa, 0x383d, "Legion Y9000X 2019", ALC285_FIXUP_LEGION_Y9000X_SPEAKERS),
- SND_PCI_QUIRK(0x17aa, 0x3843, "Yoga 9i", ALC287_FIXUP_IDEAPAD_BASS_SPK_AMP),
- SND_PCI_QUIRK(0x17aa, 0x3847, "Legion 7 16ACHG6", ALC287_FIXUP_LEGION_16ACHG6),
- SND_PCI_QUIRK(0x17aa, 0x384a, "Lenovo Yoga 7 15ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
- SND_PCI_QUIRK(0x17aa, 0x3852, "Lenovo Yoga 7 14ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
- SND_PCI_QUIRK(0x17aa, 0x3853, "Lenovo Yoga 7 15ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
- SND_PCI_QUIRK(0x17aa, 0x3855, "Legion 7 16ITHG6", ALC287_FIXUP_LEGION_16ITHG6),
- SND_PCI_QUIRK(0x17aa, 0x3865, "Lenovo 13X", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x17aa, 0x3866, "Lenovo 13X", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x17aa, 0x3869, "Lenovo Yoga7 14IAL7", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
- HDA_CODEC_QUIRK(0x17aa, 0x386e, "Legion Y9000X 2022 IAH7", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x17aa, 0x386e, "Yoga Pro 7 14ARP8", ALC285_FIXUP_SPEAKER2_TO_DAC1),
- HDA_CODEC_QUIRK(0x17aa, 0x38a8, "Legion Pro 7 16ARX8H", ALC287_FIXUP_TAS2781_I2C), /* this must match before PCI SSID 17aa:386f below */
- SND_PCI_QUIRK(0x17aa, 0x386f, "Legion Pro 7i 16IAX7", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x17aa, 0x3870, "Lenovo Yoga 7 14ARB7", ALC287_FIXUP_YOGA7_14ARB7_I2C),
- SND_PCI_QUIRK(0x17aa, 0x3877, "Lenovo Legion 7 Slim 16ARHA7", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x17aa, 0x3878, "Lenovo Legion 7 Slim 16ARHA7", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x17aa, 0x387d, "Yoga S780-16 pro Quad AAC", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x17aa, 0x387e, "Yoga S780-16 pro Quad YC", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x17aa, 0x387f, "Yoga S780-16 pro dual LX", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x17aa, 0x3880, "Yoga S780-16 pro dual YC", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x17aa, 0x3881, "YB9 dual power mode2 YC", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x17aa, 0x3882, "Lenovo Yoga Pro 7 14APH8", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
- SND_PCI_QUIRK(0x17aa, 0x3884, "Y780 YG DUAL", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x17aa, 0x3886, "Y780 VECO DUAL", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x17aa, 0x3891, "Lenovo Yoga Pro 7 14AHP9", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
- SND_PCI_QUIRK(0x17aa, 0x38a5, "Y580P AMD dual", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x17aa, 0x38a7, "Y780P AMD YG dual", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x17aa, 0x38a8, "Y780P AMD VECO dual", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x17aa, 0x38a9, "Thinkbook 16P", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
- SND_PCI_QUIRK(0x17aa, 0x38ab, "Thinkbook 16P", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
- SND_PCI_QUIRK(0x17aa, 0x38b4, "Legion Slim 7 16IRH8", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x17aa, 0x38b5, "Legion Slim 7 16IRH8", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x17aa, 0x38b6, "Legion Slim 7 16APH8", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x17aa, 0x38b7, "Legion Slim 7 16APH8", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x17aa, 0x38b8, "Yoga S780-14.5 proX AMD YC Dual", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x17aa, 0x38b9, "Yoga S780-14.5 proX AMD LX Dual", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x17aa, 0x38ba, "Yoga S780-14.5 Air AMD quad YC", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x17aa, 0x38bb, "Yoga S780-14.5 Air AMD quad AAC", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x17aa, 0x38be, "Yoga S980-14.5 proX YC Dual", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x17aa, 0x38bf, "Yoga S980-14.5 proX LX Dual", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x17aa, 0x38c3, "Y980 DUAL", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x17aa, 0x38c7, "Thinkbook 13x Gen 4", ALC287_FIXUP_CS35L41_I2C_4),
- SND_PCI_QUIRK(0x17aa, 0x38c8, "Thinkbook 13x Gen 4", ALC287_FIXUP_CS35L41_I2C_4),
- SND_PCI_QUIRK(0x17aa, 0x38cb, "Y790 YG DUAL", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x17aa, 0x38cd, "Y790 VECO DUAL", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x17aa, 0x38d2, "Lenovo Yoga 9 14IMH9", ALC287_FIXUP_YOGA9_14IMH9_BASS_SPK_PIN),
- SND_PCI_QUIRK(0x17aa, 0x38d3, "Yoga S990-16 Pro IMH YC Dual", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x17aa, 0x38d4, "Yoga S990-16 Pro IMH VECO Dual", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x17aa, 0x38d5, "Yoga S990-16 Pro IMH YC Quad", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x17aa, 0x38d6, "Yoga S990-16 Pro IMH VECO Quad", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x17aa, 0x38d7, "Lenovo Yoga 9 14IMH9", ALC287_FIXUP_YOGA9_14IMH9_BASS_SPK_PIN),
- SND_PCI_QUIRK(0x17aa, 0x38df, "Yoga Y990 Intel YC Dual", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x17aa, 0x38e0, "Yoga Y990 Intel VECO Dual", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x17aa, 0x38f8, "Yoga Book 9i", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x17aa, 0x38df, "Y990 YG DUAL", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x17aa, 0x38f9, "Thinkbook 16P Gen5", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
- SND_PCI_QUIRK(0x17aa, 0x38fa, "Thinkbook 16P Gen5", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
- SND_PCI_QUIRK(0x17aa, 0x38fd, "ThinkBook plus Gen5 Hybrid", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
- SND_PCI_QUIRK(0x17aa, 0x390d, "Lenovo Yoga Pro 7 14ASP10", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
- SND_PCI_QUIRK(0x17aa, 0x3913, "Lenovo 145", ALC236_FIXUP_LENOVO_INV_DMIC),
- SND_PCI_QUIRK(0x17aa, 0x391f, "Yoga S990-16 pro Quad YC Quad", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x17aa, 0x3920, "Yoga S990-16 pro Quad VECO Quad", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC),
- SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo B50-70", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
- SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
- SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
- SND_PCI_QUIRK(0x17aa, 0x501a, "Thinkpad", ALC283_FIXUP_INT_MIC),
- SND_PCI_QUIRK(0x17aa, 0x501e, "Thinkpad L440", ALC292_FIXUP_TPT440_DOCK),
- SND_PCI_QUIRK(0x17aa, 0x5026, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
- SND_PCI_QUIRK(0x17aa, 0x5034, "Thinkpad T450", ALC292_FIXUP_TPT440_DOCK),
- SND_PCI_QUIRK(0x17aa, 0x5036, "Thinkpad T450s", ALC292_FIXUP_TPT440_DOCK),
- SND_PCI_QUIRK(0x17aa, 0x503c, "Thinkpad L450", ALC292_FIXUP_TPT440_DOCK),
- SND_PCI_QUIRK(0x17aa, 0x504a, "ThinkPad X260", ALC292_FIXUP_TPT440_DOCK),
- SND_PCI_QUIRK(0x17aa, 0x504b, "Thinkpad", ALC293_FIXUP_LENOVO_SPK_NOISE),
- SND_PCI_QUIRK(0x17aa, 0x5050, "Thinkpad T560p", ALC292_FIXUP_TPT460),
- SND_PCI_QUIRK(0x17aa, 0x5051, "Thinkpad L460", ALC292_FIXUP_TPT460),
- SND_PCI_QUIRK(0x17aa, 0x5053, "Thinkpad T460", ALC292_FIXUP_TPT460),
- SND_PCI_QUIRK(0x17aa, 0x505d, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
- SND_PCI_QUIRK(0x17aa, 0x505f, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
- SND_PCI_QUIRK(0x17aa, 0x5062, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
- SND_PCI_QUIRK(0x17aa, 0x508b, "Thinkpad X12 Gen 1", ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS),
- SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
- SND_PCI_QUIRK(0x17aa, 0x511e, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
- SND_PCI_QUIRK(0x17aa, 0x511f, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
- SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
- SND_PCI_QUIRK(0x17aa, 0x9e56, "Lenovo ZhaoYang CF4620Z", ALC286_FIXUP_SONY_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1849, 0x0269, "Positivo Master C6400", ALC269VB_FIXUP_ASUS_ZENBOOK),
- SND_PCI_QUIRK(0x1849, 0x1233, "ASRock NUC Box 1100", ALC233_FIXUP_NO_AUDIO_JACK),
- SND_PCI_QUIRK(0x1849, 0xa233, "Positivo Master C6300", ALC269_FIXUP_HEADSET_MIC),
- SND_PCI_QUIRK(0x1854, 0x0440, "LG CQ6", ALC256_FIXUP_HEADPHONE_AMP_VOL),
- SND_PCI_QUIRK(0x1854, 0x0441, "LG CQ6 AIO", ALC256_FIXUP_HEADPHONE_AMP_VOL),
- SND_PCI_QUIRK(0x1854, 0x0488, "LG gram 16 (16Z90R)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
- SND_PCI_QUIRK(0x1854, 0x048a, "LG gram 17 (17ZD90R)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
- SND_PCI_QUIRK(0x19e5, 0x3204, "Huawei MACH-WX9", ALC256_FIXUP_HUAWEI_MACH_WX9_PINS),
- SND_PCI_QUIRK(0x19e5, 0x320f, "Huawei WRT-WX9 ", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x19e5, 0x3212, "Huawei KLV-WX9 ", ALC256_FIXUP_ACER_HEADSET_MIC),
- SND_PCI_QUIRK(0x1b35, 0x1235, "CZC B20", ALC269_FIXUP_CZC_B20),
- SND_PCI_QUIRK(0x1b35, 0x1236, "CZC TMI", ALC269_FIXUP_CZC_TMI),
- SND_PCI_QUIRK(0x1b35, 0x1237, "CZC L101", ALC269_FIXUP_CZC_L101),
- SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */
- SND_PCI_QUIRK(0x1c06, 0x2013, "Lemote A1802", ALC269_FIXUP_LEMOTE_A1802),
- SND_PCI_QUIRK(0x1c06, 0x2015, "Lemote A190X", ALC269_FIXUP_LEMOTE_A190X),
- SND_PCI_QUIRK(0x1c6c, 0x122a, "Positivo N14AP7", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
- SND_PCI_QUIRK(0x1c6c, 0x1251, "Positivo N14KP6-TG", ALC288_FIXUP_DELL1_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1d05, 0x1132, "TongFang PHxTxX1", ALC256_FIXUP_SET_COEF_DEFAULTS),
- SND_PCI_QUIRK(0x1d05, 0x1096, "TongFang GMxMRxx", ALC269_FIXUP_NO_SHUTUP),
- SND_PCI_QUIRK(0x1d05, 0x1100, "TongFang GKxNRxx", ALC269_FIXUP_NO_SHUTUP),
- SND_PCI_QUIRK(0x1d05, 0x1111, "TongFang GMxZGxx", ALC269_FIXUP_NO_SHUTUP),
- SND_PCI_QUIRK(0x1d05, 0x1119, "TongFang GMxZGxx", ALC269_FIXUP_NO_SHUTUP),
- SND_PCI_QUIRK(0x1d05, 0x1129, "TongFang GMxZGxx", ALC269_FIXUP_NO_SHUTUP),
- SND_PCI_QUIRK(0x1d05, 0x1147, "TongFang GMxTGxx", ALC269_FIXUP_NO_SHUTUP),
- SND_PCI_QUIRK(0x1d05, 0x115c, "TongFang GMxTGxx", ALC269_FIXUP_NO_SHUTUP),
- SND_PCI_QUIRK(0x1d05, 0x121b, "TongFang GMxAGxx", ALC269_FIXUP_NO_SHUTUP),
- SND_PCI_QUIRK(0x1d05, 0x1387, "TongFang GMxIXxx", ALC2XX_FIXUP_HEADSET_MIC),
- SND_PCI_QUIRK(0x1d05, 0x1409, "TongFang GMxIXxx", ALC2XX_FIXUP_HEADSET_MIC),
- SND_PCI_QUIRK(0x1d17, 0x3288, "Haier Boyue G42", ALC269VC_FIXUP_ACER_VCOPPERBOX_PINS),
- SND_PCI_QUIRK(0x1d72, 0x1602, "RedmiBook", ALC255_FIXUP_XIAOMI_HEADSET_MIC),
- SND_PCI_QUIRK(0x1d72, 0x1701, "XiaomiNotebook Pro", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1d72, 0x1901, "RedmiBook 14", ALC256_FIXUP_ASUS_HEADSET_MIC),
- SND_PCI_QUIRK(0x1d72, 0x1945, "Redmi G", ALC256_FIXUP_ASUS_HEADSET_MIC),
- SND_PCI_QUIRK(0x1d72, 0x1947, "RedmiBook Air", ALC255_FIXUP_XIAOMI_HEADSET_MIC),
- SND_PCI_QUIRK(0x1f66, 0x0105, "Ayaneo Portable Game Player", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x2014, 0x800a, "Positivo ARN50", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
- SND_PCI_QUIRK(0x2782, 0x0214, "VAIO VJFE-CL", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
- SND_PCI_QUIRK(0x2782, 0x0228, "Infinix ZERO BOOK 13", ALC269VB_FIXUP_INFINIX_ZERO_BOOK_13),
- SND_PCI_QUIRK(0x2782, 0x0232, "CHUWI CoreBook XPro", ALC269VB_FIXUP_CHUWI_COREBOOK_XPRO),
- SND_PCI_QUIRK(0x2782, 0x1407, "Positivo P15X", ALC269_FIXUP_POSITIVO_P15X_HEADSET_MIC),
- SND_PCI_QUIRK(0x2782, 0x1701, "Infinix Y4 Max", ALC269VC_FIXUP_INFINIX_Y4_MAX),
- SND_PCI_QUIRK(0x2782, 0x1705, "MEDION E15433", ALC269VC_FIXUP_INFINIX_Y4_MAX),
- SND_PCI_QUIRK(0x2782, 0x1707, "Vaio VJFE-ADL", ALC298_FIXUP_SPK_VOLUME),
- SND_PCI_QUIRK(0x2782, 0x4900, "MEDION E15443", ALC233_FIXUP_MEDION_MTL_SPK),
- SND_PCI_QUIRK(0x8086, 0x2074, "Intel NUC 8", ALC233_FIXUP_INTEL_NUC8_DMIC),
- SND_PCI_QUIRK(0x8086, 0x2080, "Intel NUC 8 Rugged", ALC256_FIXUP_INTEL_NUC8_RUGGED),
- SND_PCI_QUIRK(0x8086, 0x2081, "Intel NUC 10", ALC256_FIXUP_INTEL_NUC10),
- SND_PCI_QUIRK(0x8086, 0x3038, "Intel NUC 13", ALC295_FIXUP_CHROME_BOOK),
- SND_PCI_QUIRK(0xf111, 0x0001, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0xf111, 0x0006, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0xf111, 0x0009, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0xf111, 0x000c, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE),
-
-#if 0
- /* Below is a quirk table taken from the old code.
- * Basically the device should work as is without the fixup table.
- * If BIOS doesn't give a proper info, enable the corresponding
- * fixup entry.
- */
- SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A",
- ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1143, "ASUS B53f", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1183, "ASUS K72DR", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x11b3, "ASUS K52DR", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x11e3, "ASUS U33Jc", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1273, "ASUS UL80Jt", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1283, "ASUS U53Jc", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS N82JV", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x12d3, "ASUS N61Jv", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x13a3, "ASUS UL30Vt", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1373, "ASUS G73JX", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1383, "ASUS UJ30Jc", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x13d3, "ASUS N61JA", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1413, "ASUS UL50", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1443, "ASUS UL30", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1453, "ASUS M60Jv", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1483, "ASUS UL80", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x14f3, "ASUS F83Vf", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x14e3, "ASUS UL20", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1513, "ASUS UX30", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1593, "ASUS N51Vn", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x15a3, "ASUS N60Jv", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x15b3, "ASUS N60Dp", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x15c3, "ASUS N70De", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x15e3, "ASUS F83T", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1643, "ASUS M60J", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1693, "ASUS F50N", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x152d, 0x1778, "Quanta ON1", ALC269_FIXUP_DMIC),
- SND_PCI_QUIRK(0x17aa, 0x3be9, "Quanta Wistron", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x17ff, 0x059a, "Quanta EL3", ALC269_FIXUP_DMIC),
- SND_PCI_QUIRK(0x17ff, 0x059b, "Quanta JR1", ALC269_FIXUP_DMIC),
-#endif
- {}
-};
-
-static const struct hda_quirk alc269_fixup_vendor_tbl[] = {
- SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
- SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED),
- SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
- SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo XPAD", ALC269_FIXUP_LENOVO_XPAD_ACPI),
- SND_PCI_QUIRK_VENDOR(0x19e5, "Huawei Matebook", ALC255_FIXUP_MIC_MUTE_LED),
- {}
-};
-
-static const struct hda_model_fixup alc269_fixup_models[] = {
- {.id = ALC269_FIXUP_AMIC, .name = "laptop-amic"},
- {.id = ALC269_FIXUP_DMIC, .name = "laptop-dmic"},
- {.id = ALC269_FIXUP_STEREO_DMIC, .name = "alc269-dmic"},
- {.id = ALC271_FIXUP_DMIC, .name = "alc271-dmic"},
- {.id = ALC269_FIXUP_INV_DMIC, .name = "inv-dmic"},
- {.id = ALC269_FIXUP_HEADSET_MIC, .name = "headset-mic"},
- {.id = ALC269_FIXUP_HEADSET_MODE, .name = "headset-mode"},
- {.id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC, .name = "headset-mode-no-hp-mic"},
- {.id = ALC269_FIXUP_LENOVO_DOCK, .name = "lenovo-dock"},
- {.id = ALC269_FIXUP_LENOVO_DOCK_LIMIT_BOOST, .name = "lenovo-dock-limit-boost"},
- {.id = ALC269_FIXUP_HP_GPIO_LED, .name = "hp-gpio-led"},
- {.id = ALC269_FIXUP_HP_DOCK_GPIO_MIC1_LED, .name = "hp-dock-gpio-mic1-led"},
- {.id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "dell-headset-multi"},
- {.id = ALC269_FIXUP_DELL2_MIC_NO_PRESENCE, .name = "dell-headset-dock"},
- {.id = ALC269_FIXUP_DELL3_MIC_NO_PRESENCE, .name = "dell-headset3"},
- {.id = ALC269_FIXUP_DELL4_MIC_NO_PRESENCE, .name = "dell-headset4"},
- {.id = ALC269_FIXUP_DELL4_MIC_NO_PRESENCE_QUIET, .name = "dell-headset4-quiet"},
- {.id = ALC283_FIXUP_CHROME_BOOK, .name = "alc283-dac-wcaps"},
- {.id = ALC283_FIXUP_SENSE_COMBO_JACK, .name = "alc283-sense-combo"},
- {.id = ALC292_FIXUP_TPT440_DOCK, .name = "tpt440-dock"},
- {.id = ALC292_FIXUP_TPT440, .name = "tpt440"},
- {.id = ALC292_FIXUP_TPT460, .name = "tpt460"},
- {.id = ALC298_FIXUP_TPT470_DOCK_FIX, .name = "tpt470-dock-fix"},
- {.id = ALC298_FIXUP_TPT470_DOCK, .name = "tpt470-dock"},
- {.id = ALC233_FIXUP_LENOVO_MULTI_CODECS, .name = "dual-codecs"},
- {.id = ALC700_FIXUP_INTEL_REFERENCE, .name = "alc700-ref"},
- {.id = ALC269_FIXUP_SONY_VAIO, .name = "vaio"},
- {.id = ALC269_FIXUP_DELL_M101Z, .name = "dell-m101z"},
- {.id = ALC269_FIXUP_ASUS_G73JW, .name = "asus-g73jw"},
- {.id = ALC269_FIXUP_LENOVO_EAPD, .name = "lenovo-eapd"},
- {.id = ALC275_FIXUP_SONY_HWEQ, .name = "sony-hweq"},
- {.id = ALC269_FIXUP_PCM_44K, .name = "pcm44k"},
- {.id = ALC269_FIXUP_LIFEBOOK, .name = "lifebook"},
- {.id = ALC269_FIXUP_LIFEBOOK_EXTMIC, .name = "lifebook-extmic"},
- {.id = ALC269_FIXUP_LIFEBOOK_HP_PIN, .name = "lifebook-hp-pin"},
- {.id = ALC255_FIXUP_LIFEBOOK_U7x7_HEADSET_MIC, .name = "lifebook-u7x7"},
- {.id = ALC269VB_FIXUP_AMIC, .name = "alc269vb-amic"},
- {.id = ALC269VB_FIXUP_DMIC, .name = "alc269vb-dmic"},
- {.id = ALC269_FIXUP_HP_MUTE_LED_MIC1, .name = "hp-mute-led-mic1"},
- {.id = ALC269_FIXUP_HP_MUTE_LED_MIC2, .name = "hp-mute-led-mic2"},
- {.id = ALC269_FIXUP_HP_MUTE_LED_MIC3, .name = "hp-mute-led-mic3"},
- {.id = ALC269_FIXUP_HP_GPIO_MIC1_LED, .name = "hp-gpio-mic1"},
- {.id = ALC269_FIXUP_HP_LINE1_MIC1_LED, .name = "hp-line1-mic1"},
- {.id = ALC269_FIXUP_NO_SHUTUP, .name = "noshutup"},
- {.id = ALC286_FIXUP_SONY_MIC_NO_PRESENCE, .name = "sony-nomic"},
- {.id = ALC269_FIXUP_ASPIRE_HEADSET_MIC, .name = "aspire-headset-mic"},
- {.id = ALC269_FIXUP_ASUS_X101, .name = "asus-x101"},
- {.id = ALC271_FIXUP_HP_GATE_MIC_JACK, .name = "acer-ao7xx"},
- {.id = ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572, .name = "acer-aspire-e1"},
- {.id = ALC269_FIXUP_ACER_AC700, .name = "acer-ac700"},
- {.id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST, .name = "limit-mic-boost"},
- {.id = ALC269VB_FIXUP_ASUS_ZENBOOK, .name = "asus-zenbook"},
- {.id = ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A, .name = "asus-zenbook-ux31a"},
- {.id = ALC269VB_FIXUP_ORDISSIMO_EVE2, .name = "ordissimo"},
- {.id = ALC282_FIXUP_ASUS_TX300, .name = "asus-tx300"},
- {.id = ALC283_FIXUP_INT_MIC, .name = "alc283-int-mic"},
- {.id = ALC290_FIXUP_MONO_SPEAKERS_HSJACK, .name = "mono-speakers"},
- {.id = ALC290_FIXUP_SUBWOOFER_HSJACK, .name = "alc290-subwoofer"},
- {.id = ALC269_FIXUP_THINKPAD_ACPI, .name = "thinkpad"},
- {.id = ALC269_FIXUP_LENOVO_XPAD_ACPI, .name = "lenovo-xpad-led"},
- {.id = ALC269_FIXUP_DMIC_THINKPAD_ACPI, .name = "dmic-thinkpad"},
- {.id = ALC255_FIXUP_ACER_MIC_NO_PRESENCE, .name = "alc255-acer"},
- {.id = ALC255_FIXUP_ASUS_MIC_NO_PRESENCE, .name = "alc255-asus"},
- {.id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "alc255-dell1"},
- {.id = ALC255_FIXUP_DELL2_MIC_NO_PRESENCE, .name = "alc255-dell2"},
- {.id = ALC293_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "alc293-dell1"},
- {.id = ALC283_FIXUP_HEADSET_MIC, .name = "alc283-headset"},
- {.id = ALC255_FIXUP_MIC_MUTE_LED, .name = "alc255-dell-mute"},
- {.id = ALC282_FIXUP_ASPIRE_V5_PINS, .name = "aspire-v5"},
- {.id = ALC269VB_FIXUP_ASPIRE_E1_COEF, .name = "aspire-e1-coef"},
- {.id = ALC280_FIXUP_HP_GPIO4, .name = "hp-gpio4"},
- {.id = ALC286_FIXUP_HP_GPIO_LED, .name = "hp-gpio-led"},
- {.id = ALC280_FIXUP_HP_GPIO2_MIC_HOTKEY, .name = "hp-gpio2-hotkey"},
- {.id = ALC280_FIXUP_HP_DOCK_PINS, .name = "hp-dock-pins"},
- {.id = ALC269_FIXUP_HP_DOCK_GPIO_MIC1_LED, .name = "hp-dock-gpio-mic"},
- {.id = ALC280_FIXUP_HP_9480M, .name = "hp-9480m"},
- {.id = ALC288_FIXUP_DELL_HEADSET_MODE, .name = "alc288-dell-headset"},
- {.id = ALC288_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "alc288-dell1"},
- {.id = ALC288_FIXUP_DELL_XPS_13, .name = "alc288-dell-xps13"},
- {.id = ALC292_FIXUP_DELL_E7X, .name = "dell-e7x"},
- {.id = ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK, .name = "alc293-dell"},
- {.id = ALC298_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "alc298-dell1"},
- {.id = ALC298_FIXUP_DELL_AIO_MIC_NO_PRESENCE, .name = "alc298-dell-aio"},
- {.id = ALC275_FIXUP_DELL_XPS, .name = "alc275-dell-xps"},
- {.id = ALC293_FIXUP_LENOVO_SPK_NOISE, .name = "lenovo-spk-noise"},
- {.id = ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY, .name = "lenovo-hotkey"},
- {.id = ALC255_FIXUP_DELL_SPK_NOISE, .name = "dell-spk-noise"},
- {.id = ALC225_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "alc225-dell1"},
- {.id = ALC295_FIXUP_DISABLE_DAC3, .name = "alc295-disable-dac3"},
- {.id = ALC285_FIXUP_SPEAKER2_TO_DAC1, .name = "alc285-speaker2-to-dac1"},
- {.id = ALC280_FIXUP_HP_HEADSET_MIC, .name = "alc280-hp-headset"},
- {.id = ALC221_FIXUP_HP_FRONT_MIC, .name = "alc221-hp-mic"},
- {.id = ALC298_FIXUP_SPK_VOLUME, .name = "alc298-spk-volume"},
- {.id = ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER, .name = "dell-inspiron-7559"},
- {.id = ALC269_FIXUP_ATIV_BOOK_8, .name = "ativ-book"},
- {.id = ALC221_FIXUP_HP_MIC_NO_PRESENCE, .name = "alc221-hp-mic"},
- {.id = ALC256_FIXUP_ASUS_HEADSET_MODE, .name = "alc256-asus-headset"},
- {.id = ALC256_FIXUP_ASUS_MIC, .name = "alc256-asus-mic"},
- {.id = ALC256_FIXUP_ASUS_AIO_GPIO2, .name = "alc256-asus-aio"},
- {.id = ALC233_FIXUP_ASUS_MIC_NO_PRESENCE, .name = "alc233-asus"},
- {.id = ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE, .name = "alc233-eapd"},
- {.id = ALC294_FIXUP_LENOVO_MIC_LOCATION, .name = "alc294-lenovo-mic"},
- {.id = ALC225_FIXUP_DELL_WYSE_MIC_NO_PRESENCE, .name = "alc225-wyse"},
- {.id = ALC274_FIXUP_DELL_AIO_LINEOUT_VERB, .name = "alc274-dell-aio"},
- {.id = ALC255_FIXUP_DUMMY_LINEOUT_VERB, .name = "alc255-dummy-lineout"},
- {.id = ALC255_FIXUP_DELL_HEADSET_MIC, .name = "alc255-dell-headset"},
- {.id = ALC295_FIXUP_HP_X360, .name = "alc295-hp-x360"},
- {.id = ALC225_FIXUP_HEADSET_JACK, .name = "alc-headset-jack"},
- {.id = ALC295_FIXUP_CHROME_BOOK, .name = "alc-chrome-book"},
- {.id = ALC256_FIXUP_CHROME_BOOK, .name = "alc-2024y-chromebook"},
- {.id = ALC299_FIXUP_PREDATOR_SPK, .name = "predator-spk"},
- {.id = ALC298_FIXUP_HUAWEI_MBX_STEREO, .name = "huawei-mbx-stereo"},
- {.id = ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE, .name = "alc256-medion-headset"},
- {.id = ALC298_FIXUP_SAMSUNG_AMP, .name = "alc298-samsung-amp"},
- {.id = ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS, .name = "alc298-samsung-amp-v2-2-amps"},
- {.id = ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS, .name = "alc298-samsung-amp-v2-4-amps"},
- {.id = ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET, .name = "alc256-samsung-headphone"},
- {.id = ALC255_FIXUP_XIAOMI_HEADSET_MIC, .name = "alc255-xiaomi-headset"},
- {.id = ALC274_FIXUP_HP_MIC, .name = "alc274-hp-mic-detect"},
- {.id = ALC245_FIXUP_HP_X360_AMP, .name = "alc245-hp-x360-amp"},
- {.id = ALC295_FIXUP_HP_OMEN, .name = "alc295-hp-omen"},
- {.id = ALC285_FIXUP_HP_SPECTRE_X360, .name = "alc285-hp-spectre-x360"},
- {.id = ALC285_FIXUP_HP_SPECTRE_X360_EB1, .name = "alc285-hp-spectre-x360-eb1"},
- {.id = ALC285_FIXUP_HP_SPECTRE_X360_DF1, .name = "alc285-hp-spectre-x360-df1"},
- {.id = ALC285_FIXUP_HP_ENVY_X360, .name = "alc285-hp-envy-x360"},
- {.id = ALC287_FIXUP_IDEAPAD_BASS_SPK_AMP, .name = "alc287-ideapad-bass-spk-amp"},
- {.id = ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN, .name = "alc287-yoga9-bass-spk-pin"},
- {.id = ALC623_FIXUP_LENOVO_THINKSTATION_P340, .name = "alc623-lenovo-thinkstation-p340"},
- {.id = ALC255_FIXUP_ACER_HEADPHONE_AND_MIC, .name = "alc255-acer-headphone-and-mic"},
- {.id = ALC285_FIXUP_HP_GPIO_AMP_INIT, .name = "alc285-hp-amp-init"},
- {.id = ALC236_FIXUP_LENOVO_INV_DMIC, .name = "alc236-fixup-lenovo-inv-mic"},
- {.id = ALC2XX_FIXUP_HEADSET_MIC, .name = "alc2xx-fixup-headset-mic"},
- {}
-};
-#define ALC225_STANDARD_PINS \
- {0x21, 0x04211020}
-
-#define ALC256_STANDARD_PINS \
- {0x12, 0x90a60140}, \
- {0x14, 0x90170110}, \
- {0x21, 0x02211020}
-
-#define ALC282_STANDARD_PINS \
- {0x14, 0x90170110}
-
-#define ALC290_STANDARD_PINS \
- {0x12, 0x99a30130}
-
-#define ALC292_STANDARD_PINS \
- {0x14, 0x90170110}, \
- {0x15, 0x0221401f}
-
-#define ALC295_STANDARD_PINS \
- {0x12, 0xb7a60130}, \
- {0x14, 0x90170110}, \
- {0x21, 0x04211020}
-
-#define ALC298_STANDARD_PINS \
- {0x12, 0x90a60130}, \
- {0x21, 0x03211020}
-
-static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
- SND_HDA_PIN_QUIRK(0x10ec0221, 0x103c, "HP Workstation", ALC221_FIXUP_HP_HEADSET_MIC,
- {0x14, 0x01014020},
- {0x17, 0x90170110},
- {0x18, 0x02a11030},
- {0x19, 0x0181303F},
- {0x21, 0x0221102f}),
- SND_HDA_PIN_QUIRK(0x10ec0255, 0x1025, "Acer", ALC255_FIXUP_ACER_MIC_NO_PRESENCE,
- {0x12, 0x90a601c0},
- {0x14, 0x90171120},
- {0x21, 0x02211030}),
- SND_HDA_PIN_QUIRK(0x10ec0255, 0x1043, "ASUS", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE,
- {0x14, 0x90170110},
- {0x1b, 0x90a70130},
- {0x21, 0x03211020}),
- SND_HDA_PIN_QUIRK(0x10ec0255, 0x1043, "ASUS", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE,
- {0x1a, 0x90a70130},
- {0x1b, 0x90170110},
- {0x21, 0x03211020}),
- SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC225_FIXUP_DELL1_MIC_NO_PRESENCE,
- ALC225_STANDARD_PINS,
- {0x12, 0xb7a60130},
- {0x14, 0x901701a0}),
- SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC225_FIXUP_DELL1_MIC_NO_PRESENCE,
- ALC225_STANDARD_PINS,
- {0x12, 0xb7a60130},
- {0x14, 0x901701b0}),
- SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC225_FIXUP_DELL1_MIC_NO_PRESENCE,
- ALC225_STANDARD_PINS,
- {0x12, 0xb7a60150},
- {0x14, 0x901701a0}),
- SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC225_FIXUP_DELL1_MIC_NO_PRESENCE,
- ALC225_STANDARD_PINS,
- {0x12, 0xb7a60150},
- {0x14, 0x901701b0}),
- SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC225_FIXUP_DELL1_MIC_NO_PRESENCE,
- ALC225_STANDARD_PINS,
- {0x12, 0xb7a60130},
- {0x1b, 0x90170110}),
- SND_HDA_PIN_QUIRK(0x10ec0233, 0x8086, "Intel NUC Skull Canyon", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
- {0x1b, 0x01111010},
- {0x1e, 0x01451130},
- {0x21, 0x02211020}),
- SND_HDA_PIN_QUIRK(0x10ec0235, 0x17aa, "Lenovo", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY,
- {0x12, 0x90a60140},
- {0x14, 0x90170110},
- {0x19, 0x02a11030},
- {0x21, 0x02211020}),
- SND_HDA_PIN_QUIRK(0x10ec0235, 0x17aa, "Lenovo", ALC294_FIXUP_LENOVO_MIC_LOCATION,
- {0x14, 0x90170110},
- {0x19, 0x02a11030},
- {0x1a, 0x02a11040},
- {0x1b, 0x01014020},
- {0x21, 0x0221101f}),
- SND_HDA_PIN_QUIRK(0x10ec0235, 0x17aa, "Lenovo", ALC294_FIXUP_LENOVO_MIC_LOCATION,
- {0x14, 0x90170110},
- {0x19, 0x02a11030},
- {0x1a, 0x02a11040},
- {0x1b, 0x01011020},
- {0x21, 0x0221101f}),
- SND_HDA_PIN_QUIRK(0x10ec0235, 0x17aa, "Lenovo", ALC294_FIXUP_LENOVO_MIC_LOCATION,
- {0x14, 0x90170110},
- {0x19, 0x02a11020},
- {0x1a, 0x02a11030},
- {0x21, 0x0221101f}),
- SND_HDA_PIN_QUIRK(0x10ec0236, 0x1028, "Dell", ALC236_FIXUP_DELL_AIO_HEADSET_MIC,
- {0x21, 0x02211010}),
- SND_HDA_PIN_QUIRK(0x10ec0236, 0x103c, "HP", ALC256_FIXUP_HP_HEADSET_MIC,
- {0x14, 0x90170110},
- {0x19, 0x02a11020},
- {0x21, 0x02211030}),
- SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE,
- {0x14, 0x90170110},
- {0x21, 0x02211020}),
- SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
- {0x14, 0x90170130},
- {0x21, 0x02211040}),
- SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
- {0x12, 0x90a60140},
- {0x14, 0x90170110},
- {0x21, 0x02211020}),
- SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
- {0x12, 0x90a60160},
- {0x14, 0x90170120},
- {0x21, 0x02211030}),
- SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
- {0x14, 0x90170110},
- {0x1b, 0x02011020},
- {0x21, 0x0221101f}),
- SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
- {0x14, 0x90170110},
- {0x1b, 0x01011020},
- {0x21, 0x0221101f}),
- SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
- {0x14, 0x90170130},
- {0x1b, 0x01014020},
- {0x21, 0x0221103f}),
- SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
- {0x14, 0x90170130},
- {0x1b, 0x01011020},
- {0x21, 0x0221103f}),
- SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
- {0x14, 0x90170130},
- {0x1b, 0x02011020},
- {0x21, 0x0221103f}),
- SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
- {0x14, 0x90170150},
- {0x1b, 0x02011020},
- {0x21, 0x0221105f}),
- SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
- {0x14, 0x90170110},
- {0x1b, 0x01014020},
- {0x21, 0x0221101f}),
- SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
- {0x12, 0x90a60160},
- {0x14, 0x90170120},
- {0x17, 0x90170140},
- {0x21, 0x0321102f}),
- SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
- {0x12, 0x90a60160},
- {0x14, 0x90170130},
- {0x21, 0x02211040}),
- SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
- {0x12, 0x90a60160},
- {0x14, 0x90170140},
- {0x21, 0x02211050}),
- SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
- {0x12, 0x90a60170},
- {0x14, 0x90170120},
- {0x21, 0x02211030}),
- SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
- {0x12, 0x90a60170},
- {0x14, 0x90170130},
- {0x21, 0x02211040}),
- SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
- {0x12, 0x90a60170},
- {0x14, 0x90171130},
- {0x21, 0x02211040}),
- SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
- {0x12, 0x90a60170},
- {0x14, 0x90170140},
- {0x21, 0x02211050}),
- SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell Inspiron 5548", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
- {0x12, 0x90a60180},
- {0x14, 0x90170130},
- {0x21, 0x02211040}),
- SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell Inspiron 5565", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
- {0x12, 0x90a60180},
- {0x14, 0x90170120},
- {0x21, 0x02211030}),
- SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
- {0x1b, 0x01011020},
- {0x21, 0x02211010}),
- SND_HDA_PIN_QUIRK(0x10ec0256, 0x1043, "ASUS", ALC256_FIXUP_ASUS_MIC,
- {0x14, 0x90170110},
- {0x1b, 0x90a70130},
- {0x21, 0x04211020}),
- SND_HDA_PIN_QUIRK(0x10ec0256, 0x1043, "ASUS", ALC256_FIXUP_ASUS_MIC,
- {0x14, 0x90170110},
- {0x1b, 0x90a70130},
- {0x21, 0x03211020}),
- SND_HDA_PIN_QUIRK(0x10ec0256, 0x1043, "ASUS", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE,
- {0x12, 0x90a60130},
- {0x14, 0x90170110},
- {0x21, 0x03211020}),
- SND_HDA_PIN_QUIRK(0x10ec0256, 0x1043, "ASUS", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE,
- {0x12, 0x90a60130},
- {0x14, 0x90170110},
- {0x21, 0x04211020}),
- SND_HDA_PIN_QUIRK(0x10ec0256, 0x1043, "ASUS", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE,
- {0x1a, 0x90a70130},
- {0x1b, 0x90170110},
- {0x21, 0x03211020}),
- SND_HDA_PIN_QUIRK(0x10ec0256, 0x103c, "HP", ALC256_FIXUP_HP_HEADSET_MIC,
- {0x14, 0x90170110},
- {0x19, 0x02a11020},
- {0x21, 0x0221101f}),
- SND_HDA_PIN_QUIRK(0x10ec0274, 0x103c, "HP", ALC274_FIXUP_HP_HEADSET_MIC,
- {0x17, 0x90170110},
- {0x19, 0x03a11030},
- {0x21, 0x03211020}),
- SND_HDA_PIN_QUIRK(0x10ec0280, 0x103c, "HP", ALC280_FIXUP_HP_GPIO4,
- {0x12, 0x90a60130},
- {0x14, 0x90170110},
- {0x15, 0x0421101f},
- {0x1a, 0x04a11020}),
- SND_HDA_PIN_QUIRK(0x10ec0280, 0x103c, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED,
- {0x12, 0x90a60140},
- {0x14, 0x90170110},
- {0x15, 0x0421101f},
- {0x18, 0x02811030},
- {0x1a, 0x04a1103f},
- {0x1b, 0x02011020}),
- SND_HDA_PIN_QUIRK(0x10ec0282, 0x103c, "HP 15 Touchsmart", ALC269_FIXUP_HP_MUTE_LED_MIC1,
- ALC282_STANDARD_PINS,
- {0x12, 0x99a30130},
- {0x19, 0x03a11020},
- {0x21, 0x0321101f}),
- SND_HDA_PIN_QUIRK(0x10ec0282, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1,
- ALC282_STANDARD_PINS,
- {0x12, 0x99a30130},
- {0x19, 0x03a11020},
- {0x21, 0x03211040}),
- SND_HDA_PIN_QUIRK(0x10ec0282, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1,
- ALC282_STANDARD_PINS,
- {0x12, 0x99a30130},
- {0x19, 0x03a11030},
- {0x21, 0x03211020}),
- SND_HDA_PIN_QUIRK(0x10ec0282, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1,
- ALC282_STANDARD_PINS,
- {0x12, 0x99a30130},
- {0x19, 0x04a11020},
- {0x21, 0x0421101f}),
- SND_HDA_PIN_QUIRK(0x10ec0282, 0x103c, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED,
- ALC282_STANDARD_PINS,
- {0x12, 0x90a60140},
- {0x19, 0x04a11030},
- {0x21, 0x04211020}),
- SND_HDA_PIN_QUIRK(0x10ec0282, 0x1025, "Acer", ALC282_FIXUP_ACER_DISABLE_LINEOUT,
- ALC282_STANDARD_PINS,
- {0x12, 0x90a609c0},
- {0x18, 0x03a11830},
- {0x19, 0x04a19831},
- {0x1a, 0x0481303f},
- {0x1b, 0x04211020},
- {0x21, 0x0321101f}),
- SND_HDA_PIN_QUIRK(0x10ec0282, 0x1025, "Acer", ALC282_FIXUP_ACER_DISABLE_LINEOUT,
- ALC282_STANDARD_PINS,
- {0x12, 0x90a60940},
- {0x18, 0x03a11830},
- {0x19, 0x04a19831},
- {0x1a, 0x0481303f},
- {0x1b, 0x04211020},
- {0x21, 0x0321101f}),
- SND_HDA_PIN_QUIRK(0x10ec0283, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
- ALC282_STANDARD_PINS,
- {0x12, 0x90a60130},
- {0x21, 0x0321101f}),
- SND_HDA_PIN_QUIRK(0x10ec0283, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
- {0x12, 0x90a60160},
- {0x14, 0x90170120},
- {0x21, 0x02211030}),
- SND_HDA_PIN_QUIRK(0x10ec0283, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
- ALC282_STANDARD_PINS,
- {0x12, 0x90a60130},
- {0x19, 0x03a11020},
- {0x21, 0x0321101f}),
- SND_HDA_PIN_QUIRK(0x10ec0285, 0x17aa, "Lenovo", ALC285_FIXUP_LENOVO_PC_BEEP_IN_NOISE,
- {0x12, 0x90a60130},
- {0x14, 0x90170110},
- {0x19, 0x04a11040},
- {0x21, 0x04211020}),
- SND_HDA_PIN_QUIRK(0x10ec0285, 0x17aa, "Lenovo", ALC285_FIXUP_LENOVO_PC_BEEP_IN_NOISE,
- {0x14, 0x90170110},
- {0x19, 0x04a11040},
- {0x1d, 0x40600001},
- {0x21, 0x04211020}),
- SND_HDA_PIN_QUIRK(0x10ec0285, 0x17aa, "Lenovo", ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK,
- {0x14, 0x90170110},
- {0x19, 0x04a11040},
- {0x21, 0x04211020}),
- SND_HDA_PIN_QUIRK(0x10ec0287, 0x17aa, "Lenovo", ALC285_FIXUP_THINKPAD_HEADSET_JACK,
- {0x14, 0x90170110},
- {0x17, 0x90170111},
- {0x19, 0x03a11030},
- {0x21, 0x03211020}),
- SND_HDA_PIN_QUIRK(0x10ec0287, 0x17aa, "Lenovo", ALC287_FIXUP_THINKPAD_I2S_SPK,
- {0x17, 0x90170110},
- {0x19, 0x03a11030},
- {0x21, 0x03211020}),
- SND_HDA_PIN_QUIRK(0x10ec0287, 0x17aa, "Lenovo", ALC287_FIXUP_THINKPAD_I2S_SPK,
- {0x17, 0x90170110}, /* 0x231f with RTK I2S AMP */
- {0x19, 0x04a11040},
- {0x21, 0x04211020}),
- SND_HDA_PIN_QUIRK(0x10ec0286, 0x1025, "Acer", ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE,
- {0x12, 0x90a60130},
- {0x17, 0x90170110},
- {0x21, 0x02211020}),
- SND_HDA_PIN_QUIRK(0x10ec0288, 0x1028, "Dell", ALC288_FIXUP_DELL1_MIC_NO_PRESENCE,
- {0x12, 0x90a60120},
- {0x14, 0x90170110},
- {0x21, 0x0321101f}),
- SND_HDA_PIN_QUIRK(0x10ec0290, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1,
- ALC290_STANDARD_PINS,
- {0x15, 0x04211040},
- {0x18, 0x90170112},
- {0x1a, 0x04a11020}),
- SND_HDA_PIN_QUIRK(0x10ec0290, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1,
- ALC290_STANDARD_PINS,
- {0x15, 0x04211040},
- {0x18, 0x90170110},
- {0x1a, 0x04a11020}),
- SND_HDA_PIN_QUIRK(0x10ec0290, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1,
- ALC290_STANDARD_PINS,
- {0x15, 0x0421101f},
- {0x1a, 0x04a11020}),
- SND_HDA_PIN_QUIRK(0x10ec0290, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1,
- ALC290_STANDARD_PINS,
- {0x15, 0x04211020},
- {0x1a, 0x04a11040}),
- SND_HDA_PIN_QUIRK(0x10ec0290, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1,
- ALC290_STANDARD_PINS,
- {0x14, 0x90170110},
- {0x15, 0x04211020},
- {0x1a, 0x04a11040}),
- SND_HDA_PIN_QUIRK(0x10ec0290, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1,
- ALC290_STANDARD_PINS,
- {0x14, 0x90170110},
- {0x15, 0x04211020},
- {0x1a, 0x04a11020}),
- SND_HDA_PIN_QUIRK(0x10ec0290, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1,
- ALC290_STANDARD_PINS,
- {0x14, 0x90170110},
- {0x15, 0x0421101f},
- {0x1a, 0x04a11020}),
- SND_HDA_PIN_QUIRK(0x10ec0292, 0x1028, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE,
- ALC292_STANDARD_PINS,
- {0x12, 0x90a60140},
- {0x16, 0x01014020},
- {0x19, 0x01a19030}),
- SND_HDA_PIN_QUIRK(0x10ec0292, 0x1028, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE,
- ALC292_STANDARD_PINS,
- {0x12, 0x90a60140},
- {0x16, 0x01014020},
- {0x18, 0x02a19031},
- {0x19, 0x01a1903e}),
- SND_HDA_PIN_QUIRK(0x10ec0292, 0x1028, "Dell", ALC269_FIXUP_DELL3_MIC_NO_PRESENCE,
- ALC292_STANDARD_PINS,
- {0x12, 0x90a60140}),
- SND_HDA_PIN_QUIRK(0x10ec0293, 0x1028, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE,
- ALC292_STANDARD_PINS,
- {0x13, 0x90a60140},
- {0x16, 0x21014020},
- {0x19, 0x21a19030}),
- SND_HDA_PIN_QUIRK(0x10ec0293, 0x1028, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE,
- ALC292_STANDARD_PINS,
- {0x13, 0x90a60140}),
- SND_HDA_PIN_QUIRK(0x10ec0294, 0x1043, "ASUS", ALC294_FIXUP_ASUS_HPE,
- {0x17, 0x90170110},
- {0x21, 0x04211020}),
- SND_HDA_PIN_QUIRK(0x10ec0294, 0x1043, "ASUS", ALC294_FIXUP_ASUS_MIC,
- {0x14, 0x90170110},
- {0x1b, 0x90a70130},
- {0x21, 0x04211020}),
- SND_HDA_PIN_QUIRK(0x10ec0294, 0x1043, "ASUS", ALC294_FIXUP_ASUS_SPK,
- {0x12, 0x90a60130},
- {0x17, 0x90170110},
- {0x21, 0x03211020}),
- SND_HDA_PIN_QUIRK(0x10ec0294, 0x1043, "ASUS", ALC294_FIXUP_ASUS_SPK,
- {0x12, 0x90a60130},
- {0x17, 0x90170110},
- {0x21, 0x04211020}),
- SND_HDA_PIN_QUIRK(0x10ec0295, 0x1043, "ASUS", ALC294_FIXUP_ASUS_SPK,
- {0x12, 0x90a60130},
- {0x17, 0x90170110},
- {0x21, 0x03211020}),
- SND_HDA_PIN_QUIRK(0x10ec0295, 0x1043, "ASUS", ALC295_FIXUP_ASUS_MIC_NO_PRESENCE,
- {0x12, 0x90a60120},
- {0x17, 0x90170110},
- {0x21, 0x04211030}),
- SND_HDA_PIN_QUIRK(0x10ec0295, 0x1043, "ASUS", ALC295_FIXUP_ASUS_MIC_NO_PRESENCE,
- {0x12, 0x90a60130},
- {0x17, 0x90170110},
- {0x21, 0x03211020}),
- SND_HDA_PIN_QUIRK(0x10ec0295, 0x1043, "ASUS", ALC295_FIXUP_ASUS_MIC_NO_PRESENCE,
- {0x12, 0x90a60130},
- {0x17, 0x90170110},
- {0x21, 0x03211020}),
- SND_HDA_PIN_QUIRK(0x10ec0298, 0x1028, "Dell", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE,
- ALC298_STANDARD_PINS,
- {0x17, 0x90170110}),
- SND_HDA_PIN_QUIRK(0x10ec0298, 0x1028, "Dell", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE,
- ALC298_STANDARD_PINS,
- {0x17, 0x90170140}),
- SND_HDA_PIN_QUIRK(0x10ec0298, 0x1028, "Dell", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE,
- ALC298_STANDARD_PINS,
- {0x17, 0x90170150}),
- SND_HDA_PIN_QUIRK(0x10ec0298, 0x1028, "Dell", ALC298_FIXUP_SPK_VOLUME,
- {0x12, 0xb7a60140},
- {0x13, 0xb7a60150},
- {0x17, 0x90170110},
- {0x1a, 0x03011020},
- {0x21, 0x03211030}),
- SND_HDA_PIN_QUIRK(0x10ec0298, 0x1028, "Dell", ALC298_FIXUP_ALIENWARE_MIC_NO_PRESENCE,
- {0x12, 0xb7a60140},
- {0x17, 0x90170110},
- {0x1a, 0x03a11030},
- {0x21, 0x03211020}),
- SND_HDA_PIN_QUIRK(0x10ec0299, 0x1028, "Dell", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE,
- ALC225_STANDARD_PINS,
- {0x12, 0xb7a60130},
- {0x17, 0x90170110}),
- SND_HDA_PIN_QUIRK(0x10ec0623, 0x17aa, "Lenovo", ALC283_FIXUP_HEADSET_MIC,
- {0x14, 0x01014010},
- {0x17, 0x90170120},
- {0x18, 0x02a11030},
- {0x19, 0x02a1103f},
- {0x21, 0x0221101f}),
- {}
-};
-
-/* This is the fallback pin_fixup_tbl for alc269 family, to make the tbl match
- * more machines, don't need to match all valid pins, just need to match
- * all the pins defined in the tbl. Just because of this reason, it is possible
- * that a single machine matches multiple tbls, so there is one limitation:
- * at most one tbl is allowed to define for the same vendor and same codec
- */
-static const struct snd_hda_pin_quirk alc269_fallback_pin_fixup_tbl[] = {
- SND_HDA_PIN_QUIRK(0x10ec0256, 0x1025, "Acer", ALC2XX_FIXUP_HEADSET_MIC,
- {0x19, 0x40000000}),
- SND_HDA_PIN_QUIRK(0x10ec0289, 0x1028, "Dell", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE,
- {0x19, 0x40000000},
- {0x1b, 0x40000000}),
- SND_HDA_PIN_QUIRK(0x10ec0295, 0x1028, "Dell", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE_QUIET,
- {0x19, 0x40000000},
- {0x1b, 0x40000000}),
- SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
- {0x19, 0x40000000},
- {0x1a, 0x40000000}),
- SND_HDA_PIN_QUIRK(0x10ec0236, 0x1028, "Dell", ALC255_FIXUP_DELL1_LIMIT_INT_MIC_BOOST,
- {0x19, 0x40000000},
- {0x1a, 0x40000000}),
- SND_HDA_PIN_QUIRK(0x10ec0274, 0x1028, "Dell", ALC269_FIXUP_DELL1_LIMIT_INT_MIC_BOOST,
- {0x19, 0x40000000},
- {0x1a, 0x40000000}),
- SND_HDA_PIN_QUIRK(0x10ec0256, 0x1043, "ASUS", ALC2XX_FIXUP_HEADSET_MIC,
- {0x19, 0x40000000}),
- SND_HDA_PIN_QUIRK(0x10ec0255, 0x1558, "Clevo", ALC2XX_FIXUP_HEADSET_MIC,
- {0x19, 0x40000000}),
- {}
-};
-
-static void alc269_fill_coef(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- int val;
-
- if (spec->codec_variant != ALC269_TYPE_ALC269VB)
- return;
-
- if ((alc_get_coef0(codec) & 0x00ff) < 0x015) {
- alc_write_coef_idx(codec, 0xf, 0x960b);
- alc_write_coef_idx(codec, 0xe, 0x8817);
- }
-
- if ((alc_get_coef0(codec) & 0x00ff) == 0x016) {
- alc_write_coef_idx(codec, 0xf, 0x960b);
- alc_write_coef_idx(codec, 0xe, 0x8814);
- }
-
- if ((alc_get_coef0(codec) & 0x00ff) == 0x017) {
- /* Power up output pin */
- alc_update_coef_idx(codec, 0x04, 0, 1<<11);
- }
-
- if ((alc_get_coef0(codec) & 0x00ff) == 0x018) {
- val = alc_read_coef_idx(codec, 0xd);
- if (val != -1 && (val & 0x0c00) >> 10 != 0x1) {
- /* Capless ramp up clock control */
- alc_write_coef_idx(codec, 0xd, val | (1<<10));
- }
- val = alc_read_coef_idx(codec, 0x17);
- if (val != -1 && (val & 0x01c0) >> 6 != 0x4) {
- /* Class D power on reset */
- alc_write_coef_idx(codec, 0x17, val | (1<<7));
- }
- }
-
- /* HP */
- alc_update_coef_idx(codec, 0x4, 0, 1<<11);
-}
-
-/*
- */
-static int patch_alc269(struct hda_codec *codec)
-{
- struct alc_spec *spec;
- int err;
-
- err = alc_alloc_spec(codec, 0x0b);
- if (err < 0)
- return err;
-
- spec = codec->spec;
- spec->gen.shared_mic_vref_pin = 0x18;
- codec->power_save_node = 0;
- spec->en_3kpull_low = true;
-
- codec->patch_ops.suspend = alc269_suspend;
- codec->patch_ops.resume = alc269_resume;
- spec->shutup = alc_default_shutup;
- spec->init_hook = alc_default_init;
-
- switch (codec->core.vendor_id) {
- case 0x10ec0269:
- spec->codec_variant = ALC269_TYPE_ALC269VA;
- switch (alc_get_coef0(codec) & 0x00f0) {
- case 0x0010:
- if (codec->bus->pci &&
- codec->bus->pci->subsystem_vendor == 0x1025 &&
- spec->cdefine.platform_type == 1)
- err = alc_codec_rename(codec, "ALC271X");
- spec->codec_variant = ALC269_TYPE_ALC269VB;
- break;
- case 0x0020:
- if (codec->bus->pci &&
- codec->bus->pci->subsystem_vendor == 0x17aa &&
- codec->bus->pci->subsystem_device == 0x21f3)
- err = alc_codec_rename(codec, "ALC3202");
- spec->codec_variant = ALC269_TYPE_ALC269VC;
- break;
- case 0x0030:
- spec->codec_variant = ALC269_TYPE_ALC269VD;
- break;
- default:
- alc_fix_pll_init(codec, 0x20, 0x04, 15);
- }
- if (err < 0)
- goto error;
- spec->shutup = alc269_shutup;
- spec->init_hook = alc269_fill_coef;
- alc269_fill_coef(codec);
- break;
-
- case 0x10ec0280:
- case 0x10ec0290:
- spec->codec_variant = ALC269_TYPE_ALC280;
- break;
- case 0x10ec0282:
- spec->codec_variant = ALC269_TYPE_ALC282;
- spec->shutup = alc282_shutup;
- spec->init_hook = alc282_init;
- break;
- case 0x10ec0233:
- case 0x10ec0283:
- spec->codec_variant = ALC269_TYPE_ALC283;
- spec->shutup = alc283_shutup;
- spec->init_hook = alc283_init;
- break;
- case 0x10ec0284:
- case 0x10ec0292:
- spec->codec_variant = ALC269_TYPE_ALC284;
- break;
- case 0x10ec0293:
- spec->codec_variant = ALC269_TYPE_ALC293;
- break;
- case 0x10ec0286:
- case 0x10ec0288:
- spec->codec_variant = ALC269_TYPE_ALC286;
- break;
- case 0x10ec0298:
- spec->codec_variant = ALC269_TYPE_ALC298;
- break;
- case 0x10ec0235:
- case 0x10ec0255:
- spec->codec_variant = ALC269_TYPE_ALC255;
- spec->shutup = alc256_shutup;
- spec->init_hook = alc256_init;
- break;
- case 0x10ec0230:
- case 0x10ec0236:
- case 0x10ec0256:
- case 0x19e58326:
- spec->codec_variant = ALC269_TYPE_ALC256;
- spec->shutup = alc256_shutup;
- spec->init_hook = alc256_init;
- spec->gen.mixer_nid = 0; /* ALC256 does not have any loopback mixer path */
- if (codec->core.vendor_id == 0x10ec0236 &&
- codec->bus->pci->vendor != PCI_VENDOR_ID_AMD)
- spec->en_3kpull_low = false;
- break;
- case 0x10ec0257:
- spec->codec_variant = ALC269_TYPE_ALC257;
- spec->shutup = alc256_shutup;
- spec->init_hook = alc256_init;
- spec->gen.mixer_nid = 0;
- spec->en_3kpull_low = false;
- break;
- case 0x10ec0215:
- case 0x10ec0245:
- case 0x10ec0285:
- case 0x10ec0289:
- if (alc_get_coef0(codec) & 0x0010)
- spec->codec_variant = ALC269_TYPE_ALC245;
- else
- spec->codec_variant = ALC269_TYPE_ALC215;
- spec->shutup = alc225_shutup;
- spec->init_hook = alc225_init;
- spec->gen.mixer_nid = 0;
- break;
- case 0x10ec0225:
- case 0x10ec0295:
- case 0x10ec0299:
- spec->codec_variant = ALC269_TYPE_ALC225;
- spec->shutup = alc225_shutup;
- spec->init_hook = alc225_init;
- spec->gen.mixer_nid = 0; /* no loopback on ALC225, ALC295 and ALC299 */
- break;
- case 0x10ec0287:
- spec->codec_variant = ALC269_TYPE_ALC287;
- spec->shutup = alc225_shutup;
- spec->init_hook = alc225_init;
- spec->gen.mixer_nid = 0; /* no loopback on ALC287 */
- break;
- case 0x10ec0234:
- case 0x10ec0274:
- case 0x10ec0294:
- spec->codec_variant = ALC269_TYPE_ALC294;
- spec->gen.mixer_nid = 0; /* ALC2x4 does not have any loopback mixer path */
- alc_update_coef_idx(codec, 0x6b, 0x0018, (1<<4) | (1<<3)); /* UAJ MIC Vref control by verb */
- spec->init_hook = alc294_init;
- break;
- case 0x10ec0300:
- spec->codec_variant = ALC269_TYPE_ALC300;
- spec->gen.mixer_nid = 0; /* no loopback on ALC300 */
- break;
- case 0x10ec0222:
- case 0x10ec0623:
- spec->codec_variant = ALC269_TYPE_ALC623;
- spec->shutup = alc222_shutup;
- spec->init_hook = alc222_init;
- break;
- case 0x10ec0700:
- case 0x10ec0701:
- case 0x10ec0703:
- case 0x10ec0711:
- spec->codec_variant = ALC269_TYPE_ALC700;
- spec->gen.mixer_nid = 0; /* ALC700 does not have any loopback mixer path */
- alc_update_coef_idx(codec, 0x4a, 1 << 15, 0); /* Combo jack auto trigger control */
- spec->init_hook = alc294_init;
- break;
-
- }
-
- if (snd_hda_codec_read(codec, 0x51, 0, AC_VERB_PARAMETERS, 0) == 0x10ec5505) {
- spec->has_alc5505_dsp = 1;
- spec->init_hook = alc5505_dsp_init;
- }
-
- alc_pre_init(codec);
-
- snd_hda_pick_fixup(codec, alc269_fixup_models,
- alc269_fixup_tbl, alc269_fixups);
- /* FIXME: both TX300 and ROG Strix G17 have the same SSID, and
- * the quirk breaks the latter (bko#214101).
- * Clear the wrong entry.
- */
- if (codec->fixup_id == ALC282_FIXUP_ASUS_TX300 &&
- codec->core.vendor_id == 0x10ec0294) {
- codec_dbg(codec, "Clear wrong fixup for ASUS ROG Strix G17\n");
- codec->fixup_id = HDA_FIXUP_ID_NOT_SET;
- }
-
- snd_hda_pick_pin_fixup(codec, alc269_pin_fixup_tbl, alc269_fixups, true);
- snd_hda_pick_pin_fixup(codec, alc269_fallback_pin_fixup_tbl, alc269_fixups, false);
- snd_hda_pick_fixup(codec, NULL, alc269_fixup_vendor_tbl,
- alc269_fixups);
-
- /*
- * Check whether ACPI describes companion amplifiers that require
- * component binding
- */
- find_cirrus_companion_amps(codec);
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
-
- alc_auto_parse_customize_define(codec);
-
- if (has_cdefine_beep(codec))
- spec->gen.beep_nid = 0x01;
-
- /* automatic parse from the BIOS config */
- err = alc269_parse_auto_config(codec);
- if (err < 0)
- goto error;
-
- if (!spec->gen.no_analog && spec->gen.beep_nid && spec->gen.mixer_nid) {
- err = set_beep_amp(spec, spec->gen.mixer_nid, 0x04, HDA_INPUT);
- if (err < 0)
- goto error;
- }
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
-
- return 0;
-
- error:
- alc_free(codec);
- return err;
-}
-
-/*
- * ALC861
- */
-
-static int alc861_parse_auto_config(struct hda_codec *codec)
-{
- static const hda_nid_t alc861_ignore[] = { 0x1d, 0 };
- static const hda_nid_t alc861_ssids[] = { 0x0e, 0x0f, 0x0b, 0 };
- return alc_parse_auto_config(codec, alc861_ignore, alc861_ssids);
-}
-
-/* Pin config fixes */
-enum {
- ALC861_FIXUP_FSC_AMILO_PI1505,
- ALC861_FIXUP_AMP_VREF_0F,
- ALC861_FIXUP_NO_JACK_DETECT,
- ALC861_FIXUP_ASUS_A6RP,
- ALC660_FIXUP_ASUS_W7J,
-};
-
-/* On some laptops, VREF of pin 0x0f is abused for controlling the main amp */
-static void alc861_fixup_asus_amp_vref_0f(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
- unsigned int val;
-
- if (action != HDA_FIXUP_ACT_INIT)
- return;
- val = snd_hda_codec_get_pin_target(codec, 0x0f);
- if (!(val & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN)))
- val |= AC_PINCTL_IN_EN;
- val |= AC_PINCTL_VREF_50;
- snd_hda_set_pin_ctl(codec, 0x0f, val);
- spec->gen.keep_vref_in_automute = 1;
-}
-
-/* suppress the jack-detection */
-static void alc_fixup_no_jack_detect(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_PRE_PROBE)
- codec->no_jack_detect = 1;
-}
-
-static const struct hda_fixup alc861_fixups[] = {
- [ALC861_FIXUP_FSC_AMILO_PI1505] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x0b, 0x0221101f }, /* HP */
- { 0x0f, 0x90170310 }, /* speaker */
- { }
- }
- },
- [ALC861_FIXUP_AMP_VREF_0F] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc861_fixup_asus_amp_vref_0f,
- },
- [ALC861_FIXUP_NO_JACK_DETECT] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_no_jack_detect,
- },
- [ALC861_FIXUP_ASUS_A6RP] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc861_fixup_asus_amp_vref_0f,
- .chained = true,
- .chain_id = ALC861_FIXUP_NO_JACK_DETECT,
- },
- [ALC660_FIXUP_ASUS_W7J] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- /* ASUS W7J needs a magic pin setup on unused NID 0x10
- * for enabling outputs
- */
- {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
- { }
- },
- }
-};
-
-static const struct hda_quirk alc861_fixup_tbl[] = {
- SND_PCI_QUIRK(0x1043, 0x1253, "ASUS W7J", ALC660_FIXUP_ASUS_W7J),
- SND_PCI_QUIRK(0x1043, 0x1263, "ASUS Z35HL", ALC660_FIXUP_ASUS_W7J),
- SND_PCI_QUIRK(0x1043, 0x1393, "ASUS A6Rp", ALC861_FIXUP_ASUS_A6RP),
- SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", ALC861_FIXUP_AMP_VREF_0F),
- SND_PCI_QUIRK(0x1462, 0x7254, "HP DX2200", ALC861_FIXUP_NO_JACK_DETECT),
- SND_PCI_QUIRK_VENDOR(0x1584, "Haier/Uniwill", ALC861_FIXUP_AMP_VREF_0F),
- SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", ALC861_FIXUP_FSC_AMILO_PI1505),
- {}
-};
-
-/*
- */
-static int patch_alc861(struct hda_codec *codec)
-{
- struct alc_spec *spec;
- int err;
-
- err = alc_alloc_spec(codec, 0x15);
- if (err < 0)
- return err;
-
- spec = codec->spec;
- if (has_cdefine_beep(codec))
- spec->gen.beep_nid = 0x23;
-
- spec->power_hook = alc_power_eapd;
-
- alc_pre_init(codec);
-
- snd_hda_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups);
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
-
- /* automatic parse from the BIOS config */
- err = alc861_parse_auto_config(codec);
- if (err < 0)
- goto error;
-
- if (!spec->gen.no_analog) {
- err = set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
- if (err < 0)
- goto error;
- }
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
-
- return 0;
-
- error:
- alc_free(codec);
- return err;
-}
-
-/*
- * ALC861-VD support
- *
- * Based on ALC882
- *
- * In addition, an independent DAC
- */
-static int alc861vd_parse_auto_config(struct hda_codec *codec)
-{
- static const hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
- static const hda_nid_t alc861vd_ssids[] = { 0x15, 0x1b, 0x14, 0 };
- return alc_parse_auto_config(codec, alc861vd_ignore, alc861vd_ssids);
-}
-
-enum {
- ALC660VD_FIX_ASUS_GPIO1,
- ALC861VD_FIX_DALLAS,
-};
-
-/* exclude VREF80 */
-static void alc861vd_fixup_dallas(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- snd_hda_override_pin_caps(codec, 0x18, 0x00000734);
- snd_hda_override_pin_caps(codec, 0x19, 0x0000073c);
- }
-}
-
-/* reset GPIO1 */
-static void alc660vd_fixup_asus_gpio1(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE)
- spec->gpio_mask |= 0x02;
- alc_fixup_gpio(codec, action, 0x01);
-}
-
-static const struct hda_fixup alc861vd_fixups[] = {
- [ALC660VD_FIX_ASUS_GPIO1] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc660vd_fixup_asus_gpio1,
- },
- [ALC861VD_FIX_DALLAS] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc861vd_fixup_dallas,
- },
-};
-
-static const struct hda_quirk alc861vd_fixup_tbl[] = {
- SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_FIX_DALLAS),
- SND_PCI_QUIRK(0x1043, 0x1339, "ASUS A7-K", ALC660VD_FIX_ASUS_GPIO1),
- SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_FIX_DALLAS),
- {}
-};
-
-/*
- */
-static int patch_alc861vd(struct hda_codec *codec)
-{
- struct alc_spec *spec;
- int err;
-
- err = alc_alloc_spec(codec, 0x0b);
- if (err < 0)
- return err;
-
- spec = codec->spec;
- if (has_cdefine_beep(codec))
- spec->gen.beep_nid = 0x23;
-
- spec->shutup = alc_eapd_shutup;
-
- alc_pre_init(codec);
-
- snd_hda_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups);
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
-
- /* automatic parse from the BIOS config */
- err = alc861vd_parse_auto_config(codec);
- if (err < 0)
- goto error;
-
- if (!spec->gen.no_analog) {
- err = set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
- if (err < 0)
- goto error;
- }
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
-
- return 0;
-
- error:
- alc_free(codec);
- return err;
-}
-
-/*
- * ALC662 support
- *
- * ALC662 is almost identical with ALC880 but has cleaner and more flexible
- * configuration. Each pin widget can choose any input DACs and a mixer.
- * Each ADC is connected from a mixer of all inputs. This makes possible
- * 6-channel independent captures.
- *
- * In addition, an independent DAC for the multi-playback (not used in this
- * driver yet).
- */
-
-/*
- * BIOS auto configuration
- */
-
-static int alc662_parse_auto_config(struct hda_codec *codec)
-{
- static const hda_nid_t alc662_ignore[] = { 0x1d, 0 };
- static const hda_nid_t alc663_ssids[] = { 0x15, 0x1b, 0x14, 0x21 };
- static const hda_nid_t alc662_ssids[] = { 0x15, 0x1b, 0x14, 0 };
- const hda_nid_t *ssids;
-
- if (codec->core.vendor_id == 0x10ec0272 || codec->core.vendor_id == 0x10ec0663 ||
- codec->core.vendor_id == 0x10ec0665 || codec->core.vendor_id == 0x10ec0670 ||
- codec->core.vendor_id == 0x10ec0671)
- ssids = alc663_ssids;
- else
- ssids = alc662_ssids;
- return alc_parse_auto_config(codec, alc662_ignore, ssids);
-}
-
-static void alc272_fixup_mario(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action != HDA_FIXUP_ACT_PRE_PROBE)
- return;
- if (snd_hda_override_amp_caps(codec, 0x2, HDA_OUTPUT,
- (0x3b << AC_AMPCAP_OFFSET_SHIFT) |
- (0x3b << AC_AMPCAP_NUM_STEPS_SHIFT) |
- (0x03 << AC_AMPCAP_STEP_SIZE_SHIFT) |
- (0 << AC_AMPCAP_MUTE_SHIFT)))
- codec_warn(codec, "failed to override amp caps for NID 0x2\n");
-}
-
-static const struct snd_pcm_chmap_elem asus_pcm_2_1_chmaps[] = {
- { .channels = 2,
- .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } },
- { .channels = 4,
- .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,
- SNDRV_CHMAP_NA, SNDRV_CHMAP_LFE } }, /* LFE only on right */
- { }
-};
-
-/* override the 2.1 chmap */
-static void alc_fixup_bass_chmap(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_BUILD) {
- struct alc_spec *spec = codec->spec;
- spec->gen.pcm_rec[0]->stream[0].chmap = asus_pcm_2_1_chmaps;
- }
-}
-
-/* avoid D3 for keeping GPIO up */
-static unsigned int gpio_led_power_filter(struct hda_codec *codec,
- hda_nid_t nid,
- unsigned int power_state)
-{
- struct alc_spec *spec = codec->spec;
- if (nid == codec->core.afg && power_state == AC_PWRST_D3 && spec->gpio_data)
- return AC_PWRST_D0;
- return power_state;
-}
-
-static void alc662_fixup_led_gpio1(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
-
- alc_fixup_hp_gpio_led(codec, action, 0x01, 0);
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->mute_led_polarity = 1;
- codec->power_filter = gpio_led_power_filter;
- }
-}
-
-static void alc662_usi_automute_hook(struct hda_codec *codec,
- struct hda_jack_callback *jack)
-{
- struct alc_spec *spec = codec->spec;
- int vref;
- msleep(200);
- snd_hda_gen_hp_automute(codec, jack);
-
- vref = spec->gen.hp_jack_present ? PIN_VREF80 : 0;
- msleep(100);
- snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
- vref);
-}
-
-static void alc662_fixup_usi_headset_mic(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
- spec->gen.hp_automute_hook = alc662_usi_automute_hook;
- }
-}
-
-static void alc662_aspire_ethos_mute_speakers(struct hda_codec *codec,
- struct hda_jack_callback *cb)
-{
- /* surround speakers at 0x1b already get muted automatically when
- * headphones are plugged in, but we have to mute/unmute the remaining
- * channels manually:
- * 0x15 - front left/front right
- * 0x18 - front center/ LFE
- */
- if (snd_hda_jack_detect_state(codec, 0x1b) == HDA_JACK_PRESENT) {
- snd_hda_set_pin_ctl_cache(codec, 0x15, 0);
- snd_hda_set_pin_ctl_cache(codec, 0x18, 0);
- } else {
- snd_hda_set_pin_ctl_cache(codec, 0x15, PIN_OUT);
- snd_hda_set_pin_ctl_cache(codec, 0x18, PIN_OUT);
- }
-}
-
-static void alc662_fixup_aspire_ethos_hp(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- /* Pin 0x1b: shared headphones jack and surround speakers */
- if (!is_jack_detectable(codec, 0x1b))
- return;
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- snd_hda_jack_detect_enable_callback(codec, 0x1b,
- alc662_aspire_ethos_mute_speakers);
- /* subwoofer needs an extra GPIO setting to become audible */
- alc_setup_gpio(codec, 0x02);
- break;
- case HDA_FIXUP_ACT_INIT:
- /* Make sure to start in a correct state, i.e. if
- * headphones have been plugged in before powering up the system
- */
- alc662_aspire_ethos_mute_speakers(codec, NULL);
- break;
- }
-}
-
-static void alc671_fixup_hp_headset_mic2(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
-
- static const struct hda_pintbl pincfgs[] = {
- { 0x19, 0x02a11040 }, /* use as headset mic, with its own jack detect */
- { 0x1b, 0x0181304f },
- { }
- };
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- spec->gen.mixer_nid = 0;
- spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
- snd_hda_apply_pincfgs(codec, pincfgs);
- break;
- case HDA_FIXUP_ACT_INIT:
- alc_write_coef_idx(codec, 0x19, 0xa054);
- break;
- }
-}
-
-static void alc897_hp_automute_hook(struct hda_codec *codec,
- struct hda_jack_callback *jack)
-{
- struct alc_spec *spec = codec->spec;
- int vref;
-
- snd_hda_gen_hp_automute(codec, jack);
- vref = spec->gen.hp_jack_present ? (PIN_HP | AC_PINCTL_VREF_100) : PIN_HP;
- snd_hda_set_pin_ctl(codec, 0x1b, vref);
-}
-
-static void alc897_fixup_lenovo_headset_mic(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->gen.hp_automute_hook = alc897_hp_automute_hook;
- spec->no_shutup_pins = 1;
- }
- if (action == HDA_FIXUP_ACT_PROBE) {
- snd_hda_set_pin_ctl_cache(codec, 0x1a, PIN_IN | AC_PINCTL_VREF_100);
- }
-}
-
-static void alc897_fixup_lenovo_headset_mode(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct alc_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
- spec->gen.hp_automute_hook = alc897_hp_automute_hook;
- }
-}
-
-static const struct coef_fw alc668_coefs[] = {
- WRITE_COEF(0x01, 0xbebe), WRITE_COEF(0x02, 0xaaaa), WRITE_COEF(0x03, 0x0),
- WRITE_COEF(0x04, 0x0180), WRITE_COEF(0x06, 0x0), WRITE_COEF(0x07, 0x0f80),
- WRITE_COEF(0x08, 0x0031), WRITE_COEF(0x0a, 0x0060), WRITE_COEF(0x0b, 0x0),
- WRITE_COEF(0x0c, 0x7cf7), WRITE_COEF(0x0d, 0x1080), WRITE_COEF(0x0e, 0x7f7f),
- WRITE_COEF(0x0f, 0xcccc), WRITE_COEF(0x10, 0xddcc), WRITE_COEF(0x11, 0x0001),
- WRITE_COEF(0x13, 0x0), WRITE_COEF(0x14, 0x2aa0), WRITE_COEF(0x17, 0xa940),
- WRITE_COEF(0x19, 0x0), WRITE_COEF(0x1a, 0x0), WRITE_COEF(0x1b, 0x0),
- WRITE_COEF(0x1c, 0x0), WRITE_COEF(0x1d, 0x0), WRITE_COEF(0x1e, 0x7418),
- WRITE_COEF(0x1f, 0x0804), WRITE_COEF(0x20, 0x4200), WRITE_COEF(0x21, 0x0468),
- WRITE_COEF(0x22, 0x8ccc), WRITE_COEF(0x23, 0x0250), WRITE_COEF(0x24, 0x7418),
- WRITE_COEF(0x27, 0x0), WRITE_COEF(0x28, 0x8ccc), WRITE_COEF(0x2a, 0xff00),
- WRITE_COEF(0x2b, 0x8000), WRITE_COEF(0xa7, 0xff00), WRITE_COEF(0xa8, 0x8000),
- WRITE_COEF(0xaa, 0x2e17), WRITE_COEF(0xab, 0xa0c0), WRITE_COEF(0xac, 0x0),
- WRITE_COEF(0xad, 0x0), WRITE_COEF(0xae, 0x2ac6), WRITE_COEF(0xaf, 0xa480),
- WRITE_COEF(0xb0, 0x0), WRITE_COEF(0xb1, 0x0), WRITE_COEF(0xb2, 0x0),
- WRITE_COEF(0xb3, 0x0), WRITE_COEF(0xb4, 0x0), WRITE_COEF(0xb5, 0x1040),
- WRITE_COEF(0xb6, 0xd697), WRITE_COEF(0xb7, 0x902b), WRITE_COEF(0xb8, 0xd697),
- WRITE_COEF(0xb9, 0x902b), WRITE_COEF(0xba, 0xb8ba), WRITE_COEF(0xbb, 0xaaab),
- WRITE_COEF(0xbc, 0xaaaf), WRITE_COEF(0xbd, 0x6aaa), WRITE_COEF(0xbe, 0x1c02),
- WRITE_COEF(0xc0, 0x00ff), WRITE_COEF(0xc1, 0x0fa6),
- {}
-};
-
-static void alc668_restore_default_value(struct hda_codec *codec)
-{
- alc_process_coef_fw(codec, alc668_coefs);
-}
-
-enum {
- ALC662_FIXUP_ASPIRE,
- ALC662_FIXUP_LED_GPIO1,
- ALC662_FIXUP_IDEAPAD,
- ALC272_FIXUP_MARIO,
- ALC662_FIXUP_CZC_ET26,
- ALC662_FIXUP_CZC_P10T,
- ALC662_FIXUP_SKU_IGNORE,
- ALC662_FIXUP_HP_RP5800,
- ALC662_FIXUP_ASUS_MODE1,
- ALC662_FIXUP_ASUS_MODE2,
- ALC662_FIXUP_ASUS_MODE3,
- ALC662_FIXUP_ASUS_MODE4,
- ALC662_FIXUP_ASUS_MODE5,
- ALC662_FIXUP_ASUS_MODE6,
- ALC662_FIXUP_ASUS_MODE7,
- ALC662_FIXUP_ASUS_MODE8,
- ALC662_FIXUP_NO_JACK_DETECT,
- ALC662_FIXUP_ZOTAC_Z68,
- ALC662_FIXUP_INV_DMIC,
- ALC662_FIXUP_DELL_MIC_NO_PRESENCE,
- ALC668_FIXUP_DELL_MIC_NO_PRESENCE,
- ALC662_FIXUP_HEADSET_MODE,
- ALC668_FIXUP_HEADSET_MODE,
- ALC662_FIXUP_BASS_MODE4_CHMAP,
- ALC662_FIXUP_BASS_16,
- ALC662_FIXUP_BASS_1A,
- ALC662_FIXUP_BASS_CHMAP,
- ALC668_FIXUP_AUTO_MUTE,
- ALC668_FIXUP_DELL_DISABLE_AAMIX,
- ALC668_FIXUP_DELL_XPS13,
- ALC662_FIXUP_ASUS_Nx50,
- ALC668_FIXUP_ASUS_Nx51_HEADSET_MODE,
- ALC668_FIXUP_ASUS_Nx51,
- ALC668_FIXUP_MIC_COEF,
- ALC668_FIXUP_ASUS_G751,
- ALC891_FIXUP_HEADSET_MODE,
- ALC891_FIXUP_DELL_MIC_NO_PRESENCE,
- ALC662_FIXUP_ACER_VERITON,
- ALC892_FIXUP_ASROCK_MOBO,
- ALC662_FIXUP_USI_FUNC,
- ALC662_FIXUP_USI_HEADSET_MODE,
- ALC662_FIXUP_LENOVO_MULTI_CODECS,
- ALC669_FIXUP_ACER_ASPIRE_ETHOS,
- ALC669_FIXUP_ACER_ASPIRE_ETHOS_HEADSET,
- ALC671_FIXUP_HP_HEADSET_MIC2,
- ALC662_FIXUP_ACER_X2660G_HEADSET_MODE,
- ALC662_FIXUP_ACER_NITRO_HEADSET_MODE,
- ALC668_FIXUP_ASUS_NO_HEADSET_MIC,
- ALC668_FIXUP_HEADSET_MIC,
- ALC668_FIXUP_MIC_DET_COEF,
- ALC897_FIXUP_LENOVO_HEADSET_MIC,
- ALC897_FIXUP_HEADSET_MIC_PIN,
- ALC897_FIXUP_HP_HSMIC_VERB,
- ALC897_FIXUP_LENOVO_HEADSET_MODE,
- ALC897_FIXUP_HEADSET_MIC_PIN2,
- ALC897_FIXUP_UNIS_H3C_X500S,
- ALC897_FIXUP_HEADSET_MIC_PIN3,
-};
-
-static const struct hda_fixup alc662_fixups[] = {
- [ALC662_FIXUP_ASPIRE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x15, 0x99130112 }, /* subwoofer */
- { }
- }
- },
- [ALC662_FIXUP_LED_GPIO1] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc662_fixup_led_gpio1,
- },
- [ALC662_FIXUP_IDEAPAD] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x17, 0x99130112 }, /* subwoofer */
- { }
- },
- .chained = true,
- .chain_id = ALC662_FIXUP_LED_GPIO1,
- },
- [ALC272_FIXUP_MARIO] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc272_fixup_mario,
- },
- [ALC662_FIXUP_CZC_ET26] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- {0x12, 0x403cc000},
- {0x14, 0x90170110}, /* speaker */
- {0x15, 0x411111f0},
- {0x16, 0x411111f0},
- {0x18, 0x01a19030}, /* mic */
- {0x19, 0x90a7013f}, /* int-mic */
- {0x1a, 0x01014020},
- {0x1b, 0x0121401f},
- {0x1c, 0x411111f0},
- {0x1d, 0x411111f0},
- {0x1e, 0x40478e35},
- {}
- },
- .chained = true,
- .chain_id = ALC662_FIXUP_SKU_IGNORE
- },
- [ALC662_FIXUP_CZC_P10T] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
- {}
- }
- },
- [ALC662_FIXUP_SKU_IGNORE] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_sku_ignore,
- },
- [ALC662_FIXUP_HP_RP5800] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x14, 0x0221201f }, /* HP out */
- { }
- },
- .chained = true,
- .chain_id = ALC662_FIXUP_SKU_IGNORE
- },
- [ALC662_FIXUP_ASUS_MODE1] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x14, 0x99130110 }, /* speaker */
- { 0x18, 0x01a19c20 }, /* mic */
- { 0x19, 0x99a3092f }, /* int-mic */
- { 0x21, 0x0121401f }, /* HP out */
- { }
- },
- .chained = true,
- .chain_id = ALC662_FIXUP_SKU_IGNORE
- },
- [ALC662_FIXUP_ASUS_MODE2] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x14, 0x99130110 }, /* speaker */
- { 0x18, 0x01a19820 }, /* mic */
- { 0x19, 0x99a3092f }, /* int-mic */
- { 0x1b, 0x0121401f }, /* HP out */
- { }
- },
- .chained = true,
- .chain_id = ALC662_FIXUP_SKU_IGNORE
- },
- [ALC662_FIXUP_ASUS_MODE3] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x14, 0x99130110 }, /* speaker */
- { 0x15, 0x0121441f }, /* HP */
- { 0x18, 0x01a19840 }, /* mic */
- { 0x19, 0x99a3094f }, /* int-mic */
- { 0x21, 0x01211420 }, /* HP2 */
- { }
- },
- .chained = true,
- .chain_id = ALC662_FIXUP_SKU_IGNORE
- },
- [ALC662_FIXUP_ASUS_MODE4] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x14, 0x99130110 }, /* speaker */
- { 0x16, 0x99130111 }, /* speaker */
- { 0x18, 0x01a19840 }, /* mic */
- { 0x19, 0x99a3094f }, /* int-mic */
- { 0x21, 0x0121441f }, /* HP */
- { }
- },
- .chained = true,
- .chain_id = ALC662_FIXUP_SKU_IGNORE
- },
- [ALC662_FIXUP_ASUS_MODE5] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x14, 0x99130110 }, /* speaker */
- { 0x15, 0x0121441f }, /* HP */
- { 0x16, 0x99130111 }, /* speaker */
- { 0x18, 0x01a19840 }, /* mic */
- { 0x19, 0x99a3094f }, /* int-mic */
- { }
- },
- .chained = true,
- .chain_id = ALC662_FIXUP_SKU_IGNORE
- },
- [ALC662_FIXUP_ASUS_MODE6] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x14, 0x99130110 }, /* speaker */
- { 0x15, 0x01211420 }, /* HP2 */
- { 0x18, 0x01a19840 }, /* mic */
- { 0x19, 0x99a3094f }, /* int-mic */
- { 0x1b, 0x0121441f }, /* HP */
- { }
- },
- .chained = true,
- .chain_id = ALC662_FIXUP_SKU_IGNORE
- },
- [ALC662_FIXUP_ASUS_MODE7] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x14, 0x99130110 }, /* speaker */
- { 0x17, 0x99130111 }, /* speaker */
- { 0x18, 0x01a19840 }, /* mic */
- { 0x19, 0x99a3094f }, /* int-mic */
- { 0x1b, 0x01214020 }, /* HP */
- { 0x21, 0x0121401f }, /* HP */
- { }
- },
- .chained = true,
- .chain_id = ALC662_FIXUP_SKU_IGNORE
- },
- [ALC662_FIXUP_ASUS_MODE8] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x14, 0x99130110 }, /* speaker */
- { 0x12, 0x99a30970 }, /* int-mic */
- { 0x15, 0x01214020 }, /* HP */
- { 0x17, 0x99130111 }, /* speaker */
- { 0x18, 0x01a19840 }, /* mic */
- { 0x21, 0x0121401f }, /* HP */
- { }
- },
- .chained = true,
- .chain_id = ALC662_FIXUP_SKU_IGNORE
- },
- [ALC662_FIXUP_NO_JACK_DETECT] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_no_jack_detect,
- },
- [ALC662_FIXUP_ZOTAC_Z68] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1b, 0x02214020 }, /* Front HP */
- { }
- }
- },
- [ALC662_FIXUP_INV_DMIC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_inv_dmic,
- },
- [ALC668_FIXUP_DELL_XPS13] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_dell_xps13,
- .chained = true,
- .chain_id = ALC668_FIXUP_DELL_DISABLE_AAMIX
- },
- [ALC668_FIXUP_DELL_DISABLE_AAMIX] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_disable_aamix,
- .chained = true,
- .chain_id = ALC668_FIXUP_DELL_MIC_NO_PRESENCE
- },
- [ALC668_FIXUP_AUTO_MUTE] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_auto_mute_via_amp,
- .chained = true,
- .chain_id = ALC668_FIXUP_DELL_MIC_NO_PRESENCE
- },
- [ALC662_FIXUP_DELL_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x03a1113c }, /* use as headset mic, without its own jack detect */
- /* headphone mic by setting pin control of 0x1b (headphone out) to in + vref_50 */
- { }
- },
- .chained = true,
- .chain_id = ALC662_FIXUP_HEADSET_MODE
- },
- [ALC662_FIXUP_HEADSET_MODE] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_headset_mode_alc662,
- },
- [ALC668_FIXUP_DELL_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x03a1913d }, /* use as headphone mic, without its own jack detect */
- { 0x1b, 0x03a1113c }, /* use as headset mic, without its own jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC668_FIXUP_HEADSET_MODE
- },
- [ALC668_FIXUP_HEADSET_MODE] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_headset_mode_alc668,
- },
- [ALC662_FIXUP_BASS_MODE4_CHMAP] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_bass_chmap,
- .chained = true,
- .chain_id = ALC662_FIXUP_ASUS_MODE4
- },
- [ALC662_FIXUP_BASS_16] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- {0x16, 0x80106111}, /* bass speaker */
- {}
- },
- .chained = true,
- .chain_id = ALC662_FIXUP_BASS_CHMAP,
- },
- [ALC662_FIXUP_BASS_1A] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- {0x1a, 0x80106111}, /* bass speaker */
- {}
- },
- .chained = true,
- .chain_id = ALC662_FIXUP_BASS_CHMAP,
- },
- [ALC662_FIXUP_BASS_CHMAP] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_bass_chmap,
- },
- [ALC662_FIXUP_ASUS_Nx50] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_auto_mute_via_amp,
- .chained = true,
- .chain_id = ALC662_FIXUP_BASS_1A
- },
- [ALC668_FIXUP_ASUS_Nx51_HEADSET_MODE] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_headset_mode_alc668,
- .chain_id = ALC662_FIXUP_BASS_CHMAP
- },
- [ALC668_FIXUP_ASUS_Nx51] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x03a1913d }, /* use as headphone mic, without its own jack detect */
- { 0x1a, 0x90170151 }, /* bass speaker */
- { 0x1b, 0x03a1113c }, /* use as headset mic, without its own jack detect */
- {}
- },
- .chained = true,
- .chain_id = ALC668_FIXUP_ASUS_Nx51_HEADSET_MODE,
- },
- [ALC668_FIXUP_MIC_COEF] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- { 0x20, AC_VERB_SET_COEF_INDEX, 0xc3 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x4000 },
- {}
- },
- },
- [ALC668_FIXUP_ASUS_G751] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x16, 0x0421101f }, /* HP */
- {}
- },
- .chained = true,
- .chain_id = ALC668_FIXUP_MIC_COEF
- },
- [ALC891_FIXUP_HEADSET_MODE] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_headset_mode,
- },
- [ALC891_FIXUP_DELL_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x03a1913d }, /* use as headphone mic, without its own jack detect */
- { 0x1b, 0x03a1113c }, /* use as headset mic, without its own jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC891_FIXUP_HEADSET_MODE
- },
- [ALC662_FIXUP_ACER_VERITON] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x15, 0x50170120 }, /* no internal speaker */
- { }
- }
- },
- [ALC892_FIXUP_ASROCK_MOBO] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x15, 0x40f000f0 }, /* disabled */
- { 0x16, 0x40f000f0 }, /* disabled */
- { }
- }
- },
- [ALC662_FIXUP_USI_FUNC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc662_fixup_usi_headset_mic,
- },
- [ALC662_FIXUP_USI_HEADSET_MODE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x02a1913c }, /* use as headset mic, without its own jack detect */
- { 0x18, 0x01a1903d },
- { }
- },
- .chained = true,
- .chain_id = ALC662_FIXUP_USI_FUNC
- },
- [ALC662_FIXUP_LENOVO_MULTI_CODECS] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc233_alc662_fixup_lenovo_dual_codecs,
- },
- [ALC669_FIXUP_ACER_ASPIRE_ETHOS_HEADSET] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc662_fixup_aspire_ethos_hp,
- },
- [ALC669_FIXUP_ACER_ASPIRE_ETHOS] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x15, 0x92130110 }, /* front speakers */
- { 0x18, 0x99130111 }, /* center/subwoofer */
- { 0x1b, 0x11130012 }, /* surround plus jack for HP */
- { }
- },
- .chained = true,
- .chain_id = ALC669_FIXUP_ACER_ASPIRE_ETHOS_HEADSET
- },
- [ALC671_FIXUP_HP_HEADSET_MIC2] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc671_fixup_hp_headset_mic2,
- },
- [ALC662_FIXUP_ACER_X2660G_HEADSET_MODE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1a, 0x02a1113c }, /* use as headset mic, without its own jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC662_FIXUP_USI_FUNC
- },
- [ALC662_FIXUP_ACER_NITRO_HEADSET_MODE] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1a, 0x01a11140 }, /* use as headset mic, without its own jack detect */
- { 0x1b, 0x0221144f },
- { }
- },
- .chained = true,
- .chain_id = ALC662_FIXUP_USI_FUNC
- },
- [ALC668_FIXUP_ASUS_NO_HEADSET_MIC] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1b, 0x04a1112c },
- { }
- },
- .chained = true,
- .chain_id = ALC668_FIXUP_HEADSET_MIC
- },
- [ALC668_FIXUP_HEADSET_MIC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc269_fixup_headset_mic,
- .chained = true,
- .chain_id = ALC668_FIXUP_MIC_DET_COEF
- },
- [ALC668_FIXUP_MIC_DET_COEF] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x15 },
- { 0x20, AC_VERB_SET_PROC_COEF, 0x0d60 },
- {}
- },
- },
- [ALC897_FIXUP_LENOVO_HEADSET_MIC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc897_fixup_lenovo_headset_mic,
- },
- [ALC897_FIXUP_HEADSET_MIC_PIN] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1a, 0x03a11050 },
- { }
- },
- .chained = true,
- .chain_id = ALC897_FIXUP_LENOVO_HEADSET_MIC
- },
- [ALC897_FIXUP_HP_HSMIC_VERB] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
- { }
- },
- },
- [ALC897_FIXUP_LENOVO_HEADSET_MODE] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc897_fixup_lenovo_headset_mode,
- },
- [ALC897_FIXUP_HEADSET_MIC_PIN2] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x1a, 0x01a11140 }, /* use as headset mic, without its own jack detect */
- { }
- },
- .chained = true,
- .chain_id = ALC897_FIXUP_LENOVO_HEADSET_MODE
- },
- [ALC897_FIXUP_UNIS_H3C_X500S] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- { 0x14, AC_VERB_SET_EAPD_BTLENABLE, 0 },
- {}
- },
- },
- [ALC897_FIXUP_HEADSET_MIC_PIN3] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x03a11050 }, /* use as headset mic */
- { }
- },
- },
-};
-
-static const struct hda_quirk alc662_fixup_tbl[] = {
- SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_FIXUP_ASUS_MODE2),
- SND_PCI_QUIRK(0x1019, 0x9859, "JP-IK LEAP W502", ALC897_FIXUP_HEADSET_MIC_PIN3),
- SND_PCI_QUIRK(0x1025, 0x022f, "Acer Aspire One", ALC662_FIXUP_INV_DMIC),
- SND_PCI_QUIRK(0x1025, 0x0241, "Packard Bell DOTS", ALC662_FIXUP_INV_DMIC),
- SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
- SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
- SND_PCI_QUIRK(0x1025, 0x0349, "eMachines eM250", ALC662_FIXUP_INV_DMIC),
- SND_PCI_QUIRK(0x1025, 0x034a, "Gateway LT27", ALC662_FIXUP_INV_DMIC),
- SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
- SND_PCI_QUIRK(0x1025, 0x0566, "Acer Aspire Ethos 8951G", ALC669_FIXUP_ACER_ASPIRE_ETHOS),
- SND_PCI_QUIRK(0x1025, 0x123c, "Acer Nitro N50-600", ALC662_FIXUP_ACER_NITRO_HEADSET_MODE),
- SND_PCI_QUIRK(0x1025, 0x124e, "Acer 2660G", ALC662_FIXUP_ACER_X2660G_HEADSET_MODE),
- SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1028, 0x05fe, "Dell XPS 15", ALC668_FIXUP_DELL_XPS13),
- SND_PCI_QUIRK(0x1028, 0x060a, "Dell XPS 13", ALC668_FIXUP_DELL_XPS13),
- SND_PCI_QUIRK(0x1028, 0x060d, "Dell M3800", ALC668_FIXUP_DELL_XPS13),
- SND_PCI_QUIRK(0x1028, 0x0625, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1028, 0x0626, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1028, 0x0696, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1028, 0x0698, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x1028, 0x069f, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
- SND_PCI_QUIRK(0x103c, 0x870c, "HP", ALC897_FIXUP_HP_HSMIC_VERB),
- SND_PCI_QUIRK(0x103c, 0x8719, "HP", ALC897_FIXUP_HP_HSMIC_VERB),
- SND_PCI_QUIRK(0x103c, 0x872b, "HP", ALC897_FIXUP_HP_HSMIC_VERB),
- SND_PCI_QUIRK(0x103c, 0x873e, "HP", ALC671_FIXUP_HP_HEADSET_MIC2),
- SND_PCI_QUIRK(0x103c, 0x8768, "HP Slim Desktop S01", ALC671_FIXUP_HP_HEADSET_MIC2),
- SND_PCI_QUIRK(0x103c, 0x877e, "HP 288 Pro G6", ALC671_FIXUP_HP_HEADSET_MIC2),
- SND_PCI_QUIRK(0x103c, 0x885f, "HP 288 Pro G8", ALC671_FIXUP_HP_HEADSET_MIC2),
- SND_PCI_QUIRK(0x1043, 0x1080, "Asus UX501VW", ALC668_FIXUP_HEADSET_MODE),
- SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_ASUS_Nx50),
- SND_PCI_QUIRK(0x1043, 0x129d, "Asus N750", ALC662_FIXUP_ASUS_Nx50),
- SND_PCI_QUIRK(0x1043, 0x12ff, "ASUS G751", ALC668_FIXUP_ASUS_G751),
- SND_PCI_QUIRK(0x1043, 0x13df, "Asus N550JX", ALC662_FIXUP_BASS_1A),
- SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_MODE4_CHMAP),
- SND_PCI_QUIRK(0x1043, 0x15a7, "ASUS UX51VZH", ALC662_FIXUP_BASS_16),
- SND_PCI_QUIRK(0x1043, 0x177d, "ASUS N551", ALC668_FIXUP_ASUS_Nx51),
- SND_PCI_QUIRK(0x1043, 0x17bd, "ASUS N751", ALC668_FIXUP_ASUS_Nx51),
- SND_PCI_QUIRK(0x1043, 0x185d, "ASUS G551JW", ALC668_FIXUP_ASUS_NO_HEADSET_MIC),
- SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71SL", ALC662_FIXUP_ASUS_MODE8),
- SND_PCI_QUIRK(0x1043, 0x1b73, "ASUS N55SF", ALC662_FIXUP_BASS_16),
- SND_PCI_QUIRK(0x1043, 0x1bf3, "ASUS N76VZ", ALC662_FIXUP_BASS_MODE4_CHMAP),
- SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT),
- SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2),
- SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
- SND_PCI_QUIRK(0x14cd, 0x5003, "USI", ALC662_FIXUP_USI_HEADSET_MODE),
- SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC662_FIXUP_LENOVO_MULTI_CODECS),
- SND_PCI_QUIRK(0x17aa, 0x1057, "Lenovo P360", ALC897_FIXUP_HEADSET_MIC_PIN),
- SND_PCI_QUIRK(0x17aa, 0x1064, "Lenovo P3 Tower", ALC897_FIXUP_HEADSET_MIC_PIN),
- SND_PCI_QUIRK(0x17aa, 0x32ca, "Lenovo ThinkCentre M80", ALC897_FIXUP_HEADSET_MIC_PIN),
- SND_PCI_QUIRK(0x17aa, 0x32cb, "Lenovo ThinkCentre M70", ALC897_FIXUP_HEADSET_MIC_PIN),
- SND_PCI_QUIRK(0x17aa, 0x32cf, "Lenovo ThinkCentre M950", ALC897_FIXUP_HEADSET_MIC_PIN),
- SND_PCI_QUIRK(0x17aa, 0x32f7, "Lenovo ThinkCentre M90", ALC897_FIXUP_HEADSET_MIC_PIN),
- SND_PCI_QUIRK(0x17aa, 0x3321, "Lenovo ThinkCentre M70 Gen4", ALC897_FIXUP_HEADSET_MIC_PIN),
- SND_PCI_QUIRK(0x17aa, 0x331b, "Lenovo ThinkCentre M90 Gen4", ALC897_FIXUP_HEADSET_MIC_PIN),
- SND_PCI_QUIRK(0x17aa, 0x3364, "Lenovo ThinkCentre M90 Gen5", ALC897_FIXUP_HEADSET_MIC_PIN),
- SND_PCI_QUIRK(0x17aa, 0x3742, "Lenovo TianYi510Pro-14IOB", ALC897_FIXUP_HEADSET_MIC_PIN2),
- SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
- SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
- SND_PCI_QUIRK(0x1849, 0x5892, "ASRock B150M", ALC892_FIXUP_ASROCK_MOBO),
- SND_PCI_QUIRK(0x19da, 0xa130, "Zotac Z68", ALC662_FIXUP_ZOTAC_Z68),
- SND_PCI_QUIRK(0x1b0a, 0x01b8, "ACER Veriton", ALC662_FIXUP_ACER_VERITON),
- SND_PCI_QUIRK(0x1b35, 0x1234, "CZC ET26", ALC662_FIXUP_CZC_ET26),
- SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T),
- SND_PCI_QUIRK(0x1c6c, 0x1239, "Compaq N14JP6-V2", ALC897_FIXUP_HP_HSMIC_VERB),
-
-#if 0
- /* Below is a quirk table taken from the old code.
- * Basically the device should work as is without the fixup table.
- * If BIOS doesn't give a proper info, enable the corresponding
- * fixup entry.
- */
- SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC662_FIXUP_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC662_FIXUP_ASUS_MODE3),
- SND_PCI_QUIRK(0x1043, 0x1173, "ASUS K73Jn", ALC662_FIXUP_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC662_FIXUP_ASUS_MODE3),
- SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
- SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x1303, "ASUS G60J", ALC662_FIXUP_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x1333, "ASUS G60Jx", ALC662_FIXUP_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
- SND_PCI_QUIRK(0x1043, 0x13e3, "ASUS N71JA", ALC662_FIXUP_ASUS_MODE7),
- SND_PCI_QUIRK(0x1043, 0x1463, "ASUS N71", ALC662_FIXUP_ASUS_MODE7),
- SND_PCI_QUIRK(0x1043, 0x14d3, "ASUS G72", ALC662_FIXUP_ASUS_MODE8),
- SND_PCI_QUIRK(0x1043, 0x1563, "ASUS N90", ALC662_FIXUP_ASUS_MODE3),
- SND_PCI_QUIRK(0x1043, 0x15d3, "ASUS N50SF F50SF", ALC662_FIXUP_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x16c3, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
- SND_PCI_QUIRK(0x1043, 0x16f3, "ASUS K40C K50C", ALC662_FIXUP_ASUS_MODE2),
- SND_PCI_QUIRK(0x1043, 0x1733, "ASUS N81De", ALC662_FIXUP_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x1753, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
- SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC662_FIXUP_ASUS_MODE6),
- SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC662_FIXUP_ASUS_MODE6),
- SND_PCI_QUIRK(0x1043, 0x1783, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
- SND_PCI_QUIRK(0x1043, 0x1793, "ASUS F50GX", ALC662_FIXUP_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x17b3, "ASUS F70SL", ALC662_FIXUP_ASUS_MODE3),
- SND_PCI_QUIRK(0x1043, 0x17f3, "ASUS X58LE", ALC662_FIXUP_ASUS_MODE2),
- SND_PCI_QUIRK(0x1043, 0x1813, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
- SND_PCI_QUIRK(0x1043, 0x1823, "ASUS NB", ALC662_FIXUP_ASUS_MODE5),
- SND_PCI_QUIRK(0x1043, 0x1833, "ASUS NB", ALC662_FIXUP_ASUS_MODE6),
- SND_PCI_QUIRK(0x1043, 0x1843, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
- SND_PCI_QUIRK(0x1043, 0x1853, "ASUS F50Z", ALC662_FIXUP_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x1864, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
- SND_PCI_QUIRK(0x1043, 0x1876, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
- SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC662_FIXUP_ASUS_MODE3),
- SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC662_FIXUP_ASUS_MODE3),
- SND_PCI_QUIRK(0x1043, 0x18b3, "ASUS N80Vc", ALC662_FIXUP_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x18c3, "ASUS VX5", ALC662_FIXUP_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS N81Te", ALC662_FIXUP_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x18f3, "ASUS N505Tp", ALC662_FIXUP_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC662_FIXUP_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x1913, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
- SND_PCI_QUIRK(0x1043, 0x1933, "ASUS F80Q", ALC662_FIXUP_ASUS_MODE2),
- SND_PCI_QUIRK(0x1043, 0x1943, "ASUS Vx3V", ALC662_FIXUP_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x1953, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71C", ALC662_FIXUP_ASUS_MODE3),
- SND_PCI_QUIRK(0x1043, 0x1983, "ASUS N5051A", ALC662_FIXUP_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x1993, "ASUS N20", ALC662_FIXUP_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS F7Z", ALC662_FIXUP_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x19c3, "ASUS F5Z/F6x", ALC662_FIXUP_ASUS_MODE2),
- SND_PCI_QUIRK(0x1043, 0x19e3, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x19f3, "ASUS NB", ALC662_FIXUP_ASUS_MODE4),
-#endif
- {}
-};
-
-static const struct hda_model_fixup alc662_fixup_models[] = {
- {.id = ALC662_FIXUP_ASPIRE, .name = "aspire"},
- {.id = ALC662_FIXUP_IDEAPAD, .name = "ideapad"},
- {.id = ALC272_FIXUP_MARIO, .name = "mario"},
- {.id = ALC662_FIXUP_HP_RP5800, .name = "hp-rp5800"},
- {.id = ALC662_FIXUP_ASUS_MODE1, .name = "asus-mode1"},
- {.id = ALC662_FIXUP_ASUS_MODE2, .name = "asus-mode2"},
- {.id = ALC662_FIXUP_ASUS_MODE3, .name = "asus-mode3"},
- {.id = ALC662_FIXUP_ASUS_MODE4, .name = "asus-mode4"},
- {.id = ALC662_FIXUP_ASUS_MODE5, .name = "asus-mode5"},
- {.id = ALC662_FIXUP_ASUS_MODE6, .name = "asus-mode6"},
- {.id = ALC662_FIXUP_ASUS_MODE7, .name = "asus-mode7"},
- {.id = ALC662_FIXUP_ASUS_MODE8, .name = "asus-mode8"},
- {.id = ALC662_FIXUP_ZOTAC_Z68, .name = "zotac-z68"},
- {.id = ALC662_FIXUP_INV_DMIC, .name = "inv-dmic"},
- {.id = ALC662_FIXUP_DELL_MIC_NO_PRESENCE, .name = "alc662-headset-multi"},
- {.id = ALC668_FIXUP_DELL_MIC_NO_PRESENCE, .name = "dell-headset-multi"},
- {.id = ALC662_FIXUP_HEADSET_MODE, .name = "alc662-headset"},
- {.id = ALC668_FIXUP_HEADSET_MODE, .name = "alc668-headset"},
- {.id = ALC662_FIXUP_BASS_16, .name = "bass16"},
- {.id = ALC662_FIXUP_BASS_1A, .name = "bass1a"},
- {.id = ALC668_FIXUP_AUTO_MUTE, .name = "automute"},
- {.id = ALC668_FIXUP_DELL_XPS13, .name = "dell-xps13"},
- {.id = ALC662_FIXUP_ASUS_Nx50, .name = "asus-nx50"},
- {.id = ALC668_FIXUP_ASUS_Nx51, .name = "asus-nx51"},
- {.id = ALC668_FIXUP_ASUS_G751, .name = "asus-g751"},
- {.id = ALC891_FIXUP_HEADSET_MODE, .name = "alc891-headset"},
- {.id = ALC891_FIXUP_DELL_MIC_NO_PRESENCE, .name = "alc891-headset-multi"},
- {.id = ALC662_FIXUP_ACER_VERITON, .name = "acer-veriton"},
- {.id = ALC892_FIXUP_ASROCK_MOBO, .name = "asrock-mobo"},
- {.id = ALC662_FIXUP_USI_HEADSET_MODE, .name = "usi-headset"},
- {.id = ALC662_FIXUP_LENOVO_MULTI_CODECS, .name = "dual-codecs"},
- {.id = ALC669_FIXUP_ACER_ASPIRE_ETHOS, .name = "aspire-ethos"},
- {.id = ALC897_FIXUP_UNIS_H3C_X500S, .name = "unis-h3c-x500s"},
- {}
-};
-
-static const struct snd_hda_pin_quirk alc662_pin_fixup_tbl[] = {
- SND_HDA_PIN_QUIRK(0x10ec0867, 0x1028, "Dell", ALC891_FIXUP_DELL_MIC_NO_PRESENCE,
- {0x17, 0x02211010},
- {0x18, 0x01a19030},
- {0x1a, 0x01813040},
- {0x21, 0x01014020}),
- SND_HDA_PIN_QUIRK(0x10ec0867, 0x1028, "Dell", ALC891_FIXUP_DELL_MIC_NO_PRESENCE,
- {0x16, 0x01813030},
- {0x17, 0x02211010},
- {0x18, 0x01a19040},
- {0x21, 0x01014020}),
- SND_HDA_PIN_QUIRK(0x10ec0662, 0x1028, "Dell", ALC662_FIXUP_DELL_MIC_NO_PRESENCE,
- {0x14, 0x01014010},
- {0x18, 0x01a19020},
- {0x1a, 0x0181302f},
- {0x1b, 0x0221401f}),
- SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell", ALC668_FIXUP_AUTO_MUTE,
- {0x12, 0x99a30130},
- {0x14, 0x90170110},
- {0x15, 0x0321101f},
- {0x16, 0x03011020}),
- SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell", ALC668_FIXUP_AUTO_MUTE,
- {0x12, 0x99a30140},
- {0x14, 0x90170110},
- {0x15, 0x0321101f},
- {0x16, 0x03011020}),
- SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell", ALC668_FIXUP_AUTO_MUTE,
- {0x12, 0x99a30150},
- {0x14, 0x90170110},
- {0x15, 0x0321101f},
- {0x16, 0x03011020}),
- SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell", ALC668_FIXUP_AUTO_MUTE,
- {0x14, 0x90170110},
- {0x15, 0x0321101f},
- {0x16, 0x03011020}),
- SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell XPS 15", ALC668_FIXUP_AUTO_MUTE,
- {0x12, 0x90a60130},
- {0x14, 0x90170110},
- {0x15, 0x0321101f}),
- SND_HDA_PIN_QUIRK(0x10ec0671, 0x103c, "HP cPC", ALC671_FIXUP_HP_HEADSET_MIC2,
- {0x14, 0x01014010},
- {0x17, 0x90170150},
- {0x19, 0x02a11060},
- {0x1b, 0x01813030},
- {0x21, 0x02211020}),
- SND_HDA_PIN_QUIRK(0x10ec0671, 0x103c, "HP cPC", ALC671_FIXUP_HP_HEADSET_MIC2,
- {0x14, 0x01014010},
- {0x18, 0x01a19040},
- {0x1b, 0x01813030},
- {0x21, 0x02211020}),
- SND_HDA_PIN_QUIRK(0x10ec0671, 0x103c, "HP cPC", ALC671_FIXUP_HP_HEADSET_MIC2,
- {0x14, 0x01014020},
- {0x17, 0x90170110},
- {0x18, 0x01a19050},
- {0x1b, 0x01813040},
- {0x21, 0x02211030}),
- {}
-};
-
-/*
- */
-static int patch_alc662(struct hda_codec *codec)
-{
- struct alc_spec *spec;
- int err;
-
- err = alc_alloc_spec(codec, 0x0b);
- if (err < 0)
- return err;
-
- spec = codec->spec;
-
- spec->shutup = alc_eapd_shutup;
-
- /* handle multiple HPs as is */
- spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
-
- alc_fix_pll_init(codec, 0x20, 0x04, 15);
-
- switch (codec->core.vendor_id) {
- case 0x10ec0668:
- spec->init_hook = alc668_restore_default_value;
- break;
- }
-
- alc_pre_init(codec);
-
- snd_hda_pick_fixup(codec, alc662_fixup_models,
- alc662_fixup_tbl, alc662_fixups);
- snd_hda_pick_pin_fixup(codec, alc662_pin_fixup_tbl, alc662_fixups, true);
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
-
- alc_auto_parse_customize_define(codec);
-
- if (has_cdefine_beep(codec))
- spec->gen.beep_nid = 0x01;
-
- if ((alc_get_coef0(codec) & (1 << 14)) &&
- codec->bus->pci && codec->bus->pci->subsystem_vendor == 0x1025 &&
- spec->cdefine.platform_type == 1) {
- err = alc_codec_rename(codec, "ALC272X");
- if (err < 0)
- goto error;
- }
-
- /* automatic parse from the BIOS config */
- err = alc662_parse_auto_config(codec);
- if (err < 0)
- goto error;
-
- if (!spec->gen.no_analog && spec->gen.beep_nid) {
- switch (codec->core.vendor_id) {
- case 0x10ec0662:
- err = set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
- break;
- case 0x10ec0272:
- case 0x10ec0663:
- case 0x10ec0665:
- case 0x10ec0668:
- err = set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
- break;
- case 0x10ec0273:
- err = set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT);
- break;
- }
- if (err < 0)
- goto error;
- }
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
-
- return 0;
-
- error:
- alc_free(codec);
- return err;
-}
-
-/*
- * ALC680 support
- */
-
-static int alc680_parse_auto_config(struct hda_codec *codec)
-{
- return alc_parse_auto_config(codec, NULL, NULL);
-}
-
-/*
- */
-static int patch_alc680(struct hda_codec *codec)
-{
- int err;
-
- /* ALC680 has no aa-loopback mixer */
- err = alc_alloc_spec(codec, 0);
- if (err < 0)
- return err;
-
- /* automatic parse from the BIOS config */
- err = alc680_parse_auto_config(codec);
- if (err < 0) {
- alc_free(codec);
- return err;
- }
-
- return 0;
-}
-
-/*
- * patch entries
- */
-static const struct hda_device_id snd_hda_id_realtek[] = {
- HDA_CODEC_ENTRY(0x10ec0215, "ALC215", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0221, "ALC221", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0222, "ALC222", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0225, "ALC225", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0230, "ALC236", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0231, "ALC231", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0233, "ALC233", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0234, "ALC234", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0235, "ALC233", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0236, "ALC236", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0245, "ALC245", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0255, "ALC255", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0256, "ALC256", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0257, "ALC257", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0260, "ALC260", patch_alc260),
- HDA_CODEC_ENTRY(0x10ec0262, "ALC262", patch_alc262),
- HDA_CODEC_ENTRY(0x10ec0267, "ALC267", patch_alc268),
- HDA_CODEC_ENTRY(0x10ec0268, "ALC268", patch_alc268),
- HDA_CODEC_ENTRY(0x10ec0269, "ALC269", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0270, "ALC270", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0272, "ALC272", patch_alc662),
- HDA_CODEC_ENTRY(0x10ec0274, "ALC274", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0275, "ALC275", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0276, "ALC276", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0280, "ALC280", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0282, "ALC282", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0283, "ALC283", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0284, "ALC284", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0285, "ALC285", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0286, "ALC286", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0287, "ALC287", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0288, "ALC288", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0289, "ALC289", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0290, "ALC290", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0292, "ALC292", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0293, "ALC293", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0294, "ALC294", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0295, "ALC295", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0298, "ALC298", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0299, "ALC299", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0300, "ALC300", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0623, "ALC623", patch_alc269),
- HDA_CODEC_REV_ENTRY(0x10ec0861, 0x100340, "ALC660", patch_alc861),
- HDA_CODEC_ENTRY(0x10ec0660, "ALC660-VD", patch_alc861vd),
- HDA_CODEC_ENTRY(0x10ec0861, "ALC861", patch_alc861),
- HDA_CODEC_ENTRY(0x10ec0862, "ALC861-VD", patch_alc861vd),
- HDA_CODEC_REV_ENTRY(0x10ec0662, 0x100002, "ALC662 rev2", patch_alc882),
- HDA_CODEC_REV_ENTRY(0x10ec0662, 0x100101, "ALC662 rev1", patch_alc662),
- HDA_CODEC_REV_ENTRY(0x10ec0662, 0x100300, "ALC662 rev3", patch_alc662),
- HDA_CODEC_ENTRY(0x10ec0663, "ALC663", patch_alc662),
- HDA_CODEC_ENTRY(0x10ec0665, "ALC665", patch_alc662),
- HDA_CODEC_ENTRY(0x10ec0667, "ALC667", patch_alc662),
- HDA_CODEC_ENTRY(0x10ec0668, "ALC668", patch_alc662),
- HDA_CODEC_ENTRY(0x10ec0670, "ALC670", patch_alc662),
- HDA_CODEC_ENTRY(0x10ec0671, "ALC671", patch_alc662),
- HDA_CODEC_ENTRY(0x10ec0680, "ALC680", patch_alc680),
- HDA_CODEC_ENTRY(0x10ec0700, "ALC700", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0701, "ALC701", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0703, "ALC703", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0711, "ALC711", patch_alc269),
- HDA_CODEC_ENTRY(0x10ec0867, "ALC891", patch_alc662),
- HDA_CODEC_ENTRY(0x10ec0880, "ALC880", patch_alc880),
- HDA_CODEC_ENTRY(0x10ec0882, "ALC882", patch_alc882),
- HDA_CODEC_ENTRY(0x10ec0883, "ALC883", patch_alc882),
- HDA_CODEC_REV_ENTRY(0x10ec0885, 0x100101, "ALC889A", patch_alc882),
- HDA_CODEC_REV_ENTRY(0x10ec0885, 0x100103, "ALC889A", patch_alc882),
- HDA_CODEC_ENTRY(0x10ec0885, "ALC885", patch_alc882),
- HDA_CODEC_ENTRY(0x10ec0887, "ALC887", patch_alc882),
- HDA_CODEC_REV_ENTRY(0x10ec0888, 0x100101, "ALC1200", patch_alc882),
- HDA_CODEC_ENTRY(0x10ec0888, "ALC888", patch_alc882),
- HDA_CODEC_ENTRY(0x10ec0889, "ALC889", patch_alc882),
- HDA_CODEC_ENTRY(0x10ec0892, "ALC892", patch_alc662),
- HDA_CODEC_ENTRY(0x10ec0897, "ALC897", patch_alc662),
- HDA_CODEC_ENTRY(0x10ec0899, "ALC898", patch_alc882),
- HDA_CODEC_ENTRY(0x10ec0900, "ALC1150", patch_alc882),
- HDA_CODEC_ENTRY(0x10ec0b00, "ALCS1200A", patch_alc882),
- HDA_CODEC_ENTRY(0x10ec1168, "ALC1220", patch_alc882),
- HDA_CODEC_ENTRY(0x10ec1220, "ALC1220", patch_alc882),
- HDA_CODEC_ENTRY(0x19e58326, "HW8326", patch_alc269),
- {} /* terminator */
-};
-MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_realtek);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Realtek HD-audio codec");
-MODULE_IMPORT_NS("SND_HDA_SCODEC_COMPONENT");
-
-static struct hda_codec_driver realtek_driver = {
- .id = snd_hda_id_realtek,
-};
-
-module_hda_codec_driver(realtek_driver);
diff --git a/sound/pci/hda/patch_senarytech.c b/sound/pci/hda/patch_senarytech.c
deleted file mode 100644
index 0691996fa971..000000000000
--- a/sound/pci/hda/patch_senarytech.c
+++ /dev/null
@@ -1,244 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * HD audio interface patch for Senary HDA audio codec
- *
- * Initially based on sound/pci/hda/patch_conexant.c
- */
-
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <sound/core.h>
-#include <sound/jack.h>
-
-#include <sound/hda_codec.h>
-#include "hda_local.h"
-#include "hda_auto_parser.h"
-#include "hda_beep.h"
-#include "hda_jack.h"
-#include "hda_generic.h"
-
-struct senary_spec {
- struct hda_gen_spec gen;
-
- /* extra EAPD pins */
- unsigned int num_eapds;
- hda_nid_t eapds[4];
- hda_nid_t mute_led_eapd;
-
- unsigned int parse_flags; /* flag for snd_hda_parse_pin_defcfg() */
-
- int mute_led_polarity;
- unsigned int gpio_led;
- unsigned int gpio_mute_led_mask;
- unsigned int gpio_mic_led_mask;
-};
-
-#ifdef CONFIG_SND_HDA_INPUT_BEEP
-/* additional beep mixers; private_value will be overwritten */
-static const struct snd_kcontrol_new senary_beep_mixer[] = {
- HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0, 1, 0, HDA_OUTPUT),
- HDA_CODEC_MUTE_BEEP_MONO("Beep Playback Switch", 0, 1, 0, HDA_OUTPUT),
-};
-
-static int set_beep_amp(struct senary_spec *spec, hda_nid_t nid,
- int idx, int dir)
-{
- struct snd_kcontrol_new *knew;
- unsigned int beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir);
- int i;
-
- spec->gen.beep_nid = nid;
- for (i = 0; i < ARRAY_SIZE(senary_beep_mixer); i++) {
- knew = snd_hda_gen_add_kctl(&spec->gen, NULL,
- &senary_beep_mixer[i]);
- if (!knew)
- return -ENOMEM;
- knew->private_value = beep_amp;
- }
- return 0;
-}
-
-static int senary_auto_parse_beep(struct hda_codec *codec)
-{
- struct senary_spec *spec = codec->spec;
- hda_nid_t nid;
-
- for_each_hda_codec_node(nid, codec)
- if ((get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_BEEP) &&
- (get_wcaps(codec, nid) & (AC_WCAP_OUT_AMP | AC_WCAP_AMP_OVRD)))
- return set_beep_amp(spec, nid, 0, HDA_OUTPUT);
- return 0;
-}
-#else
-#define senary_auto_parse_beep(codec) 0
-#endif
-
-/* parse EAPDs */
-static void senary_auto_parse_eapd(struct hda_codec *codec)
-{
- struct senary_spec *spec = codec->spec;
- hda_nid_t nid;
-
- for_each_hda_codec_node(nid, codec) {
- if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
- continue;
- if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD))
- continue;
- spec->eapds[spec->num_eapds++] = nid;
- if (spec->num_eapds >= ARRAY_SIZE(spec->eapds))
- break;
- }
-}
-
-static void senary_auto_turn_eapd(struct hda_codec *codec, int num_pins,
- const hda_nid_t *pins, bool on)
-{
- int i;
-
- for (i = 0; i < num_pins; i++) {
- if (snd_hda_query_pin_caps(codec, pins[i]) & AC_PINCAP_EAPD)
- snd_hda_codec_write(codec, pins[i], 0,
- AC_VERB_SET_EAPD_BTLENABLE,
- on ? 0x02 : 0);
- }
-}
-
-/* turn on/off EAPD according to Master switch */
-static void senary_auto_vmaster_hook(void *private_data, int enabled)
-{
- struct hda_codec *codec = private_data;
- struct senary_spec *spec = codec->spec;
-
- senary_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, enabled);
-}
-
-static void senary_init_gpio_led(struct hda_codec *codec)
-{
- struct senary_spec *spec = codec->spec;
- unsigned int mask = spec->gpio_mute_led_mask | spec->gpio_mic_led_mask;
-
- if (mask) {
- snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_MASK,
- mask);
- snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DIRECTION,
- mask);
- snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
- spec->gpio_led);
- }
-}
-
-static int senary_auto_init(struct hda_codec *codec)
-{
- snd_hda_gen_init(codec);
- senary_init_gpio_led(codec);
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT);
-
- return 0;
-}
-
-static void senary_auto_shutdown(struct hda_codec *codec)
-{
- struct senary_spec *spec = codec->spec;
-
- /* Turn the problematic codec into D3 to avoid spurious noises
- * from the internal speaker during (and after) reboot
- */
- senary_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, false);
-}
-
-static void senary_auto_free(struct hda_codec *codec)
-{
- senary_auto_shutdown(codec);
- snd_hda_gen_free(codec);
-}
-
-static int senary_auto_suspend(struct hda_codec *codec)
-{
- senary_auto_shutdown(codec);
- return 0;
-}
-
-static const struct hda_codec_ops senary_auto_patch_ops = {
- .build_controls = snd_hda_gen_build_controls,
- .build_pcms = snd_hda_gen_build_pcms,
- .init = senary_auto_init,
- .free = senary_auto_free,
- .unsol_event = snd_hda_jack_unsol_event,
- .suspend = senary_auto_suspend,
- .check_power_status = snd_hda_gen_check_power_status,
-};
-
-static int patch_senary_auto(struct hda_codec *codec)
-{
- struct senary_spec *spec;
- int err;
-
- codec_info(codec, "%s: BIOS auto-probing.\n", codec->core.chip_name);
-
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (!spec)
- return -ENOMEM;
- snd_hda_gen_spec_init(&spec->gen);
- codec->spec = spec;
- codec->patch_ops = senary_auto_patch_ops;
-
- senary_auto_parse_eapd(codec);
- spec->gen.own_eapd_ctl = 1;
-
- if (!spec->gen.vmaster_mute.hook)
- spec->gen.vmaster_mute.hook = senary_auto_vmaster_hook;
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
-
- err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL,
- spec->parse_flags);
- if (err < 0)
- goto error;
-
- err = senary_auto_parse_beep(codec);
- if (err < 0)
- goto error;
-
- err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg);
- if (err < 0)
- goto error;
-
- /* Some laptops with Senary chips show stalls in S3 resume,
- * which falls into the single-cmd mode.
- * Better to make reset, then.
- */
- if (!codec->bus->core.sync_write) {
- codec_info(codec,
- "Enable sync_write for stable communication\n");
- codec->bus->core.sync_write = 1;
- codec->bus->allow_bus_reset = 1;
- }
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
-
- return 0;
-
- error:
- senary_auto_free(codec);
- return err;
-}
-
-/*
- */
-
-static const struct hda_device_id snd_hda_id_senary[] = {
- HDA_CODEC_ENTRY(0x1fa86186, "SN6186", patch_senary_auto),
- {} /* terminator */
-};
-MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_senary);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Senarytech HD-audio codec");
-
-static struct hda_codec_driver senary_driver = {
- .id = snd_hda_id_senary,
-};
-
-module_hda_codec_driver(senary_driver);
diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c
deleted file mode 100644
index 763eae80a148..000000000000
--- a/sound/pci/hda/patch_si3054.c
+++ /dev/null
@@ -1,304 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Universal Interface for Intel High Definition Audio Codec
- *
- * HD audio interface patch for Silicon Labs 3054/5 modem codec
- *
- * Copyright (c) 2005 Sasha Khapyorsky <sashak@alsa-project.org>
- * Takashi Iwai <tiwai@suse.de>
- */
-
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <sound/core.h>
-#include <sound/hda_codec.h>
-#include "hda_local.h"
-
-/* si3054 verbs */
-#define SI3054_VERB_READ_NODE 0x900
-#define SI3054_VERB_WRITE_NODE 0x100
-
-/* si3054 nodes (registers) */
-#define SI3054_EXTENDED_MID 2
-#define SI3054_LINE_RATE 3
-#define SI3054_LINE_LEVEL 4
-#define SI3054_GPIO_CFG 5
-#define SI3054_GPIO_POLARITY 6
-#define SI3054_GPIO_STICKY 7
-#define SI3054_GPIO_WAKEUP 8
-#define SI3054_GPIO_STATUS 9
-#define SI3054_GPIO_CONTROL 10
-#define SI3054_MISC_AFE 11
-#define SI3054_CHIPID 12
-#define SI3054_LINE_CFG1 13
-#define SI3054_LINE_STATUS 14
-#define SI3054_DC_TERMINATION 15
-#define SI3054_LINE_CONFIG 16
-#define SI3054_CALLPROG_ATT 17
-#define SI3054_SQ_CONTROL 18
-#define SI3054_MISC_CONTROL 19
-#define SI3054_RING_CTRL1 20
-#define SI3054_RING_CTRL2 21
-
-/* extended MID */
-#define SI3054_MEI_READY 0xf
-
-/* line level */
-#define SI3054_ATAG_MASK 0x00f0
-#define SI3054_DTAG_MASK 0xf000
-
-/* GPIO bits */
-#define SI3054_GPIO_OH 0x0001
-#define SI3054_GPIO_CID 0x0002
-
-/* chipid and revisions */
-#define SI3054_CHIPID_CODEC_REV_MASK 0x000f
-#define SI3054_CHIPID_DAA_REV_MASK 0x00f0
-#define SI3054_CHIPID_INTERNATIONAL 0x0100
-#define SI3054_CHIPID_DAA_ID 0x0f00
-#define SI3054_CHIPID_CODEC_ID (1<<12)
-
-/* si3054 codec registers (nodes) access macros */
-#define GET_REG(codec,reg) (snd_hda_codec_read(codec,reg,0,SI3054_VERB_READ_NODE,0))
-#define SET_REG(codec,reg,val) (snd_hda_codec_write(codec,reg,0,SI3054_VERB_WRITE_NODE,val))
-#define SET_REG_CACHE(codec,reg,val) \
- snd_hda_codec_write_cache(codec,reg,0,SI3054_VERB_WRITE_NODE,val)
-
-
-struct si3054_spec {
- unsigned international;
-};
-
-
-/*
- * Modem mixer
- */
-
-#define PRIVATE_VALUE(reg,mask) ((reg<<16)|(mask&0xffff))
-#define PRIVATE_REG(val) ((val>>16)&0xffff)
-#define PRIVATE_MASK(val) (val&0xffff)
-
-#define si3054_switch_info snd_ctl_boolean_mono_info
-
-static int si3054_switch_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *uvalue)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- u16 reg = PRIVATE_REG(kcontrol->private_value);
- u16 mask = PRIVATE_MASK(kcontrol->private_value);
- uvalue->value.integer.value[0] = (GET_REG(codec, reg)) & mask ? 1 : 0 ;
- return 0;
-}
-
-static int si3054_switch_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *uvalue)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- u16 reg = PRIVATE_REG(kcontrol->private_value);
- u16 mask = PRIVATE_MASK(kcontrol->private_value);
- if (uvalue->value.integer.value[0])
- SET_REG_CACHE(codec, reg, (GET_REG(codec, reg)) | mask);
- else
- SET_REG_CACHE(codec, reg, (GET_REG(codec, reg)) & ~mask);
- return 0;
-}
-
-#define SI3054_KCONTROL(kname,reg,mask) { \
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
- .name = kname, \
- .subdevice = HDA_SUBDEV_NID_FLAG | reg, \
- .info = si3054_switch_info, \
- .get = si3054_switch_get, \
- .put = si3054_switch_put, \
- .private_value = PRIVATE_VALUE(reg,mask), \
-}
-
-
-static const struct snd_kcontrol_new si3054_modem_mixer[] = {
- SI3054_KCONTROL("Off-hook Switch", SI3054_GPIO_CONTROL, SI3054_GPIO_OH),
- SI3054_KCONTROL("Caller ID Switch", SI3054_GPIO_CONTROL, SI3054_GPIO_CID),
- {}
-};
-
-static int si3054_build_controls(struct hda_codec *codec)
-{
- return snd_hda_add_new_ctls(codec, si3054_modem_mixer);
-}
-
-
-/*
- * PCM callbacks
- */
-
-static int si3054_pcm_prepare(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- unsigned int stream_tag,
- unsigned int format,
- struct snd_pcm_substream *substream)
-{
- u16 val;
-
- SET_REG(codec, SI3054_LINE_RATE, substream->runtime->rate);
- val = GET_REG(codec, SI3054_LINE_LEVEL);
- val &= 0xff << (8 * (substream->stream != SNDRV_PCM_STREAM_PLAYBACK));
- val |= ((stream_tag & 0xf) << 4) << (8 * (substream->stream == SNDRV_PCM_STREAM_PLAYBACK));
- SET_REG(codec, SI3054_LINE_LEVEL, val);
-
- snd_hda_codec_setup_stream(codec, hinfo->nid,
- stream_tag, 0, format);
- return 0;
-}
-
-static int si3054_pcm_open(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- static const unsigned int rates[] = { 8000, 9600, 16000 };
- static const struct snd_pcm_hw_constraint_list hw_constraints_rates = {
- .count = ARRAY_SIZE(rates),
- .list = rates,
- .mask = 0,
- };
- substream->runtime->hw.period_bytes_min = 80;
- return snd_pcm_hw_constraint_list(substream->runtime, 0,
- SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);
-}
-
-
-static const struct hda_pcm_stream si3054_pcm = {
- .substreams = 1,
- .channels_min = 1,
- .channels_max = 1,
- .nid = 0x1,
- .rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_KNOT,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- .maxbps = 16,
- .ops = {
- .open = si3054_pcm_open,
- .prepare = si3054_pcm_prepare,
- },
-};
-
-
-static int si3054_build_pcms(struct hda_codec *codec)
-{
- struct hda_pcm *info;
-
- info = snd_hda_codec_pcm_new(codec, "Si3054 Modem");
- if (!info)
- return -ENOMEM;
- info->stream[SNDRV_PCM_STREAM_PLAYBACK] = si3054_pcm;
- info->stream[SNDRV_PCM_STREAM_CAPTURE] = si3054_pcm;
- info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = codec->core.mfg;
- info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = codec->core.mfg;
- info->pcm_type = HDA_PCM_TYPE_MODEM;
- return 0;
-}
-
-
-/*
- * Init part
- */
-
-static int si3054_init(struct hda_codec *codec)
-{
- struct si3054_spec *spec = codec->spec;
- unsigned wait_count;
- u16 val;
-
- if (snd_hdac_regmap_add_vendor_verb(&codec->core,
- SI3054_VERB_WRITE_NODE))
- return -ENOMEM;
-
- snd_hda_codec_write(codec, AC_NODE_ROOT, 0, AC_VERB_SET_CODEC_RESET, 0);
- snd_hda_codec_write(codec, codec->core.mfg, 0, AC_VERB_SET_STREAM_FORMAT, 0);
- SET_REG(codec, SI3054_LINE_RATE, 9600);
- SET_REG(codec, SI3054_LINE_LEVEL, SI3054_DTAG_MASK|SI3054_ATAG_MASK);
- SET_REG(codec, SI3054_EXTENDED_MID, 0);
-
- wait_count = 10;
- do {
- msleep(2);
- val = GET_REG(codec, SI3054_EXTENDED_MID);
- } while ((val & SI3054_MEI_READY) != SI3054_MEI_READY && wait_count--);
-
- if((val&SI3054_MEI_READY) != SI3054_MEI_READY) {
- codec_err(codec, "si3054: cannot initialize. EXT MID = %04x\n", val);
- /* let's pray that this is no fatal error */
- /* return -EACCES; */
- }
-
- SET_REG(codec, SI3054_GPIO_POLARITY, 0xffff);
- SET_REG(codec, SI3054_GPIO_CFG, 0x0);
- SET_REG(codec, SI3054_MISC_AFE, 0);
- SET_REG(codec, SI3054_LINE_CFG1,0x200);
-
- if((GET_REG(codec,SI3054_LINE_STATUS) & (1<<6)) == 0) {
- codec_dbg(codec,
- "Link Frame Detect(FDT) is not ready (line status: %04x)\n",
- GET_REG(codec,SI3054_LINE_STATUS));
- }
-
- spec->international = GET_REG(codec, SI3054_CHIPID) & SI3054_CHIPID_INTERNATIONAL;
-
- return 0;
-}
-
-static void si3054_free(struct hda_codec *codec)
-{
- kfree(codec->spec);
-}
-
-
-/*
- */
-
-static const struct hda_codec_ops si3054_patch_ops = {
- .build_controls = si3054_build_controls,
- .build_pcms = si3054_build_pcms,
- .init = si3054_init,
- .free = si3054_free,
-};
-
-static int patch_si3054(struct hda_codec *codec)
-{
- struct si3054_spec *spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
- return -ENOMEM;
- codec->spec = spec;
- codec->patch_ops = si3054_patch_ops;
- return 0;
-}
-
-/*
- * patch entries
- */
-static const struct hda_device_id snd_hda_id_si3054[] = {
- HDA_CODEC_ENTRY(0x163c3055, "Si3054", patch_si3054),
- HDA_CODEC_ENTRY(0x163c3155, "Si3054", patch_si3054),
- HDA_CODEC_ENTRY(0x11c13026, "Si3054", patch_si3054),
- HDA_CODEC_ENTRY(0x11c13055, "Si3054", patch_si3054),
- HDA_CODEC_ENTRY(0x11c13155, "Si3054", patch_si3054),
- HDA_CODEC_ENTRY(0x10573055, "Si3054", patch_si3054),
- HDA_CODEC_ENTRY(0x10573057, "Si3054", patch_si3054),
- HDA_CODEC_ENTRY(0x10573155, "Si3054", patch_si3054),
- /* VIA HDA on Clevo m540 */
- HDA_CODEC_ENTRY(0x11063288, "Si3054", patch_si3054),
- /* Asus A8J Modem (SM56) */
- HDA_CODEC_ENTRY(0x15433155, "Si3054", patch_si3054),
- /* LG LW20 modem */
- HDA_CODEC_ENTRY(0x18540018, "Si3054", patch_si3054),
- {}
-};
-MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_si3054);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Si3054 HD-audio modem codec");
-
-static struct hda_codec_driver si3054_driver = {
- .id = snd_hda_id_si3054,
-};
-
-module_hda_codec_driver(si3054_driver);
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
deleted file mode 100644
index bde6b7373858..000000000000
--- a/sound/pci/hda/patch_sigmatel.c
+++ /dev/null
@@ -1,5161 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Universal Interface for Intel High Definition Audio Codec
- *
- * HD audio interface patch for SigmaTel STAC92xx
- *
- * Copyright (c) 2005 Embedded Alley Solutions, Inc.
- * Matt Porter <mporter@embeddedalley.com>
- *
- * Based on patch_cmedia.c and patch_realtek.c
- * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
- */
-
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/pci.h>
-#include <linux/dmi.h>
-#include <linux/module.h>
-#include <sound/core.h>
-#include <sound/jack.h>
-#include <sound/hda_codec.h>
-#include "hda_local.h"
-#include "hda_auto_parser.h"
-#include "hda_beep.h"
-#include "hda_jack.h"
-#include "hda_generic.h"
-
-enum {
- STAC_REF,
- STAC_9200_OQO,
- STAC_9200_DELL_D21,
- STAC_9200_DELL_D22,
- STAC_9200_DELL_D23,
- STAC_9200_DELL_M21,
- STAC_9200_DELL_M22,
- STAC_9200_DELL_M23,
- STAC_9200_DELL_M24,
- STAC_9200_DELL_M25,
- STAC_9200_DELL_M26,
- STAC_9200_DELL_M27,
- STAC_9200_M4,
- STAC_9200_M4_2,
- STAC_9200_PANASONIC,
- STAC_9200_EAPD_INIT,
- STAC_9200_MODELS
-};
-
-enum {
- STAC_9205_REF,
- STAC_9205_DELL_M42,
- STAC_9205_DELL_M43,
- STAC_9205_DELL_M44,
- STAC_9205_EAPD,
- STAC_9205_MODELS
-};
-
-enum {
- STAC_92HD73XX_NO_JD, /* no jack-detection */
- STAC_92HD73XX_REF,
- STAC_92HD73XX_INTEL,
- STAC_DELL_M6_AMIC,
- STAC_DELL_M6_DMIC,
- STAC_DELL_M6_BOTH,
- STAC_DELL_EQ,
- STAC_ALIENWARE_M17X,
- STAC_ELO_VUPOINT_15MX,
- STAC_92HD89XX_HP_FRONT_JACK,
- STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK,
- STAC_92HD73XX_ASUS_MOBO,
- STAC_92HD73XX_MODELS
-};
-
-enum {
- STAC_92HD83XXX_REF,
- STAC_92HD83XXX_PWR_REF,
- STAC_DELL_S14,
- STAC_DELL_VOSTRO_3500,
- STAC_92HD83XXX_HP_cNB11_INTQUAD,
- STAC_HP_DV7_4000,
- STAC_HP_ZEPHYR,
- STAC_92HD83XXX_HP_LED,
- STAC_92HD83XXX_HP_INV_LED,
- STAC_92HD83XXX_HP_MIC_LED,
- STAC_HP_LED_GPIO10,
- STAC_92HD83XXX_HEADSET_JACK,
- STAC_92HD83XXX_HP,
- STAC_HP_ENVY_BASS,
- STAC_HP_BNB13_EQ,
- STAC_HP_ENVY_TS_BASS,
- STAC_HP_ENVY_TS_DAC_BIND,
- STAC_92HD83XXX_GPIO10_EAPD,
- STAC_92HD83XXX_MODELS
-};
-
-enum {
- STAC_92HD71BXX_REF,
- STAC_DELL_M4_1,
- STAC_DELL_M4_2,
- STAC_DELL_M4_3,
- STAC_HP_M4,
- STAC_HP_DV4,
- STAC_HP_DV5,
- STAC_HP_HDX,
- STAC_92HD71BXX_HP,
- STAC_92HD71BXX_NO_DMIC,
- STAC_92HD71BXX_NO_SMUX,
- STAC_92HD71BXX_MODELS
-};
-
-enum {
- STAC_92HD95_HP_LED,
- STAC_92HD95_HP_BASS,
- STAC_92HD95_MODELS
-};
-
-enum {
- STAC_925x_REF,
- STAC_M1,
- STAC_M1_2,
- STAC_M2,
- STAC_M2_2,
- STAC_M3,
- STAC_M5,
- STAC_M6,
- STAC_925x_MODELS
-};
-
-enum {
- STAC_D945_REF,
- STAC_D945GTP3,
- STAC_D945GTP5,
- STAC_INTEL_MAC_V1,
- STAC_INTEL_MAC_V2,
- STAC_INTEL_MAC_V3,
- STAC_INTEL_MAC_V4,
- STAC_INTEL_MAC_V5,
- STAC_INTEL_MAC_AUTO,
- STAC_ECS_202,
- STAC_922X_DELL_D81,
- STAC_922X_DELL_D82,
- STAC_922X_DELL_M81,
- STAC_922X_DELL_M82,
- STAC_922X_INTEL_MAC_GPIO,
- STAC_922X_MODELS
-};
-
-enum {
- STAC_D965_REF_NO_JD, /* no jack-detection */
- STAC_D965_REF,
- STAC_D965_3ST,
- STAC_D965_5ST,
- STAC_D965_5ST_NO_FP,
- STAC_D965_VERBS,
- STAC_DELL_3ST,
- STAC_DELL_BIOS,
- STAC_NEMO_DEFAULT,
- STAC_DELL_BIOS_AMIC,
- STAC_DELL_BIOS_SPDIF,
- STAC_927X_DELL_DMIC,
- STAC_927X_VOLKNOB,
- STAC_927X_MODELS
-};
-
-enum {
- STAC_9872_VAIO,
- STAC_9872_MODELS
-};
-
-struct sigmatel_spec {
- struct hda_gen_spec gen;
-
- unsigned int eapd_switch: 1;
- unsigned int linear_tone_beep:1;
- unsigned int headset_jack:1; /* 4-pin headset jack (hp + mono mic) */
- unsigned int volknob_init:1; /* special volume-knob initialization */
- unsigned int powerdown_adcs:1;
- unsigned int have_spdif_mux:1;
-
- /* gpio lines */
- unsigned int eapd_mask;
- unsigned int gpio_mask;
- unsigned int gpio_dir;
- unsigned int gpio_data;
- unsigned int gpio_mute;
- unsigned int gpio_led;
- unsigned int gpio_led_polarity;
- unsigned int vref_mute_led_nid; /* pin NID for mute-LED vref control */
- unsigned int vref_led;
- int default_polarity;
-
- unsigned int mic_mute_led_gpio; /* capture mute LED GPIO */
- unsigned int mic_enabled; /* current mic mute state (bitmask) */
-
- /* stream */
- unsigned int stream_delay;
-
- /* analog loopback */
- const struct snd_kcontrol_new *aloopback_ctl;
- unsigned int aloopback;
- unsigned char aloopback_mask;
- unsigned char aloopback_shift;
-
- /* power management */
- unsigned int power_map_bits;
- unsigned int num_pwrs;
- const hda_nid_t *pwr_nids;
- unsigned int active_adcs;
-
- /* beep widgets */
- hda_nid_t anabeep_nid;
- bool beep_power_on;
-
- /* SPDIF-out mux */
- const char * const *spdif_labels;
- struct hda_input_mux spdif_mux;
- unsigned int cur_smux[2];
-};
-
-#define AC_VERB_IDT_SET_POWER_MAP 0x7ec
-#define AC_VERB_IDT_GET_POWER_MAP 0xfec
-
-static const hda_nid_t stac92hd73xx_pwr_nids[8] = {
- 0x0a, 0x0b, 0x0c, 0xd, 0x0e,
- 0x0f, 0x10, 0x11
-};
-
-static const hda_nid_t stac92hd83xxx_pwr_nids[7] = {
- 0x0a, 0x0b, 0x0c, 0xd, 0x0e,
- 0x0f, 0x10
-};
-
-static const hda_nid_t stac92hd71bxx_pwr_nids[3] = {
- 0x0a, 0x0d, 0x0f
-};
-
-
-/*
- * PCM hooks
- */
-static void stac_playback_pcm_hook(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream,
- int action)
-{
- struct sigmatel_spec *spec = codec->spec;
- if (action == HDA_GEN_PCM_ACT_OPEN && spec->stream_delay)
- msleep(spec->stream_delay);
-}
-
-static void stac_capture_pcm_hook(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream,
- int action)
-{
- struct sigmatel_spec *spec = codec->spec;
- int i, idx = 0;
-
- if (!spec->powerdown_adcs)
- return;
-
- for (i = 0; i < spec->gen.num_all_adcs; i++) {
- if (spec->gen.all_adcs[i] == hinfo->nid) {
- idx = i;
- break;
- }
- }
-
- switch (action) {
- case HDA_GEN_PCM_ACT_OPEN:
- msleep(40);
- snd_hda_codec_write(codec, hinfo->nid, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
- spec->active_adcs |= (1 << idx);
- break;
- case HDA_GEN_PCM_ACT_CLOSE:
- snd_hda_codec_write(codec, hinfo->nid, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
- spec->active_adcs &= ~(1 << idx);
- break;
- }
-}
-
-/*
- * Early 2006 Intel Macintoshes with STAC9220X5 codecs seem to have a
- * funky external mute control using GPIO pins.
- */
-
-static void stac_gpio_set(struct hda_codec *codec, unsigned int mask,
- unsigned int dir_mask, unsigned int data)
-{
- unsigned int gpiostate, gpiomask, gpiodir;
- hda_nid_t fg = codec->core.afg;
-
- codec_dbg(codec, "%s msk %x dir %x gpio %x\n", __func__, mask, dir_mask, data);
-
- gpiostate = snd_hda_codec_read(codec, fg, 0,
- AC_VERB_GET_GPIO_DATA, 0);
- gpiostate = (gpiostate & ~dir_mask) | (data & dir_mask);
-
- gpiomask = snd_hda_codec_read(codec, fg, 0,
- AC_VERB_GET_GPIO_MASK, 0);
- gpiomask |= mask;
-
- gpiodir = snd_hda_codec_read(codec, fg, 0,
- AC_VERB_GET_GPIO_DIRECTION, 0);
- gpiodir |= dir_mask;
-
- /* Configure GPIOx as CMOS */
- snd_hda_codec_write(codec, fg, 0, 0x7e7, 0);
-
- snd_hda_codec_write(codec, fg, 0,
- AC_VERB_SET_GPIO_MASK, gpiomask);
- snd_hda_codec_read(codec, fg, 0,
- AC_VERB_SET_GPIO_DIRECTION, gpiodir); /* sync */
-
- msleep(1);
-
- snd_hda_codec_read(codec, fg, 0,
- AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */
-}
-
-/* hook for controlling mic-mute LED GPIO */
-static int stac_capture_led_update(struct led_classdev *led_cdev,
- enum led_brightness brightness)
-{
- struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent);
- struct sigmatel_spec *spec = codec->spec;
-
- if (brightness)
- spec->gpio_data |= spec->mic_mute_led_gpio;
- else
- spec->gpio_data &= ~spec->mic_mute_led_gpio;
- stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data);
- return 0;
-}
-
-static int stac_vrefout_set(struct hda_codec *codec,
- hda_nid_t nid, unsigned int new_vref)
-{
- int error, pinctl;
-
- codec_dbg(codec, "%s, nid %x ctl %x\n", __func__, nid, new_vref);
- pinctl = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
-
- if (pinctl < 0)
- return pinctl;
-
- pinctl &= 0xff;
- pinctl &= ~AC_PINCTL_VREFEN;
- pinctl |= (new_vref & AC_PINCTL_VREFEN);
-
- error = snd_hda_set_pin_ctl_cache(codec, nid, pinctl);
- if (error < 0)
- return error;
-
- return 1;
-}
-
-/* prevent codec AFG to D3 state when vref-out pin is used for mute LED */
-/* this hook is set in stac_setup_gpio() */
-static unsigned int stac_vref_led_power_filter(struct hda_codec *codec,
- hda_nid_t nid,
- unsigned int power_state)
-{
- if (nid == codec->core.afg && power_state == AC_PWRST_D3)
- return AC_PWRST_D1;
- return snd_hda_gen_path_power_filter(codec, nid, power_state);
-}
-
-/* update mute-LED accoring to the master switch */
-static void stac_update_led_status(struct hda_codec *codec, bool muted)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- if (!spec->gpio_led)
- return;
-
- /* LED state is inverted on these systems */
- if (spec->gpio_led_polarity)
- muted = !muted;
-
- if (!spec->vref_mute_led_nid) {
- if (muted)
- spec->gpio_data |= spec->gpio_led;
- else
- spec->gpio_data &= ~spec->gpio_led;
- stac_gpio_set(codec, spec->gpio_mask,
- spec->gpio_dir, spec->gpio_data);
- } else {
- spec->vref_led = muted ? AC_PINCTL_VREF_50 : AC_PINCTL_VREF_GRD;
- stac_vrefout_set(codec, spec->vref_mute_led_nid,
- spec->vref_led);
- }
-}
-
-/* vmaster hook to update mute LED */
-static int stac_vmaster_hook(struct led_classdev *led_cdev,
- enum led_brightness brightness)
-{
- struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent);
-
- stac_update_led_status(codec, brightness);
- return 0;
-}
-
-/* automute hook to handle GPIO mute and EAPD updates */
-static void stac_update_outputs(struct hda_codec *codec)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- if (spec->gpio_mute)
- spec->gen.master_mute =
- !(snd_hda_codec_read(codec, codec->core.afg, 0,
- AC_VERB_GET_GPIO_DATA, 0) & spec->gpio_mute);
-
- snd_hda_gen_update_outputs(codec);
-
- if (spec->eapd_mask && spec->eapd_switch) {
- unsigned int val = spec->gpio_data;
- if (spec->gen.speaker_muted)
- val &= ~spec->eapd_mask;
- else
- val |= spec->eapd_mask;
- if (spec->gpio_data != val) {
- spec->gpio_data = val;
- stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir,
- val);
- }
- }
-}
-
-static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid,
- bool enable, bool do_write)
-{
- struct sigmatel_spec *spec = codec->spec;
- unsigned int idx, val;
-
- for (idx = 0; idx < spec->num_pwrs; idx++) {
- if (spec->pwr_nids[idx] == nid)
- break;
- }
- if (idx >= spec->num_pwrs)
- return;
-
- idx = 1 << idx;
-
- val = spec->power_map_bits;
- if (enable)
- val &= ~idx;
- else
- val |= idx;
-
- /* power down unused output ports */
- if (val != spec->power_map_bits) {
- spec->power_map_bits = val;
- if (do_write)
- snd_hda_codec_write(codec, codec->core.afg, 0,
- AC_VERB_IDT_SET_POWER_MAP, val);
- }
-}
-
-/* update power bit per jack plug/unplug */
-static void jack_update_power(struct hda_codec *codec,
- struct hda_jack_callback *jack)
-{
- struct sigmatel_spec *spec = codec->spec;
- int i;
-
- if (!spec->num_pwrs)
- return;
-
- if (jack && jack->nid) {
- stac_toggle_power_map(codec, jack->nid,
- snd_hda_jack_detect(codec, jack->nid),
- true);
- return;
- }
-
- /* update all jacks */
- for (i = 0; i < spec->num_pwrs; i++) {
- hda_nid_t nid = spec->pwr_nids[i];
- if (!snd_hda_jack_tbl_get(codec, nid))
- continue;
- stac_toggle_power_map(codec, nid,
- snd_hda_jack_detect(codec, nid),
- false);
- }
-
- snd_hda_codec_write(codec, codec->core.afg, 0,
- AC_VERB_IDT_SET_POWER_MAP,
- spec->power_map_bits);
-}
-
-static void stac_vref_event(struct hda_codec *codec,
- struct hda_jack_callback *event)
-{
- unsigned int data;
-
- data = snd_hda_codec_read(codec, codec->core.afg, 0,
- AC_VERB_GET_GPIO_DATA, 0);
- /* toggle VREF state based on GPIOx status */
- snd_hda_codec_write(codec, codec->core.afg, 0, 0x7e0,
- !!(data & (1 << event->private_data)));
-}
-
-/* initialize the power map and enable the power event to jacks that
- * haven't been assigned to automute
- */
-static void stac_init_power_map(struct hda_codec *codec)
-{
- struct sigmatel_spec *spec = codec->spec;
- int i;
-
- for (i = 0; i < spec->num_pwrs; i++) {
- hda_nid_t nid = spec->pwr_nids[i];
- unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);
- def_conf = get_defcfg_connect(def_conf);
- if (def_conf == AC_JACK_PORT_COMPLEX &&
- spec->vref_mute_led_nid != nid &&
- is_jack_detectable(codec, nid)) {
- snd_hda_jack_detect_enable_callback(codec, nid,
- jack_update_power);
- } else {
- if (def_conf == AC_JACK_PORT_NONE)
- stac_toggle_power_map(codec, nid, false, false);
- else
- stac_toggle_power_map(codec, nid, true, false);
- }
- }
-}
-
-/*
- */
-
-static inline bool get_int_hint(struct hda_codec *codec, const char *key,
- int *valp)
-{
- return !snd_hda_get_int_hint(codec, key, valp);
-}
-
-/* override some hints from the hwdep entry */
-static void stac_store_hints(struct hda_codec *codec)
-{
- struct sigmatel_spec *spec = codec->spec;
- int val;
-
- if (get_int_hint(codec, "gpio_mask", &spec->gpio_mask)) {
- spec->eapd_mask = spec->gpio_dir = spec->gpio_data =
- spec->gpio_mask;
- }
- if (get_int_hint(codec, "gpio_dir", &spec->gpio_dir))
- spec->gpio_dir &= spec->gpio_mask;
- if (get_int_hint(codec, "gpio_data", &spec->gpio_data))
- spec->gpio_data &= spec->gpio_mask;
- if (get_int_hint(codec, "eapd_mask", &spec->eapd_mask))
- spec->eapd_mask &= spec->gpio_mask;
- if (get_int_hint(codec, "gpio_mute", &spec->gpio_mute))
- spec->gpio_mute &= spec->gpio_mask;
- val = snd_hda_get_bool_hint(codec, "eapd_switch");
- if (val >= 0)
- spec->eapd_switch = val;
-}
-
-/*
- * loopback controls
- */
-
-#define stac_aloopback_info snd_ctl_boolean_mono_info
-
-static int stac_aloopback_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
- struct sigmatel_spec *spec = codec->spec;
-
- ucontrol->value.integer.value[0] = !!(spec->aloopback &
- (spec->aloopback_mask << idx));
- return 0;
-}
-
-static int stac_aloopback_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct sigmatel_spec *spec = codec->spec;
- unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
- unsigned int dac_mode;
- unsigned int val, idx_val;
-
- idx_val = spec->aloopback_mask << idx;
- if (ucontrol->value.integer.value[0])
- val = spec->aloopback | idx_val;
- else
- val = spec->aloopback & ~idx_val;
- if (spec->aloopback == val)
- return 0;
-
- spec->aloopback = val;
-
- /* Only return the bits defined by the shift value of the
- * first two bytes of the mask
- */
- dac_mode = snd_hda_codec_read(codec, codec->core.afg, 0,
- kcontrol->private_value & 0xFFFF, 0x0);
- dac_mode >>= spec->aloopback_shift;
-
- if (spec->aloopback & idx_val) {
- snd_hda_power_up(codec);
- dac_mode |= idx_val;
- } else {
- snd_hda_power_down(codec);
- dac_mode &= ~idx_val;
- }
-
- snd_hda_codec_write_cache(codec, codec->core.afg, 0,
- kcontrol->private_value >> 16, dac_mode);
-
- return 1;
-}
-
-#define STAC_ANALOG_LOOPBACK(verb_read, verb_write, cnt) \
- { \
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
- .name = "Analog Loopback", \
- .count = cnt, \
- .info = stac_aloopback_info, \
- .get = stac_aloopback_get, \
- .put = stac_aloopback_put, \
- .private_value = verb_read | (verb_write << 16), \
- }
-
-/*
- * Mute LED handling on HP laptops
- */
-
-/* check whether it's a HP laptop with a docking port */
-static bool hp_bnb2011_with_dock(struct hda_codec *codec)
-{
- if (codec->core.vendor_id != 0x111d7605 &&
- codec->core.vendor_id != 0x111d76d1)
- return false;
-
- switch (codec->core.subsystem_id) {
- case 0x103c1618:
- case 0x103c1619:
- case 0x103c161a:
- case 0x103c161b:
- case 0x103c161c:
- case 0x103c161d:
- case 0x103c161e:
- case 0x103c161f:
-
- case 0x103c162a:
- case 0x103c162b:
-
- case 0x103c1630:
- case 0x103c1631:
-
- case 0x103c1633:
- case 0x103c1634:
- case 0x103c1635:
-
- case 0x103c3587:
- case 0x103c3588:
- case 0x103c3589:
- case 0x103c358a:
-
- case 0x103c3667:
- case 0x103c3668:
- case 0x103c3669:
-
- return true;
- }
- return false;
-}
-
-static bool hp_blike_system(u32 subsystem_id)
-{
- switch (subsystem_id) {
- case 0x103c1473: /* HP ProBook 6550b */
- case 0x103c1520:
- case 0x103c1521:
- case 0x103c1523:
- case 0x103c1524:
- case 0x103c1525:
- case 0x103c1722:
- case 0x103c1723:
- case 0x103c1724:
- case 0x103c1725:
- case 0x103c1726:
- case 0x103c1727:
- case 0x103c1728:
- case 0x103c1729:
- case 0x103c172a:
- case 0x103c172b:
- case 0x103c307e:
- case 0x103c307f:
- case 0x103c3080:
- case 0x103c3081:
- case 0x103c7007:
- case 0x103c7008:
- return true;
- }
- return false;
-}
-
-static void set_hp_led_gpio(struct hda_codec *codec)
-{
- struct sigmatel_spec *spec = codec->spec;
- unsigned int gpio;
-
- if (spec->gpio_led)
- return;
-
- gpio = snd_hda_param_read(codec, codec->core.afg, AC_PAR_GPIO_CAP);
- gpio &= AC_GPIO_IO_COUNT;
- if (gpio > 3)
- spec->gpio_led = 0x08; /* GPIO 3 */
- else
- spec->gpio_led = 0x01; /* GPIO 0 */
-}
-
-/*
- * This method searches for the mute LED GPIO configuration
- * provided as OEM string in SMBIOS. The format of that string
- * is HP_Mute_LED_P_G or HP_Mute_LED_P
- * where P can be 0 or 1 and defines mute LED GPIO control state (low/high)
- * that corresponds to the NOT muted state of the master volume
- * and G is the index of the GPIO to use as the mute LED control (0..9)
- * If _G portion is missing it is assigned based on the codec ID
- *
- * So, HP B-series like systems may have HP_Mute_LED_0 (current models)
- * or HP_Mute_LED_0_3 (future models) OEM SMBIOS strings
- *
- *
- * The dv-series laptops don't seem to have the HP_Mute_LED* strings in
- * SMBIOS - at least the ones I have seen do not have them - which include
- * my own system (HP Pavilion dv6-1110ax) and my cousin's
- * HP Pavilion dv9500t CTO.
- * Need more information on whether it is true across the entire series.
- * -- kunal
- */
-static int find_mute_led_cfg(struct hda_codec *codec, int default_polarity)
-{
- struct sigmatel_spec *spec = codec->spec;
- const struct dmi_device *dev = NULL;
-
- if (get_int_hint(codec, "gpio_led", &spec->gpio_led)) {
- get_int_hint(codec, "gpio_led_polarity",
- &spec->gpio_led_polarity);
- return 1;
- }
-
- while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, NULL, dev))) {
- if (sscanf(dev->name, "HP_Mute_LED_%u_%x",
- &spec->gpio_led_polarity,
- &spec->gpio_led) == 2) {
- unsigned int max_gpio;
- max_gpio = snd_hda_param_read(codec, codec->core.afg,
- AC_PAR_GPIO_CAP);
- max_gpio &= AC_GPIO_IO_COUNT;
- if (spec->gpio_led < max_gpio)
- spec->gpio_led = 1 << spec->gpio_led;
- else
- spec->vref_mute_led_nid = spec->gpio_led;
- return 1;
- }
- if (sscanf(dev->name, "HP_Mute_LED_%u",
- &spec->gpio_led_polarity) == 1) {
- set_hp_led_gpio(codec);
- return 1;
- }
- /* BIOS bug: unfilled OEM string */
- if (strstr(dev->name, "HP_Mute_LED_P_G")) {
- set_hp_led_gpio(codec);
- if (default_polarity >= 0)
- spec->gpio_led_polarity = default_polarity;
- else
- spec->gpio_led_polarity = 1;
- return 1;
- }
- }
-
- /*
- * Fallback case - if we don't find the DMI strings,
- * we statically set the GPIO - if not a B-series system
- * and default polarity is provided
- */
- if (!hp_blike_system(codec->core.subsystem_id) &&
- (default_polarity == 0 || default_polarity == 1)) {
- set_hp_led_gpio(codec);
- spec->gpio_led_polarity = default_polarity;
- return 1;
- }
- return 0;
-}
-
-/* check whether a built-in speaker is included in parsed pins */
-static bool has_builtin_speaker(struct hda_codec *codec)
-{
- struct sigmatel_spec *spec = codec->spec;
- const hda_nid_t *nid_pin;
- int nids, i;
-
- if (spec->gen.autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT) {
- nid_pin = spec->gen.autocfg.line_out_pins;
- nids = spec->gen.autocfg.line_outs;
- } else {
- nid_pin = spec->gen.autocfg.speaker_pins;
- nids = spec->gen.autocfg.speaker_outs;
- }
-
- for (i = 0; i < nids; i++) {
- unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid_pin[i]);
- if (snd_hda_get_input_pin_attr(def_conf) == INPUT_PIN_ATTR_INT)
- return true;
- }
- return false;
-}
-
-/*
- * PC beep controls
- */
-
-/* create PC beep volume controls */
-static int stac_auto_create_beep_ctls(struct hda_codec *codec,
- hda_nid_t nid)
-{
- struct sigmatel_spec *spec = codec->spec;
- u32 caps = query_amp_caps(codec, nid, HDA_OUTPUT);
- struct snd_kcontrol_new *knew;
- static const struct snd_kcontrol_new abeep_mute_ctl =
- HDA_CODEC_MUTE(NULL, 0, 0, 0);
- static const struct snd_kcontrol_new dbeep_mute_ctl =
- HDA_CODEC_MUTE_BEEP(NULL, 0, 0, 0);
- static const struct snd_kcontrol_new beep_vol_ctl =
- HDA_CODEC_VOLUME(NULL, 0, 0, 0);
-
- /* check for mute support for the amp */
- if ((caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT) {
- const struct snd_kcontrol_new *temp;
- if (spec->anabeep_nid == nid)
- temp = &abeep_mute_ctl;
- else
- temp = &dbeep_mute_ctl;
- knew = snd_hda_gen_add_kctl(&spec->gen,
- "Beep Playback Switch", temp);
- if (!knew)
- return -ENOMEM;
- knew->private_value =
- HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT);
- }
-
- /* check to see if there is volume support for the amp */
- if ((caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT) {
- knew = snd_hda_gen_add_kctl(&spec->gen,
- "Beep Playback Volume",
- &beep_vol_ctl);
- if (!knew)
- return -ENOMEM;
- knew->private_value =
- HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT);
- }
- return 0;
-}
-
-#ifdef CONFIG_SND_HDA_INPUT_BEEP
-#define stac_dig_beep_switch_info snd_ctl_boolean_mono_info
-
-static int stac_dig_beep_switch_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- ucontrol->value.integer.value[0] = codec->beep->enabled;
- return 0;
-}
-
-static int stac_dig_beep_switch_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- return snd_hda_enable_beep_device(codec, ucontrol->value.integer.value[0]);
-}
-
-static const struct snd_kcontrol_new stac_dig_beep_ctrl = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Beep Playback Switch",
- .info = stac_dig_beep_switch_info,
- .get = stac_dig_beep_switch_get,
- .put = stac_dig_beep_switch_put,
-};
-
-static int stac_beep_switch_ctl(struct hda_codec *codec)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &stac_dig_beep_ctrl))
- return -ENOMEM;
- return 0;
-}
-#endif
-
-/*
- * SPDIF-out mux controls
- */
-
-static int stac_smux_enum_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct sigmatel_spec *spec = codec->spec;
- return snd_hda_input_mux_info(&spec->spdif_mux, uinfo);
-}
-
-static int stac_smux_enum_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct sigmatel_spec *spec = codec->spec;
- unsigned int smux_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
-
- ucontrol->value.enumerated.item[0] = spec->cur_smux[smux_idx];
- return 0;
-}
-
-static int stac_smux_enum_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct sigmatel_spec *spec = codec->spec;
- unsigned int smux_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
-
- return snd_hda_input_mux_put(codec, &spec->spdif_mux, ucontrol,
- spec->gen.autocfg.dig_out_pins[smux_idx],
- &spec->cur_smux[smux_idx]);
-}
-
-static const struct snd_kcontrol_new stac_smux_mixer = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "IEC958 Playback Source",
- /* count set later */
- .info = stac_smux_enum_info,
- .get = stac_smux_enum_get,
- .put = stac_smux_enum_put,
-};
-
-static const char * const stac_spdif_labels[] = {
- "Digital Playback", "Analog Mux 1", "Analog Mux 2", NULL
-};
-
-static int stac_create_spdif_mux_ctls(struct hda_codec *codec)
-{
- struct sigmatel_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->gen.autocfg;
- const char * const *labels = spec->spdif_labels;
- struct snd_kcontrol_new *kctl;
- int i, num_cons;
-
- if (cfg->dig_outs < 1)
- return 0;
-
- num_cons = snd_hda_get_num_conns(codec, cfg->dig_out_pins[0]);
- if (num_cons <= 1)
- return 0;
-
- if (!labels)
- labels = stac_spdif_labels;
- for (i = 0; i < num_cons; i++) {
- if (snd_BUG_ON(!labels[i]))
- return -EINVAL;
- snd_hda_add_imux_item(codec, &spec->spdif_mux, labels[i], i, NULL);
- }
-
- kctl = snd_hda_gen_add_kctl(&spec->gen, NULL, &stac_smux_mixer);
- if (!kctl)
- return -ENOMEM;
- kctl->count = cfg->dig_outs;
-
- return 0;
-}
-
-static const struct hda_verb stac9200_eapd_init[] = {
- /* set dac0mux for dac converter */
- {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x08, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
- {}
-};
-
-static const struct hda_verb dell_eq_core_init[] = {
- /* set master volume to max value without distortion
- * and direct control */
- { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xec},
- {}
-};
-
-static const struct hda_verb stac92hd73xx_core_init[] = {
- /* set master volume and direct control */
- { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
- {}
-};
-
-static const struct hda_verb stac92hd83xxx_core_init[] = {
- /* power state controls amps */
- { 0x01, AC_VERB_SET_EAPD, 1 << 2},
- {}
-};
-
-static const struct hda_verb stac92hd83xxx_hp_zephyr_init[] = {
- { 0x22, 0x785, 0x43 },
- { 0x22, 0x782, 0xe0 },
- { 0x22, 0x795, 0x00 },
- {}
-};
-
-static const struct hda_verb stac92hd71bxx_core_init[] = {
- /* set master volume and direct control */
- { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
- {}
-};
-
-static const hda_nid_t stac92hd71bxx_unmute_nids[] = {
- /* unmute right and left channels for nodes 0x0f, 0xa, 0x0d */
- 0x0f, 0x0a, 0x0d, 0
-};
-
-static const struct hda_verb stac925x_core_init[] = {
- /* set dac0mux for dac converter */
- { 0x06, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* mute the master volume */
- { 0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
- {}
-};
-
-static const struct hda_verb stac922x_core_init[] = {
- /* set master volume and direct control */
- { 0x16, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
- {}
-};
-
-static const struct hda_verb d965_core_init[] = {
- /* unmute node 0x1b */
- { 0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
- /* select node 0x03 as DAC */
- { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x01},
- {}
-};
-
-static const struct hda_verb dell_3st_core_init[] = {
- /* don't set delta bit */
- {0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0x7f},
- /* unmute node 0x1b */
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
- /* select node 0x03 as DAC */
- {0x0b, AC_VERB_SET_CONNECT_SEL, 0x01},
- {}
-};
-
-static const struct hda_verb stac927x_core_init[] = {
- /* set master volume and direct control */
- { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
- /* enable analog pc beep path */
- { 0x01, AC_VERB_SET_DIGI_CONVERT_2, 1 << 5},
- {}
-};
-
-static const struct hda_verb stac927x_volknob_core_init[] = {
- /* don't set delta bit */
- {0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0x7f},
- /* enable analog pc beep path */
- {0x01, AC_VERB_SET_DIGI_CONVERT_2, 1 << 5},
- {}
-};
-
-static const struct hda_verb stac9205_core_init[] = {
- /* set master volume and direct control */
- { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
- /* enable analog pc beep path */
- { 0x01, AC_VERB_SET_DIGI_CONVERT_2, 1 << 5},
- {}
-};
-
-static const struct snd_kcontrol_new stac92hd73xx_6ch_loopback =
- STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 3);
-
-static const struct snd_kcontrol_new stac92hd73xx_8ch_loopback =
- STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 4);
-
-static const struct snd_kcontrol_new stac92hd73xx_10ch_loopback =
- STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 5);
-
-static const struct snd_kcontrol_new stac92hd71bxx_loopback =
- STAC_ANALOG_LOOPBACK(0xFA0, 0x7A0, 2);
-
-static const struct snd_kcontrol_new stac9205_loopback =
- STAC_ANALOG_LOOPBACK(0xFE0, 0x7E0, 1);
-
-static const struct snd_kcontrol_new stac927x_loopback =
- STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB, 1);
-
-static const struct hda_pintbl ref9200_pin_configs[] = {
- { 0x08, 0x01c47010 },
- { 0x09, 0x01447010 },
- { 0x0d, 0x0221401f },
- { 0x0e, 0x01114010 },
- { 0x0f, 0x02a19020 },
- { 0x10, 0x01a19021 },
- { 0x11, 0x90100140 },
- { 0x12, 0x01813122 },
- {}
-};
-
-static const struct hda_pintbl gateway9200_m4_pin_configs[] = {
- { 0x08, 0x400000fe },
- { 0x09, 0x404500f4 },
- { 0x0d, 0x400100f0 },
- { 0x0e, 0x90110010 },
- { 0x0f, 0x400100f1 },
- { 0x10, 0x02a1902e },
- { 0x11, 0x500000f2 },
- { 0x12, 0x500000f3 },
- {}
-};
-
-static const struct hda_pintbl gateway9200_m4_2_pin_configs[] = {
- { 0x08, 0x400000fe },
- { 0x09, 0x404500f4 },
- { 0x0d, 0x400100f0 },
- { 0x0e, 0x90110010 },
- { 0x0f, 0x400100f1 },
- { 0x10, 0x02a1902e },
- { 0x11, 0x500000f2 },
- { 0x12, 0x500000f3 },
- {}
-};
-
-/*
- STAC 9200 pin configs for
- 102801A8
- 102801DE
- 102801E8
-*/
-static const struct hda_pintbl dell9200_d21_pin_configs[] = {
- { 0x08, 0x400001f0 },
- { 0x09, 0x400001f1 },
- { 0x0d, 0x02214030 },
- { 0x0e, 0x01014010 },
- { 0x0f, 0x02a19020 },
- { 0x10, 0x01a19021 },
- { 0x11, 0x90100140 },
- { 0x12, 0x01813122 },
- {}
-};
-
-/*
- STAC 9200 pin configs for
- 102801C0
- 102801C1
-*/
-static const struct hda_pintbl dell9200_d22_pin_configs[] = {
- { 0x08, 0x400001f0 },
- { 0x09, 0x400001f1 },
- { 0x0d, 0x0221401f },
- { 0x0e, 0x01014010 },
- { 0x0f, 0x01813020 },
- { 0x10, 0x02a19021 },
- { 0x11, 0x90100140 },
- { 0x12, 0x400001f2 },
- {}
-};
-
-/*
- STAC 9200 pin configs for
- 102801C4 (Dell Dimension E310)
- 102801C5
- 102801C7
- 102801D9
- 102801DA
- 102801E3
-*/
-static const struct hda_pintbl dell9200_d23_pin_configs[] = {
- { 0x08, 0x400001f0 },
- { 0x09, 0x400001f1 },
- { 0x0d, 0x0221401f },
- { 0x0e, 0x01014010 },
- { 0x0f, 0x01813020 },
- { 0x10, 0x01a19021 },
- { 0x11, 0x90100140 },
- { 0x12, 0x400001f2 },
- {}
-};
-
-
-/*
- STAC 9200-32 pin configs for
- 102801B5 (Dell Inspiron 630m)
- 102801D8 (Dell Inspiron 640m)
-*/
-static const struct hda_pintbl dell9200_m21_pin_configs[] = {
- { 0x08, 0x40c003fa },
- { 0x09, 0x03441340 },
- { 0x0d, 0x0321121f },
- { 0x0e, 0x90170310 },
- { 0x0f, 0x408003fb },
- { 0x10, 0x03a11020 },
- { 0x11, 0x401003fc },
- { 0x12, 0x403003fd },
- {}
-};
-
-/*
- STAC 9200-32 pin configs for
- 102801C2 (Dell Latitude D620)
- 102801C8
- 102801CC (Dell Latitude D820)
- 102801D4
- 102801D6
-*/
-static const struct hda_pintbl dell9200_m22_pin_configs[] = {
- { 0x08, 0x40c003fa },
- { 0x09, 0x0144131f },
- { 0x0d, 0x0321121f },
- { 0x0e, 0x90170310 },
- { 0x0f, 0x90a70321 },
- { 0x10, 0x03a11020 },
- { 0x11, 0x401003fb },
- { 0x12, 0x40f000fc },
- {}
-};
-
-/*
- STAC 9200-32 pin configs for
- 102801CE (Dell XPS M1710)
- 102801CF (Dell Precision M90)
-*/
-static const struct hda_pintbl dell9200_m23_pin_configs[] = {
- { 0x08, 0x40c003fa },
- { 0x09, 0x01441340 },
- { 0x0d, 0x0421421f },
- { 0x0e, 0x90170310 },
- { 0x0f, 0x408003fb },
- { 0x10, 0x04a1102e },
- { 0x11, 0x90170311 },
- { 0x12, 0x403003fc },
- {}
-};
-
-/*
- STAC 9200-32 pin configs for
- 102801C9
- 102801CA
- 102801CB (Dell Latitude 120L)
- 102801D3
-*/
-static const struct hda_pintbl dell9200_m24_pin_configs[] = {
- { 0x08, 0x40c003fa },
- { 0x09, 0x404003fb },
- { 0x0d, 0x0321121f },
- { 0x0e, 0x90170310 },
- { 0x0f, 0x408003fc },
- { 0x10, 0x03a11020 },
- { 0x11, 0x401003fd },
- { 0x12, 0x403003fe },
- {}
-};
-
-/*
- STAC 9200-32 pin configs for
- 102801BD (Dell Inspiron E1505n)
- 102801EE
- 102801EF
-*/
-static const struct hda_pintbl dell9200_m25_pin_configs[] = {
- { 0x08, 0x40c003fa },
- { 0x09, 0x01441340 },
- { 0x0d, 0x0421121f },
- { 0x0e, 0x90170310 },
- { 0x0f, 0x408003fb },
- { 0x10, 0x04a11020 },
- { 0x11, 0x401003fc },
- { 0x12, 0x403003fd },
- {}
-};
-
-/*
- STAC 9200-32 pin configs for
- 102801F5 (Dell Inspiron 1501)
- 102801F6
-*/
-static const struct hda_pintbl dell9200_m26_pin_configs[] = {
- { 0x08, 0x40c003fa },
- { 0x09, 0x404003fb },
- { 0x0d, 0x0421121f },
- { 0x0e, 0x90170310 },
- { 0x0f, 0x408003fc },
- { 0x10, 0x04a11020 },
- { 0x11, 0x401003fd },
- { 0x12, 0x403003fe },
- {}
-};
-
-/*
- STAC 9200-32
- 102801CD (Dell Inspiron E1705/9400)
-*/
-static const struct hda_pintbl dell9200_m27_pin_configs[] = {
- { 0x08, 0x40c003fa },
- { 0x09, 0x01441340 },
- { 0x0d, 0x0421121f },
- { 0x0e, 0x90170310 },
- { 0x0f, 0x90170310 },
- { 0x10, 0x04a11020 },
- { 0x11, 0x90170310 },
- { 0x12, 0x40f003fc },
- {}
-};
-
-static const struct hda_pintbl oqo9200_pin_configs[] = {
- { 0x08, 0x40c000f0 },
- { 0x09, 0x404000f1 },
- { 0x0d, 0x0221121f },
- { 0x0e, 0x02211210 },
- { 0x0f, 0x90170111 },
- { 0x10, 0x90a70120 },
- { 0x11, 0x400000f2 },
- { 0x12, 0x400000f3 },
- {}
-};
-
-/*
- * STAC 92HD700
- * 18881000 Amigaone X1000
- */
-static const struct hda_pintbl nemo_pin_configs[] = {
- { 0x0a, 0x02214020 }, /* Front panel HP socket */
- { 0x0b, 0x02a19080 }, /* Front Mic */
- { 0x0c, 0x0181304e }, /* Line in */
- { 0x0d, 0x01014010 }, /* Line out */
- { 0x0e, 0x01a19040 }, /* Rear Mic */
- { 0x0f, 0x01011012 }, /* Rear speakers */
- { 0x10, 0x01016011 }, /* Center speaker */
- { 0x11, 0x01012014 }, /* Side speakers (7.1) */
- { 0x12, 0x103301f0 }, /* Motherboard CD line in connector */
- { 0x13, 0x411111f0 }, /* Unused */
- { 0x14, 0x411111f0 }, /* Unused */
- { 0x21, 0x01442170 }, /* S/PDIF line out */
- { 0x22, 0x411111f0 }, /* Unused */
- { 0x23, 0x411111f0 }, /* Unused */
- {}
-};
-
-static void stac9200_fixup_panasonic(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->gpio_mask = spec->gpio_dir = 0x09;
- spec->gpio_data = 0x00;
- /* CF-74 has no headphone detection, and the driver should *NOT*
- * do detection and HP/speaker toggle because the hardware does it.
- */
- spec->gen.suppress_auto_mute = 1;
- }
-}
-
-
-static const struct hda_fixup stac9200_fixups[] = {
- [STAC_REF] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = ref9200_pin_configs,
- },
- [STAC_9200_OQO] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = oqo9200_pin_configs,
- .chained = true,
- .chain_id = STAC_9200_EAPD_INIT,
- },
- [STAC_9200_DELL_D21] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = dell9200_d21_pin_configs,
- },
- [STAC_9200_DELL_D22] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = dell9200_d22_pin_configs,
- },
- [STAC_9200_DELL_D23] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = dell9200_d23_pin_configs,
- },
- [STAC_9200_DELL_M21] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = dell9200_m21_pin_configs,
- },
- [STAC_9200_DELL_M22] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = dell9200_m22_pin_configs,
- },
- [STAC_9200_DELL_M23] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = dell9200_m23_pin_configs,
- },
- [STAC_9200_DELL_M24] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = dell9200_m24_pin_configs,
- },
- [STAC_9200_DELL_M25] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = dell9200_m25_pin_configs,
- },
- [STAC_9200_DELL_M26] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = dell9200_m26_pin_configs,
- },
- [STAC_9200_DELL_M27] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = dell9200_m27_pin_configs,
- },
- [STAC_9200_M4] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = gateway9200_m4_pin_configs,
- .chained = true,
- .chain_id = STAC_9200_EAPD_INIT,
- },
- [STAC_9200_M4_2] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = gateway9200_m4_2_pin_configs,
- .chained = true,
- .chain_id = STAC_9200_EAPD_INIT,
- },
- [STAC_9200_PANASONIC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = stac9200_fixup_panasonic,
- },
- [STAC_9200_EAPD_INIT] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- {0x08, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
- {}
- },
- },
-};
-
-static const struct hda_model_fixup stac9200_models[] = {
- { .id = STAC_REF, .name = "ref" },
- { .id = STAC_9200_OQO, .name = "oqo" },
- { .id = STAC_9200_DELL_D21, .name = "dell-d21" },
- { .id = STAC_9200_DELL_D22, .name = "dell-d22" },
- { .id = STAC_9200_DELL_D23, .name = "dell-d23" },
- { .id = STAC_9200_DELL_M21, .name = "dell-m21" },
- { .id = STAC_9200_DELL_M22, .name = "dell-m22" },
- { .id = STAC_9200_DELL_M23, .name = "dell-m23" },
- { .id = STAC_9200_DELL_M24, .name = "dell-m24" },
- { .id = STAC_9200_DELL_M25, .name = "dell-m25" },
- { .id = STAC_9200_DELL_M26, .name = "dell-m26" },
- { .id = STAC_9200_DELL_M27, .name = "dell-m27" },
- { .id = STAC_9200_M4, .name = "gateway-m4" },
- { .id = STAC_9200_M4_2, .name = "gateway-m4-2" },
- { .id = STAC_9200_PANASONIC, .name = "panasonic" },
- {}
-};
-
-static const struct hda_quirk stac9200_fixup_tbl[] = {
- /* SigmaTel reference board */
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
- "DFI LanParty", STAC_REF),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101,
- "DFI LanParty", STAC_REF),
- /* Dell laptops have BIOS problem */
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01a8,
- "unknown Dell", STAC_9200_DELL_D21),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01b5,
- "Dell Inspiron 630m", STAC_9200_DELL_M21),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01bd,
- "Dell Inspiron E1505n", STAC_9200_DELL_M25),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c0,
- "unknown Dell", STAC_9200_DELL_D22),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c1,
- "unknown Dell", STAC_9200_DELL_D22),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c2,
- "Dell Latitude D620", STAC_9200_DELL_M22),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c5,
- "unknown Dell", STAC_9200_DELL_D23),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c7,
- "unknown Dell", STAC_9200_DELL_D23),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c8,
- "unknown Dell", STAC_9200_DELL_M22),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c9,
- "unknown Dell", STAC_9200_DELL_M24),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ca,
- "unknown Dell", STAC_9200_DELL_M24),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cb,
- "Dell Latitude 120L", STAC_9200_DELL_M24),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cc,
- "Dell Latitude D820", STAC_9200_DELL_M22),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cd,
- "Dell Inspiron E1705/9400", STAC_9200_DELL_M27),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ce,
- "Dell XPS M1710", STAC_9200_DELL_M23),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cf,
- "Dell Precision M90", STAC_9200_DELL_M23),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d3,
- "unknown Dell", STAC_9200_DELL_M22),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d4,
- "unknown Dell", STAC_9200_DELL_M22),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d6,
- "unknown Dell", STAC_9200_DELL_M22),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d8,
- "Dell Inspiron 640m", STAC_9200_DELL_M21),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d9,
- "unknown Dell", STAC_9200_DELL_D23),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01da,
- "unknown Dell", STAC_9200_DELL_D23),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01de,
- "unknown Dell", STAC_9200_DELL_D21),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01e3,
- "unknown Dell", STAC_9200_DELL_D23),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01e8,
- "unknown Dell", STAC_9200_DELL_D21),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ee,
- "unknown Dell", STAC_9200_DELL_M25),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ef,
- "unknown Dell", STAC_9200_DELL_M25),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f5,
- "Dell Inspiron 1501", STAC_9200_DELL_M26),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f6,
- "unknown Dell", STAC_9200_DELL_M26),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0201,
- "Dell Latitude D430", STAC_9200_DELL_M22),
- /* Panasonic */
- SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-74", STAC_9200_PANASONIC),
- /* Gateway machines needs EAPD to be set on resume */
- SND_PCI_QUIRK(0x107b, 0x0205, "Gateway S-7110M", STAC_9200_M4),
- SND_PCI_QUIRK(0x107b, 0x0317, "Gateway MT3423, MX341*", STAC_9200_M4_2),
- SND_PCI_QUIRK(0x107b, 0x0318, "Gateway ML3019, MT3707", STAC_9200_M4_2),
- /* OQO Mobile */
- SND_PCI_QUIRK(0x1106, 0x3288, "OQO Model 2", STAC_9200_OQO),
- {} /* terminator */
-};
-
-static const struct hda_pintbl ref925x_pin_configs[] = {
- { 0x07, 0x40c003f0 },
- { 0x08, 0x424503f2 },
- { 0x0a, 0x01813022 },
- { 0x0b, 0x02a19021 },
- { 0x0c, 0x90a70320 },
- { 0x0d, 0x02214210 },
- { 0x10, 0x01019020 },
- { 0x11, 0x9033032e },
- {}
-};
-
-static const struct hda_pintbl stac925xM1_pin_configs[] = {
- { 0x07, 0x40c003f4 },
- { 0x08, 0x424503f2 },
- { 0x0a, 0x400000f3 },
- { 0x0b, 0x02a19020 },
- { 0x0c, 0x40a000f0 },
- { 0x0d, 0x90100210 },
- { 0x10, 0x400003f1 },
- { 0x11, 0x9033032e },
- {}
-};
-
-static const struct hda_pintbl stac925xM1_2_pin_configs[] = {
- { 0x07, 0x40c003f4 },
- { 0x08, 0x424503f2 },
- { 0x0a, 0x400000f3 },
- { 0x0b, 0x02a19020 },
- { 0x0c, 0x40a000f0 },
- { 0x0d, 0x90100210 },
- { 0x10, 0x400003f1 },
- { 0x11, 0x9033032e },
- {}
-};
-
-static const struct hda_pintbl stac925xM2_pin_configs[] = {
- { 0x07, 0x40c003f4 },
- { 0x08, 0x424503f2 },
- { 0x0a, 0x400000f3 },
- { 0x0b, 0x02a19020 },
- { 0x0c, 0x40a000f0 },
- { 0x0d, 0x90100210 },
- { 0x10, 0x400003f1 },
- { 0x11, 0x9033032e },
- {}
-};
-
-static const struct hda_pintbl stac925xM2_2_pin_configs[] = {
- { 0x07, 0x40c003f4 },
- { 0x08, 0x424503f2 },
- { 0x0a, 0x400000f3 },
- { 0x0b, 0x02a19020 },
- { 0x0c, 0x40a000f0 },
- { 0x0d, 0x90100210 },
- { 0x10, 0x400003f1 },
- { 0x11, 0x9033032e },
- {}
-};
-
-static const struct hda_pintbl stac925xM3_pin_configs[] = {
- { 0x07, 0x40c003f4 },
- { 0x08, 0x424503f2 },
- { 0x0a, 0x400000f3 },
- { 0x0b, 0x02a19020 },
- { 0x0c, 0x40a000f0 },
- { 0x0d, 0x90100210 },
- { 0x10, 0x400003f1 },
- { 0x11, 0x503303f3 },
- {}
-};
-
-static const struct hda_pintbl stac925xM5_pin_configs[] = {
- { 0x07, 0x40c003f4 },
- { 0x08, 0x424503f2 },
- { 0x0a, 0x400000f3 },
- { 0x0b, 0x02a19020 },
- { 0x0c, 0x40a000f0 },
- { 0x0d, 0x90100210 },
- { 0x10, 0x400003f1 },
- { 0x11, 0x9033032e },
- {}
-};
-
-static const struct hda_pintbl stac925xM6_pin_configs[] = {
- { 0x07, 0x40c003f4 },
- { 0x08, 0x424503f2 },
- { 0x0a, 0x400000f3 },
- { 0x0b, 0x02a19020 },
- { 0x0c, 0x40a000f0 },
- { 0x0d, 0x90100210 },
- { 0x10, 0x400003f1 },
- { 0x11, 0x90330320 },
- {}
-};
-
-static const struct hda_fixup stac925x_fixups[] = {
- [STAC_REF] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = ref925x_pin_configs,
- },
- [STAC_M1] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = stac925xM1_pin_configs,
- },
- [STAC_M1_2] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = stac925xM1_2_pin_configs,
- },
- [STAC_M2] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = stac925xM2_pin_configs,
- },
- [STAC_M2_2] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = stac925xM2_2_pin_configs,
- },
- [STAC_M3] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = stac925xM3_pin_configs,
- },
- [STAC_M5] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = stac925xM5_pin_configs,
- },
- [STAC_M6] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = stac925xM6_pin_configs,
- },
-};
-
-static const struct hda_model_fixup stac925x_models[] = {
- { .id = STAC_REF, .name = "ref" },
- { .id = STAC_M1, .name = "m1" },
- { .id = STAC_M1_2, .name = "m1-2" },
- { .id = STAC_M2, .name = "m2" },
- { .id = STAC_M2_2, .name = "m2-2" },
- { .id = STAC_M3, .name = "m3" },
- { .id = STAC_M5, .name = "m5" },
- { .id = STAC_M6, .name = "m6" },
- {}
-};
-
-static const struct hda_quirk stac925x_fixup_tbl[] = {
- /* SigmaTel reference board */
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, "DFI LanParty", STAC_REF),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, "DFI LanParty", STAC_REF),
- SND_PCI_QUIRK(0x8384, 0x7632, "Stac9202 Reference Board", STAC_REF),
-
- /* Default table for unknown ID */
- SND_PCI_QUIRK(0x1002, 0x437b, "Gateway mobile", STAC_M2_2),
-
- /* gateway machines are checked via codec ssid */
- SND_PCI_QUIRK(0x107b, 0x0316, "Gateway M255", STAC_M2),
- SND_PCI_QUIRK(0x107b, 0x0366, "Gateway MP6954", STAC_M5),
- SND_PCI_QUIRK(0x107b, 0x0461, "Gateway NX560XL", STAC_M1),
- SND_PCI_QUIRK(0x107b, 0x0681, "Gateway NX860", STAC_M2),
- SND_PCI_QUIRK(0x107b, 0x0367, "Gateway MX6453", STAC_M1_2),
- /* Not sure about the brand name for those */
- SND_PCI_QUIRK(0x107b, 0x0281, "Gateway mobile", STAC_M1),
- SND_PCI_QUIRK(0x107b, 0x0507, "Gateway mobile", STAC_M3),
- SND_PCI_QUIRK(0x107b, 0x0281, "Gateway mobile", STAC_M6),
- SND_PCI_QUIRK(0x107b, 0x0685, "Gateway mobile", STAC_M2_2),
- {} /* terminator */
-};
-
-static const struct hda_pintbl ref92hd73xx_pin_configs[] = {
- // Port A-H
- { 0x0a, 0x02214030 },
- { 0x0b, 0x02a19040 },
- { 0x0c, 0x01a19020 },
- { 0x0d, 0x02214030 },
- { 0x0e, 0x0181302e },
- { 0x0f, 0x01014010 },
- { 0x10, 0x01014020 },
- { 0x11, 0x01014030 },
- // CD in
- { 0x12, 0x02319040 },
- // Digial Mic ins
- { 0x13, 0x90a000f0 },
- { 0x14, 0x90a000f0 },
- // Digital outs
- { 0x22, 0x01452050 },
- { 0x23, 0x01452050 },
- {}
-};
-
-static const struct hda_pintbl dell_m6_pin_configs[] = {
- { 0x0a, 0x0321101f },
- { 0x0b, 0x4f00000f },
- { 0x0c, 0x4f0000f0 },
- { 0x0d, 0x90170110 },
- { 0x0e, 0x03a11020 },
- { 0x0f, 0x0321101f },
- { 0x10, 0x4f0000f0 },
- { 0x11, 0x4f0000f0 },
- { 0x12, 0x4f0000f0 },
- { 0x13, 0x90a60160 },
- { 0x14, 0x4f0000f0 },
- { 0x22, 0x4f0000f0 },
- { 0x23, 0x4f0000f0 },
- {}
-};
-
-static const struct hda_pintbl alienware_m17x_pin_configs[] = {
- { 0x0a, 0x0321101f },
- { 0x0b, 0x0321101f },
- { 0x0c, 0x03a11020 },
- { 0x0d, 0x03014020 },
- { 0x0e, 0x90170110 },
- { 0x0f, 0x4f0000f0 },
- { 0x10, 0x4f0000f0 },
- { 0x11, 0x4f0000f0 },
- { 0x12, 0x4f0000f0 },
- { 0x13, 0x90a60160 },
- { 0x14, 0x4f0000f0 },
- { 0x22, 0x4f0000f0 },
- { 0x23, 0x904601b0 },
- {}
-};
-
-static const struct hda_pintbl intel_dg45id_pin_configs[] = {
- // Analog outputs
- { 0x0a, 0x02214230 },
- { 0x0b, 0x02A19240 },
- { 0x0c, 0x01013214 },
- { 0x0d, 0x01014210 },
- { 0x0e, 0x01A19250 },
- { 0x0f, 0x01011212 },
- { 0x10, 0x01016211 },
- // Digital output
- { 0x22, 0x01451380 },
- { 0x23, 0x40f000f0 },
- {}
-};
-
-static const struct hda_pintbl stac92hd89xx_hp_front_jack_pin_configs[] = {
- { 0x0a, 0x02214030 },
- { 0x0b, 0x02A19010 },
- {}
-};
-
-static const struct hda_pintbl stac92hd89xx_hp_z1_g2_right_mic_jack_pin_configs[] = {
- { 0x0e, 0x400000f0 },
- {}
-};
-
-static void stac92hd73xx_fixup_ref(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- if (action != HDA_FIXUP_ACT_PRE_PROBE)
- return;
-
- snd_hda_apply_pincfgs(codec, ref92hd73xx_pin_configs);
- spec->gpio_mask = spec->gpio_dir = spec->gpio_data = 0;
-}
-
-static void stac92hd73xx_fixup_dell(struct hda_codec *codec)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- snd_hda_apply_pincfgs(codec, dell_m6_pin_configs);
- spec->eapd_switch = 0;
-}
-
-static void stac92hd73xx_fixup_dell_eq(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- if (action != HDA_FIXUP_ACT_PRE_PROBE)
- return;
-
- stac92hd73xx_fixup_dell(codec);
- snd_hda_add_verbs(codec, dell_eq_core_init);
- spec->volknob_init = 1;
-}
-
-/* Analog Mics */
-static void stac92hd73xx_fixup_dell_m6_amic(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action != HDA_FIXUP_ACT_PRE_PROBE)
- return;
-
- stac92hd73xx_fixup_dell(codec);
- snd_hda_codec_set_pincfg(codec, 0x0b, 0x90A70170);
-}
-
-/* Digital Mics */
-static void stac92hd73xx_fixup_dell_m6_dmic(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action != HDA_FIXUP_ACT_PRE_PROBE)
- return;
-
- stac92hd73xx_fixup_dell(codec);
- snd_hda_codec_set_pincfg(codec, 0x13, 0x90A60160);
-}
-
-/* Both */
-static void stac92hd73xx_fixup_dell_m6_both(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action != HDA_FIXUP_ACT_PRE_PROBE)
- return;
-
- stac92hd73xx_fixup_dell(codec);
- snd_hda_codec_set_pincfg(codec, 0x0b, 0x90A70170);
- snd_hda_codec_set_pincfg(codec, 0x13, 0x90A60160);
-}
-
-static void stac92hd73xx_fixup_alienware_m17x(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- if (action != HDA_FIXUP_ACT_PRE_PROBE)
- return;
-
- snd_hda_apply_pincfgs(codec, alienware_m17x_pin_configs);
- spec->eapd_switch = 0;
-}
-
-static void stac92hd73xx_fixup_no_jd(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_PRE_PROBE)
- codec->no_jack_detect = 1;
-}
-
-
-static void stac92hd73xx_disable_automute(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- if (action != HDA_FIXUP_ACT_PRE_PROBE)
- return;
-
- spec->gen.suppress_auto_mute = 1;
-}
-
-static const struct hda_fixup stac92hd73xx_fixups[] = {
- [STAC_92HD73XX_REF] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = stac92hd73xx_fixup_ref,
- },
- [STAC_DELL_M6_AMIC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = stac92hd73xx_fixup_dell_m6_amic,
- },
- [STAC_DELL_M6_DMIC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = stac92hd73xx_fixup_dell_m6_dmic,
- },
- [STAC_DELL_M6_BOTH] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = stac92hd73xx_fixup_dell_m6_both,
- },
- [STAC_DELL_EQ] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = stac92hd73xx_fixup_dell_eq,
- },
- [STAC_ALIENWARE_M17X] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = stac92hd73xx_fixup_alienware_m17x,
- },
- [STAC_ELO_VUPOINT_15MX] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = stac92hd73xx_disable_automute,
- },
- [STAC_92HD73XX_INTEL] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = intel_dg45id_pin_configs,
- },
- [STAC_92HD73XX_NO_JD] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = stac92hd73xx_fixup_no_jd,
- },
- [STAC_92HD89XX_HP_FRONT_JACK] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = stac92hd89xx_hp_front_jack_pin_configs,
- },
- [STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = stac92hd89xx_hp_z1_g2_right_mic_jack_pin_configs,
- },
- [STAC_92HD73XX_ASUS_MOBO] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- /* enable 5.1 and SPDIF out */
- { 0x0c, 0x01014411 },
- { 0x0d, 0x01014410 },
- { 0x0e, 0x01014412 },
- { 0x22, 0x014b1180 },
- { }
- }
- },
-};
-
-static const struct hda_model_fixup stac92hd73xx_models[] = {
- { .id = STAC_92HD73XX_NO_JD, .name = "no-jd" },
- { .id = STAC_92HD73XX_REF, .name = "ref" },
- { .id = STAC_92HD73XX_INTEL, .name = "intel" },
- { .id = STAC_DELL_M6_AMIC, .name = "dell-m6-amic" },
- { .id = STAC_DELL_M6_DMIC, .name = "dell-m6-dmic" },
- { .id = STAC_DELL_M6_BOTH, .name = "dell-m6" },
- { .id = STAC_DELL_EQ, .name = "dell-eq" },
- { .id = STAC_ALIENWARE_M17X, .name = "alienware" },
- { .id = STAC_ELO_VUPOINT_15MX, .name = "elo-vupoint-15mx" },
- { .id = STAC_92HD73XX_ASUS_MOBO, .name = "asus-mobo" },
- {}
-};
-
-static const struct hda_quirk stac92hd73xx_fixup_tbl[] = {
- /* SigmaTel reference board */
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
- "DFI LanParty", STAC_92HD73XX_REF),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101,
- "DFI LanParty", STAC_92HD73XX_REF),
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5001,
- "Intel DP45SG", STAC_92HD73XX_INTEL),
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5002,
- "Intel DG45ID", STAC_92HD73XX_INTEL),
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5003,
- "Intel DG45FC", STAC_92HD73XX_INTEL),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0254,
- "Dell Studio 1535", STAC_DELL_M6_DMIC),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0255,
- "unknown Dell", STAC_DELL_M6_DMIC),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0256,
- "unknown Dell", STAC_DELL_M6_BOTH),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0257,
- "unknown Dell", STAC_DELL_M6_BOTH),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x025e,
- "unknown Dell", STAC_DELL_M6_AMIC),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x025f,
- "unknown Dell", STAC_DELL_M6_AMIC),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0271,
- "unknown Dell", STAC_DELL_M6_DMIC),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0272,
- "unknown Dell", STAC_DELL_M6_DMIC),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x029f,
- "Dell Studio 1537", STAC_DELL_M6_DMIC),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02a0,
- "Dell Studio 17", STAC_DELL_M6_DMIC),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02be,
- "Dell Studio 1555", STAC_DELL_M6_DMIC),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02bd,
- "Dell Studio 1557", STAC_DELL_M6_DMIC),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02fe,
- "Dell Studio XPS 1645", STAC_DELL_M6_DMIC),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0413,
- "Dell Studio 1558", STAC_DELL_M6_DMIC),
- /* codec SSID matching */
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02a1,
- "Alienware M17x", STAC_ALIENWARE_M17X),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x043a,
- "Alienware M17x", STAC_ALIENWARE_M17X),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0490,
- "Alienware M17x R3", STAC_DELL_EQ),
- SND_PCI_QUIRK(0x1059, 0x1011,
- "ELO VuPoint 15MX", STAC_ELO_VUPOINT_15MX),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1927,
- "HP Z1 G2", STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2b17,
- "unknown HP", STAC_92HD89XX_HP_FRONT_JACK),
- SND_PCI_QUIRK(PCI_VENDOR_ID_ASUSTEK, 0x83f8, "ASUS AT4NM10",
- STAC_92HD73XX_ASUS_MOBO),
- {} /* terminator */
-};
-
-static const struct hda_pintbl ref92hd83xxx_pin_configs[] = {
- { 0x0a, 0x02214030 },
- { 0x0b, 0x02211010 },
- { 0x0c, 0x02a19020 },
- { 0x0d, 0x02170130 },
- { 0x0e, 0x01014050 },
- { 0x0f, 0x01819040 },
- { 0x10, 0x01014020 },
- { 0x11, 0x90a3014e },
- { 0x1f, 0x01451160 },
- { 0x20, 0x98560170 },
- {}
-};
-
-static const struct hda_pintbl dell_s14_pin_configs[] = {
- { 0x0a, 0x0221403f },
- { 0x0b, 0x0221101f },
- { 0x0c, 0x02a19020 },
- { 0x0d, 0x90170110 },
- { 0x0e, 0x40f000f0 },
- { 0x0f, 0x40f000f0 },
- { 0x10, 0x40f000f0 },
- { 0x11, 0x90a60160 },
- { 0x1f, 0x40f000f0 },
- { 0x20, 0x40f000f0 },
- {}
-};
-
-static const struct hda_pintbl dell_vostro_3500_pin_configs[] = {
- { 0x0a, 0x02a11020 },
- { 0x0b, 0x0221101f },
- { 0x0c, 0x400000f0 },
- { 0x0d, 0x90170110 },
- { 0x0e, 0x400000f1 },
- { 0x0f, 0x400000f2 },
- { 0x10, 0x400000f3 },
- { 0x11, 0x90a60160 },
- { 0x1f, 0x400000f4 },
- { 0x20, 0x400000f5 },
- {}
-};
-
-static const struct hda_pintbl hp_dv7_4000_pin_configs[] = {
- { 0x0a, 0x03a12050 },
- { 0x0b, 0x0321201f },
- { 0x0c, 0x40f000f0 },
- { 0x0d, 0x90170110 },
- { 0x0e, 0x40f000f0 },
- { 0x0f, 0x40f000f0 },
- { 0x10, 0x90170110 },
- { 0x11, 0xd5a30140 },
- { 0x1f, 0x40f000f0 },
- { 0x20, 0x40f000f0 },
- {}
-};
-
-static const struct hda_pintbl hp_zephyr_pin_configs[] = {
- { 0x0a, 0x01813050 },
- { 0x0b, 0x0421201f },
- { 0x0c, 0x04a1205e },
- { 0x0d, 0x96130310 },
- { 0x0e, 0x96130310 },
- { 0x0f, 0x0101401f },
- { 0x10, 0x1111611f },
- { 0x11, 0xd5a30130 },
- {}
-};
-
-static const struct hda_pintbl hp_cNB11_intquad_pin_configs[] = {
- { 0x0a, 0x40f000f0 },
- { 0x0b, 0x0221101f },
- { 0x0c, 0x02a11020 },
- { 0x0d, 0x92170110 },
- { 0x0e, 0x40f000f0 },
- { 0x0f, 0x92170110 },
- { 0x10, 0x40f000f0 },
- { 0x11, 0xd5a30130 },
- { 0x1f, 0x40f000f0 },
- { 0x20, 0x40f000f0 },
- {}
-};
-
-static void stac92hd83xxx_fixup_hp(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- if (action != HDA_FIXUP_ACT_PRE_PROBE)
- return;
-
- if (hp_bnb2011_with_dock(codec)) {
- snd_hda_codec_set_pincfg(codec, 0xa, 0x2101201f);
- snd_hda_codec_set_pincfg(codec, 0xf, 0x2181205e);
- }
-
- if (find_mute_led_cfg(codec, spec->default_polarity))
- codec_dbg(codec, "mute LED gpio %d polarity %d\n",
- spec->gpio_led,
- spec->gpio_led_polarity);
-
- /* allow auto-switching of dock line-in */
- spec->gen.line_in_auto_switch = true;
-}
-
-static void stac92hd83xxx_fixup_hp_zephyr(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action != HDA_FIXUP_ACT_PRE_PROBE)
- return;
-
- snd_hda_apply_pincfgs(codec, hp_zephyr_pin_configs);
- snd_hda_add_verbs(codec, stac92hd83xxx_hp_zephyr_init);
-}
-
-static void stac92hd83xxx_fixup_hp_led(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE)
- spec->default_polarity = 0;
-}
-
-static void stac92hd83xxx_fixup_hp_inv_led(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE)
- spec->default_polarity = 1;
-}
-
-static void stac92hd83xxx_fixup_hp_mic_led(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->mic_mute_led_gpio = 0x08; /* GPIO3 */
- /* resetting controller clears GPIO, so we need to keep on */
- codec->core.power_caps &= ~AC_PWRST_CLKSTOP;
- }
-}
-
-static void stac92hd83xxx_fixup_hp_led_gpio10(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->gpio_led = 0x10; /* GPIO4 */
- spec->default_polarity = 0;
- }
-}
-
-static void stac92hd83xxx_fixup_headset_jack(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE)
- spec->headset_jack = 1;
-}
-
-static void stac92hd83xxx_fixup_gpio10_eapd(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- if (action != HDA_FIXUP_ACT_PRE_PROBE)
- return;
- spec->eapd_mask = spec->gpio_mask = spec->gpio_dir =
- spec->gpio_data = 0x10;
- spec->eapd_switch = 0;
-}
-
-static void hp_envy_ts_fixup_dac_bind(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- struct sigmatel_spec *spec = codec->spec;
- static const hda_nid_t preferred_pairs[] = {
- 0xd, 0x13,
- 0
- };
-
- if (action != HDA_FIXUP_ACT_PRE_PROBE)
- return;
-
- spec->gen.preferred_dacs = preferred_pairs;
-}
-
-static const struct hda_verb hp_bnb13_eq_verbs[] = {
- /* 44.1KHz base */
- { 0x22, 0x7A6, 0x3E },
- { 0x22, 0x7A7, 0x68 },
- { 0x22, 0x7A8, 0x17 },
- { 0x22, 0x7A9, 0x3E },
- { 0x22, 0x7AA, 0x68 },
- { 0x22, 0x7AB, 0x17 },
- { 0x22, 0x7AC, 0x00 },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x83 },
- { 0x22, 0x7A7, 0x2F },
- { 0x22, 0x7A8, 0xD1 },
- { 0x22, 0x7A9, 0x83 },
- { 0x22, 0x7AA, 0x2F },
- { 0x22, 0x7AB, 0xD1 },
- { 0x22, 0x7AC, 0x01 },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x3E },
- { 0x22, 0x7A7, 0x68 },
- { 0x22, 0x7A8, 0x17 },
- { 0x22, 0x7A9, 0x3E },
- { 0x22, 0x7AA, 0x68 },
- { 0x22, 0x7AB, 0x17 },
- { 0x22, 0x7AC, 0x02 },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x7C },
- { 0x22, 0x7A7, 0xC6 },
- { 0x22, 0x7A8, 0x0C },
- { 0x22, 0x7A9, 0x7C },
- { 0x22, 0x7AA, 0xC6 },
- { 0x22, 0x7AB, 0x0C },
- { 0x22, 0x7AC, 0x03 },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0xC3 },
- { 0x22, 0x7A7, 0x25 },
- { 0x22, 0x7A8, 0xAF },
- { 0x22, 0x7A9, 0xC3 },
- { 0x22, 0x7AA, 0x25 },
- { 0x22, 0x7AB, 0xAF },
- { 0x22, 0x7AC, 0x04 },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x3E },
- { 0x22, 0x7A7, 0x85 },
- { 0x22, 0x7A8, 0x73 },
- { 0x22, 0x7A9, 0x3E },
- { 0x22, 0x7AA, 0x85 },
- { 0x22, 0x7AB, 0x73 },
- { 0x22, 0x7AC, 0x05 },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x85 },
- { 0x22, 0x7A7, 0x39 },
- { 0x22, 0x7A8, 0xC7 },
- { 0x22, 0x7A9, 0x85 },
- { 0x22, 0x7AA, 0x39 },
- { 0x22, 0x7AB, 0xC7 },
- { 0x22, 0x7AC, 0x06 },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x3C },
- { 0x22, 0x7A7, 0x90 },
- { 0x22, 0x7A8, 0xB0 },
- { 0x22, 0x7A9, 0x3C },
- { 0x22, 0x7AA, 0x90 },
- { 0x22, 0x7AB, 0xB0 },
- { 0x22, 0x7AC, 0x07 },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x7A },
- { 0x22, 0x7A7, 0xC6 },
- { 0x22, 0x7A8, 0x39 },
- { 0x22, 0x7A9, 0x7A },
- { 0x22, 0x7AA, 0xC6 },
- { 0x22, 0x7AB, 0x39 },
- { 0x22, 0x7AC, 0x08 },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0xC4 },
- { 0x22, 0x7A7, 0xE9 },
- { 0x22, 0x7A8, 0xDC },
- { 0x22, 0x7A9, 0xC4 },
- { 0x22, 0x7AA, 0xE9 },
- { 0x22, 0x7AB, 0xDC },
- { 0x22, 0x7AC, 0x09 },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x3D },
- { 0x22, 0x7A7, 0xE1 },
- { 0x22, 0x7A8, 0x0D },
- { 0x22, 0x7A9, 0x3D },
- { 0x22, 0x7AA, 0xE1 },
- { 0x22, 0x7AB, 0x0D },
- { 0x22, 0x7AC, 0x0A },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x89 },
- { 0x22, 0x7A7, 0xB6 },
- { 0x22, 0x7A8, 0xEB },
- { 0x22, 0x7A9, 0x89 },
- { 0x22, 0x7AA, 0xB6 },
- { 0x22, 0x7AB, 0xEB },
- { 0x22, 0x7AC, 0x0B },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x39 },
- { 0x22, 0x7A7, 0x9D },
- { 0x22, 0x7A8, 0xFE },
- { 0x22, 0x7A9, 0x39 },
- { 0x22, 0x7AA, 0x9D },
- { 0x22, 0x7AB, 0xFE },
- { 0x22, 0x7AC, 0x0C },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x76 },
- { 0x22, 0x7A7, 0x49 },
- { 0x22, 0x7A8, 0x15 },
- { 0x22, 0x7A9, 0x76 },
- { 0x22, 0x7AA, 0x49 },
- { 0x22, 0x7AB, 0x15 },
- { 0x22, 0x7AC, 0x0D },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0xC8 },
- { 0x22, 0x7A7, 0x80 },
- { 0x22, 0x7A8, 0xF5 },
- { 0x22, 0x7A9, 0xC8 },
- { 0x22, 0x7AA, 0x80 },
- { 0x22, 0x7AB, 0xF5 },
- { 0x22, 0x7AC, 0x0E },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x40 },
- { 0x22, 0x7A7, 0x00 },
- { 0x22, 0x7A8, 0x00 },
- { 0x22, 0x7A9, 0x40 },
- { 0x22, 0x7AA, 0x00 },
- { 0x22, 0x7AB, 0x00 },
- { 0x22, 0x7AC, 0x0F },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x90 },
- { 0x22, 0x7A7, 0x68 },
- { 0x22, 0x7A8, 0xF1 },
- { 0x22, 0x7A9, 0x90 },
- { 0x22, 0x7AA, 0x68 },
- { 0x22, 0x7AB, 0xF1 },
- { 0x22, 0x7AC, 0x10 },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x34 },
- { 0x22, 0x7A7, 0x47 },
- { 0x22, 0x7A8, 0x6C },
- { 0x22, 0x7A9, 0x34 },
- { 0x22, 0x7AA, 0x47 },
- { 0x22, 0x7AB, 0x6C },
- { 0x22, 0x7AC, 0x11 },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x6F },
- { 0x22, 0x7A7, 0x97 },
- { 0x22, 0x7A8, 0x0F },
- { 0x22, 0x7A9, 0x6F },
- { 0x22, 0x7AA, 0x97 },
- { 0x22, 0x7AB, 0x0F },
- { 0x22, 0x7AC, 0x12 },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0xCB },
- { 0x22, 0x7A7, 0xB8 },
- { 0x22, 0x7A8, 0x94 },
- { 0x22, 0x7A9, 0xCB },
- { 0x22, 0x7AA, 0xB8 },
- { 0x22, 0x7AB, 0x94 },
- { 0x22, 0x7AC, 0x13 },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x40 },
- { 0x22, 0x7A7, 0x00 },
- { 0x22, 0x7A8, 0x00 },
- { 0x22, 0x7A9, 0x40 },
- { 0x22, 0x7AA, 0x00 },
- { 0x22, 0x7AB, 0x00 },
- { 0x22, 0x7AC, 0x14 },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x95 },
- { 0x22, 0x7A7, 0x76 },
- { 0x22, 0x7A8, 0x5B },
- { 0x22, 0x7A9, 0x95 },
- { 0x22, 0x7AA, 0x76 },
- { 0x22, 0x7AB, 0x5B },
- { 0x22, 0x7AC, 0x15 },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x31 },
- { 0x22, 0x7A7, 0xAC },
- { 0x22, 0x7A8, 0x31 },
- { 0x22, 0x7A9, 0x31 },
- { 0x22, 0x7AA, 0xAC },
- { 0x22, 0x7AB, 0x31 },
- { 0x22, 0x7AC, 0x16 },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x6A },
- { 0x22, 0x7A7, 0x89 },
- { 0x22, 0x7A8, 0xA5 },
- { 0x22, 0x7A9, 0x6A },
- { 0x22, 0x7AA, 0x89 },
- { 0x22, 0x7AB, 0xA5 },
- { 0x22, 0x7AC, 0x17 },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0xCE },
- { 0x22, 0x7A7, 0x53 },
- { 0x22, 0x7A8, 0xCF },
- { 0x22, 0x7A9, 0xCE },
- { 0x22, 0x7AA, 0x53 },
- { 0x22, 0x7AB, 0xCF },
- { 0x22, 0x7AC, 0x18 },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x40 },
- { 0x22, 0x7A7, 0x00 },
- { 0x22, 0x7A8, 0x00 },
- { 0x22, 0x7A9, 0x40 },
- { 0x22, 0x7AA, 0x00 },
- { 0x22, 0x7AB, 0x00 },
- { 0x22, 0x7AC, 0x19 },
- { 0x22, 0x7AD, 0x80 },
- /* 48KHz base */
- { 0x22, 0x7A6, 0x3E },
- { 0x22, 0x7A7, 0x88 },
- { 0x22, 0x7A8, 0xDC },
- { 0x22, 0x7A9, 0x3E },
- { 0x22, 0x7AA, 0x88 },
- { 0x22, 0x7AB, 0xDC },
- { 0x22, 0x7AC, 0x1A },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x82 },
- { 0x22, 0x7A7, 0xEE },
- { 0x22, 0x7A8, 0x46 },
- { 0x22, 0x7A9, 0x82 },
- { 0x22, 0x7AA, 0xEE },
- { 0x22, 0x7AB, 0x46 },
- { 0x22, 0x7AC, 0x1B },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x3E },
- { 0x22, 0x7A7, 0x88 },
- { 0x22, 0x7A8, 0xDC },
- { 0x22, 0x7A9, 0x3E },
- { 0x22, 0x7AA, 0x88 },
- { 0x22, 0x7AB, 0xDC },
- { 0x22, 0x7AC, 0x1C },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x7D },
- { 0x22, 0x7A7, 0x09 },
- { 0x22, 0x7A8, 0x28 },
- { 0x22, 0x7A9, 0x7D },
- { 0x22, 0x7AA, 0x09 },
- { 0x22, 0x7AB, 0x28 },
- { 0x22, 0x7AC, 0x1D },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0xC2 },
- { 0x22, 0x7A7, 0xE5 },
- { 0x22, 0x7A8, 0xB4 },
- { 0x22, 0x7A9, 0xC2 },
- { 0x22, 0x7AA, 0xE5 },
- { 0x22, 0x7AB, 0xB4 },
- { 0x22, 0x7AC, 0x1E },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x3E },
- { 0x22, 0x7A7, 0xA3 },
- { 0x22, 0x7A8, 0x1F },
- { 0x22, 0x7A9, 0x3E },
- { 0x22, 0x7AA, 0xA3 },
- { 0x22, 0x7AB, 0x1F },
- { 0x22, 0x7AC, 0x1F },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x84 },
- { 0x22, 0x7A7, 0xCA },
- { 0x22, 0x7A8, 0xF1 },
- { 0x22, 0x7A9, 0x84 },
- { 0x22, 0x7AA, 0xCA },
- { 0x22, 0x7AB, 0xF1 },
- { 0x22, 0x7AC, 0x20 },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x3C },
- { 0x22, 0x7A7, 0xD5 },
- { 0x22, 0x7A8, 0x9C },
- { 0x22, 0x7A9, 0x3C },
- { 0x22, 0x7AA, 0xD5 },
- { 0x22, 0x7AB, 0x9C },
- { 0x22, 0x7AC, 0x21 },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x7B },
- { 0x22, 0x7A7, 0x35 },
- { 0x22, 0x7A8, 0x0F },
- { 0x22, 0x7A9, 0x7B },
- { 0x22, 0x7AA, 0x35 },
- { 0x22, 0x7AB, 0x0F },
- { 0x22, 0x7AC, 0x22 },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0xC4 },
- { 0x22, 0x7A7, 0x87 },
- { 0x22, 0x7A8, 0x45 },
- { 0x22, 0x7A9, 0xC4 },
- { 0x22, 0x7AA, 0x87 },
- { 0x22, 0x7AB, 0x45 },
- { 0x22, 0x7AC, 0x23 },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x3E },
- { 0x22, 0x7A7, 0x0A },
- { 0x22, 0x7A8, 0x78 },
- { 0x22, 0x7A9, 0x3E },
- { 0x22, 0x7AA, 0x0A },
- { 0x22, 0x7AB, 0x78 },
- { 0x22, 0x7AC, 0x24 },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x88 },
- { 0x22, 0x7A7, 0xE2 },
- { 0x22, 0x7A8, 0x05 },
- { 0x22, 0x7A9, 0x88 },
- { 0x22, 0x7AA, 0xE2 },
- { 0x22, 0x7AB, 0x05 },
- { 0x22, 0x7AC, 0x25 },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x3A },
- { 0x22, 0x7A7, 0x1A },
- { 0x22, 0x7A8, 0xA3 },
- { 0x22, 0x7A9, 0x3A },
- { 0x22, 0x7AA, 0x1A },
- { 0x22, 0x7AB, 0xA3 },
- { 0x22, 0x7AC, 0x26 },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x77 },
- { 0x22, 0x7A7, 0x1D },
- { 0x22, 0x7A8, 0xFB },
- { 0x22, 0x7A9, 0x77 },
- { 0x22, 0x7AA, 0x1D },
- { 0x22, 0x7AB, 0xFB },
- { 0x22, 0x7AC, 0x27 },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0xC7 },
- { 0x22, 0x7A7, 0xDA },
- { 0x22, 0x7A8, 0xE5 },
- { 0x22, 0x7A9, 0xC7 },
- { 0x22, 0x7AA, 0xDA },
- { 0x22, 0x7AB, 0xE5 },
- { 0x22, 0x7AC, 0x28 },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x40 },
- { 0x22, 0x7A7, 0x00 },
- { 0x22, 0x7A8, 0x00 },
- { 0x22, 0x7A9, 0x40 },
- { 0x22, 0x7AA, 0x00 },
- { 0x22, 0x7AB, 0x00 },
- { 0x22, 0x7AC, 0x29 },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x8E },
- { 0x22, 0x7A7, 0xD7 },
- { 0x22, 0x7A8, 0x22 },
- { 0x22, 0x7A9, 0x8E },
- { 0x22, 0x7AA, 0xD7 },
- { 0x22, 0x7AB, 0x22 },
- { 0x22, 0x7AC, 0x2A },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x35 },
- { 0x22, 0x7A7, 0x26 },
- { 0x22, 0x7A8, 0xC6 },
- { 0x22, 0x7A9, 0x35 },
- { 0x22, 0x7AA, 0x26 },
- { 0x22, 0x7AB, 0xC6 },
- { 0x22, 0x7AC, 0x2B },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x71 },
- { 0x22, 0x7A7, 0x28 },
- { 0x22, 0x7A8, 0xDE },
- { 0x22, 0x7A9, 0x71 },
- { 0x22, 0x7AA, 0x28 },
- { 0x22, 0x7AB, 0xDE },
- { 0x22, 0x7AC, 0x2C },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0xCA },
- { 0x22, 0x7A7, 0xD9 },
- { 0x22, 0x7A8, 0x3A },
- { 0x22, 0x7A9, 0xCA },
- { 0x22, 0x7AA, 0xD9 },
- { 0x22, 0x7AB, 0x3A },
- { 0x22, 0x7AC, 0x2D },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x40 },
- { 0x22, 0x7A7, 0x00 },
- { 0x22, 0x7A8, 0x00 },
- { 0x22, 0x7A9, 0x40 },
- { 0x22, 0x7AA, 0x00 },
- { 0x22, 0x7AB, 0x00 },
- { 0x22, 0x7AC, 0x2E },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x93 },
- { 0x22, 0x7A7, 0x5E },
- { 0x22, 0x7A8, 0xD8 },
- { 0x22, 0x7A9, 0x93 },
- { 0x22, 0x7AA, 0x5E },
- { 0x22, 0x7AB, 0xD8 },
- { 0x22, 0x7AC, 0x2F },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x32 },
- { 0x22, 0x7A7, 0xB7 },
- { 0x22, 0x7A8, 0xB1 },
- { 0x22, 0x7A9, 0x32 },
- { 0x22, 0x7AA, 0xB7 },
- { 0x22, 0x7AB, 0xB1 },
- { 0x22, 0x7AC, 0x30 },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x6C },
- { 0x22, 0x7A7, 0xA1 },
- { 0x22, 0x7A8, 0x28 },
- { 0x22, 0x7A9, 0x6C },
- { 0x22, 0x7AA, 0xA1 },
- { 0x22, 0x7AB, 0x28 },
- { 0x22, 0x7AC, 0x31 },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0xCD },
- { 0x22, 0x7A7, 0x48 },
- { 0x22, 0x7A8, 0x4F },
- { 0x22, 0x7A9, 0xCD },
- { 0x22, 0x7AA, 0x48 },
- { 0x22, 0x7AB, 0x4F },
- { 0x22, 0x7AC, 0x32 },
- { 0x22, 0x7AD, 0x80 },
- { 0x22, 0x7A6, 0x40 },
- { 0x22, 0x7A7, 0x00 },
- { 0x22, 0x7A8, 0x00 },
- { 0x22, 0x7A9, 0x40 },
- { 0x22, 0x7AA, 0x00 },
- { 0x22, 0x7AB, 0x00 },
- { 0x22, 0x7AC, 0x33 },
- { 0x22, 0x7AD, 0x80 },
- /* common */
- { 0x22, 0x782, 0xC1 },
- { 0x22, 0x771, 0x2C },
- { 0x22, 0x772, 0x2C },
- { 0x22, 0x788, 0x04 },
- { 0x01, 0x7B0, 0x08 },
- {}
-};
-
-static const struct hda_fixup stac92hd83xxx_fixups[] = {
- [STAC_92HD83XXX_REF] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = ref92hd83xxx_pin_configs,
- },
- [STAC_92HD83XXX_PWR_REF] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = ref92hd83xxx_pin_configs,
- },
- [STAC_DELL_S14] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = dell_s14_pin_configs,
- },
- [STAC_DELL_VOSTRO_3500] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = dell_vostro_3500_pin_configs,
- },
- [STAC_92HD83XXX_HP_cNB11_INTQUAD] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = hp_cNB11_intquad_pin_configs,
- .chained = true,
- .chain_id = STAC_92HD83XXX_HP,
- },
- [STAC_92HD83XXX_HP] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = stac92hd83xxx_fixup_hp,
- },
- [STAC_HP_DV7_4000] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = hp_dv7_4000_pin_configs,
- .chained = true,
- .chain_id = STAC_92HD83XXX_HP,
- },
- [STAC_HP_ZEPHYR] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = stac92hd83xxx_fixup_hp_zephyr,
- .chained = true,
- .chain_id = STAC_92HD83XXX_HP,
- },
- [STAC_92HD83XXX_HP_LED] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = stac92hd83xxx_fixup_hp_led,
- .chained = true,
- .chain_id = STAC_92HD83XXX_HP,
- },
- [STAC_92HD83XXX_HP_INV_LED] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = stac92hd83xxx_fixup_hp_inv_led,
- .chained = true,
- .chain_id = STAC_92HD83XXX_HP,
- },
- [STAC_92HD83XXX_HP_MIC_LED] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = stac92hd83xxx_fixup_hp_mic_led,
- .chained = true,
- .chain_id = STAC_92HD83XXX_HP,
- },
- [STAC_HP_LED_GPIO10] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = stac92hd83xxx_fixup_hp_led_gpio10,
- .chained = true,
- .chain_id = STAC_92HD83XXX_HP,
- },
- [STAC_92HD83XXX_HEADSET_JACK] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = stac92hd83xxx_fixup_headset_jack,
- },
- [STAC_HP_ENVY_BASS] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x0f, 0x90170111 },
- {}
- },
- },
- [STAC_HP_BNB13_EQ] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = hp_bnb13_eq_verbs,
- .chained = true,
- .chain_id = STAC_92HD83XXX_HP_MIC_LED,
- },
- [STAC_HP_ENVY_TS_BASS] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x10, 0x92170111 },
- {}
- },
- },
- [STAC_HP_ENVY_TS_DAC_BIND] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = hp_envy_ts_fixup_dac_bind,
- .chained = true,
- .chain_id = STAC_HP_ENVY_TS_BASS,
- },
- [STAC_92HD83XXX_GPIO10_EAPD] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = stac92hd83xxx_fixup_gpio10_eapd,
- },
-};
-
-static const struct hda_model_fixup stac92hd83xxx_models[] = {
- { .id = STAC_92HD83XXX_REF, .name = "ref" },
- { .id = STAC_92HD83XXX_PWR_REF, .name = "mic-ref" },
- { .id = STAC_DELL_S14, .name = "dell-s14" },
- { .id = STAC_DELL_VOSTRO_3500, .name = "dell-vostro-3500" },
- { .id = STAC_92HD83XXX_HP_cNB11_INTQUAD, .name = "hp_cNB11_intquad" },
- { .id = STAC_HP_DV7_4000, .name = "hp-dv7-4000" },
- { .id = STAC_HP_ZEPHYR, .name = "hp-zephyr" },
- { .id = STAC_92HD83XXX_HP_LED, .name = "hp-led" },
- { .id = STAC_92HD83XXX_HP_INV_LED, .name = "hp-inv-led" },
- { .id = STAC_92HD83XXX_HP_MIC_LED, .name = "hp-mic-led" },
- { .id = STAC_92HD83XXX_HEADSET_JACK, .name = "headset-jack" },
- { .id = STAC_HP_ENVY_BASS, .name = "hp-envy-bass" },
- { .id = STAC_HP_BNB13_EQ, .name = "hp-bnb13-eq" },
- { .id = STAC_HP_ENVY_TS_BASS, .name = "hp-envy-ts-bass" },
- {}
-};
-
-static const struct hda_quirk stac92hd83xxx_fixup_tbl[] = {
- /* SigmaTel reference board */
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
- "DFI LanParty", STAC_92HD83XXX_REF),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101,
- "DFI LanParty", STAC_92HD83XXX_REF),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba,
- "unknown Dell", STAC_DELL_S14),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0532,
- "Dell Latitude E6230", STAC_92HD83XXX_HEADSET_JACK),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0533,
- "Dell Latitude E6330", STAC_92HD83XXX_HEADSET_JACK),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0534,
- "Dell Latitude E6430", STAC_92HD83XXX_HEADSET_JACK),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0535,
- "Dell Latitude E6530", STAC_92HD83XXX_HEADSET_JACK),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x053c,
- "Dell Latitude E5430", STAC_92HD83XXX_HEADSET_JACK),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x053d,
- "Dell Latitude E5530", STAC_92HD83XXX_HEADSET_JACK),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0549,
- "Dell Latitude E5430", STAC_92HD83XXX_HEADSET_JACK),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x057d,
- "Dell Latitude E6430s", STAC_92HD83XXX_HEADSET_JACK),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0584,
- "Dell Latitude E6430U", STAC_92HD83XXX_HEADSET_JACK),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x1028,
- "Dell Vostro 3500", STAC_DELL_VOSTRO_3500),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1656,
- "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1657,
- "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1658,
- "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1659,
- "HP Pavilion dv7", STAC_HP_DV7_4000),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x165A,
- "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x165B,
- "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1888,
- "HP Envy Spectre", STAC_HP_ENVY_BASS),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1899,
- "HP Folio 13", STAC_HP_LED_GPIO10),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x18df,
- "HP Folio", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x18F8,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1909,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x190A,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x190e,
- "HP ENVY TS", STAC_HP_ENVY_TS_BASS),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1967,
- "HP ENVY TS", STAC_HP_ENVY_TS_DAC_BIND),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1940,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1941,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1942,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1943,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1944,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1945,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1946,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1948,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1949,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x194A,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x194B,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x194C,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x194E,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x194F,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1950,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1951,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x195A,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x195B,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x195C,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1991,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2103,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2104,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2105,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2106,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2107,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2108,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2109,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x210A,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x210B,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x211C,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x211D,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x211E,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x211F,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2120,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2121,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2122,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2123,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x213E,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x213F,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2140,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x21B2,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x21B3,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x21B5,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x21B6,
- "HP bNB13", STAC_HP_BNB13_EQ),
- SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xff00, 0x1900,
- "HP", STAC_92HD83XXX_HP_MIC_LED),
- SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xff00, 0x2000,
- "HP", STAC_92HD83XXX_HP_MIC_LED),
- SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xff00, 0x2100,
- "HP", STAC_92HD83XXX_HP_MIC_LED),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3388,
- "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3389,
- "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355B,
- "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355C,
- "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355D,
- "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355E,
- "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355F,
- "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3560,
- "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x358B,
- "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x358C,
- "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x358D,
- "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3591,
- "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3592,
- "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3593,
- "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3561,
- "HP", STAC_HP_ZEPHYR),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3660,
- "HP Mini", STAC_92HD83XXX_HP_LED),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x144E,
- "HP Pavilion dv5", STAC_92HD83XXX_HP_INV_LED),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x148a,
- "HP Mini", STAC_92HD83XXX_HP_LED),
- SND_PCI_QUIRK_VENDOR(PCI_VENDOR_ID_HP, "HP", STAC_92HD83XXX_HP),
- /* match both for 0xfa91 and 0xfa93 */
- SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_TOSHIBA, 0xfffd, 0xfa91,
- "Toshiba Satellite S50D", STAC_92HD83XXX_GPIO10_EAPD),
- {} /* terminator */
-};
-
-/* HP dv7 bass switch - GPIO5 */
-#define stac_hp_bass_gpio_info snd_ctl_boolean_mono_info
-static int stac_hp_bass_gpio_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct sigmatel_spec *spec = codec->spec;
- ucontrol->value.integer.value[0] = !!(spec->gpio_data & 0x20);
- return 0;
-}
-
-static int stac_hp_bass_gpio_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct sigmatel_spec *spec = codec->spec;
- unsigned int gpio_data;
-
- gpio_data = (spec->gpio_data & ~0x20) |
- (ucontrol->value.integer.value[0] ? 0x20 : 0);
- if (gpio_data == spec->gpio_data)
- return 0;
- spec->gpio_data = gpio_data;
- stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data);
- return 1;
-}
-
-static const struct snd_kcontrol_new stac_hp_bass_sw_ctrl = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .info = stac_hp_bass_gpio_info,
- .get = stac_hp_bass_gpio_get,
- .put = stac_hp_bass_gpio_put,
-};
-
-static int stac_add_hp_bass_switch(struct hda_codec *codec)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- if (!snd_hda_gen_add_kctl(&spec->gen, "Bass Speaker Playback Switch",
- &stac_hp_bass_sw_ctrl))
- return -ENOMEM;
-
- spec->gpio_mask |= 0x20;
- spec->gpio_dir |= 0x20;
- spec->gpio_data |= 0x20;
- return 0;
-}
-
-static const struct hda_pintbl ref92hd71bxx_pin_configs[] = {
- { 0x0a, 0x02214030 },
- { 0x0b, 0x02a19040 },
- { 0x0c, 0x01a19020 },
- { 0x0d, 0x01014010 },
- { 0x0e, 0x0181302e },
- { 0x0f, 0x01014010 },
- { 0x14, 0x01019020 },
- { 0x18, 0x90a000f0 },
- { 0x19, 0x90a000f0 },
- { 0x1e, 0x01452050 },
- { 0x1f, 0x01452050 },
- {}
-};
-
-static const struct hda_pintbl dell_m4_1_pin_configs[] = {
- { 0x0a, 0x0421101f },
- { 0x0b, 0x04a11221 },
- { 0x0c, 0x40f000f0 },
- { 0x0d, 0x90170110 },
- { 0x0e, 0x23a1902e },
- { 0x0f, 0x23014250 },
- { 0x14, 0x40f000f0 },
- { 0x18, 0x90a000f0 },
- { 0x19, 0x40f000f0 },
- { 0x1e, 0x4f0000f0 },
- { 0x1f, 0x4f0000f0 },
- {}
-};
-
-static const struct hda_pintbl dell_m4_2_pin_configs[] = {
- { 0x0a, 0x0421101f },
- { 0x0b, 0x04a11221 },
- { 0x0c, 0x90a70330 },
- { 0x0d, 0x90170110 },
- { 0x0e, 0x23a1902e },
- { 0x0f, 0x23014250 },
- { 0x14, 0x40f000f0 },
- { 0x18, 0x40f000f0 },
- { 0x19, 0x40f000f0 },
- { 0x1e, 0x044413b0 },
- { 0x1f, 0x044413b0 },
- {}
-};
-
-static const struct hda_pintbl dell_m4_3_pin_configs[] = {
- { 0x0a, 0x0421101f },
- { 0x0b, 0x04a11221 },
- { 0x0c, 0x90a70330 },
- { 0x0d, 0x90170110 },
- { 0x0e, 0x40f000f0 },
- { 0x0f, 0x40f000f0 },
- { 0x14, 0x40f000f0 },
- { 0x18, 0x90a000f0 },
- { 0x19, 0x40f000f0 },
- { 0x1e, 0x044413b0 },
- { 0x1f, 0x044413b0 },
- {}
-};
-
-static void stac92hd71bxx_fixup_ref(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- if (action != HDA_FIXUP_ACT_PRE_PROBE)
- return;
-
- snd_hda_apply_pincfgs(codec, ref92hd71bxx_pin_configs);
- spec->gpio_mask = spec->gpio_dir = spec->gpio_data = 0;
-}
-
-static void stac92hd71bxx_fixup_hp_m4(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct sigmatel_spec *spec = codec->spec;
- struct hda_jack_callback *jack;
-
- if (action != HDA_FIXUP_ACT_PRE_PROBE)
- return;
-
- /* Enable VREF power saving on GPIO1 detect */
- snd_hda_codec_write_cache(codec, codec->core.afg, 0,
- AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02);
- jack = snd_hda_jack_detect_enable_callback(codec, codec->core.afg,
- stac_vref_event);
- if (!IS_ERR(jack))
- jack->private_data = 0x02;
-
- spec->gpio_mask |= 0x02;
-
- /* enable internal microphone */
- snd_hda_codec_set_pincfg(codec, 0x0e, 0x01813040);
-}
-
-static void stac92hd71bxx_fixup_hp_dv4(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- if (action != HDA_FIXUP_ACT_PRE_PROBE)
- return;
- spec->gpio_led = 0x01;
-}
-
-static void stac92hd71bxx_fixup_hp_dv5(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- unsigned int cap;
-
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
- snd_hda_codec_set_pincfg(codec, 0x0d, 0x90170010);
- break;
-
- case HDA_FIXUP_ACT_PROBE:
- /* enable bass on HP dv7 */
- cap = snd_hda_param_read(codec, 0x1, AC_PAR_GPIO_CAP);
- cap &= AC_GPIO_IO_COUNT;
- if (cap >= 6)
- stac_add_hp_bass_switch(codec);
- break;
- }
-}
-
-static void stac92hd71bxx_fixup_hp_hdx(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- if (action != HDA_FIXUP_ACT_PRE_PROBE)
- return;
- spec->gpio_led = 0x08;
-}
-
-static bool is_hp_output(struct hda_codec *codec, hda_nid_t pin)
-{
- unsigned int pin_cfg = snd_hda_codec_get_pincfg(codec, pin);
-
- /* count line-out, too, as BIOS sets often so */
- return get_defcfg_connect(pin_cfg) != AC_JACK_PORT_NONE &&
- (get_defcfg_device(pin_cfg) == AC_JACK_LINE_OUT ||
- get_defcfg_device(pin_cfg) == AC_JACK_HP_OUT);
-}
-
-static void fixup_hp_headphone(struct hda_codec *codec, hda_nid_t pin)
-{
- unsigned int pin_cfg = snd_hda_codec_get_pincfg(codec, pin);
-
- /* It was changed in the BIOS to just satisfy MS DTM.
- * Lets turn it back into follower HP
- */
- pin_cfg = (pin_cfg & (~AC_DEFCFG_DEVICE)) |
- (AC_JACK_HP_OUT << AC_DEFCFG_DEVICE_SHIFT);
- pin_cfg = (pin_cfg & (~(AC_DEFCFG_DEF_ASSOC | AC_DEFCFG_SEQUENCE))) |
- 0x1f;
- snd_hda_codec_set_pincfg(codec, pin, pin_cfg);
-}
-
-static void stac92hd71bxx_fixup_hp(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- if (action != HDA_FIXUP_ACT_PRE_PROBE)
- return;
-
- /* when both output A and F are assigned, these are supposedly
- * dock and built-in headphones; fix both pin configs
- */
- if (is_hp_output(codec, 0x0a) && is_hp_output(codec, 0x0f)) {
- fixup_hp_headphone(codec, 0x0a);
- fixup_hp_headphone(codec, 0x0f);
- }
-
- if (find_mute_led_cfg(codec, 1))
- codec_dbg(codec, "mute LED gpio %d polarity %d\n",
- spec->gpio_led,
- spec->gpio_led_polarity);
-
-}
-
-static const struct hda_fixup stac92hd71bxx_fixups[] = {
- [STAC_92HD71BXX_REF] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = stac92hd71bxx_fixup_ref,
- },
- [STAC_DELL_M4_1] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = dell_m4_1_pin_configs,
- },
- [STAC_DELL_M4_2] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = dell_m4_2_pin_configs,
- },
- [STAC_DELL_M4_3] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = dell_m4_3_pin_configs,
- },
- [STAC_HP_M4] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = stac92hd71bxx_fixup_hp_m4,
- .chained = true,
- .chain_id = STAC_92HD71BXX_HP,
- },
- [STAC_HP_DV4] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = stac92hd71bxx_fixup_hp_dv4,
- .chained = true,
- .chain_id = STAC_HP_DV5,
- },
- [STAC_HP_DV5] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = stac92hd71bxx_fixup_hp_dv5,
- .chained = true,
- .chain_id = STAC_92HD71BXX_HP,
- },
- [STAC_HP_HDX] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = stac92hd71bxx_fixup_hp_hdx,
- .chained = true,
- .chain_id = STAC_92HD71BXX_HP,
- },
- [STAC_92HD71BXX_HP] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = stac92hd71bxx_fixup_hp,
- },
-};
-
-static const struct hda_model_fixup stac92hd71bxx_models[] = {
- { .id = STAC_92HD71BXX_REF, .name = "ref" },
- { .id = STAC_DELL_M4_1, .name = "dell-m4-1" },
- { .id = STAC_DELL_M4_2, .name = "dell-m4-2" },
- { .id = STAC_DELL_M4_3, .name = "dell-m4-3" },
- { .id = STAC_HP_M4, .name = "hp-m4" },
- { .id = STAC_HP_DV4, .name = "hp-dv4" },
- { .id = STAC_HP_DV5, .name = "hp-dv5" },
- { .id = STAC_HP_HDX, .name = "hp-hdx" },
- { .id = STAC_HP_DV4, .name = "hp-dv4-1222nr" },
- {}
-};
-
-static const struct hda_quirk stac92hd71bxx_fixup_tbl[] = {
- /* SigmaTel reference board */
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
- "DFI LanParty", STAC_92HD71BXX_REF),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101,
- "DFI LanParty", STAC_92HD71BXX_REF),
- SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x1720,
- "HP", STAC_HP_DV5),
- SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3080,
- "HP", STAC_HP_DV5),
- SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x30f0,
- "HP dv4-7", STAC_HP_DV4),
- SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3600,
- "HP dv4-7", STAC_HP_DV5),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3610,
- "HP HDX", STAC_HP_HDX), /* HDX18 */
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x361a,
- "HP mini 1000", STAC_HP_M4),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x361b,
- "HP HDX", STAC_HP_HDX), /* HDX16 */
- SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3620,
- "HP dv6", STAC_HP_DV5),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3061,
- "HP dv6", STAC_HP_DV5), /* HP dv6-1110ax */
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x363e,
- "HP DV6", STAC_HP_DV5),
- SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x7010,
- "HP", STAC_HP_DV5),
- SND_PCI_QUIRK_VENDOR(PCI_VENDOR_ID_HP, "HP", STAC_92HD71BXX_HP),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233,
- "unknown Dell", STAC_DELL_M4_1),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0234,
- "unknown Dell", STAC_DELL_M4_1),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0250,
- "unknown Dell", STAC_DELL_M4_1),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x024f,
- "unknown Dell", STAC_DELL_M4_1),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x024d,
- "unknown Dell", STAC_DELL_M4_1),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0251,
- "unknown Dell", STAC_DELL_M4_1),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0277,
- "unknown Dell", STAC_DELL_M4_1),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0263,
- "unknown Dell", STAC_DELL_M4_2),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0265,
- "unknown Dell", STAC_DELL_M4_2),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0262,
- "unknown Dell", STAC_DELL_M4_2),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0264,
- "unknown Dell", STAC_DELL_M4_2),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02aa,
- "unknown Dell", STAC_DELL_M4_3),
- {} /* terminator */
-};
-
-static const struct hda_pintbl ref922x_pin_configs[] = {
- { 0x0a, 0x01014010 },
- { 0x0b, 0x01016011 },
- { 0x0c, 0x01012012 },
- { 0x0d, 0x0221401f },
- { 0x0e, 0x01813122 },
- { 0x0f, 0x01011014 },
- { 0x10, 0x01441030 },
- { 0x11, 0x01c41030 },
- { 0x15, 0x40000100 },
- { 0x1b, 0x40000100 },
- {}
-};
-
-/*
- STAC 922X pin configs for
- 102801A7
- 102801AB
- 102801A9
- 102801D1
- 102801D2
-*/
-static const struct hda_pintbl dell_922x_d81_pin_configs[] = {
- { 0x0a, 0x02214030 },
- { 0x0b, 0x01a19021 },
- { 0x0c, 0x01111012 },
- { 0x0d, 0x01114010 },
- { 0x0e, 0x02a19020 },
- { 0x0f, 0x01117011 },
- { 0x10, 0x400001f0 },
- { 0x11, 0x400001f1 },
- { 0x15, 0x01813122 },
- { 0x1b, 0x400001f2 },
- {}
-};
-
-/*
- STAC 922X pin configs for
- 102801AC
- 102801D0
-*/
-static const struct hda_pintbl dell_922x_d82_pin_configs[] = {
- { 0x0a, 0x02214030 },
- { 0x0b, 0x01a19021 },
- { 0x0c, 0x01111012 },
- { 0x0d, 0x01114010 },
- { 0x0e, 0x02a19020 },
- { 0x0f, 0x01117011 },
- { 0x10, 0x01451140 },
- { 0x11, 0x400001f0 },
- { 0x15, 0x01813122 },
- { 0x1b, 0x400001f1 },
- {}
-};
-
-/*
- STAC 922X pin configs for
- 102801BF
-*/
-static const struct hda_pintbl dell_922x_m81_pin_configs[] = {
- { 0x0a, 0x0321101f },
- { 0x0b, 0x01112024 },
- { 0x0c, 0x01111222 },
- { 0x0d, 0x91174220 },
- { 0x0e, 0x03a11050 },
- { 0x0f, 0x01116221 },
- { 0x10, 0x90a70330 },
- { 0x11, 0x01452340 },
- { 0x15, 0x40C003f1 },
- { 0x1b, 0x405003f0 },
- {}
-};
-
-/*
- STAC 9221 A1 pin configs for
- 102801D7 (Dell XPS M1210)
-*/
-static const struct hda_pintbl dell_922x_m82_pin_configs[] = {
- { 0x0a, 0x02211211 },
- { 0x0b, 0x408103ff },
- { 0x0c, 0x02a1123e },
- { 0x0d, 0x90100310 },
- { 0x0e, 0x408003f1 },
- { 0x0f, 0x0221121f },
- { 0x10, 0x03451340 },
- { 0x11, 0x40c003f2 },
- { 0x15, 0x508003f3 },
- { 0x1b, 0x405003f4 },
- {}
-};
-
-static const struct hda_pintbl d945gtp3_pin_configs[] = {
- { 0x0a, 0x0221401f },
- { 0x0b, 0x01a19022 },
- { 0x0c, 0x01813021 },
- { 0x0d, 0x01014010 },
- { 0x0e, 0x40000100 },
- { 0x0f, 0x40000100 },
- { 0x10, 0x40000100 },
- { 0x11, 0x40000100 },
- { 0x15, 0x02a19120 },
- { 0x1b, 0x40000100 },
- {}
-};
-
-static const struct hda_pintbl d945gtp5_pin_configs[] = {
- { 0x0a, 0x0221401f },
- { 0x0b, 0x01011012 },
- { 0x0c, 0x01813024 },
- { 0x0d, 0x01014010 },
- { 0x0e, 0x01a19021 },
- { 0x0f, 0x01016011 },
- { 0x10, 0x01452130 },
- { 0x11, 0x40000100 },
- { 0x15, 0x02a19320 },
- { 0x1b, 0x40000100 },
- {}
-};
-
-static const struct hda_pintbl intel_mac_v1_pin_configs[] = {
- { 0x0a, 0x0121e21f },
- { 0x0b, 0x400000ff },
- { 0x0c, 0x9017e110 },
- { 0x0d, 0x400000fd },
- { 0x0e, 0x400000fe },
- { 0x0f, 0x0181e020 },
- { 0x10, 0x1145e030 },
- { 0x11, 0x11c5e240 },
- { 0x15, 0x400000fc },
- { 0x1b, 0x400000fb },
- {}
-};
-
-static const struct hda_pintbl intel_mac_v2_pin_configs[] = {
- { 0x0a, 0x0121e21f },
- { 0x0b, 0x90a7012e },
- { 0x0c, 0x9017e110 },
- { 0x0d, 0x400000fd },
- { 0x0e, 0x400000fe },
- { 0x0f, 0x0181e020 },
- { 0x10, 0x1145e230 },
- { 0x11, 0x500000fa },
- { 0x15, 0x400000fc },
- { 0x1b, 0x400000fb },
- {}
-};
-
-static const struct hda_pintbl intel_mac_v3_pin_configs[] = {
- { 0x0a, 0x0121e21f },
- { 0x0b, 0x90a7012e },
- { 0x0c, 0x9017e110 },
- { 0x0d, 0x400000fd },
- { 0x0e, 0x400000fe },
- { 0x0f, 0x0181e020 },
- { 0x10, 0x1145e230 },
- { 0x11, 0x11c5e240 },
- { 0x15, 0x400000fc },
- { 0x1b, 0x400000fb },
- {}
-};
-
-static const struct hda_pintbl intel_mac_v4_pin_configs[] = {
- { 0x0a, 0x0321e21f },
- { 0x0b, 0x03a1e02e },
- { 0x0c, 0x9017e110 },
- { 0x0d, 0x9017e11f },
- { 0x0e, 0x400000fe },
- { 0x0f, 0x0381e020 },
- { 0x10, 0x1345e230 },
- { 0x11, 0x13c5e240 },
- { 0x15, 0x400000fc },
- { 0x1b, 0x400000fb },
- {}
-};
-
-static const struct hda_pintbl intel_mac_v5_pin_configs[] = {
- { 0x0a, 0x0321e21f },
- { 0x0b, 0x03a1e02e },
- { 0x0c, 0x9017e110 },
- { 0x0d, 0x9017e11f },
- { 0x0e, 0x400000fe },
- { 0x0f, 0x0381e020 },
- { 0x10, 0x1345e230 },
- { 0x11, 0x13c5e240 },
- { 0x15, 0x400000fc },
- { 0x1b, 0x400000fb },
- {}
-};
-
-static const struct hda_pintbl ecs202_pin_configs[] = {
- { 0x0a, 0x0221401f },
- { 0x0b, 0x02a19020 },
- { 0x0c, 0x01a19020 },
- { 0x0d, 0x01114010 },
- { 0x0e, 0x408000f0 },
- { 0x0f, 0x01813022 },
- { 0x10, 0x074510a0 },
- { 0x11, 0x40c400f1 },
- { 0x15, 0x9037012e },
- { 0x1b, 0x40e000f2 },
- {}
-};
-
-/* codec SSIDs for Intel Mac sharing the same PCI SSID 8384:7680 */
-static const struct hda_quirk stac922x_intel_mac_fixup_tbl[] = {
- SND_PCI_QUIRK(0x0000, 0x0100, "Mac Mini", STAC_INTEL_MAC_V3),
- SND_PCI_QUIRK(0x106b, 0x0800, "Mac", STAC_INTEL_MAC_V1),
- SND_PCI_QUIRK(0x106b, 0x0600, "Mac", STAC_INTEL_MAC_V2),
- SND_PCI_QUIRK(0x106b, 0x0700, "Mac", STAC_INTEL_MAC_V2),
- SND_PCI_QUIRK(0x106b, 0x0e00, "Mac", STAC_INTEL_MAC_V3),
- SND_PCI_QUIRK(0x106b, 0x0f00, "Mac", STAC_INTEL_MAC_V3),
- SND_PCI_QUIRK(0x106b, 0x1600, "Mac", STAC_INTEL_MAC_V3),
- SND_PCI_QUIRK(0x106b, 0x1700, "Mac", STAC_INTEL_MAC_V3),
- SND_PCI_QUIRK(0x106b, 0x0200, "Mac", STAC_INTEL_MAC_V3),
- SND_PCI_QUIRK(0x106b, 0x1e00, "Mac", STAC_INTEL_MAC_V3),
- SND_PCI_QUIRK(0x106b, 0x1a00, "Mac", STAC_INTEL_MAC_V4),
- SND_PCI_QUIRK(0x106b, 0x0a00, "Mac", STAC_INTEL_MAC_V5),
- SND_PCI_QUIRK(0x106b, 0x2200, "Mac", STAC_INTEL_MAC_V5),
- {}
-};
-
-static const struct hda_fixup stac922x_fixups[];
-
-/* remap the fixup from codec SSID and apply it */
-static void stac922x_fixup_intel_mac_auto(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- if (action != HDA_FIXUP_ACT_PRE_PROBE)
- return;
-
- codec->fixup_id = HDA_FIXUP_ID_NOT_SET;
- snd_hda_pick_fixup(codec, NULL, stac922x_intel_mac_fixup_tbl,
- stac922x_fixups);
- if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET)
- snd_hda_apply_fixup(codec, action);
-}
-
-static void stac922x_fixup_intel_mac_gpio(struct hda_codec *codec,
- const struct hda_fixup *fix,
- int action)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->gpio_mask = spec->gpio_dir = 0x03;
- spec->gpio_data = 0x03;
- }
-}
-
-static const struct hda_fixup stac922x_fixups[] = {
- [STAC_D945_REF] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = ref922x_pin_configs,
- },
- [STAC_D945GTP3] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = d945gtp3_pin_configs,
- },
- [STAC_D945GTP5] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = d945gtp5_pin_configs,
- },
- [STAC_INTEL_MAC_AUTO] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = stac922x_fixup_intel_mac_auto,
- },
- [STAC_INTEL_MAC_V1] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = intel_mac_v1_pin_configs,
- .chained = true,
- .chain_id = STAC_922X_INTEL_MAC_GPIO,
- },
- [STAC_INTEL_MAC_V2] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = intel_mac_v2_pin_configs,
- .chained = true,
- .chain_id = STAC_922X_INTEL_MAC_GPIO,
- },
- [STAC_INTEL_MAC_V3] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = intel_mac_v3_pin_configs,
- .chained = true,
- .chain_id = STAC_922X_INTEL_MAC_GPIO,
- },
- [STAC_INTEL_MAC_V4] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = intel_mac_v4_pin_configs,
- .chained = true,
- .chain_id = STAC_922X_INTEL_MAC_GPIO,
- },
- [STAC_INTEL_MAC_V5] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = intel_mac_v5_pin_configs,
- .chained = true,
- .chain_id = STAC_922X_INTEL_MAC_GPIO,
- },
- [STAC_922X_INTEL_MAC_GPIO] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = stac922x_fixup_intel_mac_gpio,
- },
- [STAC_ECS_202] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = ecs202_pin_configs,
- },
- [STAC_922X_DELL_D81] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = dell_922x_d81_pin_configs,
- },
- [STAC_922X_DELL_D82] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = dell_922x_d82_pin_configs,
- },
- [STAC_922X_DELL_M81] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = dell_922x_m81_pin_configs,
- },
- [STAC_922X_DELL_M82] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = dell_922x_m82_pin_configs,
- },
-};
-
-static const struct hda_model_fixup stac922x_models[] = {
- { .id = STAC_D945_REF, .name = "ref" },
- { .id = STAC_D945GTP5, .name = "5stack" },
- { .id = STAC_D945GTP3, .name = "3stack" },
- { .id = STAC_INTEL_MAC_V1, .name = "intel-mac-v1" },
- { .id = STAC_INTEL_MAC_V2, .name = "intel-mac-v2" },
- { .id = STAC_INTEL_MAC_V3, .name = "intel-mac-v3" },
- { .id = STAC_INTEL_MAC_V4, .name = "intel-mac-v4" },
- { .id = STAC_INTEL_MAC_V5, .name = "intel-mac-v5" },
- { .id = STAC_INTEL_MAC_AUTO, .name = "intel-mac-auto" },
- { .id = STAC_ECS_202, .name = "ecs202" },
- { .id = STAC_922X_DELL_D81, .name = "dell-d81" },
- { .id = STAC_922X_DELL_D82, .name = "dell-d82" },
- { .id = STAC_922X_DELL_M81, .name = "dell-m81" },
- { .id = STAC_922X_DELL_M82, .name = "dell-m82" },
- /* for backward compatibility */
- { .id = STAC_INTEL_MAC_V3, .name = "macmini" },
- { .id = STAC_INTEL_MAC_V5, .name = "macbook" },
- { .id = STAC_INTEL_MAC_V3, .name = "macbook-pro-v1" },
- { .id = STAC_INTEL_MAC_V3, .name = "macbook-pro" },
- { .id = STAC_INTEL_MAC_V2, .name = "imac-intel" },
- { .id = STAC_INTEL_MAC_V3, .name = "imac-intel-20" },
- {}
-};
-
-static const struct hda_quirk stac922x_fixup_tbl[] = {
- /* SigmaTel reference board */
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
- "DFI LanParty", STAC_D945_REF),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101,
- "DFI LanParty", STAC_D945_REF),
- /* Intel 945G based systems */
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0101,
- "Intel D945G", STAC_D945GTP3),
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0202,
- "Intel D945G", STAC_D945GTP3),
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0606,
- "Intel D945G", STAC_D945GTP3),
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0601,
- "Intel D945G", STAC_D945GTP3),
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0111,
- "Intel D945G", STAC_D945GTP3),
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1115,
- "Intel D945G", STAC_D945GTP3),
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1116,
- "Intel D945G", STAC_D945GTP3),
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1117,
- "Intel D945G", STAC_D945GTP3),
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1118,
- "Intel D945G", STAC_D945GTP3),
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1119,
- "Intel D945G", STAC_D945GTP3),
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x8826,
- "Intel D945G", STAC_D945GTP3),
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5049,
- "Intel D945G", STAC_D945GTP3),
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5055,
- "Intel D945G", STAC_D945GTP3),
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5048,
- "Intel D945G", STAC_D945GTP3),
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0110,
- "Intel D945G", STAC_D945GTP3),
- /* Intel D945G 5-stack systems */
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0404,
- "Intel D945G", STAC_D945GTP5),
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0303,
- "Intel D945G", STAC_D945GTP5),
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0013,
- "Intel D945G", STAC_D945GTP5),
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0417,
- "Intel D945G", STAC_D945GTP5),
- /* Intel 945P based systems */
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0b0b,
- "Intel D945P", STAC_D945GTP3),
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0112,
- "Intel D945P", STAC_D945GTP3),
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0d0d,
- "Intel D945P", STAC_D945GTP3),
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0909,
- "Intel D945P", STAC_D945GTP3),
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0505,
- "Intel D945P", STAC_D945GTP3),
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0707,
- "Intel D945P", STAC_D945GTP5),
- /* other intel */
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0204,
- "Intel D945", STAC_D945_REF),
- /* other systems */
-
- /* Apple Intel Mac (Mac Mini, MacBook, MacBook Pro...) */
- SND_PCI_QUIRK(0x8384, 0x7680, "Mac", STAC_INTEL_MAC_AUTO),
-
- /* Dell systems */
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01a7,
- "unknown Dell", STAC_922X_DELL_D81),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01a9,
- "unknown Dell", STAC_922X_DELL_D81),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ab,
- "unknown Dell", STAC_922X_DELL_D81),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ac,
- "unknown Dell", STAC_922X_DELL_D82),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01bf,
- "unknown Dell", STAC_922X_DELL_M81),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d0,
- "unknown Dell", STAC_922X_DELL_D82),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d1,
- "unknown Dell", STAC_922X_DELL_D81),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d2,
- "unknown Dell", STAC_922X_DELL_D81),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d7,
- "Dell XPS M1210", STAC_922X_DELL_M82),
- /* ECS/PC Chips boards */
- SND_PCI_QUIRK_MASK(0x1019, 0xf000, 0x2000,
- "ECS/PC chips", STAC_ECS_202),
- {} /* terminator */
-};
-
-static const struct hda_pintbl ref927x_pin_configs[] = {
- { 0x0a, 0x02214020 },
- { 0x0b, 0x02a19080 },
- { 0x0c, 0x0181304e },
- { 0x0d, 0x01014010 },
- { 0x0e, 0x01a19040 },
- { 0x0f, 0x01011012 },
- { 0x10, 0x01016011 },
- { 0x11, 0x0101201f },
- { 0x12, 0x183301f0 },
- { 0x13, 0x18a001f0 },
- { 0x14, 0x18a001f0 },
- { 0x21, 0x01442070 },
- { 0x22, 0x01c42190 },
- { 0x23, 0x40000100 },
- {}
-};
-
-static const struct hda_pintbl d965_3st_pin_configs[] = {
- { 0x0a, 0x0221401f },
- { 0x0b, 0x02a19120 },
- { 0x0c, 0x40000100 },
- { 0x0d, 0x01014011 },
- { 0x0e, 0x01a19021 },
- { 0x0f, 0x01813024 },
- { 0x10, 0x40000100 },
- { 0x11, 0x40000100 },
- { 0x12, 0x40000100 },
- { 0x13, 0x40000100 },
- { 0x14, 0x40000100 },
- { 0x21, 0x40000100 },
- { 0x22, 0x40000100 },
- { 0x23, 0x40000100 },
- {}
-};
-
-static const struct hda_pintbl d965_5st_pin_configs[] = {
- { 0x0a, 0x02214020 },
- { 0x0b, 0x02a19080 },
- { 0x0c, 0x0181304e },
- { 0x0d, 0x01014010 },
- { 0x0e, 0x01a19040 },
- { 0x0f, 0x01011012 },
- { 0x10, 0x01016011 },
- { 0x11, 0x40000100 },
- { 0x12, 0x40000100 },
- { 0x13, 0x40000100 },
- { 0x14, 0x40000100 },
- { 0x21, 0x01442070 },
- { 0x22, 0x40000100 },
- { 0x23, 0x40000100 },
- {}
-};
-
-static const struct hda_pintbl d965_5st_no_fp_pin_configs[] = {
- { 0x0a, 0x40000100 },
- { 0x0b, 0x40000100 },
- { 0x0c, 0x0181304e },
- { 0x0d, 0x01014010 },
- { 0x0e, 0x01a19040 },
- { 0x0f, 0x01011012 },
- { 0x10, 0x01016011 },
- { 0x11, 0x40000100 },
- { 0x12, 0x40000100 },
- { 0x13, 0x40000100 },
- { 0x14, 0x40000100 },
- { 0x21, 0x01442070 },
- { 0x22, 0x40000100 },
- { 0x23, 0x40000100 },
- {}
-};
-
-static const struct hda_pintbl dell_3st_pin_configs[] = {
- { 0x0a, 0x02211230 },
- { 0x0b, 0x02a11220 },
- { 0x0c, 0x01a19040 },
- { 0x0d, 0x01114210 },
- { 0x0e, 0x01111212 },
- { 0x0f, 0x01116211 },
- { 0x10, 0x01813050 },
- { 0x11, 0x01112214 },
- { 0x12, 0x403003fa },
- { 0x13, 0x90a60040 },
- { 0x14, 0x90a60040 },
- { 0x21, 0x404003fb },
- { 0x22, 0x40c003fc },
- { 0x23, 0x40000100 },
- {}
-};
-
-static void stac927x_fixup_ref_no_jd(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- /* no jack detecion for ref-no-jd model */
- if (action == HDA_FIXUP_ACT_PRE_PROBE)
- codec->no_jack_detect = 1;
-}
-
-static void stac927x_fixup_ref(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- snd_hda_apply_pincfgs(codec, ref927x_pin_configs);
- spec->eapd_mask = spec->gpio_mask = 0;
- spec->gpio_dir = spec->gpio_data = 0;
- }
-}
-
-static void stac927x_fixup_dell_dmic(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- if (action != HDA_FIXUP_ACT_PRE_PROBE)
- return;
-
- if (codec->core.subsystem_id != 0x1028022f) {
- /* GPIO2 High = Enable EAPD */
- spec->eapd_mask = spec->gpio_mask = 0x04;
- spec->gpio_dir = spec->gpio_data = 0x04;
- }
-
- snd_hda_add_verbs(codec, dell_3st_core_init);
- spec->volknob_init = 1;
-}
-
-static void stac927x_fixup_volknob(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- snd_hda_add_verbs(codec, stac927x_volknob_core_init);
- spec->volknob_init = 1;
- }
-}
-
-static const struct hda_fixup stac927x_fixups[] = {
- [STAC_D965_REF_NO_JD] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = stac927x_fixup_ref_no_jd,
- .chained = true,
- .chain_id = STAC_D965_REF,
- },
- [STAC_D965_REF] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = stac927x_fixup_ref,
- },
- [STAC_D965_3ST] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = d965_3st_pin_configs,
- .chained = true,
- .chain_id = STAC_D965_VERBS,
- },
- [STAC_D965_5ST] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = d965_5st_pin_configs,
- .chained = true,
- .chain_id = STAC_D965_VERBS,
- },
- [STAC_D965_VERBS] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = d965_core_init,
- },
- [STAC_D965_5ST_NO_FP] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = d965_5st_no_fp_pin_configs,
- },
- [STAC_NEMO_DEFAULT] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = nemo_pin_configs,
- },
- [STAC_DELL_3ST] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = dell_3st_pin_configs,
- .chained = true,
- .chain_id = STAC_927X_DELL_DMIC,
- },
- [STAC_DELL_BIOS] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- /* correct the front output jack as a hp out */
- { 0x0f, 0x0221101f },
- /* correct the front input jack as a mic */
- { 0x0e, 0x02a79130 },
- {}
- },
- .chained = true,
- .chain_id = STAC_927X_DELL_DMIC,
- },
- [STAC_DELL_BIOS_AMIC] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- /* configure the analog microphone on some laptops */
- { 0x0c, 0x90a79130 },
- {}
- },
- .chained = true,
- .chain_id = STAC_DELL_BIOS,
- },
- [STAC_DELL_BIOS_SPDIF] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- /* correct the device field to SPDIF out */
- { 0x21, 0x01442070 },
- {}
- },
- .chained = true,
- .chain_id = STAC_DELL_BIOS,
- },
- [STAC_927X_DELL_DMIC] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = stac927x_fixup_dell_dmic,
- },
- [STAC_927X_VOLKNOB] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = stac927x_fixup_volknob,
- },
-};
-
-static const struct hda_model_fixup stac927x_models[] = {
- { .id = STAC_D965_REF_NO_JD, .name = "ref-no-jd" },
- { .id = STAC_D965_REF, .name = "ref" },
- { .id = STAC_D965_3ST, .name = "3stack" },
- { .id = STAC_D965_5ST, .name = "5stack" },
- { .id = STAC_D965_5ST_NO_FP, .name = "5stack-no-fp" },
- { .id = STAC_DELL_3ST, .name = "dell-3stack" },
- { .id = STAC_DELL_BIOS, .name = "dell-bios" },
- { .id = STAC_NEMO_DEFAULT, .name = "nemo-default" },
- { .id = STAC_DELL_BIOS_AMIC, .name = "dell-bios-amic" },
- { .id = STAC_927X_VOLKNOB, .name = "volknob" },
- {}
-};
-
-static const struct hda_quirk stac927x_fixup_tbl[] = {
- /* SigmaTel reference board */
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
- "DFI LanParty", STAC_D965_REF),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101,
- "DFI LanParty", STAC_D965_REF),
- /* Intel 946 based systems */
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x3d01, "Intel D946", STAC_D965_3ST),
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0xa301, "Intel D946", STAC_D965_3ST),
- /* 965 based 3 stack systems */
- SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2100,
- "Intel D965", STAC_D965_3ST),
- SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2000,
- "Intel D965", STAC_D965_3ST),
- /* Dell 3 stack systems */
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01dd, "Dell Dimension E520", STAC_DELL_3ST),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ed, "Dell ", STAC_DELL_3ST),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f4, "Dell ", STAC_DELL_3ST),
- /* Dell 3 stack systems with verb table in BIOS */
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f3, "Dell Inspiron 1420", STAC_DELL_BIOS),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f7, "Dell XPS M1730", STAC_DELL_BIOS),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0227, "Dell Vostro 1400 ", STAC_DELL_BIOS),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x022e, "Dell ", STAC_DELL_BIOS_SPDIF),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x022f, "Dell Inspiron 1525", STAC_DELL_BIOS),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0242, "Dell ", STAC_DELL_BIOS),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0243, "Dell ", STAC_DELL_BIOS),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ff, "Dell ", STAC_DELL_BIOS),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0209, "Dell XPS 1330", STAC_DELL_BIOS_SPDIF),
- /* 965 based 5 stack systems */
- SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2300,
- "Intel D965", STAC_D965_5ST),
- SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2500,
- "Intel D965", STAC_D965_5ST),
- /* Nemo */
- SND_PCI_QUIRK(0x1888, 0x1000, "AmigaOne X1000", STAC_NEMO_DEFAULT),
- /* volume-knob fixes */
- SND_PCI_QUIRK_VENDOR(0x10cf, "FSC", STAC_927X_VOLKNOB),
- {} /* terminator */
-};
-
-static const struct hda_pintbl ref9205_pin_configs[] = {
- { 0x0a, 0x40000100 },
- { 0x0b, 0x40000100 },
- { 0x0c, 0x01016011 },
- { 0x0d, 0x01014010 },
- { 0x0e, 0x01813122 },
- { 0x0f, 0x01a19021 },
- { 0x14, 0x01019020 },
- { 0x16, 0x40000100 },
- { 0x17, 0x90a000f0 },
- { 0x18, 0x90a000f0 },
- { 0x21, 0x01441030 },
- { 0x22, 0x01c41030 },
- {}
-};
-
-/*
- STAC 9205 pin configs for
- 102801F1
- 102801F2
- 102801FC
- 102801FD
- 10280204
- 1028021F
- 10280228 (Dell Vostro 1500)
- 10280229 (Dell Vostro 1700)
-*/
-static const struct hda_pintbl dell_9205_m42_pin_configs[] = {
- { 0x0a, 0x0321101F },
- { 0x0b, 0x03A11020 },
- { 0x0c, 0x400003FA },
- { 0x0d, 0x90170310 },
- { 0x0e, 0x400003FB },
- { 0x0f, 0x400003FC },
- { 0x14, 0x400003FD },
- { 0x16, 0x40F000F9 },
- { 0x17, 0x90A60330 },
- { 0x18, 0x400003FF },
- { 0x21, 0x0144131F },
- { 0x22, 0x40C003FE },
- {}
-};
-
-/*
- STAC 9205 pin configs for
- 102801F9
- 102801FA
- 102801FE
- 102801FF (Dell Precision M4300)
- 10280206
- 10280200
- 10280201
-*/
-static const struct hda_pintbl dell_9205_m43_pin_configs[] = {
- { 0x0a, 0x0321101f },
- { 0x0b, 0x03a11020 },
- { 0x0c, 0x90a70330 },
- { 0x0d, 0x90170310 },
- { 0x0e, 0x400000fe },
- { 0x0f, 0x400000ff },
- { 0x14, 0x400000fd },
- { 0x16, 0x40f000f9 },
- { 0x17, 0x400000fa },
- { 0x18, 0x400000fc },
- { 0x21, 0x0144131f },
- { 0x22, 0x40c003f8 },
- /* Enable SPDIF in/out */
- { 0x1f, 0x01441030 },
- { 0x20, 0x1c410030 },
- {}
-};
-
-static const struct hda_pintbl dell_9205_m44_pin_configs[] = {
- { 0x0a, 0x0421101f },
- { 0x0b, 0x04a11020 },
- { 0x0c, 0x400003fa },
- { 0x0d, 0x90170310 },
- { 0x0e, 0x400003fb },
- { 0x0f, 0x400003fc },
- { 0x14, 0x400003fd },
- { 0x16, 0x400003f9 },
- { 0x17, 0x90a60330 },
- { 0x18, 0x400003ff },
- { 0x21, 0x01441340 },
- { 0x22, 0x40c003fe },
- {}
-};
-
-static void stac9205_fixup_ref(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- snd_hda_apply_pincfgs(codec, ref9205_pin_configs);
- /* SPDIF-In enabled */
- spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0;
- }
-}
-
-static void stac9205_fixup_dell_m43(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct sigmatel_spec *spec = codec->spec;
- struct hda_jack_callback *jack;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- snd_hda_apply_pincfgs(codec, dell_9205_m43_pin_configs);
-
- /* Enable unsol response for GPIO4/Dock HP connection */
- snd_hda_codec_write_cache(codec, codec->core.afg, 0,
- AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10);
- jack = snd_hda_jack_detect_enable_callback(codec, codec->core.afg,
- stac_vref_event);
- if (!IS_ERR(jack))
- jack->private_data = 0x01;
-
- spec->gpio_dir = 0x0b;
- spec->eapd_mask = 0x01;
- spec->gpio_mask = 0x1b;
- spec->gpio_mute = 0x10;
- /* GPIO0 High = EAPD, GPIO1 Low = Headphone Mute,
- * GPIO3 Low = DRM
- */
- spec->gpio_data = 0x01;
- }
-}
-
-static void stac9205_fixup_eapd(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- if (action == HDA_FIXUP_ACT_PRE_PROBE)
- spec->eapd_switch = 0;
-}
-
-static const struct hda_fixup stac9205_fixups[] = {
- [STAC_9205_REF] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = stac9205_fixup_ref,
- },
- [STAC_9205_DELL_M42] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = dell_9205_m42_pin_configs,
- },
- [STAC_9205_DELL_M43] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = stac9205_fixup_dell_m43,
- },
- [STAC_9205_DELL_M44] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = dell_9205_m44_pin_configs,
- },
- [STAC_9205_EAPD] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = stac9205_fixup_eapd,
- },
- {}
-};
-
-static const struct hda_model_fixup stac9205_models[] = {
- { .id = STAC_9205_REF, .name = "ref" },
- { .id = STAC_9205_DELL_M42, .name = "dell-m42" },
- { .id = STAC_9205_DELL_M43, .name = "dell-m43" },
- { .id = STAC_9205_DELL_M44, .name = "dell-m44" },
- { .id = STAC_9205_EAPD, .name = "eapd" },
- {}
-};
-
-static const struct hda_quirk stac9205_fixup_tbl[] = {
- /* SigmaTel reference board */
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
- "DFI LanParty", STAC_9205_REF),
- SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0xfb30,
- "SigmaTel", STAC_9205_REF),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101,
- "DFI LanParty", STAC_9205_REF),
- /* Dell */
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f1,
- "unknown Dell", STAC_9205_DELL_M42),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f2,
- "unknown Dell", STAC_9205_DELL_M42),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f8,
- "Dell Precision", STAC_9205_DELL_M43),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f9,
- "Dell Precision", STAC_9205_DELL_M43),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fa,
- "Dell Precision", STAC_9205_DELL_M43),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fc,
- "unknown Dell", STAC_9205_DELL_M42),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fd,
- "unknown Dell", STAC_9205_DELL_M42),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fe,
- "Dell Precision", STAC_9205_DELL_M43),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ff,
- "Dell Precision M4300", STAC_9205_DELL_M43),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0204,
- "unknown Dell", STAC_9205_DELL_M42),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0206,
- "Dell Precision", STAC_9205_DELL_M43),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021b,
- "Dell Precision", STAC_9205_DELL_M43),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021c,
- "Dell Precision", STAC_9205_DELL_M43),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021f,
- "Dell Inspiron", STAC_9205_DELL_M44),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0228,
- "Dell Vostro 1500", STAC_9205_DELL_M42),
- SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0229,
- "Dell Vostro 1700", STAC_9205_DELL_M42),
- /* Gateway */
- SND_PCI_QUIRK(0x107b, 0x0560, "Gateway T6834c", STAC_9205_EAPD),
- SND_PCI_QUIRK(0x107b, 0x0565, "Gateway T1616", STAC_9205_EAPD),
- {} /* terminator */
-};
-
-static void stac92hd95_fixup_hp_led(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- if (action != HDA_FIXUP_ACT_PRE_PROBE)
- return;
-
- if (find_mute_led_cfg(codec, spec->default_polarity))
- codec_dbg(codec, "mute LED gpio %d polarity %d\n",
- spec->gpio_led,
- spec->gpio_led_polarity);
-}
-
-static const struct hda_fixup stac92hd95_fixups[] = {
- [STAC_92HD95_HP_LED] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = stac92hd95_fixup_hp_led,
- },
- [STAC_92HD95_HP_BASS] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
- {0x1a, 0x795, 0x00}, /* HPF to 100Hz */
- {}
- },
- .chained = true,
- .chain_id = STAC_92HD95_HP_LED,
- },
-};
-
-static const struct hda_quirk stac92hd95_fixup_tbl[] = {
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1911, "HP Spectre 13", STAC_92HD95_HP_BASS),
- {} /* terminator */
-};
-
-static const struct hda_model_fixup stac92hd95_models[] = {
- { .id = STAC_92HD95_HP_LED, .name = "hp-led" },
- { .id = STAC_92HD95_HP_BASS, .name = "hp-bass" },
- {}
-};
-
-
-static int stac_parse_auto_config(struct hda_codec *codec)
-{
- struct sigmatel_spec *spec = codec->spec;
- int err;
- int flags = 0;
-
- if (spec->headset_jack)
- flags |= HDA_PINCFG_HEADSET_MIC;
-
- err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, flags);
- if (err < 0)
- return err;
-
- /* add hooks */
- spec->gen.pcm_playback_hook = stac_playback_pcm_hook;
- spec->gen.pcm_capture_hook = stac_capture_pcm_hook;
-
- spec->gen.automute_hook = stac_update_outputs;
-
- if (spec->gpio_led)
- snd_hda_gen_add_mute_led_cdev(codec, stac_vmaster_hook);
-
- err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg);
- if (err < 0)
- return err;
-
- if (spec->vref_mute_led_nid) {
- err = snd_hda_gen_fix_pin_power(codec, spec->vref_mute_led_nid);
- if (err < 0)
- return err;
- }
-
- /* setup analog beep controls */
- if (spec->anabeep_nid > 0) {
- err = stac_auto_create_beep_ctls(codec,
- spec->anabeep_nid);
- if (err < 0)
- return err;
- }
-
- /* setup digital beep controls and input device */
-#ifdef CONFIG_SND_HDA_INPUT_BEEP
- if (spec->gen.beep_nid) {
- hda_nid_t nid = spec->gen.beep_nid;
- unsigned int caps;
-
- err = stac_auto_create_beep_ctls(codec, nid);
- if (err < 0)
- return err;
- if (codec->beep) {
- /* IDT/STAC codecs have linear beep tone parameter */
- codec->beep->linear_tone = spec->linear_tone_beep;
- /* keep power up while beep is enabled */
- codec->beep->keep_power_at_enable = 1;
- /* if no beep switch is available, make its own one */
- caps = query_amp_caps(codec, nid, HDA_OUTPUT);
- if (!(caps & AC_AMPCAP_MUTE)) {
- err = stac_beep_switch_ctl(codec);
- if (err < 0)
- return err;
- }
- }
- }
-#endif
-
- if (spec->aloopback_ctl &&
- snd_hda_get_bool_hint(codec, "loopback") == 1) {
- unsigned int wr_verb =
- spec->aloopback_ctl->private_value >> 16;
- if (snd_hdac_regmap_add_vendor_verb(&codec->core, wr_verb))
- return -ENOMEM;
- if (!snd_hda_gen_add_kctl(&spec->gen, NULL, spec->aloopback_ctl))
- return -ENOMEM;
- }
-
- if (spec->have_spdif_mux) {
- err = stac_create_spdif_mux_ctls(codec);
- if (err < 0)
- return err;
- }
-
- stac_init_power_map(codec);
-
- return 0;
-}
-
-static int stac_init(struct hda_codec *codec)
-{
- struct sigmatel_spec *spec = codec->spec;
- int i;
-
- /* override some hints */
- stac_store_hints(codec);
-
- /* set up GPIO */
- /* turn on EAPD statically when spec->eapd_switch isn't set.
- * otherwise, unsol event will turn it on/off dynamically
- */
- if (!spec->eapd_switch)
- spec->gpio_data |= spec->eapd_mask;
- stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data);
-
- snd_hda_gen_init(codec);
-
- /* sync the power-map */
- if (spec->num_pwrs)
- snd_hda_codec_write(codec, codec->core.afg, 0,
- AC_VERB_IDT_SET_POWER_MAP,
- spec->power_map_bits);
-
- /* power down inactive ADCs */
- if (spec->powerdown_adcs) {
- for (i = 0; i < spec->gen.num_all_adcs; i++) {
- if (spec->active_adcs & (1 << i))
- continue;
- snd_hda_codec_write(codec, spec->gen.all_adcs[i], 0,
- AC_VERB_SET_POWER_STATE,
- AC_PWRST_D3);
- }
- }
-
- return 0;
-}
-
-#define stac_free snd_hda_gen_free
-
-#ifdef CONFIG_SND_PROC_FS
-static void stac92hd_proc_hook(struct snd_info_buffer *buffer,
- struct hda_codec *codec, hda_nid_t nid)
-{
- if (nid == codec->core.afg)
- snd_iprintf(buffer, "Power-Map: 0x%02x\n",
- snd_hda_codec_read(codec, nid, 0,
- AC_VERB_IDT_GET_POWER_MAP, 0));
-}
-
-static void analog_loop_proc_hook(struct snd_info_buffer *buffer,
- struct hda_codec *codec,
- unsigned int verb)
-{
- snd_iprintf(buffer, "Analog Loopback: 0x%02x\n",
- snd_hda_codec_read(codec, codec->core.afg, 0, verb, 0));
-}
-
-/* stac92hd71bxx, stac92hd73xx */
-static void stac92hd7x_proc_hook(struct snd_info_buffer *buffer,
- struct hda_codec *codec, hda_nid_t nid)
-{
- stac92hd_proc_hook(buffer, codec, nid);
- if (nid == codec->core.afg)
- analog_loop_proc_hook(buffer, codec, 0xfa0);
-}
-
-static void stac9205_proc_hook(struct snd_info_buffer *buffer,
- struct hda_codec *codec, hda_nid_t nid)
-{
- if (nid == codec->core.afg)
- analog_loop_proc_hook(buffer, codec, 0xfe0);
-}
-
-static void stac927x_proc_hook(struct snd_info_buffer *buffer,
- struct hda_codec *codec, hda_nid_t nid)
-{
- if (nid == codec->core.afg)
- analog_loop_proc_hook(buffer, codec, 0xfeb);
-}
-#else
-#define stac92hd_proc_hook NULL
-#define stac92hd7x_proc_hook NULL
-#define stac9205_proc_hook NULL
-#define stac927x_proc_hook NULL
-#endif
-
-static int stac_suspend(struct hda_codec *codec)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- snd_hda_shutup_pins(codec);
-
- if (spec->eapd_mask)
- stac_gpio_set(codec, spec->gpio_mask,
- spec->gpio_dir, spec->gpio_data &
- ~spec->eapd_mask);
-
- return 0;
-}
-
-static const struct hda_codec_ops stac_patch_ops = {
- .build_controls = snd_hda_gen_build_controls,
- .build_pcms = snd_hda_gen_build_pcms,
- .init = stac_init,
- .free = stac_free,
- .unsol_event = snd_hda_jack_unsol_event,
- .suspend = stac_suspend,
-};
-
-static int alloc_stac_spec(struct hda_codec *codec)
-{
- struct sigmatel_spec *spec;
-
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (!spec)
- return -ENOMEM;
- snd_hda_gen_spec_init(&spec->gen);
- codec->spec = spec;
- codec->no_trigger_sense = 1; /* seems common with STAC/IDT codecs */
- spec->gen.dac_min_mute = true;
- codec->patch_ops = stac_patch_ops;
- return 0;
-}
-
-static int patch_stac9200(struct hda_codec *codec)
-{
- struct sigmatel_spec *spec;
- int err;
-
- err = alloc_stac_spec(codec);
- if (err < 0)
- return err;
-
- spec = codec->spec;
- spec->linear_tone_beep = 1;
- spec->gen.own_eapd_ctl = 1;
-
- codec->power_filter = snd_hda_codec_eapd_power_filter;
-
- snd_hda_add_verbs(codec, stac9200_eapd_init);
-
- snd_hda_pick_fixup(codec, stac9200_models, stac9200_fixup_tbl,
- stac9200_fixups);
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
-
- err = stac_parse_auto_config(codec);
- if (err < 0) {
- stac_free(codec);
- return err;
- }
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
-
- return 0;
-}
-
-static int patch_stac925x(struct hda_codec *codec)
-{
- struct sigmatel_spec *spec;
- int err;
-
- err = alloc_stac_spec(codec);
- if (err < 0)
- return err;
-
- spec = codec->spec;
- spec->linear_tone_beep = 1;
- spec->gen.own_eapd_ctl = 1;
-
- snd_hda_add_verbs(codec, stac925x_core_init);
-
- snd_hda_pick_fixup(codec, stac925x_models, stac925x_fixup_tbl,
- stac925x_fixups);
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
-
- err = stac_parse_auto_config(codec);
- if (err < 0) {
- stac_free(codec);
- return err;
- }
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
-
- return 0;
-}
-
-static int patch_stac92hd73xx(struct hda_codec *codec)
-{
- struct sigmatel_spec *spec;
- int err;
- int num_dacs;
-
- err = alloc_stac_spec(codec);
- if (err < 0)
- return err;
-
- spec = codec->spec;
- /* enable power_save_node only for new 92HD89xx chips, as it causes
- * click noises on old 92HD73xx chips.
- */
- if ((codec->core.vendor_id & 0xfffffff0) != 0x111d7670)
- codec->power_save_node = 1;
- spec->linear_tone_beep = 0;
- spec->gen.mixer_nid = 0x1d;
- spec->have_spdif_mux = 1;
-
- num_dacs = snd_hda_get_num_conns(codec, 0x0a) - 1;
- if (num_dacs < 3 || num_dacs > 5) {
- codec_warn(codec,
- "Could not determine number of channels defaulting to DAC count\n");
- num_dacs = 5;
- }
-
- switch (num_dacs) {
- case 0x3: /* 6 Channel */
- spec->aloopback_ctl = &stac92hd73xx_6ch_loopback;
- break;
- case 0x4: /* 8 Channel */
- spec->aloopback_ctl = &stac92hd73xx_8ch_loopback;
- break;
- case 0x5: /* 10 Channel */
- spec->aloopback_ctl = &stac92hd73xx_10ch_loopback;
- break;
- }
-
- spec->aloopback_mask = 0x01;
- spec->aloopback_shift = 8;
-
- spec->gen.beep_nid = 0x1c; /* digital beep */
-
- /* GPIO0 High = Enable EAPD */
- spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1;
- spec->gpio_data = 0x01;
-
- spec->eapd_switch = 1;
-
- spec->num_pwrs = ARRAY_SIZE(stac92hd73xx_pwr_nids);
- spec->pwr_nids = stac92hd73xx_pwr_nids;
-
- spec->gen.own_eapd_ctl = 1;
- spec->gen.power_down_unused = 1;
-
- snd_hda_pick_fixup(codec, stac92hd73xx_models, stac92hd73xx_fixup_tbl,
- stac92hd73xx_fixups);
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
-
- if (!spec->volknob_init)
- snd_hda_add_verbs(codec, stac92hd73xx_core_init);
-
- err = stac_parse_auto_config(codec);
- if (err < 0) {
- stac_free(codec);
- return err;
- }
-
- /* Don't GPIO-mute speakers if there are no internal speakers, because
- * the GPIO might be necessary for Headphone
- */
- if (spec->eapd_switch && !has_builtin_speaker(codec))
- spec->eapd_switch = 0;
-
- codec->proc_widget_hook = stac92hd7x_proc_hook;
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
-
- return 0;
-}
-
-static void stac_setup_gpio(struct hda_codec *codec)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- spec->gpio_mask |= spec->eapd_mask;
- if (spec->gpio_led) {
- if (!spec->vref_mute_led_nid) {
- spec->gpio_mask |= spec->gpio_led;
- spec->gpio_dir |= spec->gpio_led;
- spec->gpio_data |= spec->gpio_led;
- } else {
- codec->power_filter = stac_vref_led_power_filter;
- }
- }
-
- if (spec->mic_mute_led_gpio) {
- spec->gpio_mask |= spec->mic_mute_led_gpio;
- spec->gpio_dir |= spec->mic_mute_led_gpio;
- spec->mic_enabled = 0;
- spec->gpio_data |= spec->mic_mute_led_gpio;
- snd_hda_gen_add_micmute_led_cdev(codec, stac_capture_led_update);
- }
-}
-
-static int patch_stac92hd83xxx(struct hda_codec *codec)
-{
- struct sigmatel_spec *spec;
- int err;
-
- err = alloc_stac_spec(codec);
- if (err < 0)
- return err;
-
- /* longer delay needed for D3 */
- codec->core.power_caps &= ~AC_PWRST_EPSS;
-
- spec = codec->spec;
- codec->power_save_node = 1;
- spec->linear_tone_beep = 0;
- spec->gen.own_eapd_ctl = 1;
- spec->gen.power_down_unused = 1;
- spec->gen.mixer_nid = 0x1b;
-
- spec->gen.beep_nid = 0x21; /* digital beep */
- spec->pwr_nids = stac92hd83xxx_pwr_nids;
- spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids);
- spec->default_polarity = -1; /* no default cfg */
-
- snd_hda_add_verbs(codec, stac92hd83xxx_core_init);
-
- snd_hda_pick_fixup(codec, stac92hd83xxx_models, stac92hd83xxx_fixup_tbl,
- stac92hd83xxx_fixups);
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
-
- stac_setup_gpio(codec);
-
- err = stac_parse_auto_config(codec);
- if (err < 0) {
- stac_free(codec);
- return err;
- }
-
- codec->proc_widget_hook = stac92hd_proc_hook;
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
-
- return 0;
-}
-
-static const hda_nid_t stac92hd95_pwr_nids[] = {
- 0x0a, 0x0b, 0x0c, 0x0d
-};
-
-static int patch_stac92hd95(struct hda_codec *codec)
-{
- struct sigmatel_spec *spec;
- int err;
-
- err = alloc_stac_spec(codec);
- if (err < 0)
- return err;
-
- /* longer delay needed for D3 */
- codec->core.power_caps &= ~AC_PWRST_EPSS;
-
- spec = codec->spec;
- codec->power_save_node = 1;
- spec->linear_tone_beep = 0;
- spec->gen.own_eapd_ctl = 1;
- spec->gen.power_down_unused = 1;
-
- spec->gen.beep_nid = 0x19; /* digital beep */
- spec->pwr_nids = stac92hd95_pwr_nids;
- spec->num_pwrs = ARRAY_SIZE(stac92hd95_pwr_nids);
- spec->default_polarity = 0;
-
- snd_hda_pick_fixup(codec, stac92hd95_models, stac92hd95_fixup_tbl,
- stac92hd95_fixups);
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
-
- stac_setup_gpio(codec);
-
- err = stac_parse_auto_config(codec);
- if (err < 0) {
- stac_free(codec);
- return err;
- }
-
- codec->proc_widget_hook = stac92hd_proc_hook;
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
-
- return 0;
-}
-
-static int patch_stac92hd71bxx(struct hda_codec *codec)
-{
- struct sigmatel_spec *spec;
- const hda_nid_t *unmute_nids = stac92hd71bxx_unmute_nids;
- int err;
-
- err = alloc_stac_spec(codec);
- if (err < 0)
- return err;
-
- spec = codec->spec;
- /* disabled power_save_node since it causes noises on a Dell machine */
- /* codec->power_save_node = 1; */
- spec->linear_tone_beep = 0;
- spec->gen.own_eapd_ctl = 1;
- spec->gen.power_down_unused = 1;
- spec->gen.mixer_nid = 0x17;
- spec->have_spdif_mux = 1;
-
- /* GPIO0 = EAPD */
- spec->gpio_mask = 0x01;
- spec->gpio_dir = 0x01;
- spec->gpio_data = 0x01;
-
- switch (codec->core.vendor_id) {
- case 0x111d76b6: /* 4 Port without Analog Mixer */
- case 0x111d76b7:
- unmute_nids++;
- break;
- case 0x111d7608: /* 5 Port with Analog Mixer */
- if ((codec->core.revision_id & 0xf) == 0 ||
- (codec->core.revision_id & 0xf) == 1)
- spec->stream_delay = 40; /* 40 milliseconds */
-
- /* disable VSW */
- unmute_nids++;
- snd_hda_codec_set_pincfg(codec, 0x0f, 0x40f000f0);
- snd_hda_codec_set_pincfg(codec, 0x19, 0x40f000f3);
- break;
- case 0x111d7603: /* 6 Port with Analog Mixer */
- if ((codec->core.revision_id & 0xf) == 1)
- spec->stream_delay = 40; /* 40 milliseconds */
-
- break;
- }
-
- if (get_wcaps_type(get_wcaps(codec, 0x28)) == AC_WID_VOL_KNB)
- snd_hda_add_verbs(codec, stac92hd71bxx_core_init);
-
- if (get_wcaps(codec, 0xa) & AC_WCAP_IN_AMP) {
- const hda_nid_t *p;
- for (p = unmute_nids; *p; p++)
- snd_hda_codec_amp_init_stereo(codec, *p, HDA_INPUT, 0,
- 0xff, 0x00);
- }
-
- spec->aloopback_ctl = &stac92hd71bxx_loopback;
- spec->aloopback_mask = 0x50;
- spec->aloopback_shift = 0;
-
- spec->powerdown_adcs = 1;
- spec->gen.beep_nid = 0x26; /* digital beep */
- spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids);
- spec->pwr_nids = stac92hd71bxx_pwr_nids;
-
- snd_hda_pick_fixup(codec, stac92hd71bxx_models, stac92hd71bxx_fixup_tbl,
- stac92hd71bxx_fixups);
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
-
- stac_setup_gpio(codec);
-
- err = stac_parse_auto_config(codec);
- if (err < 0) {
- stac_free(codec);
- return err;
- }
-
- codec->proc_widget_hook = stac92hd7x_proc_hook;
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
-
- return 0;
-}
-
-static int patch_stac922x(struct hda_codec *codec)
-{
- struct sigmatel_spec *spec;
- int err;
-
- err = alloc_stac_spec(codec);
- if (err < 0)
- return err;
-
- spec = codec->spec;
- spec->linear_tone_beep = 1;
- spec->gen.own_eapd_ctl = 1;
-
- snd_hda_add_verbs(codec, stac922x_core_init);
-
- /* Fix Mux capture level; max to 2 */
- snd_hda_override_amp_caps(codec, 0x12, HDA_OUTPUT,
- (0 << AC_AMPCAP_OFFSET_SHIFT) |
- (2 << AC_AMPCAP_NUM_STEPS_SHIFT) |
- (0x27 << AC_AMPCAP_STEP_SIZE_SHIFT) |
- (0 << AC_AMPCAP_MUTE_SHIFT));
-
- snd_hda_pick_fixup(codec, stac922x_models, stac922x_fixup_tbl,
- stac922x_fixups);
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
-
- err = stac_parse_auto_config(codec);
- if (err < 0) {
- stac_free(codec);
- return err;
- }
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
-
- return 0;
-}
-
-static const char * const stac927x_spdif_labels[] = {
- "Digital Playback", "ADAT", "Analog Mux 1",
- "Analog Mux 2", "Analog Mux 3", NULL
-};
-
-static int patch_stac927x(struct hda_codec *codec)
-{
- struct sigmatel_spec *spec;
- int err;
-
- err = alloc_stac_spec(codec);
- if (err < 0)
- return err;
-
- spec = codec->spec;
- spec->linear_tone_beep = 1;
- spec->gen.own_eapd_ctl = 1;
- spec->have_spdif_mux = 1;
- spec->spdif_labels = stac927x_spdif_labels;
-
- spec->gen.beep_nid = 0x23; /* digital beep */
-
- /* GPIO0 High = Enable EAPD */
- spec->eapd_mask = spec->gpio_mask = 0x01;
- spec->gpio_dir = spec->gpio_data = 0x01;
-
- spec->aloopback_ctl = &stac927x_loopback;
- spec->aloopback_mask = 0x40;
- spec->aloopback_shift = 0;
- spec->eapd_switch = 1;
-
- snd_hda_pick_fixup(codec, stac927x_models, stac927x_fixup_tbl,
- stac927x_fixups);
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
-
- if (!spec->volknob_init)
- snd_hda_add_verbs(codec, stac927x_core_init);
-
- err = stac_parse_auto_config(codec);
- if (err < 0) {
- stac_free(codec);
- return err;
- }
-
- codec->proc_widget_hook = stac927x_proc_hook;
-
- /*
- * !!FIXME!!
- * The STAC927x seem to require fairly long delays for certain
- * command sequences. With too short delays (even if the answer
- * is set to RIRB properly), it results in the silence output
- * on some hardwares like Dell.
- *
- * The below flag enables the longer delay (see get_response
- * in hda_intel.c).
- */
- codec->bus->core.needs_damn_long_delay = 1;
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
-
- return 0;
-}
-
-static int patch_stac9205(struct hda_codec *codec)
-{
- struct sigmatel_spec *spec;
- int err;
-
- err = alloc_stac_spec(codec);
- if (err < 0)
- return err;
-
- spec = codec->spec;
- spec->linear_tone_beep = 1;
- spec->gen.own_eapd_ctl = 1;
- spec->have_spdif_mux = 1;
-
- spec->gen.beep_nid = 0x23; /* digital beep */
-
- snd_hda_add_verbs(codec, stac9205_core_init);
- spec->aloopback_ctl = &stac9205_loopback;
-
- spec->aloopback_mask = 0x40;
- spec->aloopback_shift = 0;
-
- /* GPIO0 High = EAPD */
- spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1;
- spec->gpio_data = 0x01;
-
- /* Turn on/off EAPD per HP plugging */
- spec->eapd_switch = 1;
-
- snd_hda_pick_fixup(codec, stac9205_models, stac9205_fixup_tbl,
- stac9205_fixups);
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
-
- err = stac_parse_auto_config(codec);
- if (err < 0) {
- stac_free(codec);
- return err;
- }
-
- codec->proc_widget_hook = stac9205_proc_hook;
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
-
- return 0;
-}
-
-/*
- * STAC9872 hack
- */
-
-static const struct hda_verb stac9872_core_init[] = {
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mic-sel: 0a,0d,14,02 */
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Mic-in -> 0x9 */
- {}
-};
-
-static const struct hda_pintbl stac9872_vaio_pin_configs[] = {
- { 0x0a, 0x03211020 },
- { 0x0b, 0x411111f0 },
- { 0x0c, 0x411111f0 },
- { 0x0d, 0x03a15030 },
- { 0x0e, 0x411111f0 },
- { 0x0f, 0x90170110 },
- { 0x11, 0x411111f0 },
- { 0x13, 0x411111f0 },
- { 0x14, 0x90a7013e },
- {}
-};
-
-static const struct hda_model_fixup stac9872_models[] = {
- { .id = STAC_9872_VAIO, .name = "vaio" },
- {}
-};
-
-static const struct hda_fixup stac9872_fixups[] = {
- [STAC_9872_VAIO] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = stac9872_vaio_pin_configs,
- },
-};
-
-static const struct hda_quirk stac9872_fixup_tbl[] = {
- SND_PCI_QUIRK_MASK(0x104d, 0xfff0, 0x81e0,
- "Sony VAIO F/S", STAC_9872_VAIO),
- {} /* terminator */
-};
-
-static int patch_stac9872(struct hda_codec *codec)
-{
- struct sigmatel_spec *spec;
- int err;
-
- err = alloc_stac_spec(codec);
- if (err < 0)
- return err;
-
- spec = codec->spec;
- spec->linear_tone_beep = 1;
- spec->gen.own_eapd_ctl = 1;
-
- snd_hda_add_verbs(codec, stac9872_core_init);
-
- snd_hda_pick_fixup(codec, stac9872_models, stac9872_fixup_tbl,
- stac9872_fixups);
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
-
- err = stac_parse_auto_config(codec);
- if (err < 0) {
- stac_free(codec);
- return -EINVAL;
- }
-
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
-
- return 0;
-}
-
-
-/*
- * patch entries
- */
-static const struct hda_device_id snd_hda_id_sigmatel[] = {
- HDA_CODEC_ENTRY(0x83847690, "STAC9200", patch_stac9200),
- HDA_CODEC_ENTRY(0x83847882, "STAC9220 A1", patch_stac922x),
- HDA_CODEC_ENTRY(0x83847680, "STAC9221 A1", patch_stac922x),
- HDA_CODEC_ENTRY(0x83847880, "STAC9220 A2", patch_stac922x),
- HDA_CODEC_ENTRY(0x83847681, "STAC9220D/9223D A2", patch_stac922x),
- HDA_CODEC_ENTRY(0x83847682, "STAC9221 A2", patch_stac922x),
- HDA_CODEC_ENTRY(0x83847683, "STAC9221D A2", patch_stac922x),
- HDA_CODEC_ENTRY(0x83847618, "STAC9227", patch_stac927x),
- HDA_CODEC_ENTRY(0x83847619, "STAC9227", patch_stac927x),
- HDA_CODEC_ENTRY(0x83847638, "STAC92HD700", patch_stac927x),
- HDA_CODEC_ENTRY(0x83847616, "STAC9228", patch_stac927x),
- HDA_CODEC_ENTRY(0x83847617, "STAC9228", patch_stac927x),
- HDA_CODEC_ENTRY(0x83847614, "STAC9229", patch_stac927x),
- HDA_CODEC_ENTRY(0x83847615, "STAC9229", patch_stac927x),
- HDA_CODEC_ENTRY(0x83847620, "STAC9274", patch_stac927x),
- HDA_CODEC_ENTRY(0x83847621, "STAC9274D", patch_stac927x),
- HDA_CODEC_ENTRY(0x83847622, "STAC9273X", patch_stac927x),
- HDA_CODEC_ENTRY(0x83847623, "STAC9273D", patch_stac927x),
- HDA_CODEC_ENTRY(0x83847624, "STAC9272X", patch_stac927x),
- HDA_CODEC_ENTRY(0x83847625, "STAC9272D", patch_stac927x),
- HDA_CODEC_ENTRY(0x83847626, "STAC9271X", patch_stac927x),
- HDA_CODEC_ENTRY(0x83847627, "STAC9271D", patch_stac927x),
- HDA_CODEC_ENTRY(0x83847628, "STAC9274X5NH", patch_stac927x),
- HDA_CODEC_ENTRY(0x83847629, "STAC9274D5NH", patch_stac927x),
- HDA_CODEC_ENTRY(0x83847632, "STAC9202", patch_stac925x),
- HDA_CODEC_ENTRY(0x83847633, "STAC9202D", patch_stac925x),
- HDA_CODEC_ENTRY(0x83847634, "STAC9250", patch_stac925x),
- HDA_CODEC_ENTRY(0x83847635, "STAC9250D", patch_stac925x),
- HDA_CODEC_ENTRY(0x83847636, "STAC9251", patch_stac925x),
- HDA_CODEC_ENTRY(0x83847637, "STAC9250D", patch_stac925x),
- HDA_CODEC_ENTRY(0x83847645, "92HD206X", patch_stac927x),
- HDA_CODEC_ENTRY(0x83847646, "92HD206D", patch_stac927x),
- /* The following does not take into account .id=0x83847661 when subsys =
- * 104D0C00 which is STAC9225s. Because of this, some SZ Notebooks are
- * currently not fully supported.
- */
- HDA_CODEC_ENTRY(0x83847661, "CXD9872RD/K", patch_stac9872),
- HDA_CODEC_ENTRY(0x83847662, "STAC9872AK", patch_stac9872),
- HDA_CODEC_ENTRY(0x83847664, "CXD9872AKD", patch_stac9872),
- HDA_CODEC_ENTRY(0x83847698, "STAC9205", patch_stac9205),
- HDA_CODEC_ENTRY(0x838476a0, "STAC9205", patch_stac9205),
- HDA_CODEC_ENTRY(0x838476a1, "STAC9205D", patch_stac9205),
- HDA_CODEC_ENTRY(0x838476a2, "STAC9204", patch_stac9205),
- HDA_CODEC_ENTRY(0x838476a3, "STAC9204D", patch_stac9205),
- HDA_CODEC_ENTRY(0x838476a4, "STAC9255", patch_stac9205),
- HDA_CODEC_ENTRY(0x838476a5, "STAC9255D", patch_stac9205),
- HDA_CODEC_ENTRY(0x838476a6, "STAC9254", patch_stac9205),
- HDA_CODEC_ENTRY(0x838476a7, "STAC9254D", patch_stac9205),
- HDA_CODEC_ENTRY(0x111d7603, "92HD75B3X5", patch_stac92hd71bxx),
- HDA_CODEC_ENTRY(0x111d7604, "92HD83C1X5", patch_stac92hd83xxx),
- HDA_CODEC_ENTRY(0x111d76d4, "92HD83C1C5", patch_stac92hd83xxx),
- HDA_CODEC_ENTRY(0x111d7605, "92HD81B1X5", patch_stac92hd83xxx),
- HDA_CODEC_ENTRY(0x111d76d5, "92HD81B1C5", patch_stac92hd83xxx),
- HDA_CODEC_ENTRY(0x111d76d1, "92HD87B1/3", patch_stac92hd83xxx),
- HDA_CODEC_ENTRY(0x111d76d9, "92HD87B2/4", patch_stac92hd83xxx),
- HDA_CODEC_ENTRY(0x111d7666, "92HD88B3", patch_stac92hd83xxx),
- HDA_CODEC_ENTRY(0x111d7667, "92HD88B1", patch_stac92hd83xxx),
- HDA_CODEC_ENTRY(0x111d7668, "92HD88B2", patch_stac92hd83xxx),
- HDA_CODEC_ENTRY(0x111d7669, "92HD88B4", patch_stac92hd83xxx),
- HDA_CODEC_ENTRY(0x111d7608, "92HD75B2X5", patch_stac92hd71bxx),
- HDA_CODEC_ENTRY(0x111d7674, "92HD73D1X5", patch_stac92hd73xx),
- HDA_CODEC_ENTRY(0x111d7675, "92HD73C1X5", patch_stac92hd73xx),
- HDA_CODEC_ENTRY(0x111d7676, "92HD73E1X5", patch_stac92hd73xx),
- HDA_CODEC_ENTRY(0x111d7695, "92HD95", patch_stac92hd95),
- HDA_CODEC_ENTRY(0x111d76b0, "92HD71B8X", patch_stac92hd71bxx),
- HDA_CODEC_ENTRY(0x111d76b1, "92HD71B8X", patch_stac92hd71bxx),
- HDA_CODEC_ENTRY(0x111d76b2, "92HD71B7X", patch_stac92hd71bxx),
- HDA_CODEC_ENTRY(0x111d76b3, "92HD71B7X", patch_stac92hd71bxx),
- HDA_CODEC_ENTRY(0x111d76b4, "92HD71B6X", patch_stac92hd71bxx),
- HDA_CODEC_ENTRY(0x111d76b5, "92HD71B6X", patch_stac92hd71bxx),
- HDA_CODEC_ENTRY(0x111d76b6, "92HD71B5X", patch_stac92hd71bxx),
- HDA_CODEC_ENTRY(0x111d76b7, "92HD71B5X", patch_stac92hd71bxx),
- HDA_CODEC_ENTRY(0x111d76c0, "92HD89C3", patch_stac92hd73xx),
- HDA_CODEC_ENTRY(0x111d76c1, "92HD89C2", patch_stac92hd73xx),
- HDA_CODEC_ENTRY(0x111d76c2, "92HD89C1", patch_stac92hd73xx),
- HDA_CODEC_ENTRY(0x111d76c3, "92HD89B3", patch_stac92hd73xx),
- HDA_CODEC_ENTRY(0x111d76c4, "92HD89B2", patch_stac92hd73xx),
- HDA_CODEC_ENTRY(0x111d76c5, "92HD89B1", patch_stac92hd73xx),
- HDA_CODEC_ENTRY(0x111d76c6, "92HD89E3", patch_stac92hd73xx),
- HDA_CODEC_ENTRY(0x111d76c7, "92HD89E2", patch_stac92hd73xx),
- HDA_CODEC_ENTRY(0x111d76c8, "92HD89E1", patch_stac92hd73xx),
- HDA_CODEC_ENTRY(0x111d76c9, "92HD89D3", patch_stac92hd73xx),
- HDA_CODEC_ENTRY(0x111d76ca, "92HD89D2", patch_stac92hd73xx),
- HDA_CODEC_ENTRY(0x111d76cb, "92HD89D1", patch_stac92hd73xx),
- HDA_CODEC_ENTRY(0x111d76cc, "92HD89F3", patch_stac92hd73xx),
- HDA_CODEC_ENTRY(0x111d76cd, "92HD89F2", patch_stac92hd73xx),
- HDA_CODEC_ENTRY(0x111d76ce, "92HD89F1", patch_stac92hd73xx),
- HDA_CODEC_ENTRY(0x111d76df, "92HD93BXX", patch_stac92hd83xxx),
- HDA_CODEC_ENTRY(0x111d76e0, "92HD91BXX", patch_stac92hd83xxx),
- HDA_CODEC_ENTRY(0x111d76e3, "92HD98BXX", patch_stac92hd83xxx),
- HDA_CODEC_ENTRY(0x111d76e5, "92HD99BXX", patch_stac92hd83xxx),
- HDA_CODEC_ENTRY(0x111d76e7, "92HD90BXX", patch_stac92hd83xxx),
- HDA_CODEC_ENTRY(0x111d76e8, "92HD66B1X5", patch_stac92hd83xxx),
- HDA_CODEC_ENTRY(0x111d76e9, "92HD66B2X5", patch_stac92hd83xxx),
- HDA_CODEC_ENTRY(0x111d76ea, "92HD66B3X5", patch_stac92hd83xxx),
- HDA_CODEC_ENTRY(0x111d76eb, "92HD66C1X5", patch_stac92hd83xxx),
- HDA_CODEC_ENTRY(0x111d76ec, "92HD66C2X5", patch_stac92hd83xxx),
- HDA_CODEC_ENTRY(0x111d76ed, "92HD66C3X5", patch_stac92hd83xxx),
- HDA_CODEC_ENTRY(0x111d76ee, "92HD66B1X3", patch_stac92hd83xxx),
- HDA_CODEC_ENTRY(0x111d76ef, "92HD66B2X3", patch_stac92hd83xxx),
- HDA_CODEC_ENTRY(0x111d76f0, "92HD66B3X3", patch_stac92hd83xxx),
- HDA_CODEC_ENTRY(0x111d76f1, "92HD66C1X3", patch_stac92hd83xxx),
- HDA_CODEC_ENTRY(0x111d76f2, "92HD66C2X3", patch_stac92hd83xxx),
- HDA_CODEC_ENTRY(0x111d76f3, "92HD66C3/65", patch_stac92hd83xxx),
- {} /* terminator */
-};
-MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_sigmatel);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("IDT/Sigmatel HD-audio codec");
-
-static struct hda_codec_driver sigmatel_driver = {
- .id = snd_hda_id_sigmatel,
-};
-
-module_hda_codec_driver(sigmatel_driver);
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
deleted file mode 100644
index d0893059b1b9..000000000000
--- a/sound/pci/hda/patch_via.c
+++ /dev/null
@@ -1,1247 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Universal Interface for Intel High Definition Audio Codec
- *
- * HD audio interface patch for VIA VT17xx/VT18xx/VT20xx codec
- *
- * (C) 2006-2009 VIA Technology, Inc.
- * (C) 2006-2008 Takashi Iwai <tiwai@suse.de>
- */
-
-/* * * * * * * * * * * * * * Release History * * * * * * * * * * * * * * * * */
-/* */
-/* 2006-03-03 Lydia Wang Create the basic patch to support VT1708 codec */
-/* 2006-03-14 Lydia Wang Modify hard code for some pin widget nid */
-/* 2006-08-02 Lydia Wang Add support to VT1709 codec */
-/* 2006-09-08 Lydia Wang Fix internal loopback recording source select bug */
-/* 2007-09-12 Lydia Wang Add EAPD enable during driver initialization */
-/* 2007-09-17 Lydia Wang Add VT1708B codec support */
-/* 2007-11-14 Lydia Wang Add VT1708A codec HP and CD pin connect config */
-/* 2008-02-03 Lydia Wang Fix Rear channels and Back channels inverse issue */
-/* 2008-03-06 Lydia Wang Add VT1702 codec and VT1708S codec support */
-/* 2008-04-09 Lydia Wang Add mute front speaker when HP plugin */
-/* 2008-04-09 Lydia Wang Add Independent HP feature */
-/* 2008-05-28 Lydia Wang Add second S/PDIF Out support for VT1702 */
-/* 2008-09-15 Logan Li Add VT1708S Mic Boost workaround/backdoor */
-/* 2009-02-16 Logan Li Add support for VT1718S */
-/* 2009-03-13 Logan Li Add support for VT1716S */
-/* 2009-04-14 Lydai Wang Add support for VT1828S and VT2020 */
-/* 2009-07-08 Lydia Wang Add support for VT2002P */
-/* 2009-07-21 Lydia Wang Add support for VT1812 */
-/* 2009-09-19 Lydia Wang Add support for VT1818S */
-/* */
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <sound/core.h>
-#include <sound/asoundef.h>
-#include <sound/hda_codec.h>
-#include "hda_local.h"
-#include "hda_auto_parser.h"
-#include "hda_jack.h"
-#include "hda_generic.h"
-
-/* Pin Widget NID */
-#define VT1708_HP_PIN_NID 0x20
-#define VT1708_CD_PIN_NID 0x24
-
-enum VIA_HDA_CODEC {
- UNKNOWN = -1,
- VT1708,
- VT1709_10CH,
- VT1709_6CH,
- VT1708B_8CH,
- VT1708B_4CH,
- VT1708S,
- VT1708BCE,
- VT1702,
- VT1718S,
- VT1716S,
- VT2002P,
- VT1812,
- VT1802,
- VT1705CF,
- VT1808,
- CODEC_TYPES,
-};
-
-#define VT2002P_COMPATIBLE(spec) \
- ((spec)->codec_type == VT2002P ||\
- (spec)->codec_type == VT1812 ||\
- (spec)->codec_type == VT1802)
-
-struct via_spec {
- struct hda_gen_spec gen;
-
- /* HP mode source */
- unsigned int dmic_enabled;
- enum VIA_HDA_CODEC codec_type;
-
- /* analog low-power control */
- bool alc_mode;
-
- /* work to check hp jack state */
- int hp_work_active;
- int vt1708_jack_detect;
-};
-
-static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec);
-static void via_playback_pcm_hook(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream,
- int action);
-
-static const struct hda_codec_ops via_patch_ops; /* defined below */
-
-static struct via_spec *via_new_spec(struct hda_codec *codec)
-{
- struct via_spec *spec;
-
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
- return NULL;
-
- codec->spec = spec;
- snd_hda_gen_spec_init(&spec->gen);
- spec->codec_type = get_codec_type(codec);
- /* VT1708BCE & VT1708S are almost same */
- if (spec->codec_type == VT1708BCE)
- spec->codec_type = VT1708S;
- spec->gen.indep_hp = 1;
- spec->gen.keep_eapd_on = 1;
- spec->gen.dac_min_mute = 1;
- spec->gen.pcm_playback_hook = via_playback_pcm_hook;
- spec->gen.add_stereo_mix_input = HDA_HINT_STEREO_MIX_AUTO;
- codec->power_save_node = 1;
- spec->gen.power_down_unused = 1;
- codec->patch_ops = via_patch_ops;
- return spec;
-}
-
-static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec)
-{
- u32 vendor_id = codec->core.vendor_id;
- u16 ven_id = vendor_id >> 16;
- u16 dev_id = vendor_id & 0xffff;
- enum VIA_HDA_CODEC codec_type;
-
- /* get codec type */
- if (ven_id != 0x1106)
- codec_type = UNKNOWN;
- else if (dev_id >= 0x1708 && dev_id <= 0x170b)
- codec_type = VT1708;
- else if (dev_id >= 0xe710 && dev_id <= 0xe713)
- codec_type = VT1709_10CH;
- else if (dev_id >= 0xe714 && dev_id <= 0xe717)
- codec_type = VT1709_6CH;
- else if (dev_id >= 0xe720 && dev_id <= 0xe723) {
- codec_type = VT1708B_8CH;
- if (snd_hda_param_read(codec, 0x16, AC_PAR_CONNLIST_LEN) == 0x7)
- codec_type = VT1708BCE;
- } else if (dev_id >= 0xe724 && dev_id <= 0xe727)
- codec_type = VT1708B_4CH;
- else if ((dev_id & 0xfff) == 0x397
- && (dev_id >> 12) < 8)
- codec_type = VT1708S;
- else if ((dev_id & 0xfff) == 0x398
- && (dev_id >> 12) < 8)
- codec_type = VT1702;
- else if ((dev_id & 0xfff) == 0x428
- && (dev_id >> 12) < 8)
- codec_type = VT1718S;
- else if (dev_id == 0x0433 || dev_id == 0xa721)
- codec_type = VT1716S;
- else if (dev_id == 0x0441 || dev_id == 0x4441)
- codec_type = VT1718S;
- else if (dev_id == 0x0438 || dev_id == 0x4438)
- codec_type = VT2002P;
- else if (dev_id == 0x0448)
- codec_type = VT1812;
- else if (dev_id == 0x0440)
- codec_type = VT1708S;
- else if ((dev_id & 0xfff) == 0x446)
- codec_type = VT1802;
- else if (dev_id == 0x4760)
- codec_type = VT1705CF;
- else if (dev_id == 0x4761 || dev_id == 0x4762)
- codec_type = VT1808;
- else
- codec_type = UNKNOWN;
- return codec_type;
-};
-
-static void analog_low_current_mode(struct hda_codec *codec);
-static bool is_aa_path_mute(struct hda_codec *codec);
-
-#define hp_detect_with_aa(codec) \
- (snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") == 1 && \
- !is_aa_path_mute(codec))
-
-static void vt1708_stop_hp_work(struct hda_codec *codec)
-{
- struct via_spec *spec = codec->spec;
- if (spec->codec_type != VT1708 || !spec->gen.autocfg.hp_outs)
- return;
- if (spec->hp_work_active) {
- snd_hda_codec_write(codec, 0x1, 0, 0xf81, 1);
- codec->jackpoll_interval = 0;
- cancel_delayed_work_sync(&codec->jackpoll_work);
- spec->hp_work_active = false;
- }
-}
-
-static void vt1708_update_hp_work(struct hda_codec *codec)
-{
- struct via_spec *spec = codec->spec;
- if (spec->codec_type != VT1708 || !spec->gen.autocfg.hp_outs)
- return;
- if (spec->vt1708_jack_detect) {
- if (!spec->hp_work_active) {
- codec->jackpoll_interval = msecs_to_jiffies(100);
- snd_hda_codec_write(codec, 0x1, 0, 0xf81, 0);
- schedule_delayed_work(&codec->jackpoll_work, 0);
- spec->hp_work_active = true;
- }
- } else if (!hp_detect_with_aa(codec))
- vt1708_stop_hp_work(codec);
-}
-
-static int via_pin_power_ctl_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
-}
-
-static int via_pin_power_ctl_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct via_spec *spec = codec->spec;
-
- ucontrol->value.enumerated.item[0] = spec->gen.power_down_unused;
- return 0;
-}
-
-static int via_pin_power_ctl_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct via_spec *spec = codec->spec;
- bool val = !!ucontrol->value.enumerated.item[0];
-
- if (val == spec->gen.power_down_unused)
- return 0;
- /* codec->power_save_node = val; */ /* widget PM seems yet broken */
- spec->gen.power_down_unused = val;
- analog_low_current_mode(codec);
- return 1;
-}
-
-static const struct snd_kcontrol_new via_pin_power_ctl_enum = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Dynamic Power-Control",
- .info = via_pin_power_ctl_info,
- .get = via_pin_power_ctl_get,
- .put = via_pin_power_ctl_put,
-};
-
-#ifdef CONFIG_SND_HDA_INPUT_BEEP
-/* additional beep mixers; the actual parameters are overwritten at build */
-static const struct snd_kcontrol_new via_beep_mixer[] = {
- HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0, 1, 0, HDA_OUTPUT),
- HDA_CODEC_MUTE_BEEP_MONO("Beep Playback Switch", 0, 1, 0, HDA_OUTPUT),
-};
-
-static int set_beep_amp(struct via_spec *spec, hda_nid_t nid,
- int idx, int dir)
-{
- struct snd_kcontrol_new *knew;
- unsigned int beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir);
- int i;
-
- spec->gen.beep_nid = nid;
- for (i = 0; i < ARRAY_SIZE(via_beep_mixer); i++) {
- knew = snd_hda_gen_add_kctl(&spec->gen, NULL,
- &via_beep_mixer[i]);
- if (!knew)
- return -ENOMEM;
- knew->private_value = beep_amp;
- }
- return 0;
-}
-
-static int auto_parse_beep(struct hda_codec *codec)
-{
- struct via_spec *spec = codec->spec;
- hda_nid_t nid;
-
- for_each_hda_codec_node(nid, codec)
- if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_BEEP)
- return set_beep_amp(spec, nid, 0, HDA_OUTPUT);
- return 0;
-}
-#else
-#define auto_parse_beep(codec) 0
-#endif
-
-/* check AA path's mute status */
-static bool is_aa_path_mute(struct hda_codec *codec)
-{
- struct via_spec *spec = codec->spec;
- const struct hda_amp_list *p;
- int ch, v;
-
- p = spec->gen.loopback.amplist;
- if (!p)
- return true;
- for (; p->nid; p++) {
- for (ch = 0; ch < 2; ch++) {
- v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir,
- p->idx);
- if (!(v & HDA_AMP_MUTE) && v > 0)
- return false;
- }
- }
- return true;
-}
-
-/* enter/exit analog low-current mode */
-static void __analog_low_current_mode(struct hda_codec *codec, bool force)
-{
- struct via_spec *spec = codec->spec;
- bool enable;
- unsigned int verb, parm;
-
- if (!codec->power_save_node)
- enable = false;
- else
- enable = is_aa_path_mute(codec) && !spec->gen.active_streams;
- if (enable == spec->alc_mode && !force)
- return;
- spec->alc_mode = enable;
-
- /* decide low current mode's verb & parameter */
- switch (spec->codec_type) {
- case VT1708B_8CH:
- case VT1708B_4CH:
- verb = 0xf70;
- parm = enable ? 0x02 : 0x00; /* 0x02: 2/3x, 0x00: 1x */
- break;
- case VT1708S:
- case VT1718S:
- case VT1716S:
- verb = 0xf73;
- parm = enable ? 0x51 : 0xe1; /* 0x51: 4/28x, 0xe1: 1x */
- break;
- case VT1702:
- verb = 0xf73;
- parm = enable ? 0x01 : 0x1d; /* 0x01: 4/40x, 0x1d: 1x */
- break;
- case VT2002P:
- case VT1812:
- case VT1802:
- verb = 0xf93;
- parm = enable ? 0x00 : 0xe0; /* 0x00: 4/40x, 0xe0: 1x */
- break;
- case VT1705CF:
- case VT1808:
- verb = 0xf82;
- parm = enable ? 0x00 : 0xe0; /* 0x00: 4/40x, 0xe0: 1x */
- break;
- default:
- return; /* other codecs are not supported */
- }
- /* send verb */
- snd_hda_codec_write(codec, codec->core.afg, 0, verb, parm);
-}
-
-static void analog_low_current_mode(struct hda_codec *codec)
-{
- return __analog_low_current_mode(codec, false);
-}
-
-static void via_playback_pcm_hook(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream,
- int action)
-{
- analog_low_current_mode(codec);
- vt1708_update_hp_work(codec);
-}
-
-static void via_free(struct hda_codec *codec)
-{
- vt1708_stop_hp_work(codec);
- snd_hda_gen_free(codec);
-}
-
-static int via_suspend(struct hda_codec *codec)
-{
- struct via_spec *spec = codec->spec;
- vt1708_stop_hp_work(codec);
-
- /* Fix pop noise on headphones */
- if (spec->codec_type == VT1802)
- snd_hda_shutup_pins(codec);
-
- return 0;
-}
-
-static int via_resume(struct hda_codec *codec)
-{
- /* some delay here to make jack detection working (bko#98921) */
- msleep(10);
- codec->patch_ops.init(codec);
- snd_hda_regmap_sync(codec);
- return 0;
-}
-
-static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid)
-{
- struct via_spec *spec = codec->spec;
- analog_low_current_mode(codec);
- vt1708_update_hp_work(codec);
- return snd_hda_check_amp_list_power(codec, &spec->gen.loopback, nid);
-}
-
-/*
- */
-
-static int via_init(struct hda_codec *codec);
-
-static const struct hda_codec_ops via_patch_ops = {
- .build_controls = snd_hda_gen_build_controls,
- .build_pcms = snd_hda_gen_build_pcms,
- .init = via_init,
- .free = via_free,
- .unsol_event = snd_hda_jack_unsol_event,
- .suspend = via_suspend,
- .resume = via_resume,
- .check_power_status = via_check_power_status,
-};
-
-
-static const struct hda_verb vt1708_init_verbs[] = {
- /* power down jack detect function */
- {0x1, 0xf81, 0x1},
- { }
-};
-static void vt1708_set_pinconfig_connect(struct hda_codec *codec, hda_nid_t nid)
-{
- unsigned int def_conf;
- unsigned char seqassoc;
-
- def_conf = snd_hda_codec_get_pincfg(codec, nid);
- seqassoc = (unsigned char) get_defcfg_association(def_conf);
- seqassoc = (seqassoc << 4) | get_defcfg_sequence(def_conf);
- if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE
- && (seqassoc == 0xf0 || seqassoc == 0xff)) {
- def_conf = def_conf & (~(AC_JACK_PORT_BOTH << 30));
- snd_hda_codec_set_pincfg(codec, nid, def_conf);
- }
-}
-
-static int vt1708_jack_detect_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct via_spec *spec = codec->spec;
-
- if (spec->codec_type != VT1708)
- return 0;
- ucontrol->value.integer.value[0] = spec->vt1708_jack_detect;
- return 0;
-}
-
-static int vt1708_jack_detect_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct via_spec *spec = codec->spec;
- int val;
-
- if (spec->codec_type != VT1708)
- return 0;
- val = !!ucontrol->value.integer.value[0];
- if (spec->vt1708_jack_detect == val)
- return 0;
- spec->vt1708_jack_detect = val;
- vt1708_update_hp_work(codec);
- return 1;
-}
-
-static const struct snd_kcontrol_new vt1708_jack_detect_ctl = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Jack Detect",
- .count = 1,
- .info = snd_ctl_boolean_mono_info,
- .get = vt1708_jack_detect_get,
- .put = vt1708_jack_detect_put,
-};
-
-static const struct badness_table via_main_out_badness = {
- .no_primary_dac = 0x10000,
- .no_dac = 0x4000,
- .shared_primary = 0x10000,
- .shared_surr = 0x20,
- .shared_clfe = 0x20,
- .shared_surr_main = 0x20,
-};
-static const struct badness_table via_extra_out_badness = {
- .no_primary_dac = 0x4000,
- .no_dac = 0x4000,
- .shared_primary = 0x12,
- .shared_surr = 0x20,
- .shared_clfe = 0x20,
- .shared_surr_main = 0x10,
-};
-
-static int via_parse_auto_config(struct hda_codec *codec)
-{
- struct via_spec *spec = codec->spec;
- int err;
-
- spec->gen.main_out_badness = &via_main_out_badness;
- spec->gen.extra_out_badness = &via_extra_out_badness;
-
- err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0);
- if (err < 0)
- return err;
-
- err = auto_parse_beep(codec);
- if (err < 0)
- return err;
-
- err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg);
- if (err < 0)
- return err;
-
- if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &via_pin_power_ctl_enum))
- return -ENOMEM;
-
- /* disable widget PM at start for compatibility */
- codec->power_save_node = 0;
- spec->gen.power_down_unused = 0;
- return 0;
-}
-
-static int via_init(struct hda_codec *codec)
-{
- /* init power states */
- __analog_low_current_mode(codec, true);
-
- snd_hda_gen_init(codec);
-
- vt1708_update_hp_work(codec);
-
- return 0;
-}
-
-static int vt1708_build_controls(struct hda_codec *codec)
-{
- /* In order not to create "Phantom Jack" controls,
- temporary enable jackpoll */
- int err;
- int old_interval = codec->jackpoll_interval;
- codec->jackpoll_interval = msecs_to_jiffies(100);
- err = snd_hda_gen_build_controls(codec);
- codec->jackpoll_interval = old_interval;
- return err;
-}
-
-static int vt1708_build_pcms(struct hda_codec *codec)
-{
- struct via_spec *spec = codec->spec;
- int i, err;
-
- err = snd_hda_gen_build_pcms(codec);
- if (err < 0 || codec->core.vendor_id != 0x11061708)
- return err;
-
- /* We got noisy outputs on the right channel on VT1708 when
- * 24bit samples are used. Until any workaround is found,
- * disable the 24bit format, so far.
- */
- for (i = 0; i < ARRAY_SIZE(spec->gen.pcm_rec); i++) {
- struct hda_pcm *info = spec->gen.pcm_rec[i];
- if (!info)
- continue;
- if (!info->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams ||
- info->pcm_type != HDA_PCM_TYPE_AUDIO)
- continue;
- info->stream[SNDRV_PCM_STREAM_PLAYBACK].formats =
- SNDRV_PCM_FMTBIT_S16_LE;
- }
-
- return 0;
-}
-
-static int patch_vt1708(struct hda_codec *codec)
-{
- struct via_spec *spec;
- int err;
-
- /* create a codec specific record */
- spec = via_new_spec(codec);
- if (spec == NULL)
- return -ENOMEM;
-
- /* override some patch_ops */
- codec->patch_ops.build_controls = vt1708_build_controls;
- codec->patch_ops.build_pcms = vt1708_build_pcms;
- spec->gen.mixer_nid = 0x17;
-
- /* set jackpoll_interval while parsing the codec */
- codec->jackpoll_interval = msecs_to_jiffies(100);
- spec->vt1708_jack_detect = 1;
-
- /* don't support the input jack switching due to lack of unsol event */
- /* (it may work with polling, though, but it needs testing) */
- spec->gen.suppress_auto_mic = 1;
- /* Some machines show the broken speaker mute */
- spec->gen.auto_mute_via_amp = 1;
-
- /* Add HP and CD pin config connect bit re-config action */
- vt1708_set_pinconfig_connect(codec, VT1708_HP_PIN_NID);
- vt1708_set_pinconfig_connect(codec, VT1708_CD_PIN_NID);
-
- err = snd_hda_add_verbs(codec, vt1708_init_verbs);
- if (err < 0)
- goto error;
-
- /* automatic parse from the BIOS config */
- err = via_parse_auto_config(codec);
- if (err < 0)
- goto error;
-
- /* add jack detect on/off control */
- if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1708_jack_detect_ctl)) {
- err = -ENOMEM;
- goto error;
- }
-
- /* clear jackpoll_interval again; it's set dynamically */
- codec->jackpoll_interval = 0;
-
- return 0;
-
- error:
- via_free(codec);
- return err;
-}
-
-static int patch_vt1709(struct hda_codec *codec)
-{
- struct via_spec *spec;
- int err;
-
- /* create a codec specific record */
- spec = via_new_spec(codec);
- if (spec == NULL)
- return -ENOMEM;
-
- spec->gen.mixer_nid = 0x18;
-
- err = via_parse_auto_config(codec);
- if (err < 0)
- goto error;
-
- return 0;
-
- error:
- via_free(codec);
- return err;
-}
-
-static int patch_vt1708S(struct hda_codec *codec);
-static int patch_vt1708B(struct hda_codec *codec)
-{
- struct via_spec *spec;
- int err;
-
- if (get_codec_type(codec) == VT1708BCE)
- return patch_vt1708S(codec);
-
- /* create a codec specific record */
- spec = via_new_spec(codec);
- if (spec == NULL)
- return -ENOMEM;
-
- spec->gen.mixer_nid = 0x16;
-
- /* automatic parse from the BIOS config */
- err = via_parse_auto_config(codec);
- if (err < 0)
- goto error;
-
- return 0;
-
- error:
- via_free(codec);
- return err;
-}
-
-/* Patch for VT1708S */
-static const struct hda_verb vt1708S_init_verbs[] = {
- /* Enable Mic Boost Volume backdoor */
- {0x1, 0xf98, 0x1},
- /* don't bybass mixer */
- {0x1, 0xf88, 0xc0},
- { }
-};
-
-static void override_mic_boost(struct hda_codec *codec, hda_nid_t pin,
- int offset, int num_steps, int step_size)
-{
- snd_hda_override_wcaps(codec, pin,
- get_wcaps(codec, pin) | AC_WCAP_IN_AMP);
- snd_hda_override_amp_caps(codec, pin, HDA_INPUT,
- (offset << AC_AMPCAP_OFFSET_SHIFT) |
- (num_steps << AC_AMPCAP_NUM_STEPS_SHIFT) |
- (step_size << AC_AMPCAP_STEP_SIZE_SHIFT) |
- (0 << AC_AMPCAP_MUTE_SHIFT));
-}
-
-static int patch_vt1708S(struct hda_codec *codec)
-{
- struct via_spec *spec;
- int err;
-
- /* create a codec specific record */
- spec = via_new_spec(codec);
- if (spec == NULL)
- return -ENOMEM;
-
- spec->gen.mixer_nid = 0x16;
- override_mic_boost(codec, 0x1a, 0, 3, 40);
- override_mic_boost(codec, 0x1e, 0, 3, 40);
-
- /* correct names for VT1708BCE */
- if (get_codec_type(codec) == VT1708BCE)
- snd_hda_codec_set_name(codec, "VT1708BCE");
- /* correct names for VT1705 */
- if (codec->core.vendor_id == 0x11064397)
- snd_hda_codec_set_name(codec, "VT1705");
-
- err = snd_hda_add_verbs(codec, vt1708S_init_verbs);
- if (err < 0)
- goto error;
-
- /* automatic parse from the BIOS config */
- err = via_parse_auto_config(codec);
- if (err < 0)
- goto error;
-
- return 0;
-
- error:
- via_free(codec);
- return err;
-}
-
-/* Patch for VT1702 */
-
-static const struct hda_verb vt1702_init_verbs[] = {
- /* mixer enable */
- {0x1, 0xF88, 0x3},
- /* GPIO 0~2 */
- {0x1, 0xF82, 0x3F},
- { }
-};
-
-static int patch_vt1702(struct hda_codec *codec)
-{
- struct via_spec *spec;
- int err;
-
- /* create a codec specific record */
- spec = via_new_spec(codec);
- if (spec == NULL)
- return -ENOMEM;
-
- spec->gen.mixer_nid = 0x1a;
-
- /* limit AA path volume to 0 dB */
- snd_hda_override_amp_caps(codec, 0x1A, HDA_INPUT,
- (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
- (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
- (0x5 << AC_AMPCAP_STEP_SIZE_SHIFT) |
- (1 << AC_AMPCAP_MUTE_SHIFT));
-
- err = snd_hda_add_verbs(codec, vt1702_init_verbs);
- if (err < 0)
- goto error;
-
- /* automatic parse from the BIOS config */
- err = via_parse_auto_config(codec);
- if (err < 0)
- goto error;
-
- return 0;
-
- error:
- via_free(codec);
- return err;
-}
-
-/* Patch for VT1718S */
-
-static const struct hda_verb vt1718S_init_verbs[] = {
- /* Enable MW0 adjust Gain 5 */
- {0x1, 0xfb2, 0x10},
- /* Enable Boost Volume backdoor */
- {0x1, 0xf88, 0x8},
-
- { }
-};
-
-/* Add a connection to the primary DAC from AA-mixer for some codecs
- * This isn't listed from the raw info, but the chip has a secret connection.
- */
-static int add_secret_dac_path(struct hda_codec *codec)
-{
- struct via_spec *spec = codec->spec;
- int i, nums;
- hda_nid_t conn[8];
- hda_nid_t nid;
-
- if (!spec->gen.mixer_nid)
- return 0;
- nums = snd_hda_get_connections(codec, spec->gen.mixer_nid, conn,
- ARRAY_SIZE(conn) - 1);
- if (nums < 0)
- return nums;
-
- for (i = 0; i < nums; i++) {
- if (get_wcaps_type(get_wcaps(codec, conn[i])) == AC_WID_AUD_OUT)
- return 0;
- }
-
- /* find the primary DAC and add to the connection list */
- for_each_hda_codec_node(nid, codec) {
- unsigned int caps = get_wcaps(codec, nid);
- if (get_wcaps_type(caps) == AC_WID_AUD_OUT &&
- !(caps & AC_WCAP_DIGITAL)) {
- conn[nums++] = nid;
- return snd_hda_override_conn_list(codec,
- spec->gen.mixer_nid,
- nums, conn);
- }
- }
- return 0;
-}
-
-
-static int patch_vt1718S(struct hda_codec *codec)
-{
- struct via_spec *spec;
- int err;
-
- /* create a codec specific record */
- spec = via_new_spec(codec);
- if (spec == NULL)
- return -ENOMEM;
-
- spec->gen.mixer_nid = 0x21;
- override_mic_boost(codec, 0x2b, 0, 3, 40);
- override_mic_boost(codec, 0x29, 0, 3, 40);
- add_secret_dac_path(codec);
-
- err = snd_hda_add_verbs(codec, vt1718S_init_verbs);
- if (err < 0)
- goto error;
-
- /* automatic parse from the BIOS config */
- err = via_parse_auto_config(codec);
- if (err < 0)
- goto error;
-
- return 0;
-
- error:
- via_free(codec);
- return err;
-}
-
-/* Patch for VT1716S */
-
-static int vt1716s_dmic_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
-
-static int vt1716s_dmic_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- int index = 0;
-
- index = snd_hda_codec_read(codec, 0x26, 0,
- AC_VERB_GET_CONNECT_SEL, 0);
- if (index != -1)
- *ucontrol->value.integer.value = index;
-
- return 0;
-}
-
-static int vt1716s_dmic_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct via_spec *spec = codec->spec;
- int index = *ucontrol->value.integer.value;
-
- snd_hda_codec_write(codec, 0x26, 0,
- AC_VERB_SET_CONNECT_SEL, index);
- spec->dmic_enabled = index;
- return 1;
-}
-
-static const struct snd_kcontrol_new vt1716s_dmic_mixer_vol =
- HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x22, 0x0, HDA_INPUT);
-static const struct snd_kcontrol_new vt1716s_dmic_mixer_sw = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Digital Mic Capture Switch",
- .subdevice = HDA_SUBDEV_NID_FLAG | 0x26,
- .count = 1,
- .info = vt1716s_dmic_info,
- .get = vt1716s_dmic_get,
- .put = vt1716s_dmic_put,
-};
-
-
-/* mono-out mixer elements */
-static const struct snd_kcontrol_new vt1716S_mono_out_mixer =
- HDA_CODEC_MUTE("Mono Playback Switch", 0x2a, 0x0, HDA_OUTPUT);
-
-static const struct hda_verb vt1716S_init_verbs[] = {
- /* Enable Boost Volume backdoor */
- {0x1, 0xf8a, 0x80},
- /* don't bybass mixer */
- {0x1, 0xf88, 0xc0},
- /* Enable mono output */
- {0x1, 0xf90, 0x08},
- { }
-};
-
-static int patch_vt1716S(struct hda_codec *codec)
-{
- struct via_spec *spec;
- int err;
-
- /* create a codec specific record */
- spec = via_new_spec(codec);
- if (spec == NULL)
- return -ENOMEM;
-
- spec->gen.mixer_nid = 0x16;
- override_mic_boost(codec, 0x1a, 0, 3, 40);
- override_mic_boost(codec, 0x1e, 0, 3, 40);
-
- err = snd_hda_add_verbs(codec, vt1716S_init_verbs);
- if (err < 0)
- goto error;
-
- /* automatic parse from the BIOS config */
- err = via_parse_auto_config(codec);
- if (err < 0)
- goto error;
-
- if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1716s_dmic_mixer_vol) ||
- !snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1716s_dmic_mixer_sw) ||
- !snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1716S_mono_out_mixer)) {
- err = -ENOMEM;
- goto error;
- }
-
- return 0;
-
- error:
- via_free(codec);
- return err;
-}
-
-/* for vt2002P */
-
-static const struct hda_verb vt2002P_init_verbs[] = {
- /* Class-D speaker related verbs */
- {0x1, 0xfe0, 0x4},
- {0x1, 0xfe9, 0x80},
- {0x1, 0xfe2, 0x22},
- /* Enable Boost Volume backdoor */
- {0x1, 0xfb9, 0x24},
- /* Enable AOW0 to MW9 */
- {0x1, 0xfb8, 0x88},
- { }
-};
-
-static const struct hda_verb vt1802_init_verbs[] = {
- /* Enable Boost Volume backdoor */
- {0x1, 0xfb9, 0x24},
- /* Enable AOW0 to MW9 */
- {0x1, 0xfb8, 0x88},
- { }
-};
-
-/*
- * pin fix-up
- */
-enum {
- VIA_FIXUP_INTMIC_BOOST,
- VIA_FIXUP_ASUS_G75,
- VIA_FIXUP_POWER_SAVE,
-};
-
-static void via_fixup_intmic_boost(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_PRE_PROBE)
- override_mic_boost(codec, 0x30, 0, 2, 40);
-}
-
-static void via_fixup_power_save(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_PRE_PROBE)
- codec->power_save_node = 0;
-}
-
-static const struct hda_fixup via_fixups[] = {
- [VIA_FIXUP_INTMIC_BOOST] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = via_fixup_intmic_boost,
- },
- [VIA_FIXUP_ASUS_G75] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- /* set 0x24 and 0x33 as speakers */
- { 0x24, 0x991301f0 },
- { 0x33, 0x991301f1 }, /* subwoofer */
- { }
- }
- },
- [VIA_FIXUP_POWER_SAVE] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = via_fixup_power_save,
- },
-};
-
-static const struct hda_quirk vt2002p_fixups[] = {
- SND_PCI_QUIRK(0x1043, 0x13f7, "Asus B23E", VIA_FIXUP_POWER_SAVE),
- SND_PCI_QUIRK(0x1043, 0x1487, "Asus G75", VIA_FIXUP_ASUS_G75),
- SND_PCI_QUIRK(0x1043, 0x8532, "Asus X202E", VIA_FIXUP_INTMIC_BOOST),
- SND_PCI_QUIRK_VENDOR(0x1558, "Clevo", VIA_FIXUP_POWER_SAVE),
- {}
-};
-
-/* NIDs 0x24 and 0x33 on VT1802 have connections to non-existing NID 0x3e
- * Replace this with mixer NID 0x1c
- */
-static void fix_vt1802_connections(struct hda_codec *codec)
-{
- static const hda_nid_t conn_24[] = { 0x14, 0x1c };
- static const hda_nid_t conn_33[] = { 0x1c };
-
- snd_hda_override_conn_list(codec, 0x24, ARRAY_SIZE(conn_24), conn_24);
- snd_hda_override_conn_list(codec, 0x33, ARRAY_SIZE(conn_33), conn_33);
-}
-
-/* patch for vt2002P */
-static int patch_vt2002P(struct hda_codec *codec)
-{
- struct via_spec *spec;
- int err;
-
- /* create a codec specific record */
- spec = via_new_spec(codec);
- if (spec == NULL)
- return -ENOMEM;
-
- spec->gen.mixer_nid = 0x21;
- override_mic_boost(codec, 0x2b, 0, 3, 40);
- override_mic_boost(codec, 0x29, 0, 3, 40);
- if (spec->codec_type == VT1802)
- fix_vt1802_connections(codec);
- add_secret_dac_path(codec);
-
- snd_hda_pick_fixup(codec, NULL, vt2002p_fixups, via_fixups);
- snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
-
- if (spec->codec_type == VT1802)
- err = snd_hda_add_verbs(codec, vt1802_init_verbs);
- else
- err = snd_hda_add_verbs(codec, vt2002P_init_verbs);
- if (err < 0)
- goto error;
-
- /* automatic parse from the BIOS config */
- err = via_parse_auto_config(codec);
- if (err < 0)
- goto error;
-
- return 0;
-
- error:
- via_free(codec);
- return err;
-}
-
-/* for vt1812 */
-
-static const struct hda_verb vt1812_init_verbs[] = {
- /* Enable Boost Volume backdoor */
- {0x1, 0xfb9, 0x24},
- /* Enable AOW0 to MW9 */
- {0x1, 0xfb8, 0xa8},
- { }
-};
-
-/* patch for vt1812 */
-static int patch_vt1812(struct hda_codec *codec)
-{
- struct via_spec *spec;
- int err;
-
- /* create a codec specific record */
- spec = via_new_spec(codec);
- if (spec == NULL)
- return -ENOMEM;
-
- spec->gen.mixer_nid = 0x21;
- override_mic_boost(codec, 0x2b, 0, 3, 40);
- override_mic_boost(codec, 0x29, 0, 3, 40);
- add_secret_dac_path(codec);
-
- err = snd_hda_add_verbs(codec, vt1812_init_verbs);
- if (err < 0)
- goto error;
-
- /* automatic parse from the BIOS config */
- err = via_parse_auto_config(codec);
- if (err < 0)
- goto error;
-
- return 0;
-
- error:
- via_free(codec);
- return err;
-}
-
-/* patch for vt3476 */
-
-static const struct hda_verb vt3476_init_verbs[] = {
- /* Enable DMic 8/16/32K */
- {0x1, 0xF7B, 0x30},
- /* Enable Boost Volume backdoor */
- {0x1, 0xFB9, 0x20},
- /* Enable AOW-MW9 path */
- {0x1, 0xFB8, 0x10},
- { }
-};
-
-static int patch_vt3476(struct hda_codec *codec)
-{
- struct via_spec *spec;
- int err;
-
- /* create a codec specific record */
- spec = via_new_spec(codec);
- if (spec == NULL)
- return -ENOMEM;
-
- spec->gen.mixer_nid = 0x3f;
- add_secret_dac_path(codec);
-
- err = snd_hda_add_verbs(codec, vt3476_init_verbs);
- if (err < 0)
- goto error;
-
- /* automatic parse from the BIOS config */
- err = via_parse_auto_config(codec);
- if (err < 0)
- goto error;
-
- return 0;
-
- error:
- via_free(codec);
- return err;
-}
-
-/*
- * patch entries
- */
-static const struct hda_device_id snd_hda_id_via[] = {
- HDA_CODEC_ENTRY(0x11061708, "VT1708", patch_vt1708),
- HDA_CODEC_ENTRY(0x11061709, "VT1708", patch_vt1708),
- HDA_CODEC_ENTRY(0x1106170a, "VT1708", patch_vt1708),
- HDA_CODEC_ENTRY(0x1106170b, "VT1708", patch_vt1708),
- HDA_CODEC_ENTRY(0x1106e710, "VT1709 10-Ch", patch_vt1709),
- HDA_CODEC_ENTRY(0x1106e711, "VT1709 10-Ch", patch_vt1709),
- HDA_CODEC_ENTRY(0x1106e712, "VT1709 10-Ch", patch_vt1709),
- HDA_CODEC_ENTRY(0x1106e713, "VT1709 10-Ch", patch_vt1709),
- HDA_CODEC_ENTRY(0x1106e714, "VT1709 6-Ch", patch_vt1709),
- HDA_CODEC_ENTRY(0x1106e715, "VT1709 6-Ch", patch_vt1709),
- HDA_CODEC_ENTRY(0x1106e716, "VT1709 6-Ch", patch_vt1709),
- HDA_CODEC_ENTRY(0x1106e717, "VT1709 6-Ch", patch_vt1709),
- HDA_CODEC_ENTRY(0x1106e720, "VT1708B 8-Ch", patch_vt1708B),
- HDA_CODEC_ENTRY(0x1106e721, "VT1708B 8-Ch", patch_vt1708B),
- HDA_CODEC_ENTRY(0x1106e722, "VT1708B 8-Ch", patch_vt1708B),
- HDA_CODEC_ENTRY(0x1106e723, "VT1708B 8-Ch", patch_vt1708B),
- HDA_CODEC_ENTRY(0x1106e724, "VT1708B 4-Ch", patch_vt1708B),
- HDA_CODEC_ENTRY(0x1106e725, "VT1708B 4-Ch", patch_vt1708B),
- HDA_CODEC_ENTRY(0x1106e726, "VT1708B 4-Ch", patch_vt1708B),
- HDA_CODEC_ENTRY(0x1106e727, "VT1708B 4-Ch", patch_vt1708B),
- HDA_CODEC_ENTRY(0x11060397, "VT1708S", patch_vt1708S),
- HDA_CODEC_ENTRY(0x11061397, "VT1708S", patch_vt1708S),
- HDA_CODEC_ENTRY(0x11062397, "VT1708S", patch_vt1708S),
- HDA_CODEC_ENTRY(0x11063397, "VT1708S", patch_vt1708S),
- HDA_CODEC_ENTRY(0x11064397, "VT1705", patch_vt1708S),
- HDA_CODEC_ENTRY(0x11065397, "VT1708S", patch_vt1708S),
- HDA_CODEC_ENTRY(0x11066397, "VT1708S", patch_vt1708S),
- HDA_CODEC_ENTRY(0x11067397, "VT1708S", patch_vt1708S),
- HDA_CODEC_ENTRY(0x11060398, "VT1702", patch_vt1702),
- HDA_CODEC_ENTRY(0x11061398, "VT1702", patch_vt1702),
- HDA_CODEC_ENTRY(0x11062398, "VT1702", patch_vt1702),
- HDA_CODEC_ENTRY(0x11063398, "VT1702", patch_vt1702),
- HDA_CODEC_ENTRY(0x11064398, "VT1702", patch_vt1702),
- HDA_CODEC_ENTRY(0x11065398, "VT1702", patch_vt1702),
- HDA_CODEC_ENTRY(0x11066398, "VT1702", patch_vt1702),
- HDA_CODEC_ENTRY(0x11067398, "VT1702", patch_vt1702),
- HDA_CODEC_ENTRY(0x11060428, "VT1718S", patch_vt1718S),
- HDA_CODEC_ENTRY(0x11064428, "VT1718S", patch_vt1718S),
- HDA_CODEC_ENTRY(0x11060441, "VT2020", patch_vt1718S),
- HDA_CODEC_ENTRY(0x11064441, "VT1828S", patch_vt1718S),
- HDA_CODEC_ENTRY(0x11060433, "VT1716S", patch_vt1716S),
- HDA_CODEC_ENTRY(0x1106a721, "VT1716S", patch_vt1716S),
- HDA_CODEC_ENTRY(0x11060438, "VT2002P", patch_vt2002P),
- HDA_CODEC_ENTRY(0x11064438, "VT2002P", patch_vt2002P),
- HDA_CODEC_ENTRY(0x11060448, "VT1812", patch_vt1812),
- HDA_CODEC_ENTRY(0x11060440, "VT1818S", patch_vt1708S),
- HDA_CODEC_ENTRY(0x11060446, "VT1802", patch_vt2002P),
- HDA_CODEC_ENTRY(0x11068446, "VT1802", patch_vt2002P),
- HDA_CODEC_ENTRY(0x11064760, "VT1705CF", patch_vt3476),
- HDA_CODEC_ENTRY(0x11064761, "VT1708SCE", patch_vt3476),
- HDA_CODEC_ENTRY(0x11064762, "VT1808", patch_vt3476),
- {} /* terminator */
-};
-MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_via);
-
-static struct hda_codec_driver via_driver = {
- .id = snd_hda_id_via,
-};
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("VIA HD-audio codec");
-
-module_hda_codec_driver(via_driver);
diff --git a/sound/pci/hda/tas2781_hda.c b/sound/pci/hda/tas2781_hda.c
deleted file mode 100644
index 5f1d4b3e9688..000000000000
--- a/sound/pci/hda/tas2781_hda.c
+++ /dev/null
@@ -1,377 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// TAS2781 HDA Shared Lib for I2C&SPI driver
-//
-// Copyright 2025 Texas Instruments, Inc.
-//
-// Author: Shenghao Ding <shenghao-ding@ti.com>
-
-#include <linux/component.h>
-#include <linux/crc8.h>
-#include <linux/crc32.h>
-#include <linux/efi.h>
-#include <linux/firmware.h>
-#include <linux/i2c.h>
-#include <linux/pm_runtime.h>
-#include <sound/soc.h>
-#include <sound/tas2781.h>
-
-#include "tas2781_hda.h"
-
-const efi_guid_t tasdev_fct_efi_guid[] = {
- /* DELL */
- EFI_GUID(0xcc92382d, 0x6337, 0x41cb, 0xa8, 0x8b, 0x8e, 0xce, 0x74,
- 0x91, 0xea, 0x9f),
- /* HP */
- EFI_GUID(0x02f9af02, 0x7734, 0x4233, 0xb4, 0x3d, 0x93, 0xfe, 0x5a,
- 0xa3, 0x5d, 0xb3),
- /* LENOVO & OTHERS */
- EFI_GUID(0x1f52d2a1, 0xbb3a, 0x457d, 0xbc, 0x09, 0x43, 0xa3, 0xf4,
- 0x31, 0x0a, 0x92),
-};
-EXPORT_SYMBOL_NS_GPL(tasdev_fct_efi_guid, "SND_HDA_SCODEC_TAS2781");
-
-static void tas2781_apply_calib(struct tasdevice_priv *p)
-{
- struct calidata *cali_data = &p->cali_data;
- struct cali_reg *r = &cali_data->cali_reg_array;
- unsigned char *data = cali_data->data;
- unsigned int *tmp_val = (unsigned int *)data;
- unsigned int cali_reg[TASDEV_CALIB_N] = {
- TASDEVICE_REG(0, 0x17, 0x74),
- TASDEVICE_REG(0, 0x18, 0x0c),
- TASDEVICE_REG(0, 0x18, 0x14),
- TASDEVICE_REG(0, 0x13, 0x70),
- TASDEVICE_REG(0, 0x18, 0x7c),
- };
- unsigned int crc, oft;
- unsigned char *buf;
- int i, j, k, l;
-
- if (tmp_val[0] == 2781) {
- /*
- * New features were added in calibrated Data V3:
- * 1. Added calibration registers address define in
- * a node, marked as Device id == 0x80.
- * New features were added in calibrated Data V2:
- * 1. Added some the fields to store the link_id and
- * uniqie_id for multi-link solutions
- * 2. Support flexible number of devices instead of
- * fixed one in V1.
- * Layout of calibrated data V2 in UEFI(total 256 bytes):
- * ChipID (2781, 4 bytes)
- * Data-Group-Sum (4 bytes)
- * TimeStamp of Calibration (4 bytes)
- * for (i = 0; i < Data-Group-Sum; i++) {
- * if (Data type != 0x80) (4 bytes)
- * Calibrated Data of Device #i (20 bytes)
- * else
- * Calibration registers address (5*4 = 20 bytes)
- * # V2: No reg addr in data grp section.
- * # V3: Normally the last grp is the reg addr.
- * }
- * CRC (4 bytes)
- * Reserved (the rest)
- */
- crc = crc32(~0, data, (3 + tmp_val[1] * 6) * 4) ^ ~0;
-
- if (crc != tmp_val[3 + tmp_val[1] * 6]) {
- cali_data->total_sz = 0;
- dev_err(p->dev, "%s: CRC error\n", __func__);
- return;
- }
-
- for (j = 0, k = 0; j < tmp_val[1]; j++) {
- oft = j * 6 + 3;
- if (tmp_val[oft] == TASDEV_UEFI_CALI_REG_ADDR_FLG) {
- for (i = 0; i < TASDEV_CALIB_N; i++) {
- buf = &data[(oft + i + 1) * 4];
- cali_reg[i] = TASDEVICE_REG(buf[1],
- buf[2], buf[3]);
- }
- } else {
- l = j * (cali_data->cali_dat_sz_per_dev + 1);
- if (k >= p->ndev || l > oft * 4) {
- dev_err(p->dev, "%s: dev sum error\n",
- __func__);
- cali_data->total_sz = 0;
- return;
- }
-
- data[l] = k;
- for (i = 0; i < TASDEV_CALIB_N * 4; i++)
- data[l + i] = data[4 * oft + i];
- k++;
- }
- }
- } else {
- /*
- * Calibration data is in V1 format.
- * struct cali_data {
- * char cali_data[20];
- * }
- *
- * struct {
- * struct cali_data cali_data[4];
- * int TimeStamp of Calibration (4 bytes)
- * int CRC (4 bytes)
- * } ueft;
- */
- crc = crc32(~0, data, 84) ^ ~0;
- if (crc != tmp_val[21]) {
- cali_data->total_sz = 0;
- dev_err(p->dev, "%s: V1 CRC error\n", __func__);
- return;
- }
-
- for (j = p->ndev - 1; j >= 0; j--) {
- l = j * (cali_data->cali_dat_sz_per_dev + 1);
- for (i = TASDEV_CALIB_N * 4; i > 0 ; i--)
- data[l + i] = data[p->index * 5 + i];
- data[l+i] = j;
- }
- }
-
- if (p->dspbin_typ == TASDEV_BASIC) {
- r->r0_reg = cali_reg[0];
- r->invr0_reg = cali_reg[1];
- r->r0_low_reg = cali_reg[2];
- r->pow_reg = cali_reg[3];
- r->tlimit_reg = cali_reg[4];
- }
-
- p->is_user_space_calidata = true;
- cali_data->total_sz = p->ndev * (cali_data->cali_dat_sz_per_dev + 1);
-}
-
-/*
- * Update the calibration data, including speaker impedance, f0, etc,
- * into algo. Calibrate data is done by manufacturer in the factory.
- * The data is used by Algo for calculating the speaker temperature,
- * speaker membrane excursion and f0 in real time during playback.
- * Calibration data format in EFI is V2, since 2024.
- */
-int tas2781_save_calibration(struct tas2781_hda *hda)
-{
- /*
- * GUID was used for data access in BIOS, it was provided by board
- * manufactory.
- */
- efi_guid_t efi_guid = tasdev_fct_efi_guid[LENOVO];
- static efi_char16_t efi_name[] = TASDEVICE_CALIBRATION_DATA_NAME;
- struct tasdevice_priv *p = hda->priv;
- struct calidata *cali_data = &p->cali_data;
- unsigned long total_sz = 0;
- unsigned int attr, size;
- unsigned char *data;
- efi_status_t status;
-
- if (hda->catlog_id < LENOVO)
- efi_guid = tasdev_fct_efi_guid[hda->catlog_id];
-
- cali_data->cali_dat_sz_per_dev = 20;
- size = p->ndev * (cali_data->cali_dat_sz_per_dev + 1);
- /* Get real size of UEFI variable */
- status = efi.get_variable(efi_name, &efi_guid, &attr, &total_sz, NULL);
- cali_data->total_sz = total_sz > size ? total_sz : size;
- if (status == EFI_BUFFER_TOO_SMALL) {
- /* Allocate data buffer of data_size bytes */
- data = p->cali_data.data = devm_kzalloc(p->dev,
- p->cali_data.total_sz, GFP_KERNEL);
- if (!data) {
- p->cali_data.total_sz = 0;
- return -ENOMEM;
- }
- /* Get variable contents into buffer */
- status = efi.get_variable(efi_name, &efi_guid, &attr,
- &p->cali_data.total_sz, data);
- }
- if (status != EFI_SUCCESS) {
- p->cali_data.total_sz = 0;
- return status;
- }
-
- tas2781_apply_calib(p);
-
- return 0;
-}
-EXPORT_SYMBOL_NS_GPL(tas2781_save_calibration, "SND_HDA_SCODEC_TAS2781");
-
-void tas2781_hda_remove(struct device *dev,
- const struct component_ops *ops)
-{
- struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
-
- component_del(tas_hda->dev, ops);
-
- pm_runtime_get_sync(tas_hda->dev);
- pm_runtime_disable(tas_hda->dev);
-
- pm_runtime_put_noidle(tas_hda->dev);
-
- tasdevice_remove(tas_hda->priv);
-}
-EXPORT_SYMBOL_NS_GPL(tas2781_hda_remove, "SND_HDA_SCODEC_TAS2781");
-
-int tasdevice_info_profile(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = tas_priv->rcabin.ncfgs - 1;
-
- return 0;
-}
-EXPORT_SYMBOL_NS_GPL(tasdevice_info_profile, "SND_HDA_SCODEC_TAS2781");
-
-int tasdevice_info_programs(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = tas_priv->fmw->nr_programs - 1;
-
- return 0;
-}
-EXPORT_SYMBOL_NS_GPL(tasdevice_info_programs, "SND_HDA_SCODEC_TAS2781");
-
-int tasdevice_info_config(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
- struct tasdevice_fw *tas_fw = tas_priv->fmw;
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = tas_fw->nr_configurations - 1;
-
- return 0;
-}
-EXPORT_SYMBOL_NS_GPL(tasdevice_info_config, "SND_HDA_SCODEC_TAS2781");
-
-int tasdevice_get_profile_id(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
-
- ucontrol->value.integer.value[0] = tas_priv->rcabin.profile_cfg_id;
-
- dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d\n", __func__,
- kcontrol->id.name, tas_priv->rcabin.profile_cfg_id);
-
- return 0;
-}
-EXPORT_SYMBOL_NS_GPL(tasdevice_get_profile_id, "SND_HDA_SCODEC_TAS2781");
-
-int tasdevice_set_profile_id(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
- int profile_id = ucontrol->value.integer.value[0];
- int max = tas_priv->rcabin.ncfgs - 1;
- int val, ret = 0;
-
- val = clamp(profile_id, 0, max);
-
- guard(mutex)(&tas_priv->codec_lock);
-
- dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d -> %d\n", __func__,
- kcontrol->id.name, tas_priv->rcabin.profile_cfg_id, val);
-
- if (tas_priv->rcabin.profile_cfg_id != val) {
- tas_priv->rcabin.profile_cfg_id = val;
- ret = 1;
- }
-
- return ret;
-}
-EXPORT_SYMBOL_NS_GPL(tasdevice_set_profile_id, "SND_HDA_SCODEC_TAS2781");
-
-int tasdevice_program_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
-
- ucontrol->value.integer.value[0] = tas_priv->cur_prog;
-
- dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d\n", __func__,
- kcontrol->id.name, tas_priv->cur_prog);
-
- return 0;
-}
-EXPORT_SYMBOL_NS_GPL(tasdevice_program_get, "SND_HDA_SCODEC_TAS2781");
-
-int tasdevice_program_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
- struct tasdevice_fw *tas_fw = tas_priv->fmw;
- int nr_program = ucontrol->value.integer.value[0];
- int max = tas_fw->nr_programs - 1;
- int val, ret = 0;
-
- val = clamp(nr_program, 0, max);
-
- guard(mutex)(&tas_priv->codec_lock);
-
- dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d -> %d\n", __func__,
- kcontrol->id.name, tas_priv->cur_prog, val);
-
- if (tas_priv->cur_prog != val) {
- tas_priv->cur_prog = val;
- ret = 1;
- }
-
- return ret;
-}
-EXPORT_SYMBOL_NS_GPL(tasdevice_program_put, "SND_HDA_SCODEC_TAS2781");
-
-int tasdevice_config_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
-
- ucontrol->value.integer.value[0] = tas_priv->cur_conf;
-
- dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d\n", __func__,
- kcontrol->id.name, tas_priv->cur_conf);
-
- return 0;
-}
-EXPORT_SYMBOL_NS_GPL(tasdevice_config_get, "SND_HDA_SCODEC_TAS2781");
-
-int tasdevice_config_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
- struct tasdevice_fw *tas_fw = tas_priv->fmw;
- int nr_config = ucontrol->value.integer.value[0];
- int max = tas_fw->nr_configurations - 1;
- int val, ret = 0;
-
- val = clamp(nr_config, 0, max);
-
- guard(mutex)(&tas_priv->codec_lock);
-
- dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d -> %d\n", __func__,
- kcontrol->id.name, tas_priv->cur_conf, val);
-
- if (tas_priv->cur_conf != val) {
- tas_priv->cur_conf = val;
- ret = 1;
- }
-
- return ret;
-}
-EXPORT_SYMBOL_NS_GPL(tasdevice_config_put, "SND_HDA_SCODEC_TAS2781");
-
-MODULE_DESCRIPTION("TAS2781 HDA Driver");
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Shenghao Ding, TI, <shenghao-ding@ti.com>");
diff --git a/sound/pci/hda/tas2781_hda.h b/sound/pci/hda/tas2781_hda.h
deleted file mode 100644
index 575a701c8dfb..000000000000
--- a/sound/pci/hda/tas2781_hda.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only
- *
- * HDA audio driver for Texas Instruments TAS2781 smart amp
- *
- * Copyright (C) 2025 Texas Instruments, Inc.
- */
-#ifndef __TAS2781_HDA_H__
-#define __TAS2781_HDA_H__
-
-#include <sound/asound.h>
-
-/* Flag of calibration registers address. */
-#define TASDEV_UEFI_CALI_REG_ADDR_FLG BIT(7)
-#define TASDEVICE_CALIBRATION_DATA_NAME L"CALI_DATA"
-#define TASDEV_CALIB_N 5
-
-/*
- * No standard control callbacks for SNDRV_CTL_ELEM_IFACE_CARD
- * Define two controls, one is Volume control callbacks, the other is
- * flag setting control callbacks.
- */
-
-/* Volume control callbacks for tas2781 */
-#define ACARD_SINGLE_RANGE_EXT_TLV(xname, xreg, xshift, xmin, xmax, xinvert, \
- xhandler_get, xhandler_put, tlv_array) { \
- .iface = SNDRV_CTL_ELEM_IFACE_CARD, .name = (xname), \
- .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
- SNDRV_CTL_ELEM_ACCESS_READWRITE, \
- .tlv.p = (tlv_array), \
- .info = snd_soc_info_volsw, \
- .get = xhandler_get, .put = xhandler_put, \
- .private_value = (unsigned long)&(struct soc_mixer_control) { \
- .reg = xreg, .rreg = xreg, \
- .shift = xshift, .rshift = xshift,\
- .min = xmin, .max = xmax, .invert = xinvert, \
- } \
-}
-
-/* Flag control callbacks for tas2781 */
-#define ACARD_SINGLE_BOOL_EXT(xname, xdata, xhandler_get, xhandler_put) { \
- .iface = SNDRV_CTL_ELEM_IFACE_CARD, \
- .name = xname, \
- .info = snd_ctl_boolean_mono_info, \
- .get = xhandler_get, \
- .put = xhandler_put, \
- .private_value = xdata, \
-}
-
-enum device_catlog_id {
- DELL = 0,
- HP,
- LENOVO,
- OTHERS
-};
-
-struct tas2781_hda {
- struct device *dev;
- struct tasdevice_priv *priv;
- struct snd_kcontrol *dsp_prog_ctl;
- struct snd_kcontrol *dsp_conf_ctl;
- struct snd_kcontrol *prof_ctl;
- enum device_catlog_id catlog_id;
- void *hda_priv;
-};
-
-extern const efi_guid_t tasdev_fct_efi_guid[];
-
-int tas2781_save_calibration(struct tas2781_hda *p);
-void tas2781_hda_remove(struct device *dev,
- const struct component_ops *ops);
-int tasdevice_info_profile(struct snd_kcontrol *kctl,
- struct snd_ctl_elem_info *uctl);
-int tasdevice_info_programs(struct snd_kcontrol *kctl,
- struct snd_ctl_elem_info *uctl);
-int tasdevice_info_config(struct snd_kcontrol *kctl,
- struct snd_ctl_elem_info *uctl);
-int tasdevice_set_profile_id(struct snd_kcontrol *kctl,
- struct snd_ctl_elem_value *uctl);
-int tasdevice_get_profile_id(struct snd_kcontrol *kctl,
- struct snd_ctl_elem_value *uctl);
-int tasdevice_program_get(struct snd_kcontrol *kctl,
- struct snd_ctl_elem_value *uctl);
-int tasdevice_program_put(struct snd_kcontrol *kctl,
- struct snd_ctl_elem_value *uctl);
-int tasdevice_config_put(struct snd_kcontrol *kctl,
- struct snd_ctl_elem_value *uctl);
-int tasdevice_config_get(struct snd_kcontrol *kctl,
- struct snd_ctl_elem_value *uctl);
-
-#endif
diff --git a/sound/pci/hda/tas2781_hda_i2c.c b/sound/pci/hda/tas2781_hda_i2c.c
deleted file mode 100644
index d91eed9f7804..000000000000
--- a/sound/pci/hda/tas2781_hda_i2c.c
+++ /dev/null
@@ -1,747 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// TAS2781 HDA I2C driver
-//
-// Copyright 2023 - 2025 Texas Instruments, Inc.
-//
-// Author: Shenghao Ding <shenghao-ding@ti.com>
-// Current maintainer: Baojun Xu <baojun.xu@ti.com>
-
-#include <linux/unaligned.h>
-#include <linux/acpi.h>
-#include <linux/crc8.h>
-#include <linux/crc32.h>
-#include <linux/efi.h>
-#include <linux/firmware.h>
-#include <linux/i2c.h>
-#include <linux/mod_devicetable.h>
-#include <linux/module.h>
-#include <linux/pci_ids.h>
-#include <linux/pm_runtime.h>
-#include <linux/regmap.h>
-#include <sound/hda_codec.h>
-#include <sound/soc.h>
-#include <sound/tas2781.h>
-#include <sound/tas2781-comlib-i2c.h>
-#include <sound/tlv.h>
-#include <sound/tas2781-tlv.h>
-
-#include "hda_local.h"
-#include "hda_auto_parser.h"
-#include "hda_component.h"
-#include "hda_jack.h"
-#include "hda_generic.h"
-#include "tas2781_hda.h"
-
-#define TAS2563_CAL_VAR_NAME_MAX 16
-#define TAS2563_CAL_ARRAY_SIZE 80
-#define TAS2563_CAL_DATA_SIZE 4
-#define TAS2563_MAX_CHANNELS 4
-#define TAS2563_CAL_CH_SIZE 20
-
-#define TAS2563_CAL_R0_LOW TASDEVICE_REG(0, 0x0f, 0x48)
-#define TAS2563_CAL_POWER TASDEVICE_REG(0, 0x0d, 0x3c)
-#define TAS2563_CAL_INVR0 TASDEVICE_REG(0, 0x0f, 0x40)
-#define TAS2563_CAL_TLIM TASDEVICE_REG(0, 0x10, 0x14)
-#define TAS2563_CAL_R0 TASDEVICE_REG(0, 0x0f, 0x34)
-
-struct tas2781_hda_i2c_priv {
- struct snd_kcontrol *snd_ctls[2];
- int (*save_calibration)(struct tas2781_hda *h);
-};
-
-static int tas2781_get_i2c_res(struct acpi_resource *ares, void *data)
-{
- struct tasdevice_priv *tas_priv = data;
- struct acpi_resource_i2c_serialbus *sb;
-
- if (i2c_acpi_get_i2c_resource(ares, &sb)) {
- if (tas_priv->ndev < TASDEVICE_MAX_CHANNELS &&
- sb->slave_address != tas_priv->global_addr) {
- tas_priv->tasdevice[tas_priv->ndev].dev_addr =
- (unsigned int)sb->slave_address;
- tas_priv->ndev++;
- }
- }
- return 1;
-}
-
-static const struct acpi_gpio_params speakerid_gpios = { 0, 0, false };
-
-static const struct acpi_gpio_mapping tas2781_speaker_id_gpios[] = {
- { "speakerid-gpios", &speakerid_gpios, 1 },
- { }
-};
-
-static int tas2781_read_acpi(struct tasdevice_priv *p, const char *hid)
-{
- struct acpi_device *adev;
- struct device *physdev;
- LIST_HEAD(resources);
- const char *sub;
- uint32_t subid;
- int ret;
-
- adev = acpi_dev_get_first_match_dev(hid, NULL, -1);
- if (!adev) {
- dev_err(p->dev,
- "Failed to find an ACPI device for %s\n", hid);
- return -ENODEV;
- }
-
- physdev = get_device(acpi_get_first_physical_node(adev));
- ret = acpi_dev_get_resources(adev, &resources, tas2781_get_i2c_res, p);
- if (ret < 0) {
- dev_err(p->dev, "Failed to get ACPI resource.\n");
- goto err;
- }
- sub = acpi_get_subsystem_id(ACPI_HANDLE(physdev));
- if (IS_ERR(sub)) {
- /* No subsys id in older tas2563 projects. */
- if (!strncmp(hid, "INT8866", sizeof("INT8866")))
- goto end_2563;
- dev_err(p->dev, "Failed to get SUBSYS ID.\n");
- ret = PTR_ERR(sub);
- goto err;
- }
- /* Speaker id was needed for ASUS projects. */
- ret = kstrtou32(sub, 16, &subid);
- if (!ret && upper_16_bits(subid) == PCI_VENDOR_ID_ASUSTEK) {
- ret = devm_acpi_dev_add_driver_gpios(p->dev,
- tas2781_speaker_id_gpios);
- if (ret < 0)
- dev_err(p->dev, "Failed to add driver gpio %d.\n",
- ret);
- p->speaker_id = devm_gpiod_get(p->dev, "speakerid", GPIOD_IN);
- if (IS_ERR(p->speaker_id)) {
- dev_err(p->dev, "Failed to get Speaker id.\n");
- ret = PTR_ERR(p->speaker_id);
- goto err;
- }
- } else {
- p->speaker_id = NULL;
- }
-
-end_2563:
- acpi_dev_free_resource_list(&resources);
- strscpy(p->dev_name, hid, sizeof(p->dev_name));
- put_device(physdev);
- acpi_dev_put(adev);
-
- return 0;
-
-err:
- dev_err(p->dev, "read acpi error, ret: %d\n", ret);
- put_device(physdev);
- acpi_dev_put(adev);
-
- return ret;
-}
-
-static void tas2781_hda_playback_hook(struct device *dev, int action)
-{
- struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
-
- dev_dbg(tas_hda->dev, "%s: action = %d\n", __func__, action);
- switch (action) {
- case HDA_GEN_PCM_ACT_OPEN:
- pm_runtime_get_sync(dev);
- mutex_lock(&tas_hda->priv->codec_lock);
- tasdevice_tuning_switch(tas_hda->priv, 0);
- tas_hda->priv->playback_started = true;
- mutex_unlock(&tas_hda->priv->codec_lock);
- break;
- case HDA_GEN_PCM_ACT_CLOSE:
- mutex_lock(&tas_hda->priv->codec_lock);
- tasdevice_tuning_switch(tas_hda->priv, 1);
- tas_hda->priv->playback_started = false;
- mutex_unlock(&tas_hda->priv->codec_lock);
-
- pm_runtime_mark_last_busy(dev);
- pm_runtime_put_autosuspend(dev);
- break;
- default:
- break;
- }
-}
-
-static int tas2781_amp_getvol(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
- struct soc_mixer_control *mc =
- (struct soc_mixer_control *)kcontrol->private_value;
- int ret;
-
- mutex_lock(&tas_priv->codec_lock);
-
- ret = tasdevice_amp_getvol(tas_priv, ucontrol, mc);
-
- dev_dbg(tas_priv->dev, "%s: kcontrol %s: %ld\n",
- __func__, kcontrol->id.name, ucontrol->value.integer.value[0]);
-
- mutex_unlock(&tas_priv->codec_lock);
-
- return ret;
-}
-
-static int tas2781_amp_putvol(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
- struct soc_mixer_control *mc =
- (struct soc_mixer_control *)kcontrol->private_value;
- int ret;
-
- mutex_lock(&tas_priv->codec_lock);
-
- dev_dbg(tas_priv->dev, "%s: kcontrol %s: -> %ld\n",
- __func__, kcontrol->id.name, ucontrol->value.integer.value[0]);
-
- /* The check of the given value is in tasdevice_amp_putvol. */
- ret = tasdevice_amp_putvol(tas_priv, ucontrol, mc);
-
- mutex_unlock(&tas_priv->codec_lock);
-
- return ret;
-}
-
-static int tas2781_force_fwload_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
-
- mutex_lock(&tas_priv->codec_lock);
-
- ucontrol->value.integer.value[0] = (int)tas_priv->force_fwload_status;
- dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d\n",
- __func__, kcontrol->id.name, tas_priv->force_fwload_status);
-
- mutex_unlock(&tas_priv->codec_lock);
-
- return 0;
-}
-
-static int tas2781_force_fwload_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
- bool change, val = (bool)ucontrol->value.integer.value[0];
-
- mutex_lock(&tas_priv->codec_lock);
-
- dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d -> %d\n",
- __func__, kcontrol->id.name,
- tas_priv->force_fwload_status, val);
-
- if (tas_priv->force_fwload_status == val)
- change = false;
- else {
- change = true;
- tas_priv->force_fwload_status = val;
- }
-
- mutex_unlock(&tas_priv->codec_lock);
-
- return change;
-}
-
-static const struct snd_kcontrol_new tas2781_snd_controls[] = {
- ACARD_SINGLE_RANGE_EXT_TLV("Speaker Analog Gain", TAS2781_AMP_LEVEL,
- 1, 0, 20, 0, tas2781_amp_getvol,
- tas2781_amp_putvol, amp_vol_tlv),
- ACARD_SINGLE_BOOL_EXT("Speaker Force Firmware Load", 0,
- tas2781_force_fwload_get, tas2781_force_fwload_put),
-};
-
-static const struct snd_kcontrol_new tas2781_prof_ctrl = {
- .name = "Speaker Profile Id",
- .iface = SNDRV_CTL_ELEM_IFACE_CARD,
- .info = tasdevice_info_profile,
- .get = tasdevice_get_profile_id,
- .put = tasdevice_set_profile_id,
-};
-
-static const struct snd_kcontrol_new tas2781_dsp_prog_ctrl = {
- .name = "Speaker Program Id",
- .iface = SNDRV_CTL_ELEM_IFACE_CARD,
- .info = tasdevice_info_programs,
- .get = tasdevice_program_get,
- .put = tasdevice_program_put,
-};
-
-static const struct snd_kcontrol_new tas2781_dsp_conf_ctrl = {
- .name = "Speaker Config Id",
- .iface = SNDRV_CTL_ELEM_IFACE_CARD,
- .info = tasdevice_info_config,
- .get = tasdevice_config_get,
- .put = tasdevice_config_put,
-};
-
-static int tas2563_save_calibration(struct tas2781_hda *h)
-{
- efi_guid_t efi_guid = tasdev_fct_efi_guid[LENOVO];
- char *vars[TASDEV_CALIB_N] = {
- "R0_%d", "InvR0_%d", "R0_Low_%d", "Power_%d", "TLim_%d"
- };
- efi_char16_t efi_name[TAS2563_CAL_VAR_NAME_MAX];
- unsigned long max_size = TAS2563_CAL_DATA_SIZE;
- unsigned char var8[TAS2563_CAL_VAR_NAME_MAX];
- struct tasdevice_priv *p = h->hda_priv;
- struct calidata *cd = &p->cali_data;
- struct cali_reg *r = &cd->cali_reg_array;
- unsigned int offset = 0;
- unsigned char *data;
- efi_status_t status;
- unsigned int attr;
- int ret, i, j, k;
-
- cd->cali_dat_sz_per_dev = TAS2563_CAL_DATA_SIZE * TASDEV_CALIB_N;
-
- /* extra byte for each device is the device number */
- cd->total_sz = (cd->cali_dat_sz_per_dev + 1) * p->ndev;
- data = cd->data = devm_kzalloc(p->dev, cd->total_sz,
- GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- for (i = 0; i < p->ndev; ++i) {
- data[offset] = i;
- offset++;
- for (j = 0; j < TASDEV_CALIB_N; ++j) {
- ret = snprintf(var8, sizeof(var8), vars[j], i);
-
- if (ret < 0 || ret >= sizeof(var8) - 1) {
- dev_err(p->dev, "%s: Read %s failed\n",
- __func__, var8);
- return -EINVAL;
- }
- /*
- * Our variable names are ASCII by construction, but
- * EFI names are wide chars. Convert and zero-pad.
- */
- memset(efi_name, 0, sizeof(efi_name));
- for (k = 0; k < sizeof(var8) && var8[k]; k++)
- efi_name[k] = var8[k];
- status = efi.get_variable(efi_name,
- &efi_guid, &attr, &max_size,
- &data[offset]);
- if (status != EFI_SUCCESS ||
- max_size != TAS2563_CAL_DATA_SIZE) {
- dev_warn(p->dev,
- "Dev %d: Caldat[%d] read failed %ld\n",
- i, j, status);
- return -EINVAL;
- }
- offset += TAS2563_CAL_DATA_SIZE;
- }
- }
-
- if (cd->total_sz != offset) {
- dev_err(p->dev, "%s: tot_size(%lu) and offset(%u) dismatch\n",
- __func__, cd->total_sz, offset);
- return -EINVAL;
- }
-
- r->r0_reg = TAS2563_CAL_R0;
- r->invr0_reg = TAS2563_CAL_INVR0;
- r->r0_low_reg = TAS2563_CAL_R0_LOW;
- r->pow_reg = TAS2563_CAL_POWER;
- r->tlimit_reg = TAS2563_CAL_TLIM;
-
- /*
- * TAS2781_FMWLIB supports two solutions of calibrated data. One is
- * from the driver itself: driver reads the calibrated files directly
- * during probe; The other from user space: during init of audio hal,
- * the audio hal will pass the calibrated data via kcontrol interface.
- * Driver will store this data in "struct calidata" for use. For hda
- * device, calibrated data are usunally saved into UEFI. So Hda side
- * codec driver use the mixture of these two solutions, driver reads
- * the data from UEFI, then store this data in "struct calidata" for
- * use.
- */
- p->is_user_space_calidata = true;
-
- return 0;
-}
-
-static void tas2781_hda_remove_controls(struct tas2781_hda *tas_hda)
-{
- struct tas2781_hda_i2c_priv *hda_priv = tas_hda->hda_priv;
- struct hda_codec *codec = tas_hda->priv->codec;
-
- snd_ctl_remove(codec->card, tas_hda->dsp_prog_ctl);
- snd_ctl_remove(codec->card, tas_hda->dsp_conf_ctl);
-
- for (int i = ARRAY_SIZE(hda_priv->snd_ctls) - 1; i >= 0; i--)
- snd_ctl_remove(codec->card, hda_priv->snd_ctls[i]);
-
- snd_ctl_remove(codec->card, tas_hda->prof_ctl);
-}
-
-static void tasdev_fw_ready(const struct firmware *fmw, void *context)
-{
- struct tasdevice_priv *tas_priv = context;
- struct tas2781_hda *tas_hda = dev_get_drvdata(tas_priv->dev);
- struct tas2781_hda_i2c_priv *hda_priv = tas_hda->hda_priv;
- struct hda_codec *codec = tas_priv->codec;
- int i, ret, spk_id;
-
- pm_runtime_get_sync(tas_priv->dev);
- mutex_lock(&tas_priv->codec_lock);
-
- ret = tasdevice_rca_parser(tas_priv, fmw);
- if (ret)
- goto out;
-
- tas_hda->prof_ctl = snd_ctl_new1(&tas2781_prof_ctrl, tas_priv);
- ret = snd_ctl_add(codec->card, tas_hda->prof_ctl);
- if (ret) {
- dev_err(tas_priv->dev,
- "Failed to add KControl %s = %d\n",
- tas2781_prof_ctrl.name, ret);
- goto out;
- }
-
- for (i = 0; i < ARRAY_SIZE(tas2781_snd_controls); i++) {
- hda_priv->snd_ctls[i] = snd_ctl_new1(&tas2781_snd_controls[i],
- tas_priv);
- ret = snd_ctl_add(codec->card, hda_priv->snd_ctls[i]);
- if (ret) {
- dev_err(tas_priv->dev,
- "Failed to add KControl %s = %d\n",
- tas2781_snd_controls[i].name, ret);
- goto out;
- }
- }
-
- tasdevice_dsp_remove(tas_priv);
-
- tas_priv->fw_state = TASDEVICE_DSP_FW_PENDING;
- if (tas_priv->speaker_id != NULL) {
- // Speaker id need to be checked for ASUS only.
- spk_id = gpiod_get_value(tas_priv->speaker_id);
- if (spk_id < 0) {
- // Speaker id is not valid, use default.
- dev_dbg(tas_priv->dev, "Wrong spk_id = %d\n", spk_id);
- spk_id = 0;
- }
- snprintf(tas_priv->coef_binaryname,
- sizeof(tas_priv->coef_binaryname),
- "TAS2XXX%04X%d.bin",
- lower_16_bits(codec->core.subsystem_id),
- spk_id);
- } else {
- snprintf(tas_priv->coef_binaryname,
- sizeof(tas_priv->coef_binaryname),
- "TAS2XXX%04X.bin",
- lower_16_bits(codec->core.subsystem_id));
- }
- ret = tasdevice_dsp_parser(tas_priv);
- if (ret) {
- dev_err(tas_priv->dev, "dspfw load %s error\n",
- tas_priv->coef_binaryname);
- tas_priv->fw_state = TASDEVICE_DSP_FW_FAIL;
- goto out;
- }
-
- tas_hda->dsp_prog_ctl = snd_ctl_new1(&tas2781_dsp_prog_ctrl,
- tas_priv);
- ret = snd_ctl_add(codec->card, tas_hda->dsp_prog_ctl);
- if (ret) {
- dev_err(tas_priv->dev,
- "Failed to add KControl %s = %d\n",
- tas2781_dsp_prog_ctrl.name, ret);
- goto out;
- }
-
- tas_hda->dsp_conf_ctl = snd_ctl_new1(&tas2781_dsp_conf_ctrl,
- tas_priv);
- ret = snd_ctl_add(codec->card, tas_hda->dsp_conf_ctl);
- if (ret) {
- dev_err(tas_priv->dev,
- "Failed to add KControl %s = %d\n",
- tas2781_dsp_conf_ctrl.name, ret);
- goto out;
- }
-
- tas_priv->fw_state = TASDEVICE_DSP_FW_ALL_OK;
- tasdevice_prmg_load(tas_priv, 0);
- if (tas_priv->fmw->nr_programs > 0)
- tas_priv->cur_prog = 0;
- if (tas_priv->fmw->nr_configurations > 0)
- tas_priv->cur_conf = 0;
-
- /* If calibrated data occurs error, dsp will still works with default
- * calibrated data inside algo.
- */
- hda_priv->save_calibration(tas_hda);
-
- tasdevice_tuning_switch(tas_hda->priv, 0);
- tas_hda->priv->playback_started = true;
-
-out:
- mutex_unlock(&tas_hda->priv->codec_lock);
- release_firmware(fmw);
- pm_runtime_mark_last_busy(tas_hda->dev);
- pm_runtime_put_autosuspend(tas_hda->dev);
-}
-
-static int tas2781_hda_bind(struct device *dev, struct device *master,
- void *master_data)
-{
- struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
- struct hda_component_parent *parent = master_data;
- struct hda_component *comp;
- struct hda_codec *codec;
- unsigned int subid;
- int ret;
-
- comp = hda_component_from_index(parent, tas_hda->priv->index);
- if (!comp)
- return -EINVAL;
-
- if (comp->dev)
- return -EBUSY;
-
- codec = parent->codec;
- subid = codec->core.subsystem_id >> 16;
-
- switch (subid) {
- case 0x1028:
- tas_hda->catlog_id = DELL;
- break;
- default:
- tas_hda->catlog_id = LENOVO;
- break;
- }
-
- pm_runtime_get_sync(dev);
-
- comp->dev = dev;
-
- strscpy(comp->name, dev_name(dev), sizeof(comp->name));
-
- ret = tascodec_init(tas_hda->priv, codec, THIS_MODULE, tasdev_fw_ready);
- if (!ret)
- comp->playback_hook = tas2781_hda_playback_hook;
-
- pm_runtime_mark_last_busy(dev);
- pm_runtime_put_autosuspend(dev);
-
- return ret;
-}
-
-static void tas2781_hda_unbind(struct device *dev,
- struct device *master, void *master_data)
-{
- struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
- struct hda_component_parent *parent = master_data;
- struct hda_component *comp;
-
- comp = hda_component_from_index(parent, tas_hda->priv->index);
- if (comp && (comp->dev == dev)) {
- comp->dev = NULL;
- memset(comp->name, 0, sizeof(comp->name));
- comp->playback_hook = NULL;
- }
-
- tas2781_hda_remove_controls(tas_hda);
-
- tasdevice_config_info_remove(tas_hda->priv);
- tasdevice_dsp_remove(tas_hda->priv);
-
- tas_hda->priv->fw_state = TASDEVICE_DSP_FW_PENDING;
-}
-
-static const struct component_ops tas2781_hda_comp_ops = {
- .bind = tas2781_hda_bind,
- .unbind = tas2781_hda_unbind,
-};
-
-static int tas2781_hda_i2c_probe(struct i2c_client *clt)
-{
- struct tas2781_hda_i2c_priv *hda_priv;
- struct tas2781_hda *tas_hda;
- const char *device_name;
- int ret;
-
- tas_hda = devm_kzalloc(&clt->dev, sizeof(*tas_hda), GFP_KERNEL);
- if (!tas_hda)
- return -ENOMEM;
-
- hda_priv = devm_kzalloc(&clt->dev, sizeof(*hda_priv), GFP_KERNEL);
- if (!hda_priv)
- return -ENOMEM;
-
- tas_hda->hda_priv = hda_priv;
-
- dev_set_drvdata(&clt->dev, tas_hda);
- tas_hda->dev = &clt->dev;
-
- tas_hda->priv = tasdevice_kzalloc(clt);
- if (!tas_hda->priv)
- return -ENOMEM;
-
- if (strstr(dev_name(&clt->dev), "TIAS2781")) {
- device_name = "TIAS2781";
- hda_priv->save_calibration = tas2781_save_calibration;
- tas_hda->priv->global_addr = TAS2781_GLOBAL_ADDR;
- } else if (strstr(dev_name(&clt->dev), "INT8866")) {
- device_name = "INT8866";
- hda_priv->save_calibration = tas2563_save_calibration;
- tas_hda->priv->global_addr = TAS2563_GLOBAL_ADDR;
- } else
- return -ENODEV;
-
- tas_hda->priv->irq = clt->irq;
- ret = tas2781_read_acpi(tas_hda->priv, device_name);
- if (ret)
- return dev_err_probe(tas_hda->dev, ret,
- "Platform not supported\n");
-
- ret = tasdevice_init(tas_hda->priv);
- if (ret)
- goto err;
-
- pm_runtime_set_autosuspend_delay(tas_hda->dev, 3000);
- pm_runtime_use_autosuspend(tas_hda->dev);
- pm_runtime_mark_last_busy(tas_hda->dev);
- pm_runtime_set_active(tas_hda->dev);
- pm_runtime_enable(tas_hda->dev);
-
- tasdevice_reset(tas_hda->priv);
-
- ret = component_add(tas_hda->dev, &tas2781_hda_comp_ops);
- if (ret) {
- dev_err(tas_hda->dev, "Register component failed: %d\n", ret);
- pm_runtime_disable(tas_hda->dev);
- }
-
-err:
- if (ret)
- tas2781_hda_remove(&clt->dev, &tas2781_hda_comp_ops);
- return ret;
-}
-
-static void tas2781_hda_i2c_remove(struct i2c_client *clt)
-{
- tas2781_hda_remove(&clt->dev, &tas2781_hda_comp_ops);
-}
-
-static int tas2781_runtime_suspend(struct device *dev)
-{
- struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
-
- dev_dbg(tas_hda->dev, "Runtime Suspend\n");
-
- mutex_lock(&tas_hda->priv->codec_lock);
-
- /* The driver powers up the amplifiers at module load time.
- * Stop the playback if it's unused.
- */
- if (tas_hda->priv->playback_started) {
- tasdevice_tuning_switch(tas_hda->priv, 1);
- tas_hda->priv->playback_started = false;
- }
-
- mutex_unlock(&tas_hda->priv->codec_lock);
-
- return 0;
-}
-
-static int tas2781_runtime_resume(struct device *dev)
-{
- struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
-
- dev_dbg(tas_hda->dev, "Runtime Resume\n");
-
- mutex_lock(&tas_hda->priv->codec_lock);
-
- tasdevice_prmg_load(tas_hda->priv, tas_hda->priv->cur_prog);
-
- mutex_unlock(&tas_hda->priv->codec_lock);
-
- return 0;
-}
-
-static int tas2781_system_suspend(struct device *dev)
-{
- struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
-
- dev_dbg(tas_hda->priv->dev, "System Suspend\n");
-
- mutex_lock(&tas_hda->priv->codec_lock);
-
- /* Shutdown chip before system suspend */
- if (tas_hda->priv->playback_started)
- tasdevice_tuning_switch(tas_hda->priv, 1);
-
- mutex_unlock(&tas_hda->priv->codec_lock);
-
- /*
- * Reset GPIO may be shared, so cannot reset here.
- * However beyond this point, amps may be powered down.
- */
- return 0;
-}
-
-static int tas2781_system_resume(struct device *dev)
-{
- struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
- int i;
-
- dev_dbg(tas_hda->priv->dev, "System Resume\n");
-
- mutex_lock(&tas_hda->priv->codec_lock);
-
- for (i = 0; i < tas_hda->priv->ndev; i++) {
- tas_hda->priv->tasdevice[i].cur_book = -1;
- tas_hda->priv->tasdevice[i].cur_prog = -1;
- tas_hda->priv->tasdevice[i].cur_conf = -1;
- }
- tasdevice_reset(tas_hda->priv);
- tasdevice_prmg_load(tas_hda->priv, tas_hda->priv->cur_prog);
-
- if (tas_hda->priv->playback_started)
- tasdevice_tuning_switch(tas_hda->priv, 0);
-
- mutex_unlock(&tas_hda->priv->codec_lock);
-
- return 0;
-}
-
-static const struct dev_pm_ops tas2781_hda_pm_ops = {
- RUNTIME_PM_OPS(tas2781_runtime_suspend, tas2781_runtime_resume, NULL)
- SYSTEM_SLEEP_PM_OPS(tas2781_system_suspend, tas2781_system_resume)
-};
-
-static const struct i2c_device_id tas2781_hda_i2c_id[] = {
- { "tas2781-hda" },
- {}
-};
-
-static const struct acpi_device_id tas2781_acpi_hda_match[] = {
- {"TIAS2781", 0 },
- {"INT8866", 0 },
- {}
-};
-MODULE_DEVICE_TABLE(acpi, tas2781_acpi_hda_match);
-
-static struct i2c_driver tas2781_hda_i2c_driver = {
- .driver = {
- .name = "tas2781-hda",
- .acpi_match_table = tas2781_acpi_hda_match,
- .pm = &tas2781_hda_pm_ops,
- },
- .id_table = tas2781_hda_i2c_id,
- .probe = tas2781_hda_i2c_probe,
- .remove = tas2781_hda_i2c_remove,
-};
-module_i2c_driver(tas2781_hda_i2c_driver);
-
-MODULE_DESCRIPTION("TAS2781 HDA Driver");
-MODULE_AUTHOR("Shenghao Ding, TI, <shenghao-ding@ti.com>");
-MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS("SND_SOC_TAS2781_FMWLIB");
-MODULE_IMPORT_NS("SND_HDA_SCODEC_TAS2781");
diff --git a/sound/pci/hda/tas2781_hda_spi.c b/sound/pci/hda/tas2781_hda_spi.c
deleted file mode 100644
index 5c03e9d2283a..000000000000
--- a/sound/pci/hda/tas2781_hda_spi.c
+++ /dev/null
@@ -1,958 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// TAS2781 HDA SPI driver
-//
-// Copyright 2024 - 2025 Texas Instruments, Inc.
-//
-// Author: Baojun Xu <baojun.xu@ti.com>
-
-#include <linux/acpi.h>
-#include <linux/array_size.h>
-#include <linux/bits.h>
-#include <linux/cleanup.h>
-#include <linux/crc8.h>
-#include <linux/crc32.h>
-#include <linux/efi.h>
-#include <linux/firmware.h>
-#include <linux/mod_devicetable.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/pm_runtime.h>
-#include <linux/property.h>
-#include <linux/regmap.h>
-#include <linux/spi/spi.h>
-#include <linux/time.h>
-#include <linux/types.h>
-#include <linux/units.h>
-
-#include <sound/hda_codec.h>
-#include <sound/soc.h>
-#include <sound/tas2781.h>
-#include <sound/tlv.h>
-#include <sound/tas2781-tlv.h>
-
-#include "hda_local.h"
-#include "hda_auto_parser.h"
-#include "hda_component.h"
-#include "hda_jack.h"
-#include "hda_generic.h"
-#include "tas2781_hda.h"
-
-#define TASDEVICE_RANGE_MAX_SIZE (256 * 128)
-#define TASDEVICE_WIN_LEN 128
-#define TAS2781_SPI_MAX_FREQ (4 * HZ_PER_MHZ)
-/* Flag of calibration registers address. */
-#define TASDEVICE_CALIBRATION_REG_ADDRESS BIT(7)
-#define TASDEV_UEFI_CALI_REG_ADDR_FLG BIT(7)
-
-/* System Reset Check Register */
-#define TAS2781_REG_CLK_CONFIG TASDEVICE_REG(0x0, 0x0, 0x5c)
-#define TAS2781_REG_CLK_CONFIG_RESET 0x19
-
-struct tas2781_hda_spi_priv {
- struct snd_kcontrol *snd_ctls[3];
-};
-
-static const struct regmap_range_cfg tasdevice_ranges[] = {
- {
- .range_min = 0,
- .range_max = TASDEVICE_RANGE_MAX_SIZE,
- .selector_reg = TASDEVICE_PAGE_SELECT,
- .selector_mask = GENMASK(7, 0),
- .selector_shift = 0,
- .window_start = 0,
- .window_len = TASDEVICE_WIN_LEN,
- },
-};
-
-static const struct regmap_config tasdevice_regmap = {
- .reg_bits = 8,
- .val_bits = 8,
- .zero_flag_mask = true,
- .read_flag_mask = 0x01,
- .reg_shift = -1,
- .cache_type = REGCACHE_NONE,
- .ranges = tasdevice_ranges,
- .num_ranges = ARRAY_SIZE(tasdevice_ranges),
- .max_register = TASDEVICE_RANGE_MAX_SIZE,
-};
-
-static int tasdevice_spi_dev_read(struct tasdevice_priv *tas_priv,
- unsigned short chn, unsigned int reg, unsigned int *val)
-{
- int ret;
-
- /*
- * In our TAS2781 SPI mode, if read from other book (not book 0),
- * or read from page number larger than 1 in book 0, one more byte
- * read is needed, and first byte is a dummy byte, need to be ignored.
- */
- if ((TASDEVICE_BOOK_ID(reg) > 0) || (TASDEVICE_PAGE_ID(reg) > 1)) {
- unsigned char data[2];
-
- ret = tasdevice_dev_bulk_read(tas_priv, chn, reg,
- data, sizeof(data));
- *val = data[1];
- } else {
- ret = tasdevice_dev_read(tas_priv, chn, reg, val);
- }
- if (ret < 0)
- dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret);
-
- return ret;
-}
-
-static int tasdevice_spi_dev_bulk_read(struct tasdevice_priv *tas_priv,
- unsigned short chn, unsigned int reg, unsigned char *data,
- unsigned int len)
-{
- int ret;
-
- /*
- * In our TAS2781 SPI mode, if read from other book (not book 0),
- * or read from page number larger than 1 in book 0, one more byte
- * read is needed, and first byte is a dummy byte, need to be ignored.
- */
- if ((TASDEVICE_BOOK_ID(reg) > 0) || (TASDEVICE_PAGE_ID(reg) > 1)) {
- unsigned char buf[TASDEVICE_WIN_LEN + 1];
-
- ret = tasdevice_dev_bulk_read(tas_priv, chn, reg,
- buf, len + 1);
- memcpy(data, buf + 1, len);
- } else {
- ret = tasdevice_dev_bulk_read(tas_priv, chn, reg, data, len);
- }
- if (ret < 0)
- dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret);
-
- return ret;
-}
-
-static int tasdevice_spi_dev_update_bits(struct tasdevice_priv *tas_priv,
- unsigned short chn, unsigned int reg, unsigned int mask,
- unsigned int value)
-{
- int ret, val;
-
- /*
- * In our TAS2781 SPI mode, read/write was masked in last bit of
- * address, it cause regmap_update_bits() not work as expected.
- */
- ret = tasdevice_dev_read(tas_priv, chn, reg, &val);
- if (ret < 0) {
- dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret);
- return ret;
- }
-
- ret = tasdevice_dev_write(tas_priv, chn, TASDEVICE_PAGE_REG(reg),
- (val & ~mask) | (mask & value));
- if (ret < 0)
- dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret);
-
- return ret;
-}
-
-static int tasdevice_spi_change_chn_book(struct tasdevice_priv *p,
- unsigned short chn, int book)
-{
- int ret = 0;
-
- if (chn == p->index) {
- struct tasdevice *tasdev = &p->tasdevice[chn];
- struct regmap *map = p->regmap;
-
- if (tasdev->cur_book != book) {
- ret = regmap_write(map, TASDEVICE_BOOKCTL_REG, book);
- if (ret < 0)
- dev_err(p->dev, "%s, E=%d\n", __func__, ret);
- else
- tasdev->cur_book = book;
- }
- } else {
- ret = -EXDEV;
- dev_dbg(p->dev, "Not error, %s ignore channel(%d)\n",
- __func__, chn);
- }
-
- return ret;
-}
-
-static void tas2781_spi_reset(struct tasdevice_priv *tas_dev)
-{
- int ret;
-
- if (tas_dev->reset) {
- gpiod_set_value_cansleep(tas_dev->reset, 0);
- fsleep(800);
- gpiod_set_value_cansleep(tas_dev->reset, 1);
- } else {
- ret = tasdevice_dev_write(tas_dev, tas_dev->index,
- TASDEVICE_REG_SWRESET, TASDEVICE_REG_SWRESET_RESET);
- if (ret < 0) {
- dev_err(tas_dev->dev, "dev sw-reset fail, %d\n", ret);
- return;
- }
- fsleep(1000);
- }
-}
-
-static int tascodec_spi_init(struct tasdevice_priv *tas_priv,
- void *codec, struct module *module,
- void (*cont)(const struct firmware *fw, void *context))
-{
- int ret;
-
- /*
- * Codec Lock Hold to ensure that codec_probe and firmware parsing and
- * loading do not simultaneously execute.
- */
- guard(mutex)(&tas_priv->codec_lock);
-
- scnprintf(tas_priv->rca_binaryname,
- sizeof(tas_priv->rca_binaryname), "%sRCA%d.bin",
- tas_priv->dev_name, tas_priv->ndev);
- crc8_populate_msb(tas_priv->crc8_lkp_tbl, TASDEVICE_CRC8_POLYNOMIAL);
- tas_priv->codec = codec;
- ret = request_firmware_nowait(module, FW_ACTION_UEVENT,
- tas_priv->rca_binaryname, tas_priv->dev, GFP_KERNEL, tas_priv,
- cont);
- if (ret)
- dev_err(tas_priv->dev, "request_firmware_nowait err:0x%08x\n",
- ret);
-
- return ret;
-}
-
-static void tasdevice_spi_init(struct tasdevice_priv *tas_priv)
-{
- tas_priv->tasdevice[tas_priv->index].cur_book = -1;
- tas_priv->tasdevice[tas_priv->index].cur_conf = -1;
- tas_priv->tasdevice[tas_priv->index].cur_prog = -1;
-
- tas_priv->isspi = true;
-
- tas_priv->update_bits = tasdevice_spi_dev_update_bits;
- tas_priv->change_chn_book = tasdevice_spi_change_chn_book;
- tas_priv->dev_read = tasdevice_spi_dev_read;
- tas_priv->dev_bulk_read = tasdevice_spi_dev_bulk_read;
-
- mutex_init(&tas_priv->codec_lock);
-}
-
-static int tasdevice_spi_amp_putvol(struct tasdevice_priv *tas_priv,
- struct snd_ctl_elem_value *ucontrol, struct soc_mixer_control *mc)
-{
- unsigned int invert = mc->invert;
- unsigned char mask;
- int max = mc->max;
- int val, ret;
-
- mask = rounddown_pow_of_two(max);
- mask <<= mc->shift;
- val = clamp(invert ? max - ucontrol->value.integer.value[0] :
- ucontrol->value.integer.value[0], 0, max);
-
- ret = tasdevice_spi_dev_update_bits(tas_priv, tas_priv->index,
- mc->reg, mask, (unsigned int)(val << mc->shift));
- if (ret)
- dev_err(tas_priv->dev, "set AMP vol error in dev %d\n",
- tas_priv->index);
-
- return ret;
-}
-
-static int tasdevice_spi_amp_getvol(struct tasdevice_priv *tas_priv,
- struct snd_ctl_elem_value *ucontrol, struct soc_mixer_control *mc)
-{
- unsigned int invert = mc->invert;
- unsigned char mask = 0;
- int max = mc->max;
- int ret, val;
-
- ret = tasdevice_spi_dev_read(tas_priv, tas_priv->index, mc->reg, &val);
- if (ret) {
- dev_err(tas_priv->dev, "%s, get AMP vol error\n", __func__);
- return ret;
- }
-
- mask = rounddown_pow_of_two(max);
- mask <<= mc->shift;
- val = (val & mask) >> mc->shift;
- val = clamp(invert ? max - val : val, 0, max);
- ucontrol->value.integer.value[0] = val;
-
- return ret;
-}
-
-static int tasdevice_spi_digital_putvol(struct tasdevice_priv *p,
- struct snd_ctl_elem_value *ucontrol, struct soc_mixer_control *mc)
-{
- unsigned int invert = mc->invert;
- int max = mc->max;
- int val, ret;
-
- val = clamp(invert ? max - ucontrol->value.integer.value[0] :
- ucontrol->value.integer.value[0], 0, max);
- ret = tasdevice_dev_write(p, p->index, mc->reg, (unsigned int)val);
- if (ret)
- dev_err(p->dev, "set digital vol err in dev %d\n", p->index);
-
- return ret;
-}
-
-static int tasdevice_spi_digital_getvol(struct tasdevice_priv *p,
- struct snd_ctl_elem_value *ucontrol, struct soc_mixer_control *mc)
-{
- unsigned int invert = mc->invert;
- int max = mc->max;
- int ret, val;
-
- ret = tasdevice_spi_dev_read(p, p->index, mc->reg, &val);
- if (ret) {
- dev_err(p->dev, "%s, get digital vol err\n", __func__);
- return ret;
- }
-
- val = clamp(invert ? max - val : val, 0, max);
- ucontrol->value.integer.value[0] = val;
-
- return ret;
-}
-
-static int tas2781_read_acpi(struct tas2781_hda *tas_hda,
- const char *hid, int id)
-{
- struct tasdevice_priv *p = tas_hda->priv;
- struct acpi_device *adev;
- struct device *physdev;
- u32 values[HDA_MAX_COMPONENTS];
- const char *property;
- size_t nval;
- int ret, i;
-
- adev = acpi_dev_get_first_match_dev(hid, NULL, -1);
- if (!adev) {
- dev_err(p->dev, "Failed to find ACPI device: %s\n", hid);
- return -ENODEV;
- }
-
- strscpy(p->dev_name, hid, sizeof(p->dev_name));
- physdev = get_device(acpi_get_first_physical_node(adev));
- acpi_dev_put(adev);
-
- property = "ti,dev-index";
- ret = device_property_count_u32(physdev, property);
- if (ret <= 0 || ret > ARRAY_SIZE(values)) {
- ret = -EINVAL;
- goto err;
- }
- p->ndev = nval = ret;
-
- ret = device_property_read_u32_array(physdev, property, values, nval);
- if (ret)
- goto err;
-
- p->index = U8_MAX;
- for (i = 0; i < nval; i++) {
- if (values[i] == id) {
- p->index = i;
- break;
- }
- }
- if (p->index == U8_MAX) {
- dev_dbg(p->dev, "No index found in %s\n", property);
- ret = -ENODEV;
- goto err;
- }
-
- if (p->index == 0) {
- /* All of amps share same RESET pin. */
- p->reset = devm_gpiod_get_index_optional(physdev, "reset",
- p->index, GPIOD_OUT_LOW);
- if (IS_ERR(p->reset)) {
- ret = PTR_ERR(p->reset);
- dev_err_probe(p->dev, ret, "Failed on reset GPIO\n");
- goto err;
- }
- }
- put_device(physdev);
-
- return 0;
-err:
- dev_err(p->dev, "read acpi error, ret: %d\n", ret);
- put_device(physdev);
- acpi_dev_put(adev);
-
- return ret;
-}
-
-static void tas2781_hda_playback_hook(struct device *dev, int action)
-{
- struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
- struct tasdevice_priv *tas_priv = tas_hda->priv;
-
- if (action == HDA_GEN_PCM_ACT_OPEN) {
- pm_runtime_get_sync(dev);
- guard(mutex)(&tas_priv->codec_lock);
- if (tas_priv->fw_state == TASDEVICE_DSP_FW_ALL_OK)
- tasdevice_tuning_switch(tas_hda->priv, 0);
- } else if (action == HDA_GEN_PCM_ACT_CLOSE) {
- guard(mutex)(&tas_priv->codec_lock);
- if (tas_priv->fw_state == TASDEVICE_DSP_FW_ALL_OK)
- tasdevice_tuning_switch(tas_priv, 1);
- pm_runtime_mark_last_busy(dev);
- pm_runtime_put_autosuspend(dev);
- }
-}
-
-/*
- * tas2781_digital_getvol - get the volum control
- * @kcontrol: control pointer
- * @ucontrol: User data
- *
- * Customer Kcontrol for tas2781 is primarily for regmap booking, paging
- * depends on internal regmap mechanism.
- * tas2781 contains book and page two-level register map, especially
- * book switching will set the register BXXP00R7F, after switching to the
- * correct book, then leverage the mechanism for paging to access the
- * register.
- *
- * Return 0 if succeeded.
- */
-static int tas2781_digital_getvol(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
- struct soc_mixer_control *mc =
- (struct soc_mixer_control *)kcontrol->private_value;
-
- guard(mutex)(&tas_priv->codec_lock);
- return tasdevice_spi_digital_getvol(tas_priv, ucontrol, mc);
-}
-
-static int tas2781_amp_getvol(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
- struct soc_mixer_control *mc =
- (struct soc_mixer_control *)kcontrol->private_value;
-
- guard(mutex)(&tas_priv->codec_lock);
- return tasdevice_spi_amp_getvol(tas_priv, ucontrol, mc);
-}
-
-static int tas2781_digital_putvol(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
- struct soc_mixer_control *mc =
- (struct soc_mixer_control *)kcontrol->private_value;
-
- guard(mutex)(&tas_priv->codec_lock);
- return tasdevice_spi_digital_putvol(tas_priv, ucontrol, mc);
-}
-
-static int tas2781_amp_putvol(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
- struct soc_mixer_control *mc =
- (struct soc_mixer_control *)kcontrol->private_value;
-
- guard(mutex)(&tas_priv->codec_lock);
- return tasdevice_spi_amp_putvol(tas_priv, ucontrol, mc);
-}
-
-static int tas2781_force_fwload_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
-
- ucontrol->value.integer.value[0] = (int)tas_priv->force_fwload_status;
- dev_dbg(tas_priv->dev, "%s : Force FWload %s\n", __func__,
- str_on_off(tas_priv->force_fwload_status));
-
- return 0;
-}
-
-static int tas2781_force_fwload_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
- bool change, val = (bool)ucontrol->value.integer.value[0];
-
- if (tas_priv->force_fwload_status == val) {
- change = false;
- } else {
- change = true;
- tas_priv->force_fwload_status = val;
- }
- dev_dbg(tas_priv->dev, "%s : Force FWload %s\n", __func__,
- str_on_off(tas_priv->force_fwload_status));
-
- return change;
-}
-
-static struct snd_kcontrol_new tas2781_snd_ctls[] = {
- ACARD_SINGLE_RANGE_EXT_TLV(NULL, TAS2781_AMP_LEVEL, 1, 0, 20, 0,
- tas2781_amp_getvol, tas2781_amp_putvol, amp_vol_tlv),
- ACARD_SINGLE_RANGE_EXT_TLV(NULL, TAS2781_DVC_LVL, 0, 0, 200, 1,
- tas2781_digital_getvol, tas2781_digital_putvol, dvc_tlv),
- ACARD_SINGLE_BOOL_EXT(NULL, 0, tas2781_force_fwload_get,
- tas2781_force_fwload_put),
-};
-
-static struct snd_kcontrol_new tas2781_prof_ctl = {
- .iface = SNDRV_CTL_ELEM_IFACE_CARD,
- .info = tasdevice_info_profile,
- .get = tasdevice_get_profile_id,
- .put = tasdevice_set_profile_id,
-};
-
-static struct snd_kcontrol_new tas2781_dsp_ctls[] = {
- /* Speaker Program */
- {
- .iface = SNDRV_CTL_ELEM_IFACE_CARD,
- .info = tasdevice_info_programs,
- .get = tasdevice_program_get,
- .put = tasdevice_program_put,
- },
- /* Speaker Config */
- {
- .iface = SNDRV_CTL_ELEM_IFACE_CARD,
- .info = tasdevice_info_config,
- .get = tasdevice_config_get,
- .put = tasdevice_config_put,
- },
-};
-
-static void tas2781_hda_remove_controls(struct tas2781_hda *tas_hda)
-{
- struct hda_codec *codec = tas_hda->priv->codec;
- struct tas2781_hda_spi_priv *h_priv = tas_hda->hda_priv;
-
- snd_ctl_remove(codec->card, tas_hda->dsp_prog_ctl);
-
- snd_ctl_remove(codec->card, tas_hda->dsp_conf_ctl);
-
- for (int i = ARRAY_SIZE(h_priv->snd_ctls) - 1; i >= 0; i--)
- snd_ctl_remove(codec->card, h_priv->snd_ctls[i]);
-
- snd_ctl_remove(codec->card, tas_hda->prof_ctl);
-}
-
-static int tas2781_hda_spi_prf_ctl(struct tas2781_hda *h)
-{
- struct tasdevice_priv *p = h->priv;
- struct hda_codec *c = p->codec;
- char name[64];
- int rc;
-
- snprintf(name, sizeof(name), "Speaker-%d Profile Id", p->index);
- tas2781_prof_ctl.name = name;
- h->prof_ctl = snd_ctl_new1(&tas2781_prof_ctl, p);
- rc = snd_ctl_add(c->card, h->prof_ctl);
- if (rc)
- dev_err(p->dev, "Failed to add KControl: %s, rc = %d\n",
- tas2781_prof_ctl.name, rc);
- return rc;
-}
-
-static int tas2781_hda_spi_snd_ctls(struct tas2781_hda *h)
-{
- struct tas2781_hda_spi_priv *h_priv = h->hda_priv;
- struct tasdevice_priv *p = h->priv;
- struct hda_codec *c = p->codec;
- char name[64];
- int i = 0;
- int rc;
-
- snprintf(name, sizeof(name), "Speaker-%d Analog Volume", p->index);
- tas2781_snd_ctls[i].name = name;
- h_priv->snd_ctls[i] = snd_ctl_new1(&tas2781_snd_ctls[i], p);
- rc = snd_ctl_add(c->card, h_priv->snd_ctls[i]);
- if (rc) {
- dev_err(p->dev, "Failed to add KControl: %s, rc = %d\n",
- tas2781_snd_ctls[i].name, rc);
- return rc;
- }
- i++;
- snprintf(name, sizeof(name), "Speaker-%d Digital Volume", p->index);
- tas2781_snd_ctls[i].name = name;
- h_priv->snd_ctls[i] = snd_ctl_new1(&tas2781_snd_ctls[i], p);
- rc = snd_ctl_add(c->card, h_priv->snd_ctls[i]);
- if (rc) {
- dev_err(p->dev, "Failed to add KControl: %s, rc = %d\n",
- tas2781_snd_ctls[i].name, rc);
- return rc;
- }
- i++;
- snprintf(name, sizeof(name), "Froce Speaker-%d FW Load", p->index);
- tas2781_snd_ctls[i].name = name;
- h_priv->snd_ctls[i] = snd_ctl_new1(&tas2781_snd_ctls[i], p);
- rc = snd_ctl_add(c->card, h_priv->snd_ctls[i]);
- if (rc) {
- dev_err(p->dev, "Failed to add KControl: %s, rc = %d\n",
- tas2781_snd_ctls[i].name, rc);
- }
- return rc;
-}
-
-static int tas2781_hda_spi_dsp_ctls(struct tas2781_hda *h)
-{
- struct tasdevice_priv *p = h->priv;
- struct hda_codec *c = p->codec;
- char name[64];
- int i = 0;
- int rc;
-
- snprintf(name, sizeof(name), "Speaker-%d Program Id", p->index);
- tas2781_dsp_ctls[i].name = name;
- h->dsp_prog_ctl = snd_ctl_new1(&tas2781_dsp_ctls[i], p);
- rc = snd_ctl_add(c->card, h->dsp_prog_ctl);
- if (rc) {
- dev_err(p->dev, "Failed to add KControl: %s, rc = %d\n",
- tas2781_dsp_ctls[i].name, rc);
- return rc;
- }
- i++;
- snprintf(name, sizeof(name), "Speaker-%d Config Id", p->index);
- tas2781_dsp_ctls[i].name = name;
- h->dsp_conf_ctl = snd_ctl_new1(&tas2781_dsp_ctls[i], p);
- rc = snd_ctl_add(c->card, h->dsp_conf_ctl);
- if (rc) {
- dev_err(p->dev, "Failed to add KControl: %s, rc = %d\n",
- tas2781_dsp_ctls[i].name, rc);
- }
-
- return rc;
-}
-
-static void tasdev_fw_ready(const struct firmware *fmw, void *context)
-{
- struct tasdevice_priv *tas_priv = context;
- struct tas2781_hda *tas_hda = dev_get_drvdata(tas_priv->dev);
- struct hda_codec *codec = tas_priv->codec;
- int ret, val;
-
- pm_runtime_get_sync(tas_priv->dev);
- guard(mutex)(&tas_priv->codec_lock);
-
- ret = tasdevice_rca_parser(tas_priv, fmw);
- if (ret)
- goto out;
-
- /* Add control one time only. */
- ret = tas2781_hda_spi_prf_ctl(tas_hda);
- if (ret)
- goto out;
-
- ret = tas2781_hda_spi_snd_ctls(tas_hda);
- if (ret)
- goto out;
-
- tasdevice_dsp_remove(tas_priv);
-
- tas_priv->fw_state = TASDEVICE_DSP_FW_PENDING;
- scnprintf(tas_priv->coef_binaryname, 64, "TAS2XXX%04X-%01d.bin",
- lower_16_bits(codec->core.subsystem_id), tas_priv->index);
- ret = tasdevice_dsp_parser(tas_priv);
- if (ret) {
- dev_err(tas_priv->dev, "dspfw load %s error\n",
- tas_priv->coef_binaryname);
- tas_priv->fw_state = TASDEVICE_DSP_FW_FAIL;
- goto out;
- }
-
- ret = tas2781_hda_spi_dsp_ctls(tas_hda);
- if (ret)
- goto out;
- /* Perform AMP reset before firmware download. */
- tas2781_spi_reset(tas_priv);
- tas_priv->rcabin.profile_cfg_id = 0;
-
- tas_priv->fw_state = TASDEVICE_DSP_FW_ALL_OK;
- ret = tasdevice_spi_dev_read(tas_priv, tas_priv->index,
- TAS2781_REG_CLK_CONFIG, &val);
- if (ret < 0)
- goto out;
-
- if (val == TAS2781_REG_CLK_CONFIG_RESET) {
- ret = tasdevice_prmg_load(tas_priv, 0);
- if (ret < 0) {
- dev_err(tas_priv->dev, "FW download failed = %d\n",
- ret);
- goto out;
- }
- tas_priv->fw_state = TASDEVICE_DSP_FW_ALL_OK;
- }
- if (tas_priv->fmw->nr_programs > 0)
- tas_priv->tasdevice[tas_priv->index].cur_prog = 0;
- if (tas_priv->fmw->nr_configurations > 0)
- tas_priv->tasdevice[tas_priv->index].cur_conf = 0;
-
- /*
- * If calibrated data occurs error, dsp will still works with default
- * calibrated data inside algo.
- */
- tas2781_save_calibration(tas_hda);
-out:
- release_firmware(fmw);
- pm_runtime_mark_last_busy(tas_hda->priv->dev);
- pm_runtime_put_autosuspend(tas_hda->priv->dev);
-}
-
-static int tas2781_hda_bind(struct device *dev, struct device *master,
- void *master_data)
-{
- struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
- struct hda_component_parent *parent = master_data;
- struct hda_component *comp;
- struct hda_codec *codec;
- int ret;
-
- comp = hda_component_from_index(parent, tas_hda->priv->index);
- if (!comp)
- return -EINVAL;
-
- if (comp->dev)
- return -EBUSY;
-
- codec = parent->codec;
-
- pm_runtime_get_sync(dev);
-
- comp->dev = dev;
-
- strscpy(comp->name, dev_name(dev), sizeof(comp->name));
-
- ret = tascodec_spi_init(tas_hda->priv, codec, THIS_MODULE,
- tasdev_fw_ready);
- if (!ret)
- comp->playback_hook = tas2781_hda_playback_hook;
-
- pm_runtime_mark_last_busy(dev);
- pm_runtime_put_autosuspend(dev);
-
- return ret;
-}
-
-static void tas2781_hda_unbind(struct device *dev, struct device *master,
- void *master_data)
-{
- struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
- struct hda_component_parent *parent = master_data;
- struct tasdevice_priv *tas_priv = tas_hda->priv;
- struct hda_component *comp;
-
- comp = hda_component_from_index(parent, tas_priv->index);
- if (comp && (comp->dev == dev)) {
- comp->dev = NULL;
- memset(comp->name, 0, sizeof(comp->name));
- comp->playback_hook = NULL;
- }
-
- tas2781_hda_remove_controls(tas_hda);
-
- tasdevice_config_info_remove(tas_priv);
- tasdevice_dsp_remove(tas_priv);
-
- tas_hda->priv->fw_state = TASDEVICE_DSP_FW_PENDING;
-}
-
-static const struct component_ops tas2781_hda_comp_ops = {
- .bind = tas2781_hda_bind,
- .unbind = tas2781_hda_unbind,
-};
-
-static int tas2781_hda_spi_probe(struct spi_device *spi)
-{
- struct tas2781_hda_spi_priv *hda_priv;
- struct tasdevice_priv *tas_priv;
- struct tas2781_hda *tas_hda;
- const char *device_name;
- int ret = 0;
-
- tas_hda = devm_kzalloc(&spi->dev, sizeof(*tas_hda), GFP_KERNEL);
- if (!tas_hda)
- return -ENOMEM;
-
- hda_priv = devm_kzalloc(&spi->dev, sizeof(*hda_priv), GFP_KERNEL);
- if (!hda_priv)
- return -ENOMEM;
-
- tas_hda->hda_priv = hda_priv;
- spi->max_speed_hz = TAS2781_SPI_MAX_FREQ;
-
- tas_priv = devm_kzalloc(&spi->dev, sizeof(*tas_priv), GFP_KERNEL);
- if (!tas_priv)
- return -ENOMEM;
- tas_priv->dev = &spi->dev;
- tas_hda->priv = tas_priv;
- tas_priv->regmap = devm_regmap_init_spi(spi, &tasdevice_regmap);
- if (IS_ERR(tas_priv->regmap)) {
- ret = PTR_ERR(tas_priv->regmap);
- dev_err(tas_priv->dev, "Failed to allocate regmap: %d\n",
- ret);
- return ret;
- }
- if (strstr(dev_name(&spi->dev), "TXNW2781")) {
- device_name = "TXNW2781";
- } else {
- dev_err(tas_priv->dev, "Unmatched spi dev %s\n",
- dev_name(&spi->dev));
- return -ENODEV;
- }
-
- tas_priv->irq = spi->irq;
- dev_set_drvdata(&spi->dev, tas_hda);
- ret = tas2781_read_acpi(tas_hda, device_name,
- spi_get_chipselect(spi, 0));
- if (ret)
- return dev_err_probe(tas_priv->dev, ret,
- "Platform not supported\n");
-
- tasdevice_spi_init(tas_priv);
-
- pm_runtime_set_autosuspend_delay(tas_priv->dev, 3000);
- pm_runtime_use_autosuspend(tas_priv->dev);
- pm_runtime_mark_last_busy(tas_priv->dev);
- pm_runtime_set_active(tas_priv->dev);
- pm_runtime_get_noresume(tas_priv->dev);
- pm_runtime_enable(tas_priv->dev);
-
- pm_runtime_put_autosuspend(tas_priv->dev);
-
- ret = component_add(tas_priv->dev, &tas2781_hda_comp_ops);
- if (ret) {
- dev_err(tas_priv->dev, "Register component fail: %d\n", ret);
- pm_runtime_disable(tas_priv->dev);
- tas2781_hda_remove(&spi->dev, &tas2781_hda_comp_ops);
- }
-
- return ret;
-}
-
-static void tas2781_hda_spi_remove(struct spi_device *spi)
-{
- tas2781_hda_remove(&spi->dev, &tas2781_hda_comp_ops);
-}
-
-static int tas2781_runtime_suspend(struct device *dev)
-{
- struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
- struct tasdevice_priv *tas_priv = tas_hda->priv;
-
- guard(mutex)(&tas_priv->codec_lock);
-
- if (tas_priv->fw_state == TASDEVICE_DSP_FW_ALL_OK
- && tas_priv->playback_started)
- tasdevice_tuning_switch(tas_priv, 1);
-
- tas_priv->tasdevice[tas_priv->index].cur_book = -1;
- tas_priv->tasdevice[tas_priv->index].cur_conf = -1;
-
- return 0;
-}
-
-static int tas2781_runtime_resume(struct device *dev)
-{
- struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
- struct tasdevice_priv *tas_priv = tas_hda->priv;
-
- guard(mutex)(&tas_priv->codec_lock);
-
- if (tas_priv->fw_state == TASDEVICE_DSP_FW_ALL_OK
- && tas_priv->playback_started)
- tasdevice_tuning_switch(tas_priv, 0);
-
- return 0;
-}
-
-static int tas2781_system_suspend(struct device *dev)
-{
- struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
- struct tasdevice_priv *tas_priv = tas_hda->priv;
- int ret;
-
- ret = pm_runtime_force_suspend(dev);
- if (ret)
- return ret;
-
- /* Shutdown chip before system suspend */
- if (tas_priv->fw_state == TASDEVICE_DSP_FW_ALL_OK
- && tas_priv->playback_started)
- tasdevice_tuning_switch(tas_priv, 1);
-
- return 0;
-}
-
-static int tas2781_system_resume(struct device *dev)
-{
- struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
- struct tasdevice_priv *tas_priv = tas_hda->priv;
- int ret, val;
-
- ret = pm_runtime_force_resume(dev);
- if (ret)
- return ret;
-
- guard(mutex)(&tas_priv->codec_lock);
- ret = tas_priv->dev_read(tas_priv, tas_priv->index,
- TAS2781_REG_CLK_CONFIG, &val);
- if (ret < 0)
- return ret;
-
- if (val == TAS2781_REG_CLK_CONFIG_RESET) {
- tas_priv->tasdevice[tas_priv->index].cur_book = -1;
- tas_priv->tasdevice[tas_priv->index].cur_conf = -1;
- tas_priv->tasdevice[tas_priv->index].cur_prog = -1;
-
- ret = tasdevice_prmg_load(tas_priv, 0);
- if (ret < 0) {
- dev_err(tas_priv->dev,
- "FW download failed = %d\n", ret);
- return ret;
- }
- tas_priv->fw_state = TASDEVICE_DSP_FW_ALL_OK;
-
- if (tas_priv->playback_started)
- tasdevice_tuning_switch(tas_priv, 0);
- }
-
- return ret;
-}
-
-static const struct dev_pm_ops tas2781_hda_pm_ops = {
- RUNTIME_PM_OPS(tas2781_runtime_suspend, tas2781_runtime_resume, NULL)
- SYSTEM_SLEEP_PM_OPS(tas2781_system_suspend, tas2781_system_resume)
-};
-
-static const struct spi_device_id tas2781_hda_spi_id[] = {
- { "tas2781-hda", },
- {}
-};
-
-static const struct acpi_device_id tas2781_acpi_hda_match[] = {
- {"TXNW2781", },
- {}
-};
-MODULE_DEVICE_TABLE(acpi, tas2781_acpi_hda_match);
-
-static struct spi_driver tas2781_hda_spi_driver = {
- .driver = {
- .name = "tas2781-hda",
- .acpi_match_table = tas2781_acpi_hda_match,
- .pm = &tas2781_hda_pm_ops,
- },
- .id_table = tas2781_hda_spi_id,
- .probe = tas2781_hda_spi_probe,
- .remove = tas2781_hda_spi_remove,
-};
-module_spi_driver(tas2781_hda_spi_driver);
-
-MODULE_DESCRIPTION("TAS2781 HDA SPI Driver");
-MODULE_AUTHOR("Baojun, Xu, <baojun.xug@ti.com>");
-MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS("SND_SOC_TAS2781_FMWLIB");
-MODULE_IMPORT_NS("SND_HDA_SCODEC_TAS2781");
diff --git a/sound/pci/hda/thinkpad_helper.c b/sound/pci/hda/thinkpad_helper.c
deleted file mode 100644
index de4d8deed102..000000000000
--- a/sound/pci/hda/thinkpad_helper.c
+++ /dev/null
@@ -1,36 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Helper functions for Thinkpad LED control;
- * to be included from codec driver
- */
-
-#if IS_ENABLED(CONFIG_THINKPAD_ACPI)
-
-#include <linux/acpi.h>
-#include <linux/leds.h>
-
-static bool is_thinkpad(struct hda_codec *codec)
-{
- return (codec->core.subsystem_id >> 16 == 0x17aa) &&
- (acpi_dev_found("LEN0068") || acpi_dev_found("LEN0268") ||
- acpi_dev_found("IBM0068"));
-}
-
-static void hda_fixup_thinkpad_acpi(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
- if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- if (!is_thinkpad(codec))
- return;
- snd_hda_gen_add_mute_led_cdev(codec, NULL);
- snd_hda_gen_add_micmute_led_cdev(codec, NULL);
- }
-}
-
-#else /* CONFIG_THINKPAD_ACPI */
-
-static void hda_fixup_thinkpad_acpi(struct hda_codec *codec,
- const struct hda_fixup *fix, int action)
-{
-}
-
-#endif /* CONFIG_THINKPAD_ACPI */
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index a8ac14887676..1aefd46ebf6b 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -850,7 +850,7 @@ static int snd_ice1712_pcm(struct snd_ice1712 *ice, int device)
pcm->private_data = ice;
pcm->info_flags = 0;
- strcpy(pcm->name, "ICE1712 consumer");
+ strscpy(pcm->name, "ICE1712 consumer");
ice->pcm = pcm;
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
@@ -875,7 +875,7 @@ static int snd_ice1712_pcm_ds(struct snd_ice1712 *ice, int device)
pcm->private_data = ice;
pcm->info_flags = 0;
- strcpy(pcm->name, "ICE1712 consumer (DS)");
+ strscpy(pcm->name, "ICE1712 consumer (DS)");
ice->pcm_ds = pcm;
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
@@ -1216,7 +1216,7 @@ static int snd_ice1712_pcm_profi(struct snd_ice1712 *ice, int device)
pcm->private_data = ice;
pcm->info_flags = 0;
- strcpy(pcm->name, "ICE1712 multi");
+ strscpy(pcm->name, "ICE1712 multi");
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
&ice->pci->dev, 256*1024, 256*1024);
@@ -2559,8 +2559,8 @@ static int snd_ice1712_probe(struct pci_dev *pci,
return err;
ice = card->private_data;
- strcpy(card->driver, "ICE1712");
- strcpy(card->shortname, "ICEnsemble ICE1712");
+ strscpy(card->driver, "ICE1712");
+ strscpy(card->shortname, "ICEnsemble ICE1712");
err = snd_ice1712_create(card, pci, model[dev], omni[dev],
cs8427_timeout[dev], dxr_enable[dev]);
@@ -2570,9 +2570,9 @@ static int snd_ice1712_probe(struct pci_dev *pci,
for (tbl = card_tables; *tbl; tbl++) {
for (c = *tbl; c->subvendor; c++) {
if (c->subvendor == ice->eeprom.subvendor) {
- strcpy(card->shortname, c->name);
+ strscpy(card->shortname, c->name);
if (c->driver) /* specific driver? */
- strcpy(card->driver, c->driver);
+ strscpy(card->driver, c->driver);
if (c->chip_init) {
err = c->chip_init(ice);
if (err < 0)
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index be22b159e65a..0445d2e8e548 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -1118,7 +1118,7 @@ static int snd_vt1724_pcm_profi(struct snd_ice1712 *ice, int device)
pcm->private_data = ice;
pcm->info_flags = 0;
- strcpy(pcm->name, "ICE1724");
+ strscpy(pcm->name, "ICE1724");
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
&ice->pci->dev, 256*1024, 256*1024);
@@ -1313,7 +1313,7 @@ static int snd_vt1724_pcm_spdif(struct snd_ice1712 *ice, int device)
pcm->private_data = ice;
pcm->info_flags = 0;
- strcpy(pcm->name, name);
+ strscpy(pcm->name, name);
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
&ice->pci->dev, 256*1024, 256*1024);
@@ -1425,7 +1425,7 @@ static int snd_vt1724_pcm_indep(struct snd_ice1712 *ice, int device)
pcm->private_data = ice;
pcm->info_flags = 0;
- strcpy(pcm->name, "ICE1724 Surround PCM");
+ strscpy(pcm->name, "ICE1724 Surround PCM");
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
&ice->pci->dev, 256*1024, 256*1024);
@@ -1820,7 +1820,7 @@ static int snd_vt1724_pro_internal_clock_info(struct snd_kcontrol *kcontrol,
uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
if (uinfo->value.enumerated.item >= hw_rates_count)
/* ext_clock items */
- strcpy(uinfo->value.enumerated.name,
+ strscpy(uinfo->value.enumerated.name,
ice->ext_clock_names[
uinfo->value.enumerated.item - hw_rates_count]);
else
@@ -2545,8 +2545,8 @@ static int __snd_vt1724_probe(struct pci_dev *pci,
return err;
ice = card->private_data;
- strcpy(card->driver, "ICE1724");
- strcpy(card->shortname, "ICEnsemble ICE1724");
+ strscpy(card->driver, "ICE1724");
+ strscpy(card->shortname, "ICEnsemble ICE1724");
err = snd_vt1724_create(card, pci, model[dev]);
if (err < 0)
@@ -2557,9 +2557,9 @@ static int __snd_vt1724_probe(struct pci_dev *pci,
c = ice->card_info;
if (c) {
- strcpy(card->shortname, c->name);
+ strscpy(card->shortname, c->name);
if (c->driver) /* specific driver? */
- strcpy(card->driver, c->driver);
+ strscpy(card->driver, c->driver);
if (c->chip_init) {
err = c->chip_init(ice);
if (err < 0)
@@ -2637,7 +2637,7 @@ static int __snd_vt1724_probe(struct pci_dev *pci,
return err;
ice->rmidi[0] = rmidi;
rmidi->private_data = ice;
- strcpy(rmidi->name, "ICE1724 MIDI");
+ strscpy(rmidi->name, "ICE1724 MIDI");
rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
SNDRV_RAWMIDI_INFO_INPUT |
SNDRV_RAWMIDI_INFO_DUPLEX;
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index 51e7f1f1a48e..9e6a5065ffbf 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -1436,7 +1436,7 @@ static int snd_intel8x0_pcm1(struct intel8x0 *chip, int device,
if (rec->suffix)
sprintf(name, "Intel ICH - %s", rec->suffix);
else
- strcpy(name, "Intel ICH");
+ strscpy(name, "Intel ICH");
err = snd_pcm_new(chip->card, name, device,
rec->playback_ops ? 1 : 0,
rec->capture_ops ? 1 : 0, &pcm);
@@ -1453,7 +1453,7 @@ static int snd_intel8x0_pcm1(struct intel8x0 *chip, int device,
if (rec->suffix)
sprintf(pcm->name, "%s - %s", chip->card->shortname, rec->suffix);
else
- strcpy(pcm->name, chip->card->shortname);
+ strscpy(pcm->name, chip->card->shortname);
chip->pcm[device] = pcm;
snd_pcm_set_managed_buffer_all(pcm, intel8x0_dma_type(chip),
@@ -2249,7 +2249,7 @@ static int snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock,
tmp |= chip->ac97_sdin[0] << ICH_DI1L_SHIFT;
for (i = 1; i < 4; i++) {
if (pcm->r[0].codec[i]) {
- tmp |= chip->ac97_sdin[pcm->r[0].codec[1]->num] << ICH_DI2L_SHIFT;
+ tmp |= chip->ac97_sdin[pcm->r[0].codec[i]->num] << ICH_DI2L_SHIFT;
break;
}
}
@@ -3118,21 +3118,21 @@ static int __snd_intel8x0_probe(struct pci_dev *pci,
if (spdif_aclink < 0)
spdif_aclink = check_default_spdif_aclink(pci);
- strcpy(card->driver, "ICH");
+ strscpy(card->driver, "ICH");
if (!spdif_aclink) {
switch (pci_id->driver_data) {
case DEVICE_NFORCE:
- strcpy(card->driver, "NFORCE");
+ strscpy(card->driver, "NFORCE");
break;
case DEVICE_INTEL_ICH4:
- strcpy(card->driver, "ICH4");
+ strscpy(card->driver, "ICH4");
}
}
- strcpy(card->shortname, "Intel ICH");
+ strscpy(card->shortname, "Intel ICH");
for (name = shortnames; name->id; name++) {
if (pci->device == name->id) {
- strcpy(card->shortname, name->s);
+ strscpy(card->shortname, name->s);
break;
}
}
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
index 1ce775fe8a70..9e5988583abe 100644
--- a/sound/pci/intel8x0m.c
+++ b/sound/pci/intel8x0m.c
@@ -678,7 +678,7 @@ static int snd_intel8x0m_pcm1(struct intel8x0m *chip, int device,
if (rec->suffix)
sprintf(name, "Intel ICH - %s", rec->suffix);
else
- strcpy(name, "Intel ICH");
+ strscpy(name, "Intel ICH");
err = snd_pcm_new(chip->card, name, device,
rec->playback_ops ? 1 : 0,
rec->capture_ops ? 1 : 0, &pcm);
@@ -696,7 +696,7 @@ static int snd_intel8x0m_pcm1(struct intel8x0m *chip, int device,
if (rec->suffix)
sprintf(pcm->name, "%s - %s", chip->card->shortname, rec->suffix);
else
- strcpy(pcm->name, chip->card->shortname);
+ strscpy(pcm->name, chip->card->shortname);
chip->pcm[device] = pcm;
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
@@ -1184,11 +1184,11 @@ static int __snd_intel8x0m_probe(struct pci_dev *pci,
return err;
chip = card->private_data;
- strcpy(card->driver, "ICH-MODEM");
- strcpy(card->shortname, "Intel ICH");
+ strscpy(card->driver, "ICH-MODEM");
+ strscpy(card->shortname, "Intel ICH");
for (name = shortnames; name->id; name++) {
if (pci->device == name->id) {
- strcpy(card->shortname, name->s);
+ strscpy(card->shortname, name->s);
break;
}
}
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index 56dea5b10828..0a66d5cfc090 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -2249,7 +2249,7 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci)
korg1212->pcm->private_data = korg1212;
korg1212->pcm->private_free = snd_korg1212_free_pcm;
- strcpy(korg1212->pcm->name, "korg1212");
+ strscpy(korg1212->pcm->name, "korg1212");
snd_pcm_set_ops(korg1212->pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_korg1212_playback_ops);
@@ -2298,8 +2298,8 @@ snd_korg1212_probe(struct pci_dev *pci,
if (err < 0)
goto error;
- strcpy(card->driver, "korg1212");
- strcpy(card->shortname, "korg1212");
+ strscpy(card->driver, "korg1212");
+ strscpy(card->shortname, "korg1212");
sprintf(card->longname, "%s at 0x%lx, irq %d", card->shortname,
korg1212->iomem, korg1212->irq);
diff --git a/sound/pci/lola/lola.c b/sound/pci/lola/lola.c
index fb8bd54e4c2d..8d927ecba165 100644
--- a/sound/pci/lola/lola.c
+++ b/sound/pci/lola/lola.c
@@ -630,12 +630,12 @@ static int lola_create(struct snd_card *card, struct pci_dev *pci, int dev)
if (err < 0)
return err;
- strcpy(card->driver, "Lola");
+ strscpy(card->driver, "Lola");
strscpy(card->shortname, "Digigram Lola", sizeof(card->shortname));
snprintf(card->longname, sizeof(card->longname),
"%s at 0x%lx irq %i",
card->shortname, chip->bar[0].addr, chip->irq);
- strcpy(card->mixername, card->shortname);
+ strscpy(card->mixername, card->shortname);
lola_irq_enable(chip);
diff --git a/sound/pci/lx6464es/lx6464es.c b/sound/pci/lx6464es/lx6464es.c
index 63ebf9803ea8..9f12c936bb1f 100644
--- a/sound/pci/lx6464es/lx6464es.c
+++ b/sound/pci/lx6464es/lx6464es.c
@@ -814,7 +814,7 @@ static int lx_pcm_create(struct lx6464es *chip)
pcm->info_flags = 0;
pcm->nonatomic = true;
- strcpy(pcm->name, card_name);
+ strscpy(pcm->name, card_name);
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
&chip->pci->dev, size, size);
@@ -1022,7 +1022,7 @@ static int snd_lx6464es_probe(struct pci_dev *pci,
goto error;
}
- strcpy(card->driver, "LX6464ES");
+ strscpy(card->driver, "LX6464ES");
sprintf(card->id, "LX6464ES_%02X%02X%02X",
chip->mac_address[3], chip->mac_address[4], chip->mac_address[5]);
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index e61e15774706..e092097599ff 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -1846,7 +1846,7 @@ snd_m3_pcm(struct snd_m3 * chip, int device)
pcm->private_data = chip;
pcm->info_flags = 0;
- strcpy(pcm->name, chip->card->driver);
+ strscpy(pcm->name, chip->card->driver);
chip->pcm = pcm;
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
@@ -2648,14 +2648,14 @@ __snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
switch (pci->device) {
case PCI_DEVICE_ID_ESS_ALLEGRO:
case PCI_DEVICE_ID_ESS_ALLEGRO_1:
- strcpy(card->driver, "Allegro");
+ strscpy(card->driver, "Allegro");
break;
case PCI_DEVICE_ID_ESS_CANYON3D_2LE:
case PCI_DEVICE_ID_ESS_CANYON3D_2:
- strcpy(card->driver, "Canyon3D-2");
+ strscpy(card->driver, "Canyon3D-2");
break;
default:
- strcpy(card->driver, "Maestro3");
+ strscpy(card->driver, "Maestro3");
break;
}
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
index 7ceaf6a7a77e..cdc0ba5dd1ad 100644
--- a/sound/pci/mixart/mixart.c
+++ b/sound/pci/mixart/mixart.c
@@ -970,7 +970,7 @@ static int snd_mixart_pcm_analog(struct snd_mixart *chip)
pcm->info_flags = 0;
pcm->nonatomic = true;
- strcpy(pcm->name, name);
+ strscpy(pcm->name, name);
preallocate_buffers(chip, pcm);
@@ -1004,7 +1004,7 @@ static int snd_mixart_pcm_digital(struct snd_mixart *chip)
pcm->info_flags = 0;
pcm->nonatomic = true;
- strcpy(pcm->name, name);
+ strscpy(pcm->name, name);
preallocate_buffers(chip, pcm);
@@ -1330,7 +1330,7 @@ static int snd_mixart_probe(struct pci_dev *pci,
return err;
}
- strcpy(card->driver, CARD_NAME);
+ strscpy(card->driver, CARD_NAME);
snprintf(card->shortname, sizeof(card->shortname),
"Digigram miXart [PCM #%d]", i);
snprintf(card->longname, sizeof(card->longname),
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
index cd4dc43dbff1..39464d171f6b 100644
--- a/sound/pci/nm256/nm256.c
+++ b/sound/pci/nm256/nm256.c
@@ -1595,13 +1595,13 @@ static int snd_nm256_probe(struct pci_dev *pci,
switch (pci->device) {
case PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO:
- strcpy(card->driver, "NM256AV");
+ strscpy(card->driver, "NM256AV");
break;
case PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO:
- strcpy(card->driver, "NM256ZX");
+ strscpy(card->driver, "NM256ZX");
break;
case PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO:
- strcpy(card->driver, "NM256XL+");
+ strscpy(card->driver, "NM256XL+");
break;
default:
dev_err(&pci->dev, "invalid device id 0x%x\n", pci->device);
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c
index 39b8ccf37cdd..9c7270e4c35e 100644
--- a/sound/pci/oxygen/oxygen_lib.c
+++ b/sound/pci/oxygen/oxygen_lib.c
@@ -655,11 +655,11 @@ static int __oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
chip->irq = pci->irq;
card->sync_irq = chip->irq;
- strcpy(card->driver, chip->model.chip);
- strcpy(card->shortname, chip->model.shortname);
+ strscpy(card->driver, chip->model.chip);
+ strscpy(card->shortname, chip->model.shortname);
sprintf(card->longname, "%s at %#lx, irq %i",
chip->model.longname, chip->addr, chip->irq);
- strcpy(card->mixername, chip->model.chip);
+ strscpy(card->mixername, chip->model.chip);
snd_component_add(card, chip->model.chip);
err = oxygen_pcm_init(chip);
diff --git a/sound/pci/oxygen/oxygen_pcm.c b/sound/pci/oxygen/oxygen_pcm.c
index b2a3fcfe31d4..643141f345bb 100644
--- a/sound/pci/oxygen/oxygen_pcm.c
+++ b/sound/pci/oxygen/oxygen_pcm.c
@@ -697,7 +697,7 @@ int oxygen_pcm_init(struct oxygen *chip)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
&oxygen_rec_b_ops);
pcm->private_data = chip;
- strcpy(pcm->name, "Multichannel");
+ strscpy(pcm->name, "Multichannel");
if (outs)
snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
SNDRV_DMA_TYPE_DEV,
@@ -725,7 +725,7 @@ int oxygen_pcm_init(struct oxygen *chip)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
&oxygen_rec_c_ops);
pcm->private_data = chip;
- strcpy(pcm->name, "Digital");
+ strscpy(pcm->name, "Digital");
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
&chip->pci->dev,
DEFAULT_BUFFER_BYTES,
@@ -755,7 +755,7 @@ int oxygen_pcm_init(struct oxygen *chip)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
&oxygen_rec_b_ops);
pcm->private_data = chip;
- strcpy(pcm->name, outs ? "Front Panel" : "Analog 2");
+ strscpy(pcm->name, outs ? "Front Panel" : "Analog 2");
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
&chip->pci->dev,
DEFAULT_BUFFER_BYTES,
@@ -773,7 +773,7 @@ int oxygen_pcm_init(struct oxygen *chip)
OXYGEN_REC_C_ROUTE_I2S_ADC_3,
OXYGEN_REC_C_ROUTE_MASK);
pcm->private_data = chip;
- strcpy(pcm->name, "Analog 3");
+ strscpy(pcm->name, "Analog 3");
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
&chip->pci->dev,
DEFAULT_BUFFER_BYTES,
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c
index 242bd7e04b3e..bfd84c50e981 100644
--- a/sound/pci/pcxhr/pcxhr.c
+++ b/sound/pci/pcxhr/pcxhr.c
@@ -1149,7 +1149,7 @@ int pcxhr_create_pcm(struct snd_pcxhr *chip)
pcm->info_flags = 0;
pcm->nonatomic = true;
- strcpy(pcm->name, name);
+ strscpy(pcm->name, name);
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
&chip->mgr->pci->dev,
@@ -1605,7 +1605,7 @@ static int pcxhr_probe(struct pci_dev *pci,
return err;
}
- strcpy(card->driver, DRIVER_NAME);
+ strscpy(card->driver, DRIVER_NAME);
snprintf(card->shortname, sizeof(card->shortname),
"Digigram [PCM #%d]", i);
snprintf(card->longname, sizeof(card->longname),
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
index 578be0755b8a..e983cd657e28 100644
--- a/sound/pci/riptide/riptide.c
+++ b/sound/pci/riptide/riptide.c
@@ -1688,7 +1688,7 @@ static int snd_riptide_pcm(struct snd_riptide *chip, int device)
&snd_riptide_capture_ops);
pcm->private_data = chip;
pcm->info_flags = 0;
- strcpy(pcm->name, "RIPTIDE");
+ strscpy(pcm->name, "RIPTIDE");
chip->pcm = pcm;
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
&chip->pci->dev, 64 * 1024, 128 * 1024);
@@ -2098,8 +2098,8 @@ __snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id
}
#endif
- strcpy(card->driver, "RIPTIDE");
- strcpy(card->shortname, "Riptide");
+ strscpy(card->driver, "RIPTIDE");
+ strscpy(card->shortname, "Riptide");
#ifdef SUPPORT_JOYSTICK
scnprintf(card->longname, sizeof(card->longname),
"%s at 0x%lx, irq %i mpu 0x%x opl3 0x%x gameport 0x%x",
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index 4bf122abea48..f07b6023473a 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -1314,7 +1314,7 @@ static int snd_rme32_create(struct rme32 *rme32)
return err;
rme32->spdif_pcm->private_data = rme32;
rme32->spdif_pcm->private_free = snd_rme32_free_spdif_pcm;
- strcpy(rme32->spdif_pcm->name, "Digi32 IEC958");
+ strscpy(rme32->spdif_pcm->name, "Digi32 IEC958");
if (rme32->fullduplex_mode) {
snd_pcm_set_ops(rme32->spdif_pcm, SNDRV_PCM_STREAM_PLAYBACK,
&snd_rme32_playback_spdif_fd_ops);
@@ -1344,7 +1344,7 @@ static int snd_rme32_create(struct rme32 *rme32)
return err;
rme32->adat_pcm->private_data = rme32;
rme32->adat_pcm->private_free = snd_rme32_free_adat_pcm;
- strcpy(rme32->adat_pcm->name, "Digi32 ADAT");
+ strscpy(rme32->adat_pcm->name, "Digi32 ADAT");
if (rme32->fullduplex_mode) {
snd_pcm_set_ops(rme32->adat_pcm, SNDRV_PCM_STREAM_PLAYBACK,
&snd_rme32_playback_adat_fd_ops);
@@ -1879,16 +1879,16 @@ __snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
if (err < 0)
return err;
- strcpy(card->driver, "Digi32");
+ strscpy(card->driver, "Digi32");
switch (rme32->pci->device) {
case PCI_DEVICE_ID_RME_DIGI32:
- strcpy(card->shortname, "RME Digi32");
+ strscpy(card->shortname, "RME Digi32");
break;
case PCI_DEVICE_ID_RME_DIGI32_8:
- strcpy(card->shortname, "RME Digi32/8");
+ strscpy(card->shortname, "RME Digi32/8");
break;
case PCI_DEVICE_ID_RME_DIGI32_PRO:
- strcpy(card->shortname, "RME Digi32 PRO");
+ strscpy(card->shortname, "RME Digi32 PRO");
break;
}
sprintf(card->longname, "%s (Rev. %d) at 0x%lx, irq %d",
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index 01029843d7f3..5cdbbe9cf994 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -1607,7 +1607,7 @@ snd_rme96_create(struct rme96 *rme96)
rme96->spdif_pcm->private_data = rme96;
rme96->spdif_pcm->private_free = snd_rme96_free_spdif_pcm;
- strcpy(rme96->spdif_pcm->name, "Digi96 IEC958");
+ strscpy(rme96->spdif_pcm->name, "Digi96 IEC958");
snd_pcm_set_ops(rme96->spdif_pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_rme96_playback_spdif_ops);
snd_pcm_set_ops(rme96->spdif_pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_rme96_capture_spdif_ops);
@@ -1624,7 +1624,7 @@ snd_rme96_create(struct rme96 *rme96)
return err;
rme96->adat_pcm->private_data = rme96;
rme96->adat_pcm->private_free = snd_rme96_free_adat_pcm;
- strcpy(rme96->adat_pcm->name, "Digi96 ADAT");
+ strscpy(rme96->adat_pcm->name, "Digi96 ADAT");
snd_pcm_set_ops(rme96->adat_pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_rme96_playback_adat_ops);
snd_pcm_set_ops(rme96->adat_pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_rme96_capture_adat_ops);
@@ -2434,23 +2434,23 @@ __snd_rme96_probe(struct pci_dev *pci,
return -ENOMEM;
}
- strcpy(card->driver, "Digi96");
+ strscpy(card->driver, "Digi96");
switch (rme96->pci->device) {
case PCI_DEVICE_ID_RME_DIGI96:
- strcpy(card->shortname, "RME Digi96");
+ strscpy(card->shortname, "RME Digi96");
break;
case PCI_DEVICE_ID_RME_DIGI96_8:
- strcpy(card->shortname, "RME Digi96/8");
+ strscpy(card->shortname, "RME Digi96/8");
break;
case PCI_DEVICE_ID_RME_DIGI96_8_PRO:
- strcpy(card->shortname, "RME Digi96/8 PRO");
+ strscpy(card->shortname, "RME Digi96/8 PRO");
break;
case PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST:
pci_read_config_byte(rme96->pci, 8, &val);
if (val < 5) {
- strcpy(card->shortname, "RME Digi96/8 PAD");
+ strscpy(card->shortname, "RME Digi96/8 PAD");
} else {
- strcpy(card->shortname, "RME Digi96/8 PST");
+ strscpy(card->shortname, "RME Digi96/8 PST");
}
break;
}
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index 8df0f5bba0f6..7ce73746168a 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -4944,7 +4944,7 @@ static int snd_hdsp_create_hwdep(struct snd_card *card, struct hdsp *hdsp)
hdsp->hwdep = hw;
hw->private_data = hdsp;
- strcpy(hw->name, "HDSP hwdep interface");
+ strscpy(hw->name, "HDSP hwdep interface");
hw->ops.ioctl = snd_hdsp_hwdep_ioctl;
hw->ops.ioctl_compat = snd_hdsp_hwdep_ioctl;
@@ -4963,7 +4963,7 @@ static int snd_hdsp_create_pcm(struct snd_card *card, struct hdsp *hdsp)
hdsp->pcm = pcm;
pcm->private_data = hdsp;
- strcpy(pcm->name, hdsp->card_name);
+ strscpy(pcm->name, hdsp->card_name);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_hdsp_playback_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_hdsp_capture_ops);
@@ -5111,7 +5111,7 @@ static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp
}
if (!(hdsp->state & HDSP_InitializationComplete)) {
- strcpy(card->shortname, "Hammerfall DSP");
+ strscpy(card->shortname, "Hammerfall DSP");
sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name,
hdsp->port, hdsp->irq);
@@ -5255,8 +5255,8 @@ static int snd_hdsp_create(struct snd_card *card,
*/
pci_write_config_byte(hdsp->pci, PCI_LATENCY_TIMER, 0xFF);
- strcpy(card->driver, "H-DSP");
- strcpy(card->mixername, "Xilinx FPGA");
+ strscpy(card->driver, "H-DSP");
+ strscpy(card->mixername, "Xilinx FPGA");
if (hdsp->firmware_rev < 0xa)
return -ENODEV;
@@ -5412,7 +5412,7 @@ static int snd_hdsp_probe(struct pci_dev *pci,
if (err)
goto error;
- strcpy(card->shortname, "Hammerfall DSP");
+ strscpy(card->shortname, "Hammerfall DSP");
sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name,
hdsp->port, hdsp->irq);
err = snd_card_register(card);
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 2041cf00cca0..a0976824beda 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -6355,7 +6355,7 @@ static int snd_hdspm_create_hwdep(struct snd_card *card,
hdspm->hwdep = hw;
hw->private_data = hdspm;
- strcpy(hw->name, "HDSPM hwdep interface");
+ strscpy(hw->name, "HDSPM hwdep interface");
hw->ops.open = snd_hdspm_hwdep_dummy_op;
hw->ops.ioctl = snd_hdspm_hwdep_ioctl;
@@ -6412,7 +6412,7 @@ static int snd_hdspm_create_pcm(struct snd_card *card,
hdspm->pcm = pcm;
pcm->private_data = hdspm;
- strcpy(pcm->name, hdspm->card_name);
+ strscpy(pcm->name, hdspm->card_name);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
&snd_hdspm_ops);
@@ -6512,8 +6512,8 @@ static int snd_hdspm_create(struct snd_card *card,
pci_read_config_word(hdspm->pci,
PCI_CLASS_REVISION, &hdspm->firmware_rev);
- strcpy(card->mixername, "Xilinx FPGA");
- strcpy(card->driver, "HDSPM");
+ strscpy(card->mixername, "Xilinx FPGA");
+ strscpy(card->driver, "HDSPM");
switch (hdspm->firmware_rev) {
case HDSPM_RAYDAT_REV:
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
index 34d9c7995ddd..7dc8e3777c37 100644
--- a/sound/pci/rme9652/rme9652.c
+++ b/sound/pci/rme9652/rme9652.c
@@ -2364,7 +2364,7 @@ static int snd_rme9652_create_pcm(struct snd_card *card,
rme9652->pcm = pcm;
pcm->private_data = rme9652;
- strcpy(pcm->name, rme9652->card_name);
+ strscpy(pcm->name, rme9652->card_name);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_rme9652_playback_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_rme9652_capture_ops);
@@ -2447,7 +2447,7 @@ static int snd_rme9652_create(struct snd_card *card,
switch (rev) {
case 8: /* original eprom */
- strcpy(card->driver, "RME9636");
+ strscpy(card->driver, "RME9636");
if (rme9652->hw_rev == 15) {
rme9652->card_name = "RME Digi9636 (Rev 1.5)";
} else {
@@ -2456,17 +2456,17 @@ static int snd_rme9652_create(struct snd_card *card,
rme9652->ss_channels = RME9636_NCHANNELS;
break;
case 9: /* W36_G EPROM */
- strcpy(card->driver, "RME9636");
+ strscpy(card->driver, "RME9636");
rme9652->card_name = "RME Digi9636 (Rev G)";
rme9652->ss_channels = RME9636_NCHANNELS;
break;
case 4: /* W52_G EPROM */
- strcpy(card->driver, "RME9652");
+ strscpy(card->driver, "RME9652");
rme9652->card_name = "RME Digi9652 (Rev G)";
rme9652->ss_channels = RME9652_NCHANNELS;
break;
case 3: /* original eprom */
- strcpy(card->driver, "RME9652");
+ strscpy(card->driver, "RME9652");
if (rme9652->hw_rev == 15) {
rme9652->card_name = "RME Digi9652 (Rev 1.5)";
} else {
@@ -2539,7 +2539,7 @@ static int snd_rme9652_probe(struct pci_dev *pci,
if (err)
goto error;
- strcpy(card->shortname, rme9652->card_name);
+ strscpy(card->shortname, rme9652->card_name);
sprintf(card->longname, "%s at 0x%lx, irq %d",
card->shortname, rme9652->port, rme9652->irq);
diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c
index 42b22f123fa7..3d7abcb31679 100644
--- a/sound/pci/sis7019.c
+++ b/sound/pci/sis7019.c
@@ -868,7 +868,7 @@ static int sis_pcm_create(struct sis7019 *sis)
return rc;
pcm->private_data = sis;
- strcpy(pcm->name, "SiS7019");
+ strscpy(pcm->name, "SiS7019");
sis->pcm = pcm;
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &sis_playback_ops);
@@ -1348,8 +1348,8 @@ static int __snd_sis7019_probe(struct pci_dev *pci,
if (rc < 0)
return rc;
- strcpy(card->driver, "SiS7019");
- strcpy(card->shortname, "SiS7019");
+ strscpy(card->driver, "SiS7019");
+ strscpy(card->shortname, "SiS7019");
rc = sis_chip_create(card, pci);
if (rc)
return rc;
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
index 808a793ff4da..f85a9556dacb 100644
--- a/sound/pci/sonicvibes.c
+++ b/sound/pci/sonicvibes.c
@@ -863,7 +863,7 @@ static int snd_sonicvibes_pcm(struct sonicvibes *sonic, int device)
pcm->private_data = sonic;
pcm->info_flags = 0;
- strcpy(pcm->name, "S3 SonicVibes");
+ strscpy(pcm->name, "S3 SonicVibes");
sonic->pcm = pcm;
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
@@ -1091,7 +1091,7 @@ static int snd_sonicvibes_mixer(struct sonicvibes *sonic)
if (snd_BUG_ON(!sonic || !sonic->card))
return -EINVAL;
card = sonic->card;
- strcpy(card->mixername, "S3 SonicVibes");
+ strscpy(card->mixername, "S3 SonicVibes");
for (idx = 0; idx < ARRAY_SIZE(snd_sonicvibes_controls); idx++) {
kctl = snd_ctl_new1(&snd_sonicvibes_controls[idx], sonic);
@@ -1415,8 +1415,8 @@ static int __snd_sonic_probe(struct pci_dev *pci,
if (err < 0)
return err;
- strcpy(card->driver, "SonicVibes");
- strcpy(card->shortname, "S3 SonicVibes");
+ strscpy(card->driver, "SonicVibes");
+ strscpy(card->shortname, "S3 SonicVibes");
sprintf(card->longname, "%s rev %i at 0x%llx, irq %i",
card->shortname,
sonic->revision,
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c
index 9922ab40798c..ddb6ccc72e44 100644
--- a/sound/pci/trident/trident.c
+++ b/sound/pci/trident/trident.c
@@ -88,11 +88,11 @@ static int snd_trident_probe(struct pci_dev *pci,
default:
str = "Unknown";
}
- strcpy(card->driver, str);
+ strscpy(card->driver, str);
if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
- strcpy(card->shortname, "SiS ");
+ strscpy(card->shortname, "SiS ");
} else {
- strcpy(card->shortname, "Trident ");
+ strscpy(card->shortname, "Trident ");
}
strcat(card->shortname, str);
sprintf(card->longname, "%s PCI Audio at 0x%lx, irq %d",
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
index 4e16b79d6584..39ed52bf8631 100644
--- a/sound/pci/trident/trident_main.c
+++ b/sound/pci/trident/trident_main.c
@@ -2137,7 +2137,7 @@ int snd_trident_pcm(struct snd_trident *trident, int device)
pcm->info_flags = 0;
pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
- strcpy(pcm->name, "Trident 4DWave");
+ strscpy(pcm->name, "Trident 4DWave");
trident->pcm = pcm;
if (trident->tlb.entries) {
@@ -2189,16 +2189,16 @@ int snd_trident_foldback_pcm(struct snd_trident *trident, int device)
else
snd_pcm_set_ops(foldback, SNDRV_PCM_STREAM_CAPTURE, &snd_trident_foldback_ops);
foldback->info_flags = 0;
- strcpy(foldback->name, "Trident 4DWave");
+ strscpy(foldback->name, "Trident 4DWave");
substream = foldback->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
- strcpy(substream->name, "Front Mixer");
+ strscpy(substream->name, "Front Mixer");
substream = substream->next;
- strcpy(substream->name, "Reverb Mixer");
+ strscpy(substream->name, "Reverb Mixer");
substream = substream->next;
- strcpy(substream->name, "Chorus Mixer");
+ strscpy(substream->name, "Chorus Mixer");
if (num_chan == 4) {
substream = substream->next;
- strcpy(substream->name, "Second AC'97 ADC");
+ strscpy(substream->name, "Second AC'97 ADC");
}
trident->foldback = foldback;
@@ -2241,7 +2241,7 @@ int snd_trident_spdif_pcm(struct snd_trident *trident, int device)
snd_pcm_set_ops(spdif, SNDRV_PCM_STREAM_PLAYBACK, &snd_trident_spdif_7018_ops);
}
spdif->info_flags = 0;
- strcpy(spdif->name, "Trident 4DWave IEC958");
+ strscpy(spdif->name, "Trident 4DWave IEC958");
trident->spdif = spdif;
snd_pcm_set_managed_buffer_all(spdif, SNDRV_DMA_TYPE_DEV,
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index a04dbc0a420f..0753c0c73f51 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -1436,7 +1436,7 @@ static int snd_via8233_pcm_new(struct via82xx *chip)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_via8233_playback_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_via8233_capture_ops);
pcm->private_data = chip;
- strcpy(pcm->name, chip->card->shortname);
+ strscpy(pcm->name, chip->card->shortname);
chip->pcms[0] = pcm;
/* set up playbacks */
for (i = 0; i < 4; i++)
@@ -1461,7 +1461,7 @@ static int snd_via8233_pcm_new(struct via82xx *chip)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_via8233_multi_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_via8233_capture_ops);
pcm->private_data = chip;
- strcpy(pcm->name, chip->card->shortname);
+ strscpy(pcm->name, chip->card->shortname);
chip->pcms[1] = pcm;
/* set up playback */
init_viadev(chip, chip->multi_devno, VIA_REG_MULTPLAY_STATUS, 4, 0);
@@ -1504,7 +1504,7 @@ static int snd_via8233a_pcm_new(struct via82xx *chip)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_via8233_multi_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_via8233_capture_ops);
pcm->private_data = chip;
- strcpy(pcm->name, chip->card->shortname);
+ strscpy(pcm->name, chip->card->shortname);
chip->pcms[0] = pcm;
/* set up playback */
init_viadev(chip, chip->multi_devno, VIA_REG_MULTPLAY_STATUS, 4, 0);
@@ -1532,7 +1532,7 @@ static int snd_via8233a_pcm_new(struct via82xx *chip)
return err;
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_via8233_playback_ops);
pcm->private_data = chip;
- strcpy(pcm->name, chip->card->shortname);
+ strscpy(pcm->name, chip->card->shortname);
chip->pcms[1] = pcm;
/* set up playback */
init_viadev(chip, chip->playback_devno, 0x30, 3, 0);
@@ -1562,7 +1562,7 @@ static int snd_via686_pcm_new(struct via82xx *chip)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_via686_playback_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_via686_capture_ops);
pcm->private_data = chip;
- strcpy(pcm->name, chip->card->shortname);
+ strscpy(pcm->name, chip->card->shortname);
chip->pcms[0] = pcm;
init_viadev(chip, 0, VIA_REG_PLAYBACK_STATUS, 0, 0);
init_viadev(chip, 1, VIA_REG_CAPTURE_STATUS, 0, 1);
@@ -2461,7 +2461,7 @@ static int __snd_via82xx_probe(struct pci_dev *pci,
card_type = pci_id->driver_data;
switch (card_type) {
case TYPE_CARD_VIA686:
- strcpy(card->driver, "VIA686A");
+ strscpy(card->driver, "VIA686A");
sprintf(card->shortname, "VIA 82C686A/B rev%x", pci->revision);
chip_type = TYPE_VIA686;
break;
@@ -2471,7 +2471,7 @@ static int __snd_via82xx_probe(struct pci_dev *pci,
for (i = 0; i < ARRAY_SIZE(via823x_cards); i++) {
if (pci->revision == via823x_cards[i].revision) {
chip_type = via823x_cards[i].type;
- strcpy(card->shortname, via823x_cards[i].name);
+ strscpy(card->shortname, via823x_cards[i].name);
break;
}
}
@@ -2487,11 +2487,11 @@ static int __snd_via82xx_probe(struct pci_dev *pci,
chip_type = TYPE_VIA8233;
}
if (chip_type == TYPE_VIA8233A)
- strcpy(card->driver, "VIA8233A");
+ strscpy(card->driver, "VIA8233A");
else if (pci->revision >= VIA_REV_8237)
- strcpy(card->driver, "VIA8237"); /* no slog assignment */
+ strscpy(card->driver, "VIA8237"); /* no slog assignment */
else
- strcpy(card->driver, "VIA8233");
+ strscpy(card->driver, "VIA8233");
break;
default:
dev_err(card->dev, "invalid card type %d\n", card_type);
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
index eef0f9ddaae0..12a8c620724d 100644
--- a/sound/pci/via82xx_modem.c
+++ b/sound/pci/via82xx_modem.c
@@ -842,7 +842,7 @@ static int snd_via686_pcm_new(struct via82xx_modem *chip)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_via686_capture_ops);
pcm->dev_class = SNDRV_PCM_CLASS_MODEM;
pcm->private_data = chip;
- strcpy(pcm->name, chip->card->shortname);
+ strscpy(pcm->name, chip->card->shortname);
chip->pcms[0] = pcm;
init_viadev(chip, 0, VIA_REG_MO_STATUS, 0);
init_viadev(chip, 1, VIA_REG_MI_STATUS, 1);
@@ -1116,7 +1116,7 @@ static int __snd_via82xx_probe(struct pci_dev *pci,
card_type = pci_id->driver_data;
switch (card_type) {
case TYPE_CARD_VIA82XX_MODEM:
- strcpy(card->driver, "VIA82XX-MODEM");
+ strscpy(card->driver, "VIA82XX-MODEM");
sprintf(card->shortname, "VIA 82XX modem");
break;
default:
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c
index 48444dda44de..764ca59e98d1 100644
--- a/sound/pci/ymfpci/ymfpci.c
+++ b/sound/pci/ymfpci/ymfpci.c
@@ -188,7 +188,7 @@ static int __snd_card_ymfpci_probe(struct pci_dev *pci,
default: model = str = "???"; break;
}
- strcpy(card->driver, str);
+ strscpy(card->driver, str);
sprintf(card->shortname, "Yamaha %s (%s)", model, str);
sprintf(card->longname, "%s at 0x%lx, irq %i",
card->shortname,
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index d495f53a8324..75e013b66c5b 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -1134,7 +1134,7 @@ int snd_ymfpci_pcm(struct snd_ymfpci *chip, int device)
/* global setup */
pcm->info_flags = 0;
- strcpy(pcm->name, "YMFPCI");
+ strscpy(pcm->name, "YMFPCI");
chip->pcm = pcm;
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
@@ -1201,7 +1201,7 @@ int snd_ymfpci_pcm_spdif(struct snd_ymfpci *chip, int device)
/* global setup */
pcm->info_flags = 0;
- strcpy(pcm->name, "YMFPCI - IEC958");
+ strscpy(pcm->name, "YMFPCI - IEC958");
chip->pcm_spdif = pcm;
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
@@ -1242,7 +1242,7 @@ int snd_ymfpci_pcm_4ch(struct snd_ymfpci *chip, int device)
/* global setup */
pcm->info_flags = 0;
- strcpy(pcm->name, "YMFPCI - Rear PCM");
+ strscpy(pcm->name, "YMFPCI - Rear PCM");
chip->pcm_4ch = pcm;
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
@@ -1948,7 +1948,7 @@ int snd_ymfpci_timer(struct snd_ymfpci *chip, int device)
tid.subdevice = 0;
err = snd_timer_new(chip->card, "YMFPCI", &tid, &timer);
if (err >= 0) {
- strcpy(timer->name, "YMFPCI timer");
+ strscpy(timer->name, "YMFPCI timer");
timer->private_data = chip;
timer->hw = snd_ymfpci_timer_hw;
}