Changeset 679 for GPL/trunk/alsa-kernel/pci/cs4281.c
- Timestamp:
- Mar 18, 2021, 8:57:36 PM (4 years ago)
- Location:
- GPL/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
GPL/trunk
- Property svn:mergeinfo changed
/GPL/branches/uniaud32-linux-3.2.102 (added) merged: 611-614 /GPL/branches/uniaud32-next (added) merged: 615-678
- Property svn:mergeinfo changed
-
GPL/trunk/alsa-kernel/pci/cs4281.c
r598 r679 1 // SPDX-License-Identifier: GPL-2.0-or-later 1 2 /* 2 3 * Driver for Cirrus Logic CS4281 based PCI soundcard 3 4 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>, 4 *5 *6 * This program is free software; you can redistribute it and/or modify7 * it under the terms of the GNU General Public License as published by8 * the Free Software Foundation; either version 2 of the License, or9 * (at your option) any later version.10 *11 * This program is distributed in the hope that it will be useful,12 * but WITHOUT ANY WARRANTY; without even the implied warranty of13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the14 * GNU General Public License for more details.15 *16 * You should have received a copy of the GNU General Public License17 * along with this program; if not, write to the Free Software18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA19 *20 5 */ 21 6 22 #include < asm/io.h>7 #include <linux/io.h> 23 8 #include <linux/delay.h> 24 9 #include <linux/interrupt.h> … … 27 12 #include <linux/slab.h> 28 13 #include <linux/gameport.h> 29 #include <linux/module param.h>14 #include <linux/module.h> 30 15 #include <sound/core.h> 31 16 #include <sound/control.h> … … 38 23 39 24 25 #ifdef TARGET_OS2 26 #define KBUILD_MODNAME "cs4281" 27 #endif 40 28 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); 41 29 MODULE_DESCRIPTION("Cirrus Logic CS4281"); … … 45 33 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ 46 34 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ 47 static intenable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable switches */48 static intdual_codec[SNDRV_CARDS]; /* dual codec */35 static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable switches */ 36 static bool dual_codec[SNDRV_CARDS]; /* dual codec */ 49 37 50 38 module_param_array(index, int, NULL, 0444); … … 487 475 struct gameport *gameport; 488 476 489 #ifdef CONFIG_PM 477 #ifdef CONFIG_PM_SLEEP 490 478 u32 suspend_regs[SUSPEND_REGISTERS]; 491 479 #endif … … 495 483 static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id); 496 484 497 static DEFINE_PCI_DEVICE_TABLE(snd_cs4281_ids)= {485 static const struct pci_device_id snd_cs4281_ids[] = { 498 486 { PCI_VDEVICE(CIRRUS, 0x6005), 0, }, /* CS4281 */ 499 487 { 0, } … … 565 553 } 566 554 } 567 snd_printk(KERN_ERR "AC'97 write problem, reg = 0x%x, val = 0x%x\n", reg, val); 555 dev_err(chip->card->dev, 556 "AC'97 write problem, reg = 0x%x, val = 0x%x\n", reg, val); 568 557 } 569 558 … … 625 614 } 626 615 627 snd_printk(KERN_ERR "AC'97 read problem (ACCTL_DCV), reg = 0x%x\n", reg); 616 dev_err(chip->card->dev, 617 "AC'97 read problem (ACCTL_DCV), reg = 0x%x\n", reg); 628 618 result = 0xffff; 629 619 goto __end; … … 644 634 } 645 635 646 snd_printk(KERN_ERR "AC'97 read problem (ACSTS_VSTS), reg = 0x%x\n", reg); 636 dev_err(chip->card->dev, 637 "AC'97 read problem (ACSTS_VSTS), reg = 0x%x\n", reg); 647 638 result = 0xffff; 648 639 goto __end; … … 707 698 static unsigned int snd_cs4281_rate(unsigned int rate, unsigned int *real_rate) 708 699 { 709 unsigned int val = ~0;700 unsigned int val; 710 701 711 702 if (real_rate) … … 720 711 case 48000: return 0; 721 712 default: 722 goto __variable; 723 } 724 __variable: 713 break; 714 } 725 715 val = 1536000 / rate; 726 716 if (real_rate) … … 794 784 } 795 785 796 static int snd_cs4281_hw_params(struct snd_pcm_substream *substream,797 struct snd_pcm_hw_params *hw_params)798 {799 return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));800 }801 802 static int snd_cs4281_hw_free(struct snd_pcm_substream *substream)803 {804 return snd_pcm_lib_free_pages(substream);805 }806 807 786 static int snd_cs4281_playback_prepare(struct snd_pcm_substream *substream) 808 787 { … … 836 815 837 816 /* 838 printk(KERN_DEBUG "DCC = 0x%x, buffer_size = 0x%x, jiffies = %li\n", 839 snd_cs4281_peekBA0(chip, dma->regDCC), runtime->buffer_size, 817 dev_dbg(chip->card->dev, 818 "DCC = 0x%x, buffer_size = 0x%x, jiffies = %li\n", 819 snd_cs4281_peekBA0(chip, dma->regDCC), runtime->buffer_size, 840 820 jiffies); 841 821 */ … … 844 824 } 845 825 846 static struct snd_pcm_hardware snd_cs4281_playback =826 static const struct snd_pcm_hardware snd_cs4281_playback = 847 827 { 848 828 .info = SNDRV_PCM_INFO_MMAP | … … 869 849 }; 870 850 871 static struct snd_pcm_hardware snd_cs4281_capture =851 static const struct snd_pcm_hardware snd_cs4281_capture = 872 852 { 873 853 .info = SNDRV_PCM_INFO_MMAP | … … 948 928 } 949 929 950 static struct snd_pcm_ops snd_cs4281_playback_ops = {930 static const struct snd_pcm_ops snd_cs4281_playback_ops = { 951 931 .open = snd_cs4281_playback_open, 952 932 .close = snd_cs4281_playback_close, 953 .ioctl = snd_pcm_lib_ioctl,954 .hw_params = snd_cs4281_hw_params,955 .hw_free = snd_cs4281_hw_free,956 933 .prepare = snd_cs4281_playback_prepare, 957 934 .trigger = snd_cs4281_trigger, … … 959 936 }; 960 937 961 static struct snd_pcm_ops snd_cs4281_capture_ops = {938 static const struct snd_pcm_ops snd_cs4281_capture_ops = { 962 939 .open = snd_cs4281_capture_open, 963 940 .close = snd_cs4281_capture_close, 964 .ioctl = snd_pcm_lib_ioctl,965 .hw_params = snd_cs4281_hw_params,966 .hw_free = snd_cs4281_hw_free,967 941 .prepare = snd_cs4281_capture_prepare, 968 942 .trigger = snd_cs4281_trigger, … … 970 944 }; 971 945 972 static int __devinit snd_cs4281_pcm(struct cs4281 * chip, int device, 973 struct snd_pcm ** rpcm) 946 static int snd_cs4281_pcm(struct cs4281 *chip, int device) 974 947 { 975 948 struct snd_pcm *pcm; 976 949 int err; 977 950 978 if (rpcm)979 *rpcm = NULL;980 951 err = snd_pcm_new(chip->card, "CS4281", device, 1, 1, &pcm); 981 952 if (err < 0) … … 990 961 chip->pcm = pcm; 991 962 992 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, 993 snd_dma_pci_data(chip->pci), 64*1024, 512*1024); 994 995 if (rpcm) 996 *rpcm = pcm; 963 snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, &chip->pci->dev, 964 64*1024, 512*1024); 965 997 966 return 0; 998 967 } … … 1057 1026 static const DECLARE_TLV_DB_SCALE(db_scale_dsp, -4650, 150, 0); 1058 1027 1059 static struct snd_kcontrol_new snd_cs4281_fm_vol =1028 static const struct snd_kcontrol_new snd_cs4281_fm_vol = 1060 1029 { 1061 1030 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, … … 1068 1037 }; 1069 1038 1070 static struct snd_kcontrol_new snd_cs4281_pcm_vol =1039 static const struct snd_kcontrol_new snd_cs4281_pcm_vol = 1071 1040 { 1072 1041 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, … … 1094 1063 } 1095 1064 1096 static int __devinit snd_cs4281_mixer(struct cs4281 *chip)1065 static int snd_cs4281_mixer(struct cs4281 *chip) 1097 1066 { 1098 1067 struct snd_card *card = chip->card; 1099 1068 struct snd_ac97_template ac97; 1100 1069 int err; 1101 static struct snd_ac97_bus_ops ops = {1070 static const struct snd_ac97_bus_ops ops = { 1102 1071 .write = snd_cs4281_ac97_write, 1103 1072 .read = snd_cs4281_ac97_read, … … 1164 1133 } 1165 1134 1166 static struct snd_info_entry_ops snd_cs4281_proc_ops_BA0 = {1135 static const struct snd_info_entry_ops snd_cs4281_proc_ops_BA0 = { 1167 1136 .read = snd_cs4281_BA0_read, 1168 1137 }; 1169 1138 1170 static struct snd_info_entry_ops snd_cs4281_proc_ops_BA1 = {1139 static const struct snd_info_entry_ops snd_cs4281_proc_ops_BA1 = { 1171 1140 .read = snd_cs4281_BA1_read, 1172 1141 }; 1173 1142 1174 static void __devinit snd_cs4281_proc_init(struct cs4281 *chip)1143 static void snd_cs4281_proc_init(struct cs4281 *chip) 1175 1144 { 1176 1145 struct snd_info_entry *entry; 1177 1146 1178 if (! snd_card_proc_new(chip->card, "cs4281", &entry)) 1179 snd_info_set_text_ops(entry, chip, snd_cs4281_proc_read); 1147 snd_card_ro_proc_new(chip->card, "cs4281", chip, snd_cs4281_proc_read); 1180 1148 if (! snd_card_proc_new(chip->card, "cs4281_BA0", &entry)) { 1181 1149 entry->content = SNDRV_INFO_CONTENT_DATA; … … 1196 1164 */ 1197 1165 1198 #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))1166 #if IS_REACHABLE(CONFIG_GAMEPORT) 1199 1167 1200 1168 static void snd_cs4281_gameport_trigger(struct gameport *gameport) … … 1260 1228 } 1261 1229 1262 static int __devinitsnd_cs4281_create_gameport(struct cs4281 *chip)1230 static int snd_cs4281_create_gameport(struct cs4281 *chip) 1263 1231 { 1264 1232 struct gameport *gp; … … 1266 1234 chip->gameport = gp = gameport_allocate_port(); 1267 1235 if (!gp) { 1268 printk(KERN_ERR "cs4281: cannot allocate memory for gameport\n"); 1236 dev_err(chip->card->dev, 1237 "cannot allocate memory for gameport\n"); 1269 1238 return -ENOMEM; 1270 1239 } … … 1297 1266 static inline int snd_cs4281_create_gameport(struct cs4281 *chip) { return -ENOSYS; } 1298 1267 static inline void snd_cs4281_free_gameport(struct cs4281 *chip) { } 1299 #endif /* CONFIG_GAMEPORT || (MODULE && CONFIG_GAMEPORT_MODULE) */1268 #endif /* IS_REACHABLE(CONFIG_GAMEPORT) */ 1300 1269 1301 1270 static int snd_cs4281_free(struct cs4281 *chip) 1302 1271 { 1303 1272 snd_cs4281_free_gameport(chip); 1304 1305 if (chip->irq >= 0)1306 synchronize_irq(chip->irq);1307 1273 1308 1274 /* Mask interrupts */ … … 1313 1279 snd_cs4281_pokeBA0(chip, BA0_SSPM, 0); 1314 1280 /* PCI interface - D3 state */ 1315 pci_set_power_state(chip->pci, 3);1281 pci_set_power_state(chip->pci, PCI_D3hot); 1316 1282 1317 1283 if (chip->irq >= 0) 1318 1284 free_irq(chip->irq, chip); 1319 if (chip->ba0) 1320 iounmap(chip->ba0); 1321 if (chip->ba1) 1322 iounmap(chip->ba1); 1285 iounmap(chip->ba0); 1286 iounmap(chip->ba1); 1323 1287 pci_release_regions(chip->pci); 1324 1288 pci_disable_device(chip->pci); … … 1336 1300 static int snd_cs4281_chip_init(struct cs4281 *chip); /* defined below */ 1337 1301 1338 static int __devinitsnd_cs4281_create(struct snd_card *card,1339 1340 struct cs4281 **rchip,1341 1302 static int snd_cs4281_create(struct snd_card *card, 1303 struct pci_dev *pci, 1304 struct cs4281 **rchip, 1305 int dual_codec) 1342 1306 { 1343 1307 struct cs4281 *chip; 1344 1308 unsigned int tmp; 1345 1309 int err; 1346 static struct snd_device_ops ops = {1310 static const struct snd_device_ops ops = { 1347 1311 .dev_free = snd_cs4281_dev_free, 1348 1312 }; … … 1362 1326 pci_set_master(pci); 1363 1327 if (dual_codec < 0 || dual_codec > 3) { 1364 snd_printk(KERN_ERR"invalid dual_codec option %d\n", dual_codec);1328 dev_err(card->dev, "invalid dual_codec option %d\n", dual_codec); 1365 1329 dual_codec = 0; 1366 1330 } … … 1383 1347 1384 1348 if (request_irq(pci->irq, snd_cs4281_interrupt, IRQF_SHARED, 1385 "CS4281", chip)) {1386 snd_printk(KERN_ERR"unable to grab IRQ %d\n", pci->irq);1349 KBUILD_MODNAME, chip)) { 1350 dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); 1387 1351 snd_cs4281_free(chip); 1388 1352 return -ENOMEM; 1389 1353 } 1390 1354 chip->irq = pci->irq; 1355 card->sync_irq = chip->irq; 1391 1356 1392 1357 tmp = snd_cs4281_chip_init(chip); … … 1402 1367 1403 1368 snd_cs4281_proc_init(chip); 1404 1405 snd_card_set_dev(card, &pci->dev);1406 1369 1407 1370 *rchip = chip; … … 1426 1389 tmp = snd_cs4281_peekBA0(chip, BA0_CFLR); 1427 1390 if (tmp != BA0_CFLR_DEFAULT) { 1428 snd_printk(KERN_ERR "CFLR setup failed (0x%x)\n", tmp); 1391 dev_err(chip->card->dev, 1392 "CFLR setup failed (0x%x)\n", tmp); 1429 1393 return -EIO; 1430 1394 } … … 1437 1401 1438 1402 if ((tmp = snd_cs4281_peekBA0(chip, BA0_SERC1)) != (BA0_SERC1_SO1EN | BA0_SERC1_AC97)) { 1439 snd_printk(KERN_ERR "SERC1 AC'97 check failed (0x%x)\n", tmp); 1403 dev_err(chip->card->dev, 1404 "SERC1 AC'97 check failed (0x%x)\n", tmp); 1440 1405 return -EIO; 1441 1406 } 1442 1407 if ((tmp = snd_cs4281_peekBA0(chip, BA0_SERC2)) != (BA0_SERC2_SI1EN | BA0_SERC2_AC97)) { 1443 snd_printk(KERN_ERR "SERC2 AC'97 check failed (0x%x)\n", tmp); 1408 dev_err(chip->card->dev, 1409 "SERC2 AC'97 check failed (0x%x)\n", tmp); 1444 1410 return -EIO; 1445 1411 } … … 1503 1469 } while (time_after_eq(end_time, jiffies)); 1504 1470 1505 snd_printk(KERN_ERR"DLLRDY not seen\n");1471 dev_err(chip->card->dev, "DLLRDY not seen\n"); 1506 1472 return -EIO; 1507 1473 … … 1529 1495 } while (time_after_eq(end_time, jiffies)); 1530 1496 1531 snd_printk(KERN_ERR "never read codec ready from AC'97 (0x%x)\n", snd_cs4281_peekBA0(chip, BA0_ACSTS)); 1497 dev_err(chip->card->dev, 1498 "never read codec ready from AC'97 (0x%x)\n", 1499 snd_cs4281_peekBA0(chip, BA0_ACSTS)); 1532 1500 return -EIO; 1533 1501 … … 1540 1508 schedule_timeout_uninterruptible(1); 1541 1509 } while (time_after_eq(end_time, jiffies)); 1542 snd_printk(KERN_INFO "secondary codec doesn't respond. disable it...\n"); 1510 dev_info(chip->card->dev, 1511 "secondary codec doesn't respond. disable it...\n"); 1543 1512 chip->dual_codec = 0; 1544 1513 __codec2_ok: ; … … 1570 1539 if (--retry_count > 0) 1571 1540 goto __retry; 1572 snd_printk(KERN_ERR"never read ISV3 and ISV4 from AC'97\n");1541 dev_err(chip->card->dev, "never read ISV3 and ISV4 from AC'97\n"); 1573 1542 return -EIO; 1574 1543 … … 1633 1602 BA0_HISR_DMA(2) | 1634 1603 BA0_HISR_DMA(3))); 1635 synchronize_irq(chip->irq);1636 1604 1637 1605 return 0; … … 1766 1734 } 1767 1735 1768 static struct snd_rawmidi_ops snd_cs4281_midi_output =1736 static const struct snd_rawmidi_ops snd_cs4281_midi_output = 1769 1737 { 1770 1738 .open = snd_cs4281_midi_output_open, … … 1773 1741 }; 1774 1742 1775 static struct snd_rawmidi_ops snd_cs4281_midi_input =1743 static const struct snd_rawmidi_ops snd_cs4281_midi_input = 1776 1744 { 1777 1745 .open = snd_cs4281_midi_input_open, … … 1780 1748 }; 1781 1749 1782 static int __devinit snd_cs4281_midi(struct cs4281 * chip, int device, 1783 struct snd_rawmidi **rrawmidi) 1750 static int snd_cs4281_midi(struct cs4281 *chip, int device) 1784 1751 { 1785 1752 struct snd_rawmidi *rmidi; 1786 1753 int err; 1787 1754 1788 if (rrawmidi)1789 *rrawmidi = NULL;1790 1755 if ((err = snd_rawmidi_new(chip->card, "CS4281", device, 1, 1, &rmidi)) < 0) 1791 1756 return err; … … 1796 1761 rmidi->private_data = chip; 1797 1762 chip->rmidi = rmidi; 1798 if (rrawmidi)1799 *rrawmidi = rmidi;1800 1763 return 0; 1801 1764 } … … 1902 1865 } 1903 1866 1904 static int __devinitsnd_cs4281_probe(struct pci_dev *pci,1905 1867 static int snd_cs4281_probe(struct pci_dev *pci, 1868 const struct pci_device_id *pci_id) 1906 1869 { 1907 1870 static int dev; … … 1918 1881 } 1919 1882 1920 err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); 1883 err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, 1884 0, &card); 1921 1885 if (err < 0) 1922 1886 return err; … … 1932 1896 return err; 1933 1897 } 1934 if ((err = snd_cs4281_pcm(chip, 0 , NULL)) < 0) {1898 if ((err = snd_cs4281_pcm(chip, 0)) < 0) { 1935 1899 snd_card_free(card); 1936 1900 return err; 1937 1901 } 1938 if ((err = snd_cs4281_midi(chip, 0 , NULL)) < 0) {1902 if ((err = snd_cs4281_midi(chip, 0)) < 0) { 1939 1903 snd_card_free(card); 1940 1904 return err; … … 1969 1933 } 1970 1934 1971 static void __devexitsnd_cs4281_remove(struct pci_dev *pci)1935 static void snd_cs4281_remove(struct pci_dev *pci) 1972 1936 { 1973 1937 snd_card_free(pci_get_drvdata(pci)); 1974 pci_set_drvdata(pci, NULL);1975 1938 } 1976 1939 … … 1978 1941 * Power Management 1979 1942 */ 1980 #ifdef CONFIG_PM 1981 1982 static int saved_regs[SUSPEND_REGISTERS] = {1943 #ifdef CONFIG_PM_SLEEP 1944 1945 static const int saved_regs[SUSPEND_REGISTERS] = { 1983 1946 BA0_JSCTL, 1984 1947 BA0_GPIOR, … … 1998 1961 #define CLKCR1_CKRA 0x00010000L 1999 1962 2000 static int cs4281_suspend(struct pci_dev *pci, pm_message_t state)2001 { 2002 struct snd_card *card = pci_get_drvdata(pci);1963 static int cs4281_suspend(struct device *dev) 1964 { 1965 struct snd_card *card = dev_get_drvdata(dev); 2003 1966 struct cs4281 *chip = card->private_data; 2004 1967 u32 ulCLK; … … 2006 1969 2007 1970 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); 2008 snd_pcm_suspend_all(chip->pcm);2009 2010 1971 snd_ac97_suspend(chip->ac97); 2011 1972 snd_ac97_suspend(chip->ac97_secondary); … … 2038 1999 ulCLK &= ~CLKCR1_CKRA; 2039 2000 snd_cs4281_pokeBA0(chip, BA0_CLKCR1, ulCLK); 2040 2041 pci_disable_device(pci); 2042 pci_save_state(pci); 2043 pci_set_power_state(pci, pci_choose_state(pci, state)); 2044 return 0; 2045 } 2046 2047 static int cs4281_resume(struct pci_dev *pci) 2048 { 2049 struct snd_card *card = pci_get_drvdata(pci); 2001 return 0; 2002 } 2003 2004 static int cs4281_resume(struct device *dev) 2005 { 2006 struct snd_card *card = dev_get_drvdata(dev); 2050 2007 struct cs4281 *chip = card->private_data; 2051 2008 unsigned int i; 2052 2009 u32 ulCLK; 2053 2054 pci_set_power_state(pci, PCI_D0);2055 pci_restore_state(pci);2056 if (pci_enable_device(pci) < 0) {2057 printk(KERN_ERR "cs4281: pci_enable_device failed, "2058 "disabling device\n");2059 snd_card_disconnect(card);2060 return -EIO;2061 }2062 pci_set_master(pci);2063 2010 2064 2011 ulCLK = snd_cs4281_peekBA0(chip, BA0_CLKCR1); … … 2083 2030 return 0; 2084 2031 } 2085 #endif /* CONFIG_PM */ 2086 2087 static struct pci_driver driver = { 2088 .name = "CS4281", 2032 2033 static SIMPLE_DEV_PM_OPS(cs4281_pm, cs4281_suspend, cs4281_resume); 2034 #define CS4281_PM_OPS &cs4281_pm 2035 #else 2036 #define CS4281_PM_OPS NULL 2037 #endif /* CONFIG_PM_SLEEP */ 2038 2039 static struct pci_driver cs4281_driver = { 2040 .name = KBUILD_MODNAME, 2089 2041 .id_table = snd_cs4281_ids, 2090 2042 .probe = snd_cs4281_probe, 2091 .remove = __devexit_p(snd_cs4281_remove), 2092 #ifdef CONFIG_PM 2093 .suspend = cs4281_suspend, 2094 .resume = cs4281_resume, 2095 #endif 2043 .remove = snd_cs4281_remove, 2044 .driver = { 2045 .pm = CS4281_PM_OPS, 2046 }, 2096 2047 }; 2097 2048 2098 static int __init alsa_card_cs4281_init(void) 2099 { 2100 return pci_register_driver(&driver); 2101 } 2102 2103 static void __exit alsa_card_cs4281_exit(void) 2104 { 2105 pci_unregister_driver(&driver); 2106 } 2107 2108 module_init(alsa_card_cs4281_init) 2109 module_exit(alsa_card_cs4281_exit) 2049 module_pci_driver(cs4281_driver);
Note:
See TracChangeset
for help on using the changeset viewer.