3 card-es968.c - driver for ESS AudioDrive ES968 based soundcards.
4 Copyright (C) 1999 by Massimo Piccioni <dafastidio@libero.it>
6 Thanks to Pierfrancesco 'qM2' Passerini.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include <sound/driver.h>
24 #include <linux/init.h>
25 #include <linux/time.h>
26 #include <linux/pnp.h>
27 #include <linux/moduleparam.h>
28 #include <sound/core.h>
29 #include <sound/initval.h>
34 MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
35 MODULE_DESCRIPTION("ESS AudioDrive ES968");
36 MODULE_LICENSE("GPL");
37 MODULE_SUPPORTED_DEVICE("{{ESS,AudioDrive ES968}}");
39 static int index
[SNDRV_CARDS
] = SNDRV_DEFAULT_IDX
; /* Index 0-MAX */
40 static char *id
[SNDRV_CARDS
] = SNDRV_DEFAULT_STR
; /* ID for this card */
41 static int enable
[SNDRV_CARDS
] = SNDRV_DEFAULT_ENABLE_ISAPNP
; /* Enable this card */
42 static long port
[SNDRV_CARDS
] = SNDRV_DEFAULT_PORT
; /* PnP setup */
43 static int irq
[SNDRV_CARDS
] = SNDRV_DEFAULT_IRQ
; /* Pnp setup */
44 static int dma8
[SNDRV_CARDS
] = SNDRV_DEFAULT_DMA
; /* PnP setup */
46 module_param_array(index
, int, NULL
, 0444);
47 MODULE_PARM_DESC(index
, "Index value for es968 based soundcard.");
48 module_param_array(id
, charp
, NULL
, 0444);
49 MODULE_PARM_DESC(id
, "ID string for es968 based soundcard.");
50 module_param_array(enable
, bool, NULL
, 0444);
51 MODULE_PARM_DESC(enable
, "Enable es968 based soundcard.");
52 module_param_array(port
, long, NULL
, 0444);
53 MODULE_PARM_DESC(port
, "Port # for es968 driver.");
54 module_param_array(irq
, int, NULL
, 0444);
55 MODULE_PARM_DESC(irq
, "IRQ # for es968 driver.");
56 module_param_array(dma8
, int, NULL
, 0444);
57 MODULE_PARM_DESC(dma8
, "8-bit DMA # for es968 driver.");
59 struct snd_card_es968
{
64 static struct pnp_card_device_id snd_es968_pnpids
[] = {
65 { .id
= "ESS0968", .devs
= { { "@@@0968" }, } },
66 { .id
= "", } /* end */
69 MODULE_DEVICE_TABLE(pnp_card
, snd_es968_pnpids
);
71 #define DRIVER_NAME "snd-card-es968"
73 static irqreturn_t
snd_card_es968_interrupt(int irq
, void *dev_id
)
75 struct snd_sb
*chip
= dev_id
;
77 if (chip
->open
& SB_OPEN_PCM
) {
78 return snd_sb8dsp_interrupt(chip
);
80 return snd_sb8dsp_midi_interrupt(chip
);
84 static int __devinit
snd_card_es968_pnp(int dev
, struct snd_card_es968
*acard
,
85 struct pnp_card_link
*card
,
86 const struct pnp_card_device_id
*id
)
89 struct pnp_resource_table
*cfg
= kmalloc(sizeof(*cfg
), GFP_KERNEL
);
93 acard
->dev
= pnp_request_card_device(card
, id
->devs
[0].id
, NULL
);
94 if (acard
->dev
== NULL
) {
101 pnp_init_resource_table(cfg
);
103 /* override resources */
104 if (port
[dev
] != SNDRV_AUTO_PORT
)
105 pnp_resource_change(&cfg
->port_resource
[0], port
[dev
], 16);
106 if (dma8
[dev
] != SNDRV_AUTO_DMA
)
107 pnp_resource_change(&cfg
->dma_resource
[0], dma8
[dev
], 1);
108 if (irq
[dev
] != SNDRV_AUTO_IRQ
)
109 pnp_resource_change(&cfg
->irq_resource
[0], irq
[dev
], 1);
110 if ((pnp_manual_config_dev(pdev
, cfg
, 0)) < 0)
111 snd_printk(KERN_ERR PFX
"AUDIO the requested resources are invalid, using auto config\n");
112 err
= pnp_activate_dev(pdev
);
114 snd_printk(KERN_ERR PFX
"AUDIO pnp configure failure\n");
118 port
[dev
] = pnp_port_start(pdev
, 0);
119 dma8
[dev
] = pnp_dma(pdev
, 1);
120 irq
[dev
] = pnp_irq(pdev
, 0);
126 static int __devinit
snd_card_es968_probe(int dev
,
127 struct pnp_card_link
*pcard
,
128 const struct pnp_card_device_id
*pid
)
132 struct snd_card
*card
;
133 struct snd_card_es968
*acard
;
135 if ((card
= snd_card_new(index
[dev
], id
[dev
], THIS_MODULE
,
136 sizeof(struct snd_card_es968
))) == NULL
)
138 acard
= card
->private_data
;
139 if ((error
= snd_card_es968_pnp(dev
, acard
, pcard
, pid
))) {
143 snd_card_set_dev(card
, &pcard
->card
->dev
);
145 if ((error
= snd_sbdsp_create(card
, port
[dev
],
147 snd_card_es968_interrupt
,
150 SB_HW_AUTO
, &chip
)) < 0) {
156 if ((error
= snd_sb8dsp_pcm(chip
, 0, NULL
)) < 0) {
161 if ((error
= snd_sbmixer_new(chip
)) < 0) {
166 if ((error
= snd_sb8dsp_midi(chip
, 0, NULL
)) < 0) {
171 strcpy(card
->driver
, "ES968");
172 strcpy(card
->shortname
, "ESS ES968");
173 sprintf(card
->longname
, "%s soundcard, %s at 0x%lx, irq %d, dma %d",
174 card
->shortname
, chip
->name
, chip
->port
, irq
[dev
], dma8
[dev
]);
176 if ((error
= snd_card_register(card
)) < 0) {
180 pnp_set_card_drvdata(pcard
, card
);
184 static unsigned int __devinitdata es968_devices
;
186 static int __devinit
snd_es968_pnp_detect(struct pnp_card_link
*card
,
187 const struct pnp_card_device_id
*id
)
192 for ( ; dev
< SNDRV_CARDS
; dev
++) {
195 res
= snd_card_es968_probe(dev
, card
, id
);
205 static void __devexit
snd_es968_pnp_remove(struct pnp_card_link
* pcard
)
207 snd_card_free(pnp_get_card_drvdata(pcard
));
208 pnp_set_card_drvdata(pcard
, NULL
);
212 static int snd_es968_pnp_suspend(struct pnp_card_link
*pcard
, pm_message_t state
)
214 struct snd_card
*card
= pnp_get_card_drvdata(pcard
);
215 struct snd_card_es968
*acard
= card
->private_data
;
216 struct snd_sb
*chip
= acard
->chip
;
218 snd_power_change_state(card
, SNDRV_CTL_POWER_D3hot
);
219 snd_pcm_suspend_all(chip
->pcm
);
220 snd_sbmixer_suspend(chip
);
224 static int snd_es968_pnp_resume(struct pnp_card_link
*pcard
)
226 struct snd_card
*card
= pnp_get_card_drvdata(pcard
);
227 struct snd_card_es968
*acard
= card
->private_data
;
228 struct snd_sb
*chip
= acard
->chip
;
230 snd_sbdsp_reset(chip
);
231 snd_sbmixer_resume(chip
);
232 snd_power_change_state(card
, SNDRV_CTL_POWER_D0
);
237 static struct pnp_card_driver es968_pnpc_driver
= {
238 .flags
= PNP_DRIVER_RES_DISABLE
,
240 .id_table
= snd_es968_pnpids
,
241 .probe
= snd_es968_pnp_detect
,
242 .remove
= __devexit_p(snd_es968_pnp_remove
),
244 .suspend
= snd_es968_pnp_suspend
,
245 .resume
= snd_es968_pnp_resume
,
249 static int __init
alsa_card_es968_init(void)
251 int err
= pnp_register_card_driver(&es968_pnpc_driver
);
255 if (!es968_devices
) {
256 pnp_unregister_card_driver(&es968_pnpc_driver
);
258 snd_printk(KERN_ERR
"no ES968 based soundcards found\n");
265 static void __exit
alsa_card_es968_exit(void)
267 pnp_unregister_card_driver(&es968_pnpc_driver
);
270 module_init(alsa_card_es968_init
)
271 module_exit(alsa_card_es968_exit
)