Blame view

sound/isa/azt2320.c 9.71 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
  /*
      card-azt2320.c - driver for Aztech Systems AZT2320 based soundcards.
      Copyright (C) 1999-2000 by Massimo Piccioni <dafastidio@libero.it>
  
      This program is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published by
      the Free Software Foundation; either version 2 of the License, or
      (at your option) any later version.
  
      This program is distributed in the hope that it will be useful,
      but WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      GNU General Public License for more details.
  
      You should have received a copy of the GNU General Public License
      along with this program; if not, write to the Free Software
      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
  
  /*
      This driver should provide support for most Aztech AZT2320 based cards.
      Several AZT2316 chips are also supported/tested, but autoprobe doesn't
      work: all module option have to be set.
  
      No docs available for us at Aztech headquarters !!!   Unbelievable ...
      No other help obtained.
  
      Thanks to Rainer Wiesner <rainer.wiesner@01019freenet.de> for the WSS
      activation method (full-duplex audio!).
  */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
32
33
34
35
36
  #include <asm/io.h>
  #include <linux/delay.h>
  #include <linux/init.h>
  #include <linux/time.h>
  #include <linux/wait.h>
  #include <linux/pnp.h>
65a772172   Paul Gortmaker   sound: fix driver...
37
  #include <linux/module.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
39
  #include <sound/core.h>
  #include <sound/initval.h>
61ef19d7e   Krzysztof Helt   ALSA: wss_lib: re...
40
  #include <sound/wss.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
  #include <sound/mpu401.h>
  #include <sound/opl3.h>
  
  #define PFX "azt2320: "
  
  MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
  MODULE_DESCRIPTION("Aztech Systems AZT2320");
  MODULE_LICENSE("GPL");
  MODULE_SUPPORTED_DEVICE("{{Aztech Systems,PRO16V},"
  		"{Aztech Systems,AZT2320},"
  		"{Aztech Systems,AZT3300},"
  		"{Aztech Systems,AZT2320},"
  		"{Aztech Systems,AZT3000}}");
  
  static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
  static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
a67ff6a54   Rusty Russell   ALSA: module_para...
57
  static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
  static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;	/* PnP setup */
  static long wss_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;	/* PnP setup */
  static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;	/* PnP setup */
  static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;	/* PnP setup */
  static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;	/* Pnp setup */
  static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;	/* Pnp setup */
  static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;	/* PnP setup */
  static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;	/* PnP setup */
  
  module_param_array(index, int, NULL, 0444);
  MODULE_PARM_DESC(index, "Index value for azt2320 based soundcard.");
  module_param_array(id, charp, NULL, 0444);
  MODULE_PARM_DESC(id, "ID string for azt2320 based soundcard.");
  module_param_array(enable, bool, NULL, 0444);
  MODULE_PARM_DESC(enable, "Enable azt2320 based soundcard.");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73
74
75
76
77
  
  struct snd_card_azt2320 {
  	int dev_no;
  	struct pnp_dev *dev;
  	struct pnp_dev *devmpu;
7779f75f0   Krzysztof Helt   ALSA: wss_lib: re...
78
  	struct snd_wss *chip;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
  };
  
  static struct pnp_card_device_id snd_azt2320_pnpids[] = {
  	/* PRO16V */
  	{ .id = "AZT1008", .devs = { { "AZT1008" }, { "AZT2001" }, } },
  	/* Aztech Sound Galaxy 16 */
  	{ .id = "AZT2320", .devs = { { "AZT0001" }, { "AZT0002" }, } },
  	/* Packard Bell Sound III 336 AM/SP */
  	{ .id = "AZT3000", .devs = { { "AZT1003" }, { "AZT2001" }, } },
  	/* AT3300 */
  	{ .id = "AZT3002", .devs = { { "AZT1004" }, { "AZT2001" }, } },
  	/* --- */
  	{ .id = "AZT3005", .devs = { { "AZT1003" }, { "AZT2001" }, } },
  	/* --- */
  	{ .id = "AZT3011", .devs = { { "AZT1003" }, { "AZT2001" }, } },
  	{ .id = "" }	/* end */
  };
  
  MODULE_DEVICE_TABLE(pnp_card, snd_azt2320_pnpids);
  
  #define	DRIVER_NAME	"snd-card-azt2320"
  
  static int __devinit snd_card_azt2320_pnp(int dev, struct snd_card_azt2320 *acard,
  					  struct pnp_card_link *card,
  					  const struct pnp_card_device_id *id)
  {
  	struct pnp_dev *pdev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
106
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
  	acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL);
109c53f84   Rene Herman   [ALSA] sound/isa:...
108
  	if (acard->dev == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
111
112
113
  
  	acard->devmpu = pnp_request_card_device(card, id->devs[1].id, NULL);
  
  	pdev = acard->dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114
115
116
117
118
  
  	err = pnp_activate_dev(pdev);
  	if (err < 0) {
  		snd_printk(KERN_ERR PFX "AUDIO pnp configure failure
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
119
120
121
122
123
124
125
126
127
128
129
  		return err;
  	}
  	port[dev] = pnp_port_start(pdev, 0);
  	fm_port[dev] = pnp_port_start(pdev, 1);
  	wss_port[dev] = pnp_port_start(pdev, 2);
  	dma1[dev] = pnp_dma(pdev, 0);
  	dma2[dev] = pnp_dma(pdev, 1);
  	irq[dev] = pnp_irq(pdev, 0);
  
  	pdev = acard->devmpu;
  	if (pdev != NULL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
  		err = pnp_activate_dev(pdev);
  		if (err < 0)
  			goto __mpu_error;
  		mpu_port[dev] = pnp_port_start(pdev, 0);
  		mpu_irq[dev] = pnp_irq(pdev, 0);
  	} else {
  	     __mpu_error:
  	     	if (pdev) {
  		     	pnp_release_card_device(pdev);
  	     		snd_printk(KERN_ERR PFX "MPU401 pnp configure failure, skipping
  ");
  	     	}
  	     	acard->devmpu = NULL;
  	     	mpu_port[dev] = -1;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
  	return 0;
  }
  
  /* same of snd_sbdsp_command by Jaroslav Kysela */
  static int __devinit snd_card_azt2320_command(unsigned long port, unsigned char val)
  {
  	int i;
  	unsigned long limit;
  
  	limit = jiffies + HZ / 10;
  	for (i = 50000; i && time_after(limit, jiffies); i--)
  		if (!(inb(port + 0x0c) & 0x80)) {
  			outb(val, port + 0x0c);
  			return 0;
  		}
  	return -EBUSY;
  }
  
  static int __devinit snd_card_azt2320_enable_wss(unsigned long port)
  {
  	int error;
  
  	if ((error = snd_card_azt2320_command(port, 0x09)))
  		return error;
  	if ((error = snd_card_azt2320_command(port, 0x00)))
  		return error;
  
  	mdelay(5);
  	return 0;
  }
  
  static int __devinit snd_card_azt2320_probe(int dev,
  					    struct pnp_card_link *pcard,
  					    const struct pnp_card_device_id *pid)
  {
  	int error;
11ff5c62b   Takashi Iwai   [ALSA] Remove xxx...
181
  	struct snd_card *card;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
182
  	struct snd_card_azt2320 *acard;
7779f75f0   Krzysztof Helt   ALSA: wss_lib: re...
183
  	struct snd_wss *chip;
11ff5c62b   Takashi Iwai   [ALSA] Remove xxx...
184
  	struct snd_opl3 *opl3;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185

c95eadd2f   Takashi Iwai   ALSA: Convert to ...
186
187
188
189
  	error = snd_card_create(index[dev], id[dev], THIS_MODULE,
  				sizeof(struct snd_card_azt2320), &card);
  	if (error < 0)
  		return error;
9fe856e47   Joe Perches   sound: Remove unn...
190
  	acard = card->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
191
192
193
194
195
196
197
198
199
200
201
  
  	if ((error = snd_card_azt2320_pnp(dev, acard, pcard, pid))) {
  		snd_card_free(card);
  		return error;
  	}
  	snd_card_set_dev(card, &pcard->card->dev);
  
  	if ((error = snd_card_azt2320_enable_wss(port[dev]))) {
  		snd_card_free(card);
  		return error;
  	}
7779f75f0   Krzysztof Helt   ALSA: wss_lib: re...
202
203
204
205
206
  	error = snd_wss_create(card, wss_port[dev], -1,
  			       irq[dev],
  			       dma1[dev], dma2[dev],
  			       WSS_HW_DETECT, 0, &chip);
  	if (error < 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
207
208
209
210
211
212
213
214
  		snd_card_free(card);
  		return error;
  	}
  
  	strcpy(card->driver, "AZT2320");
  	strcpy(card->shortname, "Aztech AZT2320");
  	sprintf(card->longname, "%s, WSS at 0x%lx, irq %i, dma %i&%i",
  		card->shortname, chip->port, irq[dev], dma1[dev], dma2[dev]);
7779f75f0   Krzysztof Helt   ALSA: wss_lib: re...
215
216
  	error = snd_wss_pcm(chip, 0, NULL);
  	if (error < 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
217
218
219
  		snd_card_free(card);
  		return error;
  	}
7779f75f0   Krzysztof Helt   ALSA: wss_lib: re...
220
221
  	error = snd_wss_mixer(chip);
  	if (error < 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222
223
224
  		snd_card_free(card);
  		return error;
  	}
7779f75f0   Krzysztof Helt   ALSA: wss_lib: re...
225
226
  	error = snd_wss_timer(chip, 0, NULL);
  	if (error < 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
227
228
229
230
231
232
233
  		snd_card_free(card);
  		return error;
  	}
  
  	if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
  		if (snd_mpu401_uart_new(card, 0, MPU401_HW_AZT2320,
  				mpu_port[dev], 0,
dba8b4699   Clemens Ladisch   ALSA: mpu401: cle...
234
  				mpu_irq[dev], NULL) < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
  			snd_printk(KERN_ERR PFX "no MPU-401 device at 0x%lx
  ", mpu_port[dev]);
  	}
  
  	if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) {
  		if (snd_opl3_create(card,
  				    fm_port[dev], fm_port[dev] + 2,
  				    OPL3_HW_AUTO, 0, &opl3) < 0) {
  			snd_printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx
  ",
  				   fm_port[dev], fm_port[dev] + 2);
  		} else {
  			if ((error = snd_opl3_timer_new(opl3, 1, 2)) < 0) {
  				snd_card_free(card);
  				return error;
  			}
  			if ((error = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
  				snd_card_free(card);
  				return error;
  			}
  		}
  	}
  
  	if ((error = snd_card_register(card)) < 0) {
  		snd_card_free(card);
  		return error;
  	}
  	pnp_set_card_drvdata(pcard, card);
  	return 0;
  }
db2735eb9   Bjorn Helgaas   [PATCH] PNP: adju...
265
  static unsigned int __devinitdata azt2320_devices;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
266
267
268
269
270
271
272
273
274
275
276
277
278
  static int __devinit snd_azt2320_pnp_detect(struct pnp_card_link *card,
  					    const struct pnp_card_device_id *id)
  {
  	static int dev;
  	int res;
  
  	for ( ; dev < SNDRV_CARDS; dev++) {
  		if (!enable[dev])
  			continue;
  		res = snd_card_azt2320_probe(dev, card, id);
  		if (res < 0)
  			return res;
  		dev++;
db2735eb9   Bjorn Helgaas   [PATCH] PNP: adju...
279
  		azt2320_devices++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280
281
282
283
284
285
286
  		return 0;
  	}
          return -ENODEV;
  }
  
  static void __devexit snd_azt2320_pnp_remove(struct pnp_card_link * pcard)
  {
b6cc25cae   Takashi Iwai   [ALSA] azt2320 - ...
287
288
289
290
291
292
293
294
295
  	snd_card_free(pnp_get_card_drvdata(pcard));
  	pnp_set_card_drvdata(pcard, NULL);
  }
  
  #ifdef CONFIG_PM
  static int snd_azt2320_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state)
  {
  	struct snd_card *card = pnp_get_card_drvdata(pcard);
  	struct snd_card_azt2320 *acard = card->private_data;
7779f75f0   Krzysztof Helt   ALSA: wss_lib: re...
296
  	struct snd_wss *chip = acard->chip;
b6cc25cae   Takashi Iwai   [ALSA] azt2320 - ...
297
298
299
300
301
302
303
304
305
306
  
  	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
  	chip->suspend(chip);
  	return 0;
  }
  
  static int snd_azt2320_pnp_resume(struct pnp_card_link *pcard)
  {
  	struct snd_card *card = pnp_get_card_drvdata(pcard);
  	struct snd_card_azt2320 *acard = card->private_data;
7779f75f0   Krzysztof Helt   ALSA: wss_lib: re...
307
  	struct snd_wss *chip = acard->chip;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
308

b6cc25cae   Takashi Iwai   [ALSA] azt2320 - ...
309
310
311
  	chip->resume(chip);
  	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
312
  }
b6cc25cae   Takashi Iwai   [ALSA] azt2320 - ...
313
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
314
315
316
317
318
319
320
  
  static struct pnp_card_driver azt2320_pnpc_driver = {
  	.flags          = PNP_DRIVER_RES_DISABLE,
  	.name           = "azt2320",
  	.id_table       = snd_azt2320_pnpids,
  	.probe          = snd_azt2320_pnp_detect,
  	.remove         = __devexit_p(snd_azt2320_pnp_remove),
b6cc25cae   Takashi Iwai   [ALSA] azt2320 - ...
321
322
323
324
  #ifdef CONFIG_PM
  	.suspend	= snd_azt2320_pnp_suspend,
  	.resume		= snd_azt2320_pnp_resume,
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
326
327
328
  };
  
  static int __init alsa_card_azt2320_init(void)
  {
db2735eb9   Bjorn Helgaas   [PATCH] PNP: adju...
329
330
331
332
333
  	int err;
  
  	err = pnp_register_card_driver(&azt2320_pnpc_driver);
  	if (err)
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
334

db2735eb9   Bjorn Helgaas   [PATCH] PNP: adju...
335
  	if (!azt2320_devices) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
336
  		pnp_unregister_card_driver(&azt2320_pnpc_driver);
b6cc25cae   Takashi Iwai   [ALSA] azt2320 - ...
337
  #ifdef MODULE
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
338
339
  		snd_printk(KERN_ERR "no AZT2320 based soundcards found
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
340
  #endif
b6cc25cae   Takashi Iwai   [ALSA] azt2320 - ...
341
342
343
  		return -ENODEV;
  	}
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
344
345
346
347
348
349
350
351
352
  }
  
  static void __exit alsa_card_azt2320_exit(void)
  {
  	pnp_unregister_card_driver(&azt2320_pnpc_driver);
  }
  
  module_init(alsa_card_azt2320_init)
  module_exit(alsa_card_azt2320_exit)