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