1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * The driver for the Yamaha's DS1/DS1E cards
4*4882a593Smuzhiyun * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include <linux/init.h>
8*4882a593Smuzhiyun #include <linux/pci.h>
9*4882a593Smuzhiyun #include <linux/time.h>
10*4882a593Smuzhiyun #include <linux/module.h>
11*4882a593Smuzhiyun #include <sound/core.h>
12*4882a593Smuzhiyun #include "ymfpci.h"
13*4882a593Smuzhiyun #include <sound/mpu401.h>
14*4882a593Smuzhiyun #include <sound/opl3.h>
15*4882a593Smuzhiyun #include <sound/initval.h>
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
18*4882a593Smuzhiyun MODULE_DESCRIPTION("Yamaha DS-1 PCI");
19*4882a593Smuzhiyun MODULE_LICENSE("GPL");
20*4882a593Smuzhiyun MODULE_SUPPORTED_DEVICE("{{Yamaha,YMF724},"
21*4882a593Smuzhiyun "{Yamaha,YMF724F},"
22*4882a593Smuzhiyun "{Yamaha,YMF740},"
23*4882a593Smuzhiyun "{Yamaha,YMF740C},"
24*4882a593Smuzhiyun "{Yamaha,YMF744},"
25*4882a593Smuzhiyun "{Yamaha,YMF754}}");
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
28*4882a593Smuzhiyun static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
29*4882a593Smuzhiyun static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
30*4882a593Smuzhiyun static long fm_port[SNDRV_CARDS];
31*4882a593Smuzhiyun static long mpu_port[SNDRV_CARDS];
32*4882a593Smuzhiyun #ifdef SUPPORT_JOYSTICK
33*4882a593Smuzhiyun static long joystick_port[SNDRV_CARDS];
34*4882a593Smuzhiyun #endif
35*4882a593Smuzhiyun static bool rear_switch[SNDRV_CARDS];
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun module_param_array(index, int, NULL, 0444);
38*4882a593Smuzhiyun MODULE_PARM_DESC(index, "Index value for the Yamaha DS-1 PCI soundcard.");
39*4882a593Smuzhiyun module_param_array(id, charp, NULL, 0444);
40*4882a593Smuzhiyun MODULE_PARM_DESC(id, "ID string for the Yamaha DS-1 PCI soundcard.");
41*4882a593Smuzhiyun module_param_array(enable, bool, NULL, 0444);
42*4882a593Smuzhiyun MODULE_PARM_DESC(enable, "Enable Yamaha DS-1 soundcard.");
43*4882a593Smuzhiyun module_param_hw_array(mpu_port, long, ioport, NULL, 0444);
44*4882a593Smuzhiyun MODULE_PARM_DESC(mpu_port, "MPU-401 Port.");
45*4882a593Smuzhiyun module_param_hw_array(fm_port, long, ioport, NULL, 0444);
46*4882a593Smuzhiyun MODULE_PARM_DESC(fm_port, "FM OPL-3 Port.");
47*4882a593Smuzhiyun #ifdef SUPPORT_JOYSTICK
48*4882a593Smuzhiyun module_param_hw_array(joystick_port, long, ioport, NULL, 0444);
49*4882a593Smuzhiyun MODULE_PARM_DESC(joystick_port, "Joystick port address");
50*4882a593Smuzhiyun #endif
51*4882a593Smuzhiyun module_param_array(rear_switch, bool, NULL, 0444);
52*4882a593Smuzhiyun MODULE_PARM_DESC(rear_switch, "Enable shared rear/line-in switch");
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun static const struct pci_device_id snd_ymfpci_ids[] = {
55*4882a593Smuzhiyun { PCI_VDEVICE(YAMAHA, 0x0004), 0, }, /* YMF724 */
56*4882a593Smuzhiyun { PCI_VDEVICE(YAMAHA, 0x000d), 0, }, /* YMF724F */
57*4882a593Smuzhiyun { PCI_VDEVICE(YAMAHA, 0x000a), 0, }, /* YMF740 */
58*4882a593Smuzhiyun { PCI_VDEVICE(YAMAHA, 0x000c), 0, }, /* YMF740C */
59*4882a593Smuzhiyun { PCI_VDEVICE(YAMAHA, 0x0010), 0, }, /* YMF744 */
60*4882a593Smuzhiyun { PCI_VDEVICE(YAMAHA, 0x0012), 0, }, /* YMF754 */
61*4882a593Smuzhiyun { 0, }
62*4882a593Smuzhiyun };
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun MODULE_DEVICE_TABLE(pci, snd_ymfpci_ids);
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun #ifdef SUPPORT_JOYSTICK
snd_ymfpci_create_gameport(struct snd_ymfpci * chip,int dev,int legacy_ctrl,int legacy_ctrl2)67*4882a593Smuzhiyun static int snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev,
68*4882a593Smuzhiyun int legacy_ctrl, int legacy_ctrl2)
69*4882a593Smuzhiyun {
70*4882a593Smuzhiyun struct gameport *gp;
71*4882a593Smuzhiyun struct resource *r = NULL;
72*4882a593Smuzhiyun int io_port = joystick_port[dev];
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun if (!io_port)
75*4882a593Smuzhiyun return -ENODEV;
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun if (chip->pci->device >= 0x0010) { /* YMF 744/754 */
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun if (io_port == 1) {
80*4882a593Smuzhiyun /* auto-detect */
81*4882a593Smuzhiyun if (!(io_port = pci_resource_start(chip->pci, 2)))
82*4882a593Smuzhiyun return -ENODEV;
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun } else {
85*4882a593Smuzhiyun if (io_port == 1) {
86*4882a593Smuzhiyun /* auto-detect */
87*4882a593Smuzhiyun for (io_port = 0x201; io_port <= 0x205; io_port++) {
88*4882a593Smuzhiyun if (io_port == 0x203)
89*4882a593Smuzhiyun continue;
90*4882a593Smuzhiyun if ((r = request_region(io_port, 1, "YMFPCI gameport")) != NULL)
91*4882a593Smuzhiyun break;
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun if (!r) {
94*4882a593Smuzhiyun dev_err(chip->card->dev,
95*4882a593Smuzhiyun "no gameport ports available\n");
96*4882a593Smuzhiyun return -EBUSY;
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun }
99*4882a593Smuzhiyun switch (io_port) {
100*4882a593Smuzhiyun case 0x201: legacy_ctrl2 |= 0 << 6; break;
101*4882a593Smuzhiyun case 0x202: legacy_ctrl2 |= 1 << 6; break;
102*4882a593Smuzhiyun case 0x204: legacy_ctrl2 |= 2 << 6; break;
103*4882a593Smuzhiyun case 0x205: legacy_ctrl2 |= 3 << 6; break;
104*4882a593Smuzhiyun default:
105*4882a593Smuzhiyun dev_err(chip->card->dev,
106*4882a593Smuzhiyun "invalid joystick port %#x", io_port);
107*4882a593Smuzhiyun return -EINVAL;
108*4882a593Smuzhiyun }
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun if (!r && !(r = request_region(io_port, 1, "YMFPCI gameport"))) {
112*4882a593Smuzhiyun dev_err(chip->card->dev,
113*4882a593Smuzhiyun "joystick port %#x is in use.\n", io_port);
114*4882a593Smuzhiyun return -EBUSY;
115*4882a593Smuzhiyun }
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun chip->gameport = gp = gameport_allocate_port();
118*4882a593Smuzhiyun if (!gp) {
119*4882a593Smuzhiyun dev_err(chip->card->dev,
120*4882a593Smuzhiyun "cannot allocate memory for gameport\n");
121*4882a593Smuzhiyun release_and_free_resource(r);
122*4882a593Smuzhiyun return -ENOMEM;
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun gameport_set_name(gp, "Yamaha YMF Gameport");
127*4882a593Smuzhiyun gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
128*4882a593Smuzhiyun gameport_set_dev_parent(gp, &chip->pci->dev);
129*4882a593Smuzhiyun gp->io = io_port;
130*4882a593Smuzhiyun gameport_set_port_data(gp, r);
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun if (chip->pci->device >= 0x0010) /* YMF 744/754 */
133*4882a593Smuzhiyun pci_write_config_word(chip->pci, PCIR_DSXG_JOYBASE, io_port);
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun pci_write_config_word(chip->pci, PCIR_DSXG_LEGACY, legacy_ctrl | YMFPCI_LEGACY_JPEN);
136*4882a593Smuzhiyun pci_write_config_word(chip->pci, PCIR_DSXG_ELEGACY, legacy_ctrl2);
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun gameport_register_port(chip->gameport);
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun return 0;
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun
snd_ymfpci_free_gameport(struct snd_ymfpci * chip)143*4882a593Smuzhiyun void snd_ymfpci_free_gameport(struct snd_ymfpci *chip)
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun if (chip->gameport) {
146*4882a593Smuzhiyun struct resource *r = gameport_get_port_data(chip->gameport);
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun gameport_unregister_port(chip->gameport);
149*4882a593Smuzhiyun chip->gameport = NULL;
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun release_and_free_resource(r);
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun #else
snd_ymfpci_create_gameport(struct snd_ymfpci * chip,int dev,int l,int l2)155*4882a593Smuzhiyun static inline int snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev, int l, int l2) { return -ENOSYS; }
snd_ymfpci_free_gameport(struct snd_ymfpci * chip)156*4882a593Smuzhiyun void snd_ymfpci_free_gameport(struct snd_ymfpci *chip) { }
157*4882a593Smuzhiyun #endif /* SUPPORT_JOYSTICK */
158*4882a593Smuzhiyun
snd_card_ymfpci_probe(struct pci_dev * pci,const struct pci_device_id * pci_id)159*4882a593Smuzhiyun static int snd_card_ymfpci_probe(struct pci_dev *pci,
160*4882a593Smuzhiyun const struct pci_device_id *pci_id)
161*4882a593Smuzhiyun {
162*4882a593Smuzhiyun static int dev;
163*4882a593Smuzhiyun struct snd_card *card;
164*4882a593Smuzhiyun struct resource *fm_res = NULL;
165*4882a593Smuzhiyun struct resource *mpu_res = NULL;
166*4882a593Smuzhiyun struct snd_ymfpci *chip;
167*4882a593Smuzhiyun struct snd_opl3 *opl3;
168*4882a593Smuzhiyun const char *str, *model;
169*4882a593Smuzhiyun int err;
170*4882a593Smuzhiyun u16 legacy_ctrl, legacy_ctrl2, old_legacy_ctrl;
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun if (dev >= SNDRV_CARDS)
173*4882a593Smuzhiyun return -ENODEV;
174*4882a593Smuzhiyun if (!enable[dev]) {
175*4882a593Smuzhiyun dev++;
176*4882a593Smuzhiyun return -ENOENT;
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
180*4882a593Smuzhiyun 0, &card);
181*4882a593Smuzhiyun if (err < 0)
182*4882a593Smuzhiyun return err;
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun switch (pci_id->device) {
185*4882a593Smuzhiyun case 0x0004: str = "YMF724"; model = "DS-1"; break;
186*4882a593Smuzhiyun case 0x000d: str = "YMF724F"; model = "DS-1"; break;
187*4882a593Smuzhiyun case 0x000a: str = "YMF740"; model = "DS-1L"; break;
188*4882a593Smuzhiyun case 0x000c: str = "YMF740C"; model = "DS-1L"; break;
189*4882a593Smuzhiyun case 0x0010: str = "YMF744"; model = "DS-1S"; break;
190*4882a593Smuzhiyun case 0x0012: str = "YMF754"; model = "DS-1E"; break;
191*4882a593Smuzhiyun default: model = str = "???"; break;
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun legacy_ctrl = 0;
195*4882a593Smuzhiyun legacy_ctrl2 = 0x0800; /* SBEN = 0, SMOD = 01, LAD = 0 */
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun if (pci_id->device >= 0x0010) { /* YMF 744/754 */
198*4882a593Smuzhiyun if (fm_port[dev] == 1) {
199*4882a593Smuzhiyun /* auto-detect */
200*4882a593Smuzhiyun fm_port[dev] = pci_resource_start(pci, 1);
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun if (fm_port[dev] > 0 &&
203*4882a593Smuzhiyun (fm_res = request_region(fm_port[dev], 4, "YMFPCI OPL3")) != NULL) {
204*4882a593Smuzhiyun legacy_ctrl |= YMFPCI_LEGACY_FMEN;
205*4882a593Smuzhiyun pci_write_config_word(pci, PCIR_DSXG_FMBASE, fm_port[dev]);
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun if (mpu_port[dev] == 1) {
208*4882a593Smuzhiyun /* auto-detect */
209*4882a593Smuzhiyun mpu_port[dev] = pci_resource_start(pci, 1) + 0x20;
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun if (mpu_port[dev] > 0 &&
212*4882a593Smuzhiyun (mpu_res = request_region(mpu_port[dev], 2, "YMFPCI MPU401")) != NULL) {
213*4882a593Smuzhiyun legacy_ctrl |= YMFPCI_LEGACY_MEN;
214*4882a593Smuzhiyun pci_write_config_word(pci, PCIR_DSXG_MPU401BASE, mpu_port[dev]);
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun } else {
217*4882a593Smuzhiyun switch (fm_port[dev]) {
218*4882a593Smuzhiyun case 0x388: legacy_ctrl2 |= 0; break;
219*4882a593Smuzhiyun case 0x398: legacy_ctrl2 |= 1; break;
220*4882a593Smuzhiyun case 0x3a0: legacy_ctrl2 |= 2; break;
221*4882a593Smuzhiyun case 0x3a8: legacy_ctrl2 |= 3; break;
222*4882a593Smuzhiyun default: fm_port[dev] = 0; break;
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun if (fm_port[dev] > 0 &&
225*4882a593Smuzhiyun (fm_res = request_region(fm_port[dev], 4, "YMFPCI OPL3")) != NULL) {
226*4882a593Smuzhiyun legacy_ctrl |= YMFPCI_LEGACY_FMEN;
227*4882a593Smuzhiyun } else {
228*4882a593Smuzhiyun legacy_ctrl2 &= ~YMFPCI_LEGACY2_FMIO;
229*4882a593Smuzhiyun fm_port[dev] = 0;
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun switch (mpu_port[dev]) {
232*4882a593Smuzhiyun case 0x330: legacy_ctrl2 |= 0 << 4; break;
233*4882a593Smuzhiyun case 0x300: legacy_ctrl2 |= 1 << 4; break;
234*4882a593Smuzhiyun case 0x332: legacy_ctrl2 |= 2 << 4; break;
235*4882a593Smuzhiyun case 0x334: legacy_ctrl2 |= 3 << 4; break;
236*4882a593Smuzhiyun default: mpu_port[dev] = 0; break;
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun if (mpu_port[dev] > 0 &&
239*4882a593Smuzhiyun (mpu_res = request_region(mpu_port[dev], 2, "YMFPCI MPU401")) != NULL) {
240*4882a593Smuzhiyun legacy_ctrl |= YMFPCI_LEGACY_MEN;
241*4882a593Smuzhiyun } else {
242*4882a593Smuzhiyun legacy_ctrl2 &= ~YMFPCI_LEGACY2_MPUIO;
243*4882a593Smuzhiyun mpu_port[dev] = 0;
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun if (mpu_res) {
247*4882a593Smuzhiyun legacy_ctrl |= YMFPCI_LEGACY_MIEN;
248*4882a593Smuzhiyun legacy_ctrl2 |= YMFPCI_LEGACY2_IMOD;
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun pci_read_config_word(pci, PCIR_DSXG_LEGACY, &old_legacy_ctrl);
251*4882a593Smuzhiyun pci_write_config_word(pci, PCIR_DSXG_LEGACY, legacy_ctrl);
252*4882a593Smuzhiyun pci_write_config_word(pci, PCIR_DSXG_ELEGACY, legacy_ctrl2);
253*4882a593Smuzhiyun if ((err = snd_ymfpci_create(card, pci,
254*4882a593Smuzhiyun old_legacy_ctrl,
255*4882a593Smuzhiyun &chip)) < 0) {
256*4882a593Smuzhiyun release_and_free_resource(mpu_res);
257*4882a593Smuzhiyun release_and_free_resource(fm_res);
258*4882a593Smuzhiyun goto free_card;
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun chip->fm_res = fm_res;
261*4882a593Smuzhiyun chip->mpu_res = mpu_res;
262*4882a593Smuzhiyun card->private_data = chip;
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun strcpy(card->driver, str);
265*4882a593Smuzhiyun sprintf(card->shortname, "Yamaha %s (%s)", model, str);
266*4882a593Smuzhiyun sprintf(card->longname, "%s at 0x%lx, irq %i",
267*4882a593Smuzhiyun card->shortname,
268*4882a593Smuzhiyun chip->reg_area_phys,
269*4882a593Smuzhiyun chip->irq);
270*4882a593Smuzhiyun err = snd_ymfpci_pcm(chip, 0);
271*4882a593Smuzhiyun if (err < 0)
272*4882a593Smuzhiyun goto free_card;
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun err = snd_ymfpci_pcm_spdif(chip, 1);
275*4882a593Smuzhiyun if (err < 0)
276*4882a593Smuzhiyun goto free_card;
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun err = snd_ymfpci_mixer(chip, rear_switch[dev]);
279*4882a593Smuzhiyun if (err < 0)
280*4882a593Smuzhiyun goto free_card;
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun if (chip->ac97->ext_id & AC97_EI_SDAC) {
283*4882a593Smuzhiyun err = snd_ymfpci_pcm_4ch(chip, 2);
284*4882a593Smuzhiyun if (err < 0)
285*4882a593Smuzhiyun goto free_card;
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun err = snd_ymfpci_pcm2(chip, 3);
288*4882a593Smuzhiyun if (err < 0)
289*4882a593Smuzhiyun goto free_card;
290*4882a593Smuzhiyun }
291*4882a593Smuzhiyun err = snd_ymfpci_timer(chip, 0);
292*4882a593Smuzhiyun if (err < 0)
293*4882a593Smuzhiyun goto free_card;
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun if (chip->mpu_res) {
296*4882a593Smuzhiyun if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_YMFPCI,
297*4882a593Smuzhiyun mpu_port[dev],
298*4882a593Smuzhiyun MPU401_INFO_INTEGRATED |
299*4882a593Smuzhiyun MPU401_INFO_IRQ_HOOK,
300*4882a593Smuzhiyun -1, &chip->rawmidi)) < 0) {
301*4882a593Smuzhiyun dev_warn(card->dev,
302*4882a593Smuzhiyun "cannot initialize MPU401 at 0x%lx, skipping...\n",
303*4882a593Smuzhiyun mpu_port[dev]);
304*4882a593Smuzhiyun legacy_ctrl &= ~YMFPCI_LEGACY_MIEN; /* disable MPU401 irq */
305*4882a593Smuzhiyun pci_write_config_word(pci, PCIR_DSXG_LEGACY, legacy_ctrl);
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun }
308*4882a593Smuzhiyun if (chip->fm_res) {
309*4882a593Smuzhiyun if ((err = snd_opl3_create(card,
310*4882a593Smuzhiyun fm_port[dev],
311*4882a593Smuzhiyun fm_port[dev] + 2,
312*4882a593Smuzhiyun OPL3_HW_OPL3, 1, &opl3)) < 0) {
313*4882a593Smuzhiyun dev_warn(card->dev,
314*4882a593Smuzhiyun "cannot initialize FM OPL3 at 0x%lx, skipping...\n",
315*4882a593Smuzhiyun fm_port[dev]);
316*4882a593Smuzhiyun legacy_ctrl &= ~YMFPCI_LEGACY_FMEN;
317*4882a593Smuzhiyun pci_write_config_word(pci, PCIR_DSXG_LEGACY, legacy_ctrl);
318*4882a593Smuzhiyun } else if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
319*4882a593Smuzhiyun dev_err(card->dev, "cannot create opl3 hwdep\n");
320*4882a593Smuzhiyun goto free_card;
321*4882a593Smuzhiyun }
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun snd_ymfpci_create_gameport(chip, dev, legacy_ctrl, legacy_ctrl2);
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun err = snd_card_register(card);
327*4882a593Smuzhiyun if (err < 0)
328*4882a593Smuzhiyun goto free_card;
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun pci_set_drvdata(pci, card);
331*4882a593Smuzhiyun dev++;
332*4882a593Smuzhiyun return 0;
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun free_card:
335*4882a593Smuzhiyun snd_card_free(card);
336*4882a593Smuzhiyun return err;
337*4882a593Smuzhiyun }
338*4882a593Smuzhiyun
snd_card_ymfpci_remove(struct pci_dev * pci)339*4882a593Smuzhiyun static void snd_card_ymfpci_remove(struct pci_dev *pci)
340*4882a593Smuzhiyun {
341*4882a593Smuzhiyun snd_card_free(pci_get_drvdata(pci));
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun static struct pci_driver ymfpci_driver = {
345*4882a593Smuzhiyun .name = KBUILD_MODNAME,
346*4882a593Smuzhiyun .id_table = snd_ymfpci_ids,
347*4882a593Smuzhiyun .probe = snd_card_ymfpci_probe,
348*4882a593Smuzhiyun .remove = snd_card_ymfpci_remove,
349*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
350*4882a593Smuzhiyun .driver = {
351*4882a593Smuzhiyun .pm = &snd_ymfpci_pm,
352*4882a593Smuzhiyun },
353*4882a593Smuzhiyun #endif
354*4882a593Smuzhiyun };
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun module_pci_driver(ymfpci_driver);
357