xref: /OK3568_Linux_fs/kernel/sound/isa/azt2320.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun     card-azt2320.c - driver for Aztech Systems AZT2320 based soundcards.
4*4882a593Smuzhiyun     Copyright (C) 1999-2000 by Massimo Piccioni <dafastidio@libero.it>
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun /*
9*4882a593Smuzhiyun     This driver should provide support for most Aztech AZT2320 based cards.
10*4882a593Smuzhiyun     Several AZT2316 chips are also supported/tested, but autoprobe doesn't
11*4882a593Smuzhiyun     work: all module option have to be set.
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun     No docs available for us at Aztech headquarters !!!   Unbelievable ...
14*4882a593Smuzhiyun     No other help obtained.
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun     Thanks to Rainer Wiesner <rainer.wiesner@01019freenet.de> for the WSS
17*4882a593Smuzhiyun     activation method (full-duplex audio!).
18*4882a593Smuzhiyun */
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun #include <linux/io.h>
21*4882a593Smuzhiyun #include <linux/delay.h>
22*4882a593Smuzhiyun #include <linux/init.h>
23*4882a593Smuzhiyun #include <linux/time.h>
24*4882a593Smuzhiyun #include <linux/wait.h>
25*4882a593Smuzhiyun #include <linux/pnp.h>
26*4882a593Smuzhiyun #include <linux/module.h>
27*4882a593Smuzhiyun #include <sound/core.h>
28*4882a593Smuzhiyun #include <sound/initval.h>
29*4882a593Smuzhiyun #include <sound/wss.h>
30*4882a593Smuzhiyun #include <sound/mpu401.h>
31*4882a593Smuzhiyun #include <sound/opl3.h>
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun #define PFX "azt2320: "
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
36*4882a593Smuzhiyun MODULE_DESCRIPTION("Aztech Systems AZT2320");
37*4882a593Smuzhiyun MODULE_LICENSE("GPL");
38*4882a593Smuzhiyun MODULE_SUPPORTED_DEVICE("{{Aztech Systems,PRO16V},"
39*4882a593Smuzhiyun 		"{Aztech Systems,AZT2320},"
40*4882a593Smuzhiyun 		"{Aztech Systems,AZT3300},"
41*4882a593Smuzhiyun 		"{Aztech Systems,AZT2320},"
42*4882a593Smuzhiyun 		"{Aztech Systems,AZT3000}}");
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
45*4882a593Smuzhiyun static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
46*4882a593Smuzhiyun static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */
47*4882a593Smuzhiyun static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;	/* PnP setup */
48*4882a593Smuzhiyun static long wss_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;	/* PnP setup */
49*4882a593Smuzhiyun static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;	/* PnP setup */
50*4882a593Smuzhiyun static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;	/* PnP setup */
51*4882a593Smuzhiyun static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;	/* Pnp setup */
52*4882a593Smuzhiyun static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;	/* Pnp setup */
53*4882a593Smuzhiyun static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;	/* PnP setup */
54*4882a593Smuzhiyun static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;	/* PnP setup */
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun module_param_array(index, int, NULL, 0444);
57*4882a593Smuzhiyun MODULE_PARM_DESC(index, "Index value for azt2320 based soundcard.");
58*4882a593Smuzhiyun module_param_array(id, charp, NULL, 0444);
59*4882a593Smuzhiyun MODULE_PARM_DESC(id, "ID string for azt2320 based soundcard.");
60*4882a593Smuzhiyun module_param_array(enable, bool, NULL, 0444);
61*4882a593Smuzhiyun MODULE_PARM_DESC(enable, "Enable azt2320 based soundcard.");
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun struct snd_card_azt2320 {
64*4882a593Smuzhiyun 	int dev_no;
65*4882a593Smuzhiyun 	struct pnp_dev *dev;
66*4882a593Smuzhiyun 	struct pnp_dev *devmpu;
67*4882a593Smuzhiyun 	struct snd_wss *chip;
68*4882a593Smuzhiyun };
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun static const struct pnp_card_device_id snd_azt2320_pnpids[] = {
71*4882a593Smuzhiyun 	/* PRO16V */
72*4882a593Smuzhiyun 	{ .id = "AZT1008", .devs = { { "AZT1008" }, { "AZT2001" }, } },
73*4882a593Smuzhiyun 	/* Aztech Sound Galaxy 16 */
74*4882a593Smuzhiyun 	{ .id = "AZT2320", .devs = { { "AZT0001" }, { "AZT0002" }, } },
75*4882a593Smuzhiyun 	/* Packard Bell Sound III 336 AM/SP */
76*4882a593Smuzhiyun 	{ .id = "AZT3000", .devs = { { "AZT1003" }, { "AZT2001" }, } },
77*4882a593Smuzhiyun 	/* AT3300 */
78*4882a593Smuzhiyun 	{ .id = "AZT3002", .devs = { { "AZT1004" }, { "AZT2001" }, } },
79*4882a593Smuzhiyun 	/* --- */
80*4882a593Smuzhiyun 	{ .id = "AZT3005", .devs = { { "AZT1003" }, { "AZT2001" }, } },
81*4882a593Smuzhiyun 	/* --- */
82*4882a593Smuzhiyun 	{ .id = "AZT3011", .devs = { { "AZT1003" }, { "AZT2001" }, } },
83*4882a593Smuzhiyun 	{ .id = "" }	/* end */
84*4882a593Smuzhiyun };
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun MODULE_DEVICE_TABLE(pnp_card, snd_azt2320_pnpids);
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun #define	DRIVER_NAME	"snd-card-azt2320"
89*4882a593Smuzhiyun 
snd_card_azt2320_pnp(int dev,struct snd_card_azt2320 * acard,struct pnp_card_link * card,const struct pnp_card_device_id * id)90*4882a593Smuzhiyun static int snd_card_azt2320_pnp(int dev, struct snd_card_azt2320 *acard,
91*4882a593Smuzhiyun 				struct pnp_card_link *card,
92*4882a593Smuzhiyun 				const struct pnp_card_device_id *id)
93*4882a593Smuzhiyun {
94*4882a593Smuzhiyun 	struct pnp_dev *pdev;
95*4882a593Smuzhiyun 	int err;
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 	acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL);
98*4882a593Smuzhiyun 	if (acard->dev == NULL)
99*4882a593Smuzhiyun 		return -ENODEV;
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 	acard->devmpu = pnp_request_card_device(card, id->devs[1].id, NULL);
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun 	pdev = acard->dev;
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 	err = pnp_activate_dev(pdev);
106*4882a593Smuzhiyun 	if (err < 0) {
107*4882a593Smuzhiyun 		snd_printk(KERN_ERR PFX "AUDIO pnp configure failure\n");
108*4882a593Smuzhiyun 		return err;
109*4882a593Smuzhiyun 	}
110*4882a593Smuzhiyun 	port[dev] = pnp_port_start(pdev, 0);
111*4882a593Smuzhiyun 	fm_port[dev] = pnp_port_start(pdev, 1);
112*4882a593Smuzhiyun 	wss_port[dev] = pnp_port_start(pdev, 2);
113*4882a593Smuzhiyun 	dma1[dev] = pnp_dma(pdev, 0);
114*4882a593Smuzhiyun 	dma2[dev] = pnp_dma(pdev, 1);
115*4882a593Smuzhiyun 	irq[dev] = pnp_irq(pdev, 0);
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 	pdev = acard->devmpu;
118*4882a593Smuzhiyun 	if (pdev != NULL) {
119*4882a593Smuzhiyun 		err = pnp_activate_dev(pdev);
120*4882a593Smuzhiyun 		if (err < 0)
121*4882a593Smuzhiyun 			goto __mpu_error;
122*4882a593Smuzhiyun 		mpu_port[dev] = pnp_port_start(pdev, 0);
123*4882a593Smuzhiyun 		mpu_irq[dev] = pnp_irq(pdev, 0);
124*4882a593Smuzhiyun 	} else {
125*4882a593Smuzhiyun 	     __mpu_error:
126*4882a593Smuzhiyun 	     	if (pdev) {
127*4882a593Smuzhiyun 		     	pnp_release_card_device(pdev);
128*4882a593Smuzhiyun 	     		snd_printk(KERN_ERR PFX "MPU401 pnp configure failure, skipping\n");
129*4882a593Smuzhiyun 	     	}
130*4882a593Smuzhiyun 	     	acard->devmpu = NULL;
131*4882a593Smuzhiyun 	     	mpu_port[dev] = -1;
132*4882a593Smuzhiyun 	}
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun 	return 0;
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun /* same of snd_sbdsp_command by Jaroslav Kysela */
snd_card_azt2320_command(unsigned long port,unsigned char val)138*4882a593Smuzhiyun static int snd_card_azt2320_command(unsigned long port, unsigned char val)
139*4882a593Smuzhiyun {
140*4882a593Smuzhiyun 	int i;
141*4882a593Smuzhiyun 	unsigned long limit;
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun 	limit = jiffies + HZ / 10;
144*4882a593Smuzhiyun 	for (i = 50000; i && time_after(limit, jiffies); i--)
145*4882a593Smuzhiyun 		if (!(inb(port + 0x0c) & 0x80)) {
146*4882a593Smuzhiyun 			outb(val, port + 0x0c);
147*4882a593Smuzhiyun 			return 0;
148*4882a593Smuzhiyun 		}
149*4882a593Smuzhiyun 	return -EBUSY;
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun 
snd_card_azt2320_enable_wss(unsigned long port)152*4882a593Smuzhiyun static int snd_card_azt2320_enable_wss(unsigned long port)
153*4882a593Smuzhiyun {
154*4882a593Smuzhiyun 	int error;
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun 	if ((error = snd_card_azt2320_command(port, 0x09)))
157*4882a593Smuzhiyun 		return error;
158*4882a593Smuzhiyun 	if ((error = snd_card_azt2320_command(port, 0x00)))
159*4882a593Smuzhiyun 		return error;
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 	mdelay(5);
162*4882a593Smuzhiyun 	return 0;
163*4882a593Smuzhiyun }
164*4882a593Smuzhiyun 
snd_card_azt2320_probe(int dev,struct pnp_card_link * pcard,const struct pnp_card_device_id * pid)165*4882a593Smuzhiyun static int snd_card_azt2320_probe(int dev,
166*4882a593Smuzhiyun 				  struct pnp_card_link *pcard,
167*4882a593Smuzhiyun 				  const struct pnp_card_device_id *pid)
168*4882a593Smuzhiyun {
169*4882a593Smuzhiyun 	int error;
170*4882a593Smuzhiyun 	struct snd_card *card;
171*4882a593Smuzhiyun 	struct snd_card_azt2320 *acard;
172*4882a593Smuzhiyun 	struct snd_wss *chip;
173*4882a593Smuzhiyun 	struct snd_opl3 *opl3;
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 	error = snd_card_new(&pcard->card->dev,
176*4882a593Smuzhiyun 			     index[dev], id[dev], THIS_MODULE,
177*4882a593Smuzhiyun 			     sizeof(struct snd_card_azt2320), &card);
178*4882a593Smuzhiyun 	if (error < 0)
179*4882a593Smuzhiyun 		return error;
180*4882a593Smuzhiyun 	acard = card->private_data;
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	if ((error = snd_card_azt2320_pnp(dev, acard, pcard, pid))) {
183*4882a593Smuzhiyun 		snd_card_free(card);
184*4882a593Smuzhiyun 		return error;
185*4882a593Smuzhiyun 	}
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun 	if ((error = snd_card_azt2320_enable_wss(port[dev]))) {
188*4882a593Smuzhiyun 		snd_card_free(card);
189*4882a593Smuzhiyun 		return error;
190*4882a593Smuzhiyun 	}
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun 	error = snd_wss_create(card, wss_port[dev], -1,
193*4882a593Smuzhiyun 			       irq[dev],
194*4882a593Smuzhiyun 			       dma1[dev], dma2[dev],
195*4882a593Smuzhiyun 			       WSS_HW_DETECT, 0, &chip);
196*4882a593Smuzhiyun 	if (error < 0) {
197*4882a593Smuzhiyun 		snd_card_free(card);
198*4882a593Smuzhiyun 		return error;
199*4882a593Smuzhiyun 	}
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 	strcpy(card->driver, "AZT2320");
202*4882a593Smuzhiyun 	strcpy(card->shortname, "Aztech AZT2320");
203*4882a593Smuzhiyun 	sprintf(card->longname, "%s, WSS at 0x%lx, irq %i, dma %i&%i",
204*4882a593Smuzhiyun 		card->shortname, chip->port, irq[dev], dma1[dev], dma2[dev]);
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 	error = snd_wss_pcm(chip, 0);
207*4882a593Smuzhiyun 	if (error < 0) {
208*4882a593Smuzhiyun 		snd_card_free(card);
209*4882a593Smuzhiyun 		return error;
210*4882a593Smuzhiyun 	}
211*4882a593Smuzhiyun 	error = snd_wss_mixer(chip);
212*4882a593Smuzhiyun 	if (error < 0) {
213*4882a593Smuzhiyun 		snd_card_free(card);
214*4882a593Smuzhiyun 		return error;
215*4882a593Smuzhiyun 	}
216*4882a593Smuzhiyun 	error = snd_wss_timer(chip, 0);
217*4882a593Smuzhiyun 	if (error < 0) {
218*4882a593Smuzhiyun 		snd_card_free(card);
219*4882a593Smuzhiyun 		return error;
220*4882a593Smuzhiyun 	}
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 	if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
223*4882a593Smuzhiyun 		if (snd_mpu401_uart_new(card, 0, MPU401_HW_AZT2320,
224*4882a593Smuzhiyun 				mpu_port[dev], 0,
225*4882a593Smuzhiyun 				mpu_irq[dev], NULL) < 0)
226*4882a593Smuzhiyun 			snd_printk(KERN_ERR PFX "no MPU-401 device at 0x%lx\n", mpu_port[dev]);
227*4882a593Smuzhiyun 	}
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun 	if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) {
230*4882a593Smuzhiyun 		if (snd_opl3_create(card,
231*4882a593Smuzhiyun 				    fm_port[dev], fm_port[dev] + 2,
232*4882a593Smuzhiyun 				    OPL3_HW_AUTO, 0, &opl3) < 0) {
233*4882a593Smuzhiyun 			snd_printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx\n",
234*4882a593Smuzhiyun 				   fm_port[dev], fm_port[dev] + 2);
235*4882a593Smuzhiyun 		} else {
236*4882a593Smuzhiyun 			if ((error = snd_opl3_timer_new(opl3, 1, 2)) < 0) {
237*4882a593Smuzhiyun 				snd_card_free(card);
238*4882a593Smuzhiyun 				return error;
239*4882a593Smuzhiyun 			}
240*4882a593Smuzhiyun 			if ((error = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
241*4882a593Smuzhiyun 				snd_card_free(card);
242*4882a593Smuzhiyun 				return error;
243*4882a593Smuzhiyun 			}
244*4882a593Smuzhiyun 		}
245*4882a593Smuzhiyun 	}
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 	if ((error = snd_card_register(card)) < 0) {
248*4882a593Smuzhiyun 		snd_card_free(card);
249*4882a593Smuzhiyun 		return error;
250*4882a593Smuzhiyun 	}
251*4882a593Smuzhiyun 	pnp_set_card_drvdata(pcard, card);
252*4882a593Smuzhiyun 	return 0;
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun static unsigned int azt2320_devices;
256*4882a593Smuzhiyun 
snd_azt2320_pnp_detect(struct pnp_card_link * card,const struct pnp_card_device_id * id)257*4882a593Smuzhiyun static int snd_azt2320_pnp_detect(struct pnp_card_link *card,
258*4882a593Smuzhiyun 				  const struct pnp_card_device_id *id)
259*4882a593Smuzhiyun {
260*4882a593Smuzhiyun 	static int dev;
261*4882a593Smuzhiyun 	int res;
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 	for ( ; dev < SNDRV_CARDS; dev++) {
264*4882a593Smuzhiyun 		if (!enable[dev])
265*4882a593Smuzhiyun 			continue;
266*4882a593Smuzhiyun 		res = snd_card_azt2320_probe(dev, card, id);
267*4882a593Smuzhiyun 		if (res < 0)
268*4882a593Smuzhiyun 			return res;
269*4882a593Smuzhiyun 		dev++;
270*4882a593Smuzhiyun 		azt2320_devices++;
271*4882a593Smuzhiyun 		return 0;
272*4882a593Smuzhiyun 	}
273*4882a593Smuzhiyun         return -ENODEV;
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun 
snd_azt2320_pnp_remove(struct pnp_card_link * pcard)276*4882a593Smuzhiyun static void snd_azt2320_pnp_remove(struct pnp_card_link *pcard)
277*4882a593Smuzhiyun {
278*4882a593Smuzhiyun 	snd_card_free(pnp_get_card_drvdata(pcard));
279*4882a593Smuzhiyun 	pnp_set_card_drvdata(pcard, NULL);
280*4882a593Smuzhiyun }
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun #ifdef CONFIG_PM
snd_azt2320_pnp_suspend(struct pnp_card_link * pcard,pm_message_t state)283*4882a593Smuzhiyun static int snd_azt2320_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state)
284*4882a593Smuzhiyun {
285*4882a593Smuzhiyun 	struct snd_card *card = pnp_get_card_drvdata(pcard);
286*4882a593Smuzhiyun 	struct snd_card_azt2320 *acard = card->private_data;
287*4882a593Smuzhiyun 	struct snd_wss *chip = acard->chip;
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
290*4882a593Smuzhiyun 	chip->suspend(chip);
291*4882a593Smuzhiyun 	return 0;
292*4882a593Smuzhiyun }
293*4882a593Smuzhiyun 
snd_azt2320_pnp_resume(struct pnp_card_link * pcard)294*4882a593Smuzhiyun static int snd_azt2320_pnp_resume(struct pnp_card_link *pcard)
295*4882a593Smuzhiyun {
296*4882a593Smuzhiyun 	struct snd_card *card = pnp_get_card_drvdata(pcard);
297*4882a593Smuzhiyun 	struct snd_card_azt2320 *acard = card->private_data;
298*4882a593Smuzhiyun 	struct snd_wss *chip = acard->chip;
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 	chip->resume(chip);
301*4882a593Smuzhiyun 	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
302*4882a593Smuzhiyun 	return 0;
303*4882a593Smuzhiyun }
304*4882a593Smuzhiyun #endif
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun static struct pnp_card_driver azt2320_pnpc_driver = {
307*4882a593Smuzhiyun 	.flags          = PNP_DRIVER_RES_DISABLE,
308*4882a593Smuzhiyun 	.name           = "azt2320",
309*4882a593Smuzhiyun 	.id_table       = snd_azt2320_pnpids,
310*4882a593Smuzhiyun 	.probe          = snd_azt2320_pnp_detect,
311*4882a593Smuzhiyun 	.remove         = snd_azt2320_pnp_remove,
312*4882a593Smuzhiyun #ifdef CONFIG_PM
313*4882a593Smuzhiyun 	.suspend	= snd_azt2320_pnp_suspend,
314*4882a593Smuzhiyun 	.resume		= snd_azt2320_pnp_resume,
315*4882a593Smuzhiyun #endif
316*4882a593Smuzhiyun };
317*4882a593Smuzhiyun 
alsa_card_azt2320_init(void)318*4882a593Smuzhiyun static int __init alsa_card_azt2320_init(void)
319*4882a593Smuzhiyun {
320*4882a593Smuzhiyun 	int err;
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun 	err = pnp_register_card_driver(&azt2320_pnpc_driver);
323*4882a593Smuzhiyun 	if (err)
324*4882a593Smuzhiyun 		return err;
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 	if (!azt2320_devices) {
327*4882a593Smuzhiyun 		pnp_unregister_card_driver(&azt2320_pnpc_driver);
328*4882a593Smuzhiyun #ifdef MODULE
329*4882a593Smuzhiyun 		snd_printk(KERN_ERR "no AZT2320 based soundcards found\n");
330*4882a593Smuzhiyun #endif
331*4882a593Smuzhiyun 		return -ENODEV;
332*4882a593Smuzhiyun 	}
333*4882a593Smuzhiyun 	return 0;
334*4882a593Smuzhiyun }
335*4882a593Smuzhiyun 
alsa_card_azt2320_exit(void)336*4882a593Smuzhiyun static void __exit alsa_card_azt2320_exit(void)
337*4882a593Smuzhiyun {
338*4882a593Smuzhiyun 	pnp_unregister_card_driver(&azt2320_pnpc_driver);
339*4882a593Smuzhiyun }
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun module_init(alsa_card_azt2320_init)
342*4882a593Smuzhiyun module_exit(alsa_card_azt2320_exit)
343