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
,
76 struct snd_sb
*chip
= dev_id
;
78 if (chip
->open
& SB_OPEN_PCM
) {
79 return snd_sb8dsp_interrupt(chip
);
81 return snd_sb8dsp_midi_interrupt(chip
);
85 static int __devinit
snd_card_es968_pnp(int dev
, struct snd_card_es968
*acard
,
86 struct pnp_card_link
*card
,
87 const struct pnp_card_device_id
*id
)
90 struct pnp_resource_table
*cfg
= kmalloc(sizeof(*cfg
), GFP_KERNEL
);
94 acard
->dev
= pnp_request_card_device(card
, id
->devs
[0].id
, NULL
);
95 if (acard
->dev
== NULL
) {
102 pnp_init_resource_table(cfg
);
104 /* override resources */
105 if (port
[dev
] != SNDRV_AUTO_PORT
)
106 pnp_resource_change(&cfg
->port_resource
[0], port
[dev
], 16);
107 if (dma8
[dev
] != SNDRV_AUTO_DMA
)
108 pnp_resource_change(&cfg
->dma_resource
[0], dma8
[dev
], 1);
109 if (irq
[dev
] != SNDRV_AUTO_IRQ
)
110 pnp_resource_change(&cfg
->irq_resource
[0], irq
[dev
], 1);
111 if ((pnp_manual_config_dev(pdev
, cfg
, 0)) < 0)
112 snd_printk(KERN_ERR PFX
"AUDIO the requested resources are invalid, using auto config\n");
113 err
= pnp_activate_dev(pdev
);
115 snd_printk(KERN_ERR PFX
"AUDIO pnp configure failure\n");
119 port
[dev
] = pnp_port_start(pdev
, 0);
120 dma8
[dev
] = pnp_dma(pdev
, 1);
121 irq
[dev
] = pnp_irq(pdev
, 0);
127 static int __init
snd_card_es968_probe(int dev
,
128 struct pnp_card_link
*pcard
,
129 const struct pnp_card_device_id
*pid
)
133 struct snd_card
*card
;
134 struct snd_card_es968
*acard
;
136 if ((card
= snd_card_new(index
[dev
], id
[dev
], THIS_MODULE
,
137 sizeof(struct snd_card_es968
))) == NULL
)
139 acard
= card
->private_data
;
140 if ((error
= snd_card_es968_pnp(dev
, acard
, pcard
, pid
))) {
144 snd_card_set_dev(card
, &pcard
->card
->dev
);
146 if ((error
= snd_sbdsp_create(card
, port
[dev
],
148 snd_card_es968_interrupt
,
151 SB_HW_AUTO
, &chip
)) < 0) {
157 if ((error
= snd_sb8dsp_pcm(chip
, 0, NULL
)) < 0) {
162 if ((error
= snd_sbmixer_new(chip
)) < 0) {
167 if ((error
= snd_sb8dsp_midi(chip
, 0, NULL
)) < 0) {
172 strcpy(card
->driver
, "ES968");
173 strcpy(card
->shortname
, "ESS ES968");
174 sprintf(card
->longname
, "%s soundcard, %s at 0x%lx, irq %d, dma %d",
175 card
->shortname
, chip
->name
, chip
->port
, irq
[dev
], dma8
[dev
]);
177 if ((error
= snd_card_register(card
)) < 0) {
181 pnp_set_card_drvdata(pcard
, card
);
185 static int __devinit
snd_es968_pnp_detect(struct pnp_card_link
*card
,
186 const struct pnp_card_device_id
*id
)
191 for ( ; dev
< SNDRV_CARDS
; dev
++) {
194 res
= snd_card_es968_probe(dev
, card
, id
);
203 static void __devexit
snd_es968_pnp_remove(struct pnp_card_link
* pcard
)
205 snd_card_free(pnp_get_card_drvdata(pcard
));
206 pnp_set_card_drvdata(pcard
, NULL
);
210 static int snd_es968_pnp_suspend(struct pnp_card_link
*pcard
, pm_message_t state
)
212 struct snd_card
*card
= pnp_get_card_drvdata(pcard
);
213 struct snd_card_es968
*acard
= card
->private_data
;
214 struct snd_sb
*chip
= acard
->chip
;
216 snd_power_change_state(card
, SNDRV_CTL_POWER_D3hot
);
217 snd_pcm_suspend_all(chip
->pcm
);
218 snd_sbmixer_suspend(chip
);
222 static int snd_es968_pnp_resume(struct pnp_card_link
*pcard
)
224 struct snd_card
*card
= pnp_get_card_drvdata(pcard
);
225 struct snd_card_es968
*acard
= card
->private_data
;
226 struct snd_sb
*chip
= acard
->chip
;
228 snd_sbdsp_reset(chip
);
229 snd_sbmixer_resume(chip
);
230 snd_power_change_state(card
, SNDRV_CTL_POWER_D0
);
235 static struct pnp_card_driver es968_pnpc_driver
= {
236 .flags
= PNP_DRIVER_RES_DISABLE
,
238 .id_table
= snd_es968_pnpids
,
239 .probe
= snd_es968_pnp_detect
,
240 .remove
= __devexit_p(snd_es968_pnp_remove
),
242 .suspend
= snd_es968_pnp_suspend
,
243 .resume
= snd_es968_pnp_resume
,
247 static int __init
alsa_card_es968_init(void)
249 int cards
= pnp_register_card_driver(&es968_pnpc_driver
);
251 pnp_unregister_card_driver(&es968_pnpc_driver
);
253 snd_printk(KERN_ERR
"no ES968 based soundcards found\n");
260 static void __exit
alsa_card_es968_exit(void)
262 pnp_unregister_card_driver(&es968_pnpc_driver
);
265 module_init(alsa_card_es968_init
)
266 module_exit(alsa_card_es968_exit
)