diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/pci/ens1370.c | 154 |
1 files changed, 70 insertions, 84 deletions
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index a84f6b21024f..425b167522d5 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c | |||
@@ -413,8 +413,6 @@ struct ensoniq { | |||
413 | } u; | 413 | } u; |
414 | 414 | ||
415 | struct pci_dev *pci; | 415 | struct pci_dev *pci; |
416 | unsigned short subsystem_vendor_id; | ||
417 | unsigned short subsystem_device_id; | ||
418 | struct snd_card *card; | 416 | struct snd_card *card; |
419 | struct snd_pcm *pcm1; /* DAC1/ADC PCM */ | 417 | struct snd_pcm *pcm1; /* DAC1/ADC PCM */ |
420 | struct snd_pcm *pcm2; /* DAC2 PCM */ | 418 | struct snd_pcm *pcm2; /* DAC2 PCM */ |
@@ -1607,11 +1605,26 @@ static void snd_ensoniq_mixer_free_ac97(struct snd_ac97 *ac97) | |||
1607 | ensoniq->u.es1371.ac97 = NULL; | 1605 | ensoniq->u.es1371.ac97 = NULL; |
1608 | } | 1606 | } |
1609 | 1607 | ||
1610 | static struct { | 1608 | struct es1371_quirk { |
1611 | unsigned short vid; /* vendor ID */ | 1609 | unsigned short vid; /* vendor ID */ |
1612 | unsigned short did; /* device ID */ | 1610 | unsigned short did; /* device ID */ |
1613 | unsigned char rev; /* revision */ | 1611 | unsigned char rev; /* revision */ |
1614 | } es1371_spdif_present[] __devinitdata = { | 1612 | }; |
1613 | |||
1614 | static int __devinit es1371_quirk_lookup(struct ensoniq *ensoniq, | ||
1615 | struct es1371_quirk *list) | ||
1616 | { | ||
1617 | while (list->vid != (unsigned short)PCI_ANY_ID) { | ||
1618 | if (ensoniq->pci->vendor == list->vid && | ||
1619 | ensoniq->pci->device == list->did && | ||
1620 | ensoniq->rev == list->rev) | ||
1621 | return 1; | ||
1622 | list++; | ||
1623 | } | ||
1624 | return 0; | ||
1625 | } | ||
1626 | |||
1627 | static struct es1371_quirk es1371_spdif_present[] __devinitdata = { | ||
1615 | { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_C }, | 1628 | { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_C }, |
1616 | { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_D }, | 1629 | { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_D }, |
1617 | { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_E }, | 1630 | { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_E }, |
@@ -1620,12 +1633,19 @@ static struct { | |||
1620 | { .vid = PCI_ANY_ID, .did = PCI_ANY_ID } | 1633 | { .vid = PCI_ANY_ID, .did = PCI_ANY_ID } |
1621 | }; | 1634 | }; |
1622 | 1635 | ||
1623 | static int snd_ensoniq_1371_mixer(struct ensoniq * ensoniq, int has_spdif, int has_line) | 1636 | static struct snd_pci_quirk ens1373_line_quirk[] __devinitdata = { |
1637 | SND_PCI_QUIRK_ID(0x1274, 0x2000), /* GA-7DXR */ | ||
1638 | SND_PCI_QUIRK_ID(0x1458, 0xa000), /* GA-8IEXP */ | ||
1639 | { } /* end */ | ||
1640 | }; | ||
1641 | |||
1642 | static int __devinit snd_ensoniq_1371_mixer(struct ensoniq *ensoniq, | ||
1643 | int has_spdif, int has_line) | ||
1624 | { | 1644 | { |
1625 | struct snd_card *card = ensoniq->card; | 1645 | struct snd_card *card = ensoniq->card; |
1626 | struct snd_ac97_bus *pbus; | 1646 | struct snd_ac97_bus *pbus; |
1627 | struct snd_ac97_template ac97; | 1647 | struct snd_ac97_template ac97; |
1628 | int err, idx; | 1648 | int err; |
1629 | static struct snd_ac97_bus_ops ops = { | 1649 | static struct snd_ac97_bus_ops ops = { |
1630 | .write = snd_es1371_codec_write, | 1650 | .write = snd_es1371_codec_write, |
1631 | .read = snd_es1371_codec_read, | 1651 | .read = snd_es1371_codec_read, |
@@ -1641,33 +1661,28 @@ static int snd_ensoniq_1371_mixer(struct ensoniq * ensoniq, int has_spdif, int h | |||
1641 | ac97.scaps = AC97_SCAP_AUDIO; | 1661 | ac97.scaps = AC97_SCAP_AUDIO; |
1642 | if ((err = snd_ac97_mixer(pbus, &ac97, &ensoniq->u.es1371.ac97)) < 0) | 1662 | if ((err = snd_ac97_mixer(pbus, &ac97, &ensoniq->u.es1371.ac97)) < 0) |
1643 | return err; | 1663 | return err; |
1644 | for (idx = 0; es1371_spdif_present[idx].vid != (unsigned short)PCI_ANY_ID; idx++) | 1664 | if (has_spdif > 0 || |
1645 | if ((ensoniq->pci->vendor == es1371_spdif_present[idx].vid && | 1665 | (!has_spdif && es1371_quirk_lookup(ensoniq, es1371_spdif_present))) { |
1646 | ensoniq->pci->device == es1371_spdif_present[idx].did && | 1666 | struct snd_kcontrol *kctl; |
1647 | ensoniq->rev == es1371_spdif_present[idx].rev) || has_spdif > 0) { | 1667 | int i, index = 0; |
1648 | struct snd_kcontrol *kctl; | 1668 | |
1649 | int i, index = 0; | 1669 | ensoniq->spdif_default = ensoniq->spdif_stream = |
1650 | 1670 | SNDRV_PCM_DEFAULT_CON_SPDIF; | |
1651 | if (has_spdif < 0) | 1671 | outl(ensoniq->spdif_default, ES_REG(ensoniq, CHANNEL_STATUS)); |
1652 | break; | 1672 | |
1653 | 1673 | if (ensoniq->u.es1371.ac97->ext_id & AC97_EI_SPDIF) | |
1654 | ensoniq->spdif_default = ensoniq->spdif_stream = | 1674 | index++; |
1655 | SNDRV_PCM_DEFAULT_CON_SPDIF; | 1675 | |
1656 | outl(ensoniq->spdif_default, ES_REG(ensoniq, CHANNEL_STATUS)); | 1676 | for (i = 0; i < ARRAY_SIZE(snd_es1371_mixer_spdif); i++) { |
1657 | 1677 | kctl = snd_ctl_new1(&snd_es1371_mixer_spdif[i], ensoniq); | |
1658 | if (ensoniq->u.es1371.ac97->ext_id & AC97_EI_SPDIF) | 1678 | if (!kctl) |
1659 | index++; | 1679 | return -ENOMEM; |
1660 | 1680 | kctl->id.index = index; | |
1661 | for (i = 0; i < (int)ARRAY_SIZE(snd_es1371_mixer_spdif); i++) { | 1681 | err = snd_ctl_add(card, kctl); |
1662 | kctl = snd_ctl_new1(&snd_es1371_mixer_spdif[i], ensoniq); | 1682 | if (err < 0) |
1663 | if (! kctl) | 1683 | return err; |
1664 | return -ENOMEM; | ||
1665 | kctl->id.index = index; | ||
1666 | if ((err = snd_ctl_add(card, kctl)) < 0) | ||
1667 | return err; | ||
1668 | } | ||
1669 | break; | ||
1670 | } | 1684 | } |
1685 | } | ||
1671 | if (ensoniq->u.es1371.ac97->ext_id & AC97_EI_SDAC) { | 1686 | if (ensoniq->u.es1371.ac97->ext_id & AC97_EI_SDAC) { |
1672 | /* mirror rear to front speakers */ | 1687 | /* mirror rear to front speakers */ |
1673 | ensoniq->cssr &= ~(ES_1373_REAR_BIT27|ES_1373_REAR_BIT24); | 1688 | 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 | |||
1676 | if (err < 0) | 1691 | if (err < 0) |
1677 | return err; | 1692 | return err; |
1678 | } | 1693 | } |
1679 | if (((ensoniq->subsystem_vendor_id == 0x1274) && | 1694 | if (has_line > 0 || |
1680 | (ensoniq->subsystem_device_id == 0x2000)) || /* GA-7DXR */ | 1695 | snd_pci_quirk_lookup(ensoniq->pci, ens1373_line_quirk)) { |
1681 | ((ensoniq->subsystem_vendor_id == 0x1458) && | 1696 | err = snd_ctl_add(card, snd_ctl_new1(&snd_ens1373_line, |
1682 | (ensoniq->subsystem_device_id == 0xa000)) || /* GA-8IEXP */ | 1697 | ensoniq)); |
1683 | has_line > 0) { | ||
1684 | err = snd_ctl_add(card, snd_ctl_new1(&snd_ens1373_line, ensoniq)); | ||
1685 | if (err < 0) | 1698 | if (err < 0) |
1686 | return err; | 1699 | return err; |
1687 | } | 1700 | } |
@@ -1956,21 +1969,15 @@ static int snd_ensoniq_dev_free(struct snd_device *device) | |||
1956 | } | 1969 | } |
1957 | 1970 | ||
1958 | #ifdef CHIP1371 | 1971 | #ifdef CHIP1371 |
1959 | static struct { | 1972 | static struct snd_pci_quirk es1371_amplifier_hack[] __devinitdata = { |
1960 | unsigned short svid; /* subsystem vendor ID */ | 1973 | SND_PCI_QUIRK_ID(0x107b, 0x2150), /* Gateway Solo 2150 */ |
1961 | unsigned short sdid; /* subsystem device ID */ | 1974 | SND_PCI_QUIRK_ID(0x13bd, 0x100c), /* EV1938 on Mebius PC-MJ100V */ |
1962 | } es1371_amplifier_hack[] = { | 1975 | SND_PCI_QUIRK_ID(0x1102, 0x5938), /* Targa Xtender300 */ |
1963 | { .svid = 0x107b, .sdid = 0x2150 }, /* Gateway Solo 2150 */ | 1976 | SND_PCI_QUIRK_ID(0x1102, 0x8938), /* IPC Topnote G notebook */ |
1964 | { .svid = 0x13bd, .sdid = 0x100c }, /* EV1938 on Mebius PC-MJ100V */ | 1977 | { } /* end */ |
1965 | { .svid = 0x1102, .sdid = 0x5938 }, /* Targa Xtender300 */ | ||
1966 | { .svid = 0x1102, .sdid = 0x8938 }, /* IPC Topnote G notebook */ | ||
1967 | { .svid = PCI_ANY_ID, .sdid = PCI_ANY_ID } | ||
1968 | }; | 1978 | }; |
1969 | static struct { | 1979 | |
1970 | unsigned short vid; /* vendor ID */ | 1980 | static struct es1371_quirk es1371_ac97_reset_hack[] = { |
1971 | unsigned short did; /* device ID */ | ||
1972 | unsigned char rev; /* revision */ | ||
1973 | } es1371_ac97_reset_hack[] = { | ||
1974 | { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_C }, | 1981 | { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_C }, |
1975 | { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_D }, | 1982 | { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_D }, |
1976 | { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_E }, | 1983 | { .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) | |||
1984 | { | 1991 | { |
1985 | #ifdef CHIP1371 | 1992 | #ifdef CHIP1371 |
1986 | int idx; | 1993 | int idx; |
1987 | struct pci_dev *pci = ensoniq->pci; | ||
1988 | #endif | 1994 | #endif |
1989 | /* this code was part of snd_ensoniq_create before intruduction | 1995 | /* this code was part of snd_ensoniq_create before intruduction |
1990 | * of suspend/resume | 1996 | * of suspend/resume |
@@ -1999,16 +2005,12 @@ static void snd_ensoniq_chip_init(struct ensoniq *ensoniq) | |||
1999 | outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); | 2005 | outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); |
2000 | outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL)); | 2006 | outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL)); |
2001 | outl(0, ES_REG(ensoniq, 1371_LEGACY)); | 2007 | outl(0, ES_REG(ensoniq, 1371_LEGACY)); |
2002 | for (idx = 0; es1371_ac97_reset_hack[idx].vid != (unsigned short)PCI_ANY_ID; idx++) | 2008 | if (es1371_quirk_lookup(ensoniq, es1371_ac97_reset_hack)) { |
2003 | if (pci->vendor == es1371_ac97_reset_hack[idx].vid && | 2009 | outl(ensoniq->cssr, ES_REG(ensoniq, STATUS)); |
2004 | pci->device == es1371_ac97_reset_hack[idx].did && | 2010 | /* need to delay around 20ms(bleech) to give |
2005 | ensoniq->rev == es1371_ac97_reset_hack[idx].rev) { | 2011 | some CODECs enough time to wakeup */ |
2006 | outl(ensoniq->cssr, ES_REG(ensoniq, STATUS)); | 2012 | msleep(20); |
2007 | /* need to delay around 20ms(bleech) to give | 2013 | } |
2008 | some CODECs enough time to wakeup */ | ||
2009 | msleep(20); | ||
2010 | break; | ||
2011 | } | ||
2012 | /* AC'97 warm reset to start the bitclk */ | 2014 | /* AC'97 warm reset to start the bitclk */ |
2013 | outl(ensoniq->ctrl | ES_1371_SYNC_RES, ES_REG(ensoniq, CONTROL)); | 2015 | outl(ensoniq->ctrl | ES_1371_SYNC_RES, ES_REG(ensoniq, CONTROL)); |
2014 | inl(ES_REG(ensoniq, CONTROL)); | 2016 | inl(ES_REG(ensoniq, CONTROL)); |
@@ -2112,11 +2114,7 @@ static int __devinit snd_ensoniq_create(struct snd_card *card, | |||
2112 | struct ensoniq ** rensoniq) | 2114 | struct ensoniq ** rensoniq) |
2113 | { | 2115 | { |
2114 | struct ensoniq *ensoniq; | 2116 | struct ensoniq *ensoniq; |
2115 | unsigned short cmdw; | ||
2116 | unsigned char cmdb; | 2117 | unsigned char cmdb; |
2117 | #ifdef CHIP1371 | ||
2118 | int idx; | ||
2119 | #endif | ||
2120 | int err; | 2118 | int err; |
2121 | static struct snd_device_ops ops = { | 2119 | static struct snd_device_ops ops = { |
2122 | .dev_free = snd_ensoniq_dev_free, | 2120 | .dev_free = snd_ensoniq_dev_free, |
@@ -2159,10 +2157,6 @@ static int __devinit snd_ensoniq_create(struct snd_card *card, | |||
2159 | pci_set_master(pci); | 2157 | pci_set_master(pci); |
2160 | pci_read_config_byte(pci, PCI_REVISION_ID, &cmdb); | 2158 | pci_read_config_byte(pci, PCI_REVISION_ID, &cmdb); |
2161 | ensoniq->rev = cmdb; | 2159 | ensoniq->rev = cmdb; |
2162 | pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &cmdw); | ||
2163 | ensoniq->subsystem_vendor_id = cmdw; | ||
2164 | pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &cmdw); | ||
2165 | ensoniq->subsystem_device_id = cmdw; | ||
2166 | #ifdef CHIP1370 | 2160 | #ifdef CHIP1370 |
2167 | #if 0 | 2161 | #if 0 |
2168 | ensoniq->ctrl = ES_1370_CDC_EN | ES_1370_SERR_DISABLE | | 2162 | ensoniq->ctrl = ES_1370_CDC_EN | ES_1370_SERR_DISABLE | |
@@ -2175,19 +2169,11 @@ static int __devinit snd_ensoniq_create(struct snd_card *card, | |||
2175 | ensoniq->ctrl = 0; | 2169 | ensoniq->ctrl = 0; |
2176 | ensoniq->sctrl = 0; | 2170 | ensoniq->sctrl = 0; |
2177 | ensoniq->cssr = 0; | 2171 | ensoniq->cssr = 0; |
2178 | for (idx = 0; es1371_amplifier_hack[idx].svid != (unsigned short)PCI_ANY_ID; idx++) | 2172 | if (snd_pci_quirk_lookup(pci, es1371_amplifier_hack)) |
2179 | if (ensoniq->subsystem_vendor_id == es1371_amplifier_hack[idx].svid && | 2173 | ensoniq->ctrl |= ES_1371_GPIO_OUT(1); /* turn amplifier on */ |
2180 | ensoniq->subsystem_device_id == es1371_amplifier_hack[idx].sdid) { | 2174 | |
2181 | ensoniq->ctrl |= ES_1371_GPIO_OUT(1); /* turn amplifier on */ | 2175 | if (es1371_quirk_lookup(ensoniq, es1371_ac97_reset_hack)) |
2182 | break; | 2176 | ensoniq->cssr |= ES_1371_ST_AC97_RST; |
2183 | } | ||
2184 | for (idx = 0; es1371_ac97_reset_hack[idx].vid != (unsigned short)PCI_ANY_ID; idx++) | ||
2185 | if (pci->vendor == es1371_ac97_reset_hack[idx].vid && | ||
2186 | pci->device == es1371_ac97_reset_hack[idx].did && | ||
2187 | ensoniq->rev == es1371_ac97_reset_hack[idx].rev) { | ||
2188 | ensoniq->cssr |= ES_1371_ST_AC97_RST; | ||
2189 | break; | ||
2190 | } | ||
2191 | #endif | 2177 | #endif |
2192 | 2178 | ||
2193 | snd_ensoniq_chip_init(ensoniq); | 2179 | snd_ensoniq_chip_init(ensoniq); |