[ALSA] ens1371 - Clean up quirks

Clean up quirks in snd-ens1371 driver using snd_pci_quirk_lookup().

Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
This commit is contained in:
Takashi Iwai 2006-11-24 15:38:18 +01:00 committed by Jaroslav Kysela
parent 9d74958a84
commit 5da8fa2516

View file

@ -413,8 +413,6 @@ struct ensoniq {
} u; } u;
struct pci_dev *pci; struct pci_dev *pci;
unsigned short subsystem_vendor_id;
unsigned short subsystem_device_id;
struct snd_card *card; struct snd_card *card;
struct snd_pcm *pcm1; /* DAC1/ADC PCM */ struct snd_pcm *pcm1; /* DAC1/ADC PCM */
struct snd_pcm *pcm2; /* DAC2 PCM */ struct snd_pcm *pcm2; /* DAC2 PCM */
@ -1607,11 +1605,26 @@ static void snd_ensoniq_mixer_free_ac97(struct snd_ac97 *ac97)
ensoniq->u.es1371.ac97 = NULL; ensoniq->u.es1371.ac97 = NULL;
} }
static struct { struct es1371_quirk {
unsigned short vid; /* vendor ID */ unsigned short vid; /* vendor ID */
unsigned short did; /* device ID */ unsigned short did; /* device ID */
unsigned char rev; /* revision */ unsigned char rev; /* revision */
} es1371_spdif_present[] __devinitdata = { };
static int __devinit es1371_quirk_lookup(struct ensoniq *ensoniq,
struct es1371_quirk *list)
{
while (list->vid != (unsigned short)PCI_ANY_ID) {
if (ensoniq->pci->vendor == list->vid &&
ensoniq->pci->device == list->did &&
ensoniq->rev == list->rev)
return 1;
list++;
}
return 0;
}
static struct es1371_quirk es1371_spdif_present[] __devinitdata = {
{ .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_C }, { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_C },
{ .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_D }, { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_D },
{ .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_E }, { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_E },
@ -1620,12 +1633,19 @@ static struct {
{ .vid = PCI_ANY_ID, .did = PCI_ANY_ID } { .vid = PCI_ANY_ID, .did = PCI_ANY_ID }
}; };
static int snd_ensoniq_1371_mixer(struct ensoniq * ensoniq, int has_spdif, int has_line) static struct snd_pci_quirk ens1373_line_quirk[] __devinitdata = {
SND_PCI_QUIRK_ID(0x1274, 0x2000), /* GA-7DXR */
SND_PCI_QUIRK_ID(0x1458, 0xa000), /* GA-8IEXP */
{ } /* end */
};
static int __devinit snd_ensoniq_1371_mixer(struct ensoniq *ensoniq,
int has_spdif, int has_line)
{ {
struct snd_card *card = ensoniq->card; struct snd_card *card = ensoniq->card;
struct snd_ac97_bus *pbus; struct snd_ac97_bus *pbus;
struct snd_ac97_template ac97; struct snd_ac97_template ac97;
int err, idx; int err;
static struct snd_ac97_bus_ops ops = { static struct snd_ac97_bus_ops ops = {
.write = snd_es1371_codec_write, .write = snd_es1371_codec_write,
.read = snd_es1371_codec_read, .read = snd_es1371_codec_read,
@ -1641,33 +1661,28 @@ static int snd_ensoniq_1371_mixer(struct ensoniq * ensoniq, int has_spdif, int h
ac97.scaps = AC97_SCAP_AUDIO; ac97.scaps = AC97_SCAP_AUDIO;
if ((err = snd_ac97_mixer(pbus, &ac97, &ensoniq->u.es1371.ac97)) < 0) if ((err = snd_ac97_mixer(pbus, &ac97, &ensoniq->u.es1371.ac97)) < 0)
return err; return err;
for (idx = 0; es1371_spdif_present[idx].vid != (unsigned short)PCI_ANY_ID; idx++) if (has_spdif > 0 ||
if ((ensoniq->pci->vendor == es1371_spdif_present[idx].vid && (!has_spdif && es1371_quirk_lookup(ensoniq, es1371_spdif_present))) {
ensoniq->pci->device == es1371_spdif_present[idx].did && struct snd_kcontrol *kctl;
ensoniq->rev == es1371_spdif_present[idx].rev) || has_spdif > 0) { int i, index = 0;
struct snd_kcontrol *kctl;
int i, index = 0;
if (has_spdif < 0) ensoniq->spdif_default = ensoniq->spdif_stream =
break; SNDRV_PCM_DEFAULT_CON_SPDIF;
outl(ensoniq->spdif_default, ES_REG(ensoniq, CHANNEL_STATUS));
ensoniq->spdif_default = ensoniq->spdif_stream = if (ensoniq->u.es1371.ac97->ext_id & AC97_EI_SPDIF)
SNDRV_PCM_DEFAULT_CON_SPDIF; index++;
outl(ensoniq->spdif_default, ES_REG(ensoniq, CHANNEL_STATUS));
if (ensoniq->u.es1371.ac97->ext_id & AC97_EI_SPDIF) for (i = 0; i < ARRAY_SIZE(snd_es1371_mixer_spdif); i++) {
index++; kctl = snd_ctl_new1(&snd_es1371_mixer_spdif[i], ensoniq);
if (!kctl)
for (i = 0; i < (int)ARRAY_SIZE(snd_es1371_mixer_spdif); i++) { return -ENOMEM;
kctl = snd_ctl_new1(&snd_es1371_mixer_spdif[i], ensoniq); kctl->id.index = index;
if (! kctl) err = snd_ctl_add(card, kctl);
return -ENOMEM; if (err < 0)
kctl->id.index = index; return err;
if ((err = snd_ctl_add(card, kctl)) < 0)
return err;
}
break;
} }
}
if (ensoniq->u.es1371.ac97->ext_id & AC97_EI_SDAC) { if (ensoniq->u.es1371.ac97->ext_id & AC97_EI_SDAC) {
/* mirror rear to front speakers */ /* mirror rear to front speakers */
ensoniq->cssr &= ~(ES_1373_REAR_BIT27|ES_1373_REAR_BIT24); ensoniq->cssr &= ~(ES_1373_REAR_BIT27|ES_1373_REAR_BIT24);
@ -1676,12 +1691,10 @@ static int snd_ensoniq_1371_mixer(struct ensoniq * ensoniq, int has_spdif, int h
if (err < 0) if (err < 0)
return err; return err;
} }
if (((ensoniq->subsystem_vendor_id == 0x1274) && if (has_line > 0 ||
(ensoniq->subsystem_device_id == 0x2000)) || /* GA-7DXR */ snd_pci_quirk_lookup(ensoniq->pci, ens1373_line_quirk)) {
((ensoniq->subsystem_vendor_id == 0x1458) && err = snd_ctl_add(card, snd_ctl_new1(&snd_ens1373_line,
(ensoniq->subsystem_device_id == 0xa000)) || /* GA-8IEXP */ ensoniq));
has_line > 0) {
err = snd_ctl_add(card, snd_ctl_new1(&snd_ens1373_line, ensoniq));
if (err < 0) if (err < 0)
return err; return err;
} }
@ -1956,21 +1969,15 @@ static int snd_ensoniq_dev_free(struct snd_device *device)
} }
#ifdef CHIP1371 #ifdef CHIP1371
static struct { static struct snd_pci_quirk es1371_amplifier_hack[] __devinitdata = {
unsigned short svid; /* subsystem vendor ID */ SND_PCI_QUIRK_ID(0x107b, 0x2150), /* Gateway Solo 2150 */
unsigned short sdid; /* subsystem device ID */ SND_PCI_QUIRK_ID(0x13bd, 0x100c), /* EV1938 on Mebius PC-MJ100V */
} es1371_amplifier_hack[] = { SND_PCI_QUIRK_ID(0x1102, 0x5938), /* Targa Xtender300 */
{ .svid = 0x107b, .sdid = 0x2150 }, /* Gateway Solo 2150 */ SND_PCI_QUIRK_ID(0x1102, 0x8938), /* IPC Topnote G notebook */
{ .svid = 0x13bd, .sdid = 0x100c }, /* EV1938 on Mebius PC-MJ100V */ { } /* end */
{ .svid = 0x1102, .sdid = 0x5938 }, /* Targa Xtender300 */
{ .svid = 0x1102, .sdid = 0x8938 }, /* IPC Topnote G notebook */
{ .svid = PCI_ANY_ID, .sdid = PCI_ANY_ID }
}; };
static struct {
unsigned short vid; /* vendor ID */ static struct es1371_quirk es1371_ac97_reset_hack[] = {
unsigned short did; /* device ID */
unsigned char rev; /* revision */
} es1371_ac97_reset_hack[] = {
{ .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_C }, { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_C },
{ .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_D }, { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_D },
{ .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_E }, { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_E },
@ -1984,7 +1991,6 @@ static void snd_ensoniq_chip_init(struct ensoniq *ensoniq)
{ {
#ifdef CHIP1371 #ifdef CHIP1371
int idx; int idx;
struct pci_dev *pci = ensoniq->pci;
#endif #endif
/* this code was part of snd_ensoniq_create before intruduction /* this code was part of snd_ensoniq_create before intruduction
* of suspend/resume * of suspend/resume
@ -1999,16 +2005,12 @@ static void snd_ensoniq_chip_init(struct ensoniq *ensoniq)
outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL)); outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL));
outl(0, ES_REG(ensoniq, 1371_LEGACY)); outl(0, ES_REG(ensoniq, 1371_LEGACY));
for (idx = 0; es1371_ac97_reset_hack[idx].vid != (unsigned short)PCI_ANY_ID; idx++) if (es1371_quirk_lookup(ensoniq, es1371_ac97_reset_hack)) {
if (pci->vendor == es1371_ac97_reset_hack[idx].vid && outl(ensoniq->cssr, ES_REG(ensoniq, STATUS));
pci->device == es1371_ac97_reset_hack[idx].did && /* need to delay around 20ms(bleech) to give
ensoniq->rev == es1371_ac97_reset_hack[idx].rev) { some CODECs enough time to wakeup */
outl(ensoniq->cssr, ES_REG(ensoniq, STATUS)); msleep(20);
/* need to delay around 20ms(bleech) to give }
some CODECs enough time to wakeup */
msleep(20);
break;
}
/* AC'97 warm reset to start the bitclk */ /* AC'97 warm reset to start the bitclk */
outl(ensoniq->ctrl | ES_1371_SYNC_RES, ES_REG(ensoniq, CONTROL)); outl(ensoniq->ctrl | ES_1371_SYNC_RES, ES_REG(ensoniq, CONTROL));
inl(ES_REG(ensoniq, CONTROL)); inl(ES_REG(ensoniq, CONTROL));
@ -2112,11 +2114,7 @@ static int __devinit snd_ensoniq_create(struct snd_card *card,
struct ensoniq ** rensoniq) struct ensoniq ** rensoniq)
{ {
struct ensoniq *ensoniq; struct ensoniq *ensoniq;
unsigned short cmdw;
unsigned char cmdb; unsigned char cmdb;
#ifdef CHIP1371
int idx;
#endif
int err; int err;
static struct snd_device_ops ops = { static struct snd_device_ops ops = {
.dev_free = snd_ensoniq_dev_free, .dev_free = snd_ensoniq_dev_free,
@ -2159,10 +2157,6 @@ static int __devinit snd_ensoniq_create(struct snd_card *card,
pci_set_master(pci); pci_set_master(pci);
pci_read_config_byte(pci, PCI_REVISION_ID, &cmdb); pci_read_config_byte(pci, PCI_REVISION_ID, &cmdb);
ensoniq->rev = cmdb; ensoniq->rev = cmdb;
pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &cmdw);
ensoniq->subsystem_vendor_id = cmdw;
pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &cmdw);
ensoniq->subsystem_device_id = cmdw;
#ifdef CHIP1370 #ifdef CHIP1370
#if 0 #if 0
ensoniq->ctrl = ES_1370_CDC_EN | ES_1370_SERR_DISABLE | ensoniq->ctrl = ES_1370_CDC_EN | ES_1370_SERR_DISABLE |
@ -2175,19 +2169,11 @@ static int __devinit snd_ensoniq_create(struct snd_card *card,
ensoniq->ctrl = 0; ensoniq->ctrl = 0;
ensoniq->sctrl = 0; ensoniq->sctrl = 0;
ensoniq->cssr = 0; ensoniq->cssr = 0;
for (idx = 0; es1371_amplifier_hack[idx].svid != (unsigned short)PCI_ANY_ID; idx++) if (snd_pci_quirk_lookup(pci, es1371_amplifier_hack))
if (ensoniq->subsystem_vendor_id == es1371_amplifier_hack[idx].svid && ensoniq->ctrl |= ES_1371_GPIO_OUT(1); /* turn amplifier on */
ensoniq->subsystem_device_id == es1371_amplifier_hack[idx].sdid) {
ensoniq->ctrl |= ES_1371_GPIO_OUT(1); /* turn amplifier on */ if (es1371_quirk_lookup(ensoniq, es1371_ac97_reset_hack))
break; ensoniq->cssr |= ES_1371_ST_AC97_RST;
}
for (idx = 0; es1371_ac97_reset_hack[idx].vid != (unsigned short)PCI_ANY_ID; idx++)
if (pci->vendor == es1371_ac97_reset_hack[idx].vid &&
pci->device == es1371_ac97_reset_hack[idx].did &&
ensoniq->rev == es1371_ac97_reset_hack[idx].rev) {
ensoniq->cssr |= ES_1371_ST_AC97_RST;
break;
}
#endif #endif
snd_ensoniq_chip_init(ensoniq); snd_ensoniq_chip_init(ensoniq);