diff options
Diffstat (limited to 'sound/pcmcia/pdaudiocf/pdaudiocf.c')
-rw-r--r-- | sound/pcmcia/pdaudiocf/pdaudiocf.c | 154 |
1 files changed, 60 insertions, 94 deletions
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c index a7cd2d4df757..77caf43a3109 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c | |||
@@ -52,16 +52,13 @@ MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard."); | |||
52 | /* | 52 | /* |
53 | */ | 53 | */ |
54 | 54 | ||
55 | static dev_info_t dev_info = "snd-pdaudiocf"; | ||
56 | static struct snd_card *card_list[SNDRV_CARDS]; | 55 | static struct snd_card *card_list[SNDRV_CARDS]; |
57 | static dev_link_t *dev_list; | ||
58 | 56 | ||
59 | /* | 57 | /* |
60 | * prototypes | 58 | * prototypes |
61 | */ | 59 | */ |
62 | static void pdacf_config(dev_link_t *link); | 60 | static void pdacf_config(dev_link_t *link); |
63 | static int pdacf_event(event_t event, int priority, event_callback_args_t *args); | 61 | static void snd_pdacf_detach(struct pcmcia_device *p_dev); |
64 | static void snd_pdacf_detach(dev_link_t *link); | ||
65 | 62 | ||
66 | static void pdacf_release(dev_link_t *link) | 63 | static void pdacf_release(dev_link_t *link) |
67 | { | 64 | { |
@@ -83,10 +80,6 @@ static int snd_pdacf_free(struct snd_pdacf *pdacf) | |||
83 | 80 | ||
84 | pdacf_release(link); | 81 | pdacf_release(link); |
85 | 82 | ||
86 | /* Break the link with Card Services */ | ||
87 | if (link->handle) | ||
88 | pcmcia_deregister_client(link->handle); | ||
89 | |||
90 | card_list[pdacf->index] = NULL; | 83 | card_list[pdacf->index] = NULL; |
91 | pdacf->card = NULL; | 84 | pdacf->card = NULL; |
92 | 85 | ||
@@ -103,11 +96,10 @@ static int snd_pdacf_dev_free(struct snd_device *device) | |||
103 | /* | 96 | /* |
104 | * snd_pdacf_attach - attach callback for cs | 97 | * snd_pdacf_attach - attach callback for cs |
105 | */ | 98 | */ |
106 | static dev_link_t *snd_pdacf_attach(void) | 99 | static int snd_pdacf_attach(struct pcmcia_device *p_dev) |
107 | { | 100 | { |
108 | client_reg_t client_reg; /* Register with cardmgr */ | 101 | int i; |
109 | dev_link_t *link; /* Info for cardmgr */ | 102 | dev_link_t *link; /* Info for cardmgr */ |
110 | int i, ret; | ||
111 | struct snd_pdacf *pdacf; | 103 | struct snd_pdacf *pdacf; |
112 | struct snd_card *card; | 104 | struct snd_card *card; |
113 | static struct snd_device_ops ops = { | 105 | static struct snd_device_ops ops = { |
@@ -122,26 +114,26 @@ static dev_link_t *snd_pdacf_attach(void) | |||
122 | } | 114 | } |
123 | if (i >= SNDRV_CARDS) { | 115 | if (i >= SNDRV_CARDS) { |
124 | snd_printk(KERN_ERR "pdacf: too many cards found\n"); | 116 | snd_printk(KERN_ERR "pdacf: too many cards found\n"); |
125 | return NULL; | 117 | return -EINVAL; |
126 | } | 118 | } |
127 | if (! enable[i]) | 119 | if (! enable[i]) |
128 | return NULL; /* disabled explicitly */ | 120 | return -ENODEV; /* disabled explicitly */ |
129 | 121 | ||
130 | /* ok, create a card instance */ | 122 | /* ok, create a card instance */ |
131 | card = snd_card_new(index[i], id[i], THIS_MODULE, 0); | 123 | card = snd_card_new(index[i], id[i], THIS_MODULE, 0); |
132 | if (card == NULL) { | 124 | if (card == NULL) { |
133 | snd_printk(KERN_ERR "pdacf: cannot create a card instance\n"); | 125 | snd_printk(KERN_ERR "pdacf: cannot create a card instance\n"); |
134 | return NULL; | 126 | return -ENOMEM; |
135 | } | 127 | } |
136 | 128 | ||
137 | pdacf = snd_pdacf_create(card); | 129 | pdacf = snd_pdacf_create(card); |
138 | if (! pdacf) | 130 | if (! pdacf) |
139 | return NULL; | 131 | return -EIO; |
140 | 132 | ||
141 | if (snd_device_new(card, SNDRV_DEV_LOWLEVEL, pdacf, &ops) < 0) { | 133 | if (snd_device_new(card, SNDRV_DEV_LOWLEVEL, pdacf, &ops) < 0) { |
142 | kfree(pdacf); | 134 | kfree(pdacf); |
143 | snd_card_free(card); | 135 | snd_card_free(card); |
144 | return NULL; | 136 | return -ENODEV; |
145 | } | 137 | } |
146 | 138 | ||
147 | pdacf->index = i; | 139 | pdacf->index = i; |
@@ -165,22 +157,12 @@ static dev_link_t *snd_pdacf_attach(void) | |||
165 | link->conf.Present = PRESENT_OPTION; | 157 | link->conf.Present = PRESENT_OPTION; |
166 | 158 | ||
167 | /* Chain drivers */ | 159 | /* Chain drivers */ |
168 | link->next = dev_list; | 160 | link->next = NULL; |
169 | dev_list = link; | ||
170 | |||
171 | /* Register with Card Services */ | ||
172 | client_reg.dev_info = &dev_info; | ||
173 | client_reg.Version = 0x0210; | ||
174 | client_reg.event_callback_args.client_data = link; | ||
175 | |||
176 | ret = pcmcia_register_client(&link->handle, &client_reg); | ||
177 | if (ret != CS_SUCCESS) { | ||
178 | cs_error(link->handle, RegisterClient, ret); | ||
179 | snd_pdacf_detach(link); | ||
180 | return NULL; | ||
181 | } | ||
182 | 161 | ||
183 | return link; | 162 | link->handle = p_dev; |
163 | pdacf_config(link); | ||
164 | |||
165 | return 0; | ||
184 | } | 166 | } |
185 | 167 | ||
186 | 168 | ||
@@ -227,21 +209,13 @@ static int snd_pdacf_assign_resources(struct snd_pdacf *pdacf, int port, int irq | |||
227 | /* | 209 | /* |
228 | * snd_pdacf_detach - detach callback for cs | 210 | * snd_pdacf_detach - detach callback for cs |
229 | */ | 211 | */ |
230 | static void snd_pdacf_detach(dev_link_t *link) | 212 | static void snd_pdacf_detach(struct pcmcia_device *p_dev) |
231 | { | 213 | { |
214 | dev_link_t *link = dev_to_instance(p_dev); | ||
232 | struct snd_pdacf *chip = link->priv; | 215 | struct snd_pdacf *chip = link->priv; |
233 | 216 | ||
234 | snd_printdd(KERN_DEBUG "pdacf_detach called\n"); | 217 | snd_printdd(KERN_DEBUG "pdacf_detach called\n"); |
235 | /* Remove the interface data from the linked list */ | 218 | |
236 | { | ||
237 | dev_link_t **linkp; | ||
238 | /* Locate device structure */ | ||
239 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
240 | if (*linkp == link) | ||
241 | break; | ||
242 | if (*linkp) | ||
243 | *linkp = link->next; | ||
244 | } | ||
245 | if (chip->chip_status & PDAUDIOCF_STAT_IS_CONFIGURED) | 219 | if (chip->chip_status & PDAUDIOCF_STAT_IS_CONFIGURED) |
246 | snd_pdacf_powerdown(chip); | 220 | snd_pdacf_powerdown(chip); |
247 | chip->chip_status |= PDAUDIOCF_STAT_IS_STALE; /* to be sure */ | 221 | chip->chip_status |= PDAUDIOCF_STAT_IS_STALE; /* to be sure */ |
@@ -310,62 +284,51 @@ failed: | |||
310 | pcmcia_release_irq(link->handle, &link->irq); | 284 | pcmcia_release_irq(link->handle, &link->irq); |
311 | } | 285 | } |
312 | 286 | ||
313 | /* | 287 | #ifdef CONFIG_PM |
314 | * event callback | 288 | |
315 | */ | 289 | static int pdacf_suspend(struct pcmcia_device *dev) |
316 | static int pdacf_event(event_t event, int priority, event_callback_args_t *args) | ||
317 | { | 290 | { |
318 | dev_link_t *link = args->client_data; | 291 | dev_link_t *link = dev_to_instance(dev); |
319 | struct snd_pdacf *chip = link->priv; | 292 | struct snd_pdacf *chip = link->priv; |
320 | 293 | ||
321 | switch (event) { | 294 | snd_printdd(KERN_DEBUG "SUSPEND\n"); |
322 | case CS_EVENT_CARD_REMOVAL: | 295 | link->state |= DEV_SUSPEND; |
323 | snd_printdd(KERN_DEBUG "CARD_REMOVAL..\n"); | 296 | if (chip) { |
324 | link->state &= ~DEV_PRESENT; | 297 | snd_printdd(KERN_DEBUG "snd_pdacf_suspend calling\n"); |
325 | if (link->state & DEV_CONFIG) { | 298 | snd_pdacf_suspend(chip, PMSG_SUSPEND); |
326 | chip->chip_status |= PDAUDIOCF_STAT_IS_STALE; | 299 | } |
327 | } | 300 | |
328 | break; | 301 | snd_printdd(KERN_DEBUG "RESET_PHYSICAL\n"); |
329 | case CS_EVENT_CARD_INSERTION: | 302 | if (link->state & DEV_CONFIG) |
330 | snd_printdd(KERN_DEBUG "CARD_INSERTION..\n"); | 303 | pcmcia_release_configuration(link->handle); |
331 | link->state |= DEV_PRESENT; | 304 | |
332 | pdacf_config(link); | 305 | return 0; |
333 | break; | 306 | } |
334 | #ifdef CONFIG_PM | 307 | |
335 | case CS_EVENT_PM_SUSPEND: | 308 | static int pdacf_resume(struct pcmcia_device *dev) |
336 | snd_printdd(KERN_DEBUG "SUSPEND\n"); | 309 | { |
337 | link->state |= DEV_SUSPEND; | 310 | dev_link_t *link = dev_to_instance(dev); |
311 | struct snd_pdacf *chip = link->priv; | ||
312 | |||
313 | snd_printdd(KERN_DEBUG "RESUME\n"); | ||
314 | link->state &= ~DEV_SUSPEND; | ||
315 | |||
316 | snd_printdd(KERN_DEBUG "CARD_RESET\n"); | ||
317 | if (DEV_OK(link)) { | ||
318 | snd_printdd(KERN_DEBUG "requestconfig...\n"); | ||
319 | pcmcia_request_configuration(link->handle, &link->conf); | ||
338 | if (chip) { | 320 | if (chip) { |
339 | snd_printdd(KERN_DEBUG "snd_pdacf_suspend calling\n"); | 321 | snd_printdd(KERN_DEBUG "calling snd_pdacf_resume\n"); |
340 | snd_pdacf_suspend(chip, PMSG_SUSPEND); | 322 | snd_pdacf_resume(chip); |
341 | } | ||
342 | /* Fall through... */ | ||
343 | case CS_EVENT_RESET_PHYSICAL: | ||
344 | snd_printdd(KERN_DEBUG "RESET_PHYSICAL\n"); | ||
345 | if (link->state & DEV_CONFIG) | ||
346 | pcmcia_release_configuration(link->handle); | ||
347 | break; | ||
348 | case CS_EVENT_PM_RESUME: | ||
349 | snd_printdd(KERN_DEBUG "RESUME\n"); | ||
350 | link->state &= ~DEV_SUSPEND; | ||
351 | /* Fall through... */ | ||
352 | case CS_EVENT_CARD_RESET: | ||
353 | snd_printdd(KERN_DEBUG "CARD_RESET\n"); | ||
354 | if (DEV_OK(link)) { | ||
355 | snd_printdd(KERN_DEBUG "requestconfig...\n"); | ||
356 | pcmcia_request_configuration(link->handle, &link->conf); | ||
357 | if (chip) { | ||
358 | snd_printdd(KERN_DEBUG "calling snd_pdacf_resume\n"); | ||
359 | snd_pdacf_resume(chip); | ||
360 | } | ||
361 | } | 323 | } |
362 | snd_printdd(KERN_DEBUG "resume done!\n"); | ||
363 | break; | ||
364 | #endif | ||
365 | } | 324 | } |
325 | snd_printdd(KERN_DEBUG "resume done!\n"); | ||
326 | |||
366 | return 0; | 327 | return 0; |
367 | } | 328 | } |
368 | 329 | ||
330 | #endif | ||
331 | |||
369 | /* | 332 | /* |
370 | * Module entry points | 333 | * Module entry points |
371 | */ | 334 | */ |
@@ -380,10 +343,14 @@ static struct pcmcia_driver pdacf_cs_driver = { | |||
380 | .drv = { | 343 | .drv = { |
381 | .name = "snd-pdaudiocf", | 344 | .name = "snd-pdaudiocf", |
382 | }, | 345 | }, |
383 | .attach = snd_pdacf_attach, | 346 | .probe = snd_pdacf_attach, |
384 | .event = pdacf_event, | 347 | .remove = snd_pdacf_detach, |
385 | .detach = snd_pdacf_detach, | ||
386 | .id_table = snd_pdacf_ids, | 348 | .id_table = snd_pdacf_ids, |
349 | #ifdef CONFIG_PM | ||
350 | .suspend = pdacf_suspend, | ||
351 | .resume = pdacf_resume, | ||
352 | #endif | ||
353 | |||
387 | }; | 354 | }; |
388 | 355 | ||
389 | static int __init init_pdacf(void) | 356 | static int __init init_pdacf(void) |
@@ -394,7 +361,6 @@ static int __init init_pdacf(void) | |||
394 | static void __exit exit_pdacf(void) | 361 | static void __exit exit_pdacf(void) |
395 | { | 362 | { |
396 | pcmcia_unregister_driver(&pdacf_cs_driver); | 363 | pcmcia_unregister_driver(&pdacf_cs_driver); |
397 | BUG_ON(dev_list != NULL); | ||
398 | } | 364 | } |
399 | 365 | ||
400 | module_init(init_pdacf); | 366 | module_init(init_pdacf); |