aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/isa/cmi8330.c241
1 files changed, 163 insertions, 78 deletions
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
index cf160062beb0..ba0114ebafde 100644
--- a/sound/isa/cmi8330.c
+++ b/sound/isa/cmi8330.c
@@ -45,6 +45,8 @@
45 45
46#include <sound/driver.h> 46#include <sound/driver.h>
47#include <linux/init.h> 47#include <linux/init.h>
48#include <linux/err.h>
49#include <linux/platform_device.h>
48#include <linux/slab.h> 50#include <linux/slab.h>
49#include <linux/pnp.h> 51#include <linux/pnp.h>
50#include <linux/moduleparam.h> 52#include <linux/moduleparam.h>
@@ -156,8 +158,6 @@ struct snd_cmi8330 {
156 } streams[2]; 158 } streams[2];
157}; 159};
158 160
159static struct snd_card *snd_cmi8330_legacy[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
160
161#ifdef CONFIG_PNP 161#ifdef CONFIG_PNP
162 162
163static struct pnp_card_device_id snd_cmi8330_pnpids[] = { 163static struct pnp_card_device_id snd_cmi8330_pnpids[] = {
@@ -429,6 +429,31 @@ static int __devinit snd_cmi8330_pcm(struct snd_card *card, struct snd_cmi8330 *
429} 429}
430 430
431 431
432#ifdef CONFIG_PM
433static int snd_cmi8330_suspend(struct snd_card *card)
434{
435 struct snd_cmi8330 *acard = card->private_data;
436
437 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
438 snd_pcm_suspend_all(acard->pcm);
439 acard->wss->suspend(acard->wss);
440 snd_sbmixer_suspend(acard->sb);
441 return 0;
442}
443
444static int snd_cmi8330_resume(struct snd_card *card)
445{
446 struct snd_cmi8330 *acard = card->private_data;
447
448 snd_sbdsp_reset(acard->sb);
449 snd_sbmixer_suspend(acard->sb);
450 acard->wss->resume(acard->wss);
451 snd_power_change_state(card, SNDRV_CTL_POWER_D0);
452 return 0;
453}
454#endif
455
456
432/* 457/*
433 */ 458 */
434 459
@@ -440,44 +465,28 @@ static int __devinit snd_cmi8330_pcm(struct snd_card *card, struct snd_cmi8330 *
440 465
441#define PFX "cmi8330: " 466#define PFX "cmi8330: "
442 467
443static int __devinit snd_cmi8330_probe(int dev, 468static struct snd_card *snd_cmi8330_card_new(int dev)
444 struct pnp_card_link *pcard,
445 const struct pnp_card_device_id *pid)
446{ 469{
447 struct snd_card *card; 470 struct snd_card *card;
448 struct snd_cmi8330 *acard; 471 struct snd_cmi8330 *acard;
449 int i, err;
450
451 if (! is_isapnp_selected(dev)) {
452 if (wssport[dev] == SNDRV_AUTO_PORT) {
453 snd_printk(KERN_ERR PFX "specify wssport\n");
454 return -EINVAL;
455 }
456 if (sbport[dev] == SNDRV_AUTO_PORT) {
457 snd_printk(KERN_ERR PFX "specify sbport\n");
458 return -EINVAL;
459 }
460 }
461 472
462 card = snd_card_new(index[dev], id[dev], THIS_MODULE, 473 card = snd_card_new(index[dev], id[dev], THIS_MODULE,
463 sizeof(struct snd_cmi8330)); 474 sizeof(struct snd_cmi8330));
464 if (card == NULL) { 475 if (card == NULL) {
465 snd_printk(KERN_ERR PFX "could not get a new card\n"); 476 snd_printk(KERN_ERR PFX "could not get a new card\n");
466 return -ENOMEM; 477 return NULL;
467 } 478 }
468 acard = (struct snd_cmi8330 *)card->private_data; 479 acard = card->private_data;
469 acard->card = card; 480 acard->card = card;
481 return card;
482}
470 483
471#ifdef CONFIG_PNP 484static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev)
472 if (isapnp[dev]) { 485{
473 if ((err = snd_cmi8330_pnp(dev, acard, pcard, pid)) < 0) { 486 struct snd_cmi8330 *acard;
474 snd_printk(KERN_ERR PFX "PnP detection failed\n"); 487 int i, err;
475 goto _err;
476 }
477 snd_card_set_dev(card, &pcard->card->dev);
478 }
479#endif
480 488
489 acard = card->private_data;
481 if ((err = snd_ad1848_create(card, 490 if ((err = snd_ad1848_create(card,
482 wssport[dev] + 4, 491 wssport[dev] + 4,
483 wssirq[dev], 492 wssirq[dev],
@@ -485,12 +494,11 @@ static int __devinit snd_cmi8330_probe(int dev,
485 AD1848_HW_DETECT, 494 AD1848_HW_DETECT,
486 &acard->wss)) < 0) { 495 &acard->wss)) < 0) {
487 snd_printk(KERN_ERR PFX "(AD1848) device busy??\n"); 496 snd_printk(KERN_ERR PFX "(AD1848) device busy??\n");
488 goto _err; 497 return err;
489 } 498 }
490 if (acard->wss->hardware != AD1848_HW_CMI8330) { 499 if (acard->wss->hardware != AD1848_HW_CMI8330) {
491 snd_printk(KERN_ERR PFX "(AD1848) not found during probe\n"); 500 snd_printk(KERN_ERR PFX "(AD1848) not found during probe\n");
492 err = -ENODEV; 501 return -ENODEV;
493 goto _err;
494 } 502 }
495 503
496 if ((err = snd_sbdsp_create(card, sbport[dev], 504 if ((err = snd_sbdsp_create(card, sbport[dev],
@@ -500,11 +508,11 @@ static int __devinit snd_cmi8330_probe(int dev,
500 sbdma16[dev], 508 sbdma16[dev],
501 SB_HW_AUTO, &acard->sb)) < 0) { 509 SB_HW_AUTO, &acard->sb)) < 0) {
502 snd_printk(KERN_ERR PFX "(SB16) device busy??\n"); 510 snd_printk(KERN_ERR PFX "(SB16) device busy??\n");
503 goto _err; 511 return err;
504 } 512 }
505 if (acard->sb->hardware != SB_HW_16) { 513 if (acard->sb->hardware != SB_HW_16) {
506 snd_printk(KERN_ERR PFX "(SB16) not found during probe\n"); 514 snd_printk(KERN_ERR PFX "(SB16) not found during probe\n");
507 goto _err; 515 return err;
508 } 516 }
509 517
510 snd_ad1848_out(acard->wss, AD1848_MISC_INFO, 0x40); /* switch on MODE2 */ 518 snd_ad1848_out(acard->wss, AD1848_MISC_INFO, 0x40); /* switch on MODE2 */
@@ -513,12 +521,12 @@ static int __devinit snd_cmi8330_probe(int dev,
513 521
514 if ((err = snd_cmi8330_mixer(card, acard)) < 0) { 522 if ((err = snd_cmi8330_mixer(card, acard)) < 0) {
515 snd_printk(KERN_ERR PFX "failed to create mixers\n"); 523 snd_printk(KERN_ERR PFX "failed to create mixers\n");
516 goto _err; 524 return err;
517 } 525 }
518 526
519 if ((err = snd_cmi8330_pcm(card, acard)) < 0) { 527 if ((err = snd_cmi8330_pcm(card, acard)) < 0) {
520 snd_printk(KERN_ERR PFX "failed to create pcms\n"); 528 snd_printk(KERN_ERR PFX "failed to create pcms\n");
521 goto _err; 529 return err;
522 } 530 }
523 531
524 strcpy(card->driver, "CMI8330/C3D"); 532 strcpy(card->driver, "CMI8330/C3D");
@@ -529,79 +537,162 @@ static int __devinit snd_cmi8330_probe(int dev,
529 wssirq[dev], 537 wssirq[dev],
530 wssdma[dev]); 538 wssdma[dev]);
531 539
532 if ((err = snd_card_set_generic_dev(card)) < 0) 540 return snd_card_register(card);
533 goto _err; 541}
542
543static int __init snd_cmi8330_nonpnp_probe(struct platform_device *pdev)
544{
545 struct snd_card *card;
546 int err;
547 int dev = pdev->id;
534 548
535 if ((err = snd_card_register(card)) < 0) 549 if (wssport[dev] == SNDRV_AUTO_PORT) {
536 goto _err; 550 snd_printk(KERN_ERR PFX "specify wssport\n");
551 return -EINVAL;
552 }
553 if (sbport[dev] == SNDRV_AUTO_PORT) {
554 snd_printk(KERN_ERR PFX "specify sbport\n");
555 return -EINVAL;
556 }
537 557
538 if (pcard) 558 card = snd_cmi8330_card_new(dev);
539 pnp_set_card_drvdata(pcard, card); 559 if (! card)
540 else 560 return -ENOMEM;
541 snd_cmi8330_legacy[dev] = card; 561 snd_card_set_dev(card, &pdev->dev);
562 if ((err = snd_cmi8330_probe(card, dev)) < 0) {
563 snd_card_free(card);
564 return err;
565 }
566 platform_set_drvdata(pdev, card);
542 return 0; 567 return 0;
568}
569
570static int snd_cmi8330_nonpnp_remove(struct platform_device *devptr)
571{
572 snd_card_free(platform_get_drvdata(devptr));
573 platform_set_drvdata(devptr, NULL);
574 return 0;
575}
543 576
544 _err: 577#ifdef CONFIG_PM
545 snd_card_free(card); 578static int snd_cmi8330_nonpnp_suspend(struct platform_device *dev, pm_message_t state)
546 return err; 579{
580 return snd_cmi8330_suspend(platform_get_drvdata(dev));
547} 581}
548 582
583static int snd_cmi8330_nonpnp_resume(struct platform_device *dev)
584{
585 return snd_cmi8330_resume(platform_get_drvdata(dev));
586}
587#endif
588
589#define CMI8330_DRIVER "snd_cmi8330"
590
591static struct platform_driver snd_cmi8330_driver = {
592 .probe = snd_cmi8330_nonpnp_probe,
593 .remove = snd_cmi8330_nonpnp_remove,
594#ifdef CONFIG_PM
595 .suspend = snd_cmi8330_nonpnp_suspend,
596 .resume = snd_cmi8330_nonpnp_resume,
597#endif
598 .driver = {
599 .name = CMI8330_DRIVER
600 },
601};
602
603
549#ifdef CONFIG_PNP 604#ifdef CONFIG_PNP
550static int __devinit snd_cmi8330_pnp_detect(struct pnp_card_link *card, 605static int __devinit snd_cmi8330_pnp_detect(struct pnp_card_link *pcard,
551 const struct pnp_card_device_id *id) 606 const struct pnp_card_device_id *pid)
552{ 607{
553 static int dev; 608 static int dev;
609 struct snd_card *card;
554 int res; 610 int res;
555 611
556 for ( ; dev < SNDRV_CARDS; dev++) { 612 for ( ; dev < SNDRV_CARDS; dev++) {
557 if (!enable[dev] || !isapnp[dev]) 613 if (enable[dev] && isapnp[dev])
558 continue; 614 break;
559 res = snd_cmi8330_probe(dev, card, id); 615 }
560 if (res < 0) 616 if (dev >= SNDRV_CARDS)
561 return res; 617 return -ENODEV;
562 dev++; 618
563 return 0; 619 card = snd_cmi8330_card_new(dev);
620 if (! card)
621 return -ENOMEM;
622 if ((res = snd_cmi8330_pnp(dev, card->private_data, pcard, pid)) < 0) {
623 snd_printk(KERN_ERR PFX "PnP detection failed\n");
624 snd_card_free(card);
625 return res;
626 }
627 snd_card_set_dev(card, &pcard->card->dev);
628 if ((res = snd_cmi8330_probe(card, dev)) < 0) {
629 snd_card_free(card);
630 return res;
564 } 631 }
565 return -ENODEV; 632 pnp_set_card_drvdata(pcard, card);
633 dev++;
634 return 0;
566} 635}
567 636
568static void __devexit snd_cmi8330_pnp_remove(struct pnp_card_link * pcard) 637static void __devexit snd_cmi8330_pnp_remove(struct pnp_card_link * pcard)
569{ 638{
570 struct snd_card *card = (struct snd_card *) pnp_get_card_drvdata(pcard); 639 snd_card_free(pnp_get_card_drvdata(pcard));
640 pnp_set_card_drvdata(pcard, NULL);
641}
571 642
572 snd_card_disconnect(card); 643#ifdef CONFIG_PM
573 snd_card_free_in_thread(card); 644static int snd_cmi8330_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state)
645{
646 return snd_cmi8330_suspend(pnp_get_card_drvdata(pcard));
574} 647}
575 648
649static int snd_cmi8330_pnp_resume(struct pnp_card_link *pcard)
650{
651 return snd_cmi8330_resume(pnp_get_card_drvdata(pcard));
652}
653#endif
654
576static struct pnp_card_driver cmi8330_pnpc_driver = { 655static struct pnp_card_driver cmi8330_pnpc_driver = {
577 .flags = PNP_DRIVER_RES_DISABLE, 656 .flags = PNP_DRIVER_RES_DISABLE,
578 .name = "cmi8330", 657 .name = "cmi8330",
579 .id_table = snd_cmi8330_pnpids, 658 .id_table = snd_cmi8330_pnpids,
580 .probe = snd_cmi8330_pnp_detect, 659 .probe = snd_cmi8330_pnp_detect,
581 .remove = __devexit_p(snd_cmi8330_pnp_remove), 660 .remove = __devexit_p(snd_cmi8330_pnp_remove),
661#ifdef CONFIG_PM
662 .suspend = snd_cmi8330_pnp_suspend,
663 .resume = snd_cmi8330_pnp_resume,
664#endif
582}; 665};
583#endif /* CONFIG_PNP */ 666#endif /* CONFIG_PNP */
584 667
585static int __init alsa_card_cmi8330_init(void) 668static int __init alsa_card_cmi8330_init(void)
586{ 669{
587 int dev, cards = 0; 670 int i, err, cards = 0;
588 671
589 for (dev = 0; dev < SNDRV_CARDS; dev++) { 672 if ((err = platform_driver_register(&snd_cmi8330_driver)) < 0)
590 if (!enable[dev]) 673 return err;
591 continue; 674
592 if (is_isapnp_selected(dev)) 675 for (i = 0; i < SNDRV_CARDS && enable[i]; i++) {
676 struct platform_device *device;
677 if (is_isapnp_selected(i))
593 continue; 678 continue;
594 if (snd_cmi8330_probe(dev, NULL, NULL) >= 0) 679 device = platform_device_register_simple(CMI8330_DRIVER,
595 cards++; 680 i, NULL, 0);
681 if (IS_ERR(device)) {
682 err = PTR_ERR(device);
683 platform_driver_unregister(&snd_cmi8330_driver);
684 return err;
685 }
686 cards++;
596 } 687 }
597#ifdef CONFIG_PNP 688
598 cards += pnp_register_card_driver(&cmi8330_pnpc_driver); 689 err = pnp_register_card_driver(&cmi8330_pnpc_driver);
599#endif 690 if (err > 0)
691 cards += err;
600 692
601 if (!cards) { 693 if (!cards) {
602#ifdef CONFIG_PNP
603 pnp_unregister_card_driver(&cmi8330_pnpc_driver); 694 pnp_unregister_card_driver(&cmi8330_pnpc_driver);
604#endif 695 platform_driver_unregister(&snd_cmi8330_driver);
605#ifdef MODULE 696#ifdef MODULE
606 snd_printk(KERN_ERR "CMI8330 not found or device busy\n"); 697 snd_printk(KERN_ERR "CMI8330 not found or device busy\n");
607#endif 698#endif
@@ -612,14 +703,8 @@ static int __init alsa_card_cmi8330_init(void)
612 703
613static void __exit alsa_card_cmi8330_exit(void) 704static void __exit alsa_card_cmi8330_exit(void)
614{ 705{
615 int i;
616
617#ifdef CONFIG_PNP
618 /* PnP cards first */
619 pnp_unregister_card_driver(&cmi8330_pnpc_driver); 706 pnp_unregister_card_driver(&cmi8330_pnpc_driver);
620#endif 707 platform_driver_unregister(&snd_cmi8330_driver);
621 for (i = 0; i < SNDRV_CARDS; i++)
622 snd_card_free(snd_cmi8330_legacy[i]);
623} 708}
624 709
625module_init(alsa_card_cmi8330_init) 710module_init(alsa_card_cmi8330_init)