diff options
Diffstat (limited to 'sound/sparc/dbri.c')
-rw-r--r-- | sound/sparc/dbri.c | 143 |
1 files changed, 69 insertions, 74 deletions
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index 12d11fc5f825..e96023fcdbec 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c | |||
@@ -66,6 +66,7 @@ | |||
66 | #include <sound/control.h> | 66 | #include <sound/control.h> |
67 | #include <sound/initval.h> | 67 | #include <sound/initval.h> |
68 | 68 | ||
69 | #include <asm/prom.h> | ||
69 | #include <asm/sbus.h> | 70 | #include <asm/sbus.h> |
70 | #include <asm/atomic.h> | 71 | #include <asm/atomic.h> |
71 | 72 | ||
@@ -296,8 +297,6 @@ struct dbri_streaminfo { | |||
296 | 297 | ||
297 | /* This structure holds the information for both chips (DBRI & CS4215) */ | 298 | /* This structure holds the information for both chips (DBRI & CS4215) */ |
298 | struct snd_dbri { | 299 | struct snd_dbri { |
299 | struct snd_card *card; /* ALSA card */ | ||
300 | |||
301 | int regs_size, irq; /* Needed for unload */ | 300 | int regs_size, irq; /* Needed for unload */ |
302 | struct sbus_dev *sdev; /* SBUS device info */ | 301 | struct sbus_dev *sdev; /* SBUS device info */ |
303 | spinlock_t lock; | 302 | spinlock_t lock; |
@@ -318,8 +317,6 @@ struct snd_dbri { | |||
318 | struct cs4215 mm; /* mmcodec special info */ | 317 | struct cs4215 mm; /* mmcodec special info */ |
319 | /* per stream (playback/record) info */ | 318 | /* per stream (playback/record) info */ |
320 | struct dbri_streaminfo stream_info[DBRI_NO_STREAMS]; | 319 | struct dbri_streaminfo stream_info[DBRI_NO_STREAMS]; |
321 | |||
322 | struct snd_dbri *next; | ||
323 | }; | 320 | }; |
324 | 321 | ||
325 | #define DBRI_MAX_VOLUME 63 /* Output volume */ | 322 | #define DBRI_MAX_VOLUME 63 /* Output volume */ |
@@ -571,8 +568,6 @@ struct snd_dbri { | |||
571 | #define DBRI_STREAM(dbri, substream) \ | 568 | #define DBRI_STREAM(dbri, substream) \ |
572 | &dbri->stream_info[DBRI_STREAMNO(substream)] | 569 | &dbri->stream_info[DBRI_STREAMNO(substream)] |
573 | 570 | ||
574 | static struct snd_dbri *dbri_list; /* All DBRI devices */ | ||
575 | |||
576 | /* | 571 | /* |
577 | * Short data pipes transmit LSB first. The CS4215 receives MSB first. Grrr. | 572 | * Short data pipes transmit LSB first. The CS4215 receives MSB first. Grrr. |
578 | * So we have to reverse the bits. Note: not all bit lengths are supported | 573 | * So we have to reverse the bits. Note: not all bit lengths are supported |
@@ -748,7 +743,7 @@ static void dbri_reset(struct snd_dbri *dbri) | |||
748 | } | 743 | } |
749 | 744 | ||
750 | /* Lock must not be held before calling this */ | 745 | /* Lock must not be held before calling this */ |
751 | static void __init dbri_initialize(struct snd_dbri *dbri) | 746 | static void __devinit dbri_initialize(struct snd_dbri *dbri) |
752 | { | 747 | { |
753 | s32 *cmd; | 748 | s32 *cmd; |
754 | u32 dma_addr; | 749 | u32 dma_addr; |
@@ -1308,7 +1303,7 @@ to the DBRI via the CHI interface and few of the DBRI's PIO pins. | |||
1308 | * Lock must not be held before calling it. | 1303 | * Lock must not be held before calling it. |
1309 | 1304 | ||
1310 | */ | 1305 | */ |
1311 | static __init void cs4215_setup_pipes(struct snd_dbri *dbri) | 1306 | static __devinit void cs4215_setup_pipes(struct snd_dbri *dbri) |
1312 | { | 1307 | { |
1313 | unsigned long flags; | 1308 | unsigned long flags; |
1314 | 1309 | ||
@@ -1341,7 +1336,7 @@ static __init void cs4215_setup_pipes(struct snd_dbri *dbri) | |||
1341 | dbri_cmdwait(dbri); | 1336 | dbri_cmdwait(dbri); |
1342 | } | 1337 | } |
1343 | 1338 | ||
1344 | static __init int cs4215_init_data(struct cs4215 *mm) | 1339 | static __devinit int cs4215_init_data(struct cs4215 *mm) |
1345 | { | 1340 | { |
1346 | /* | 1341 | /* |
1347 | * No action, memory resetting only. | 1342 | * No action, memory resetting only. |
@@ -1633,7 +1628,7 @@ static int cs4215_prepare(struct snd_dbri *dbri, unsigned int rate, | |||
1633 | /* | 1628 | /* |
1634 | * | 1629 | * |
1635 | */ | 1630 | */ |
1636 | static __init int cs4215_init(struct snd_dbri *dbri) | 1631 | static __devinit int cs4215_init(struct snd_dbri *dbri) |
1637 | { | 1632 | { |
1638 | u32 reg2 = sbus_readl(dbri->regs + REG2); | 1633 | u32 reg2 = sbus_readl(dbri->regs + REG2); |
1639 | dprintk(D_MM, "cs4215_init: reg2=0x%x\n", reg2); | 1634 | dprintk(D_MM, "cs4215_init: reg2=0x%x\n", reg2); |
@@ -2218,12 +2213,12 @@ static struct snd_pcm_ops snd_dbri_ops = { | |||
2218 | .pointer = snd_dbri_pointer, | 2213 | .pointer = snd_dbri_pointer, |
2219 | }; | 2214 | }; |
2220 | 2215 | ||
2221 | static int __devinit snd_dbri_pcm(struct snd_dbri *dbri) | 2216 | static int __devinit snd_dbri_pcm(struct snd_card *card) |
2222 | { | 2217 | { |
2223 | struct snd_pcm *pcm; | 2218 | struct snd_pcm *pcm; |
2224 | int err; | 2219 | int err; |
2225 | 2220 | ||
2226 | if ((err = snd_pcm_new(dbri->card, | 2221 | if ((err = snd_pcm_new(card, |
2227 | /* ID */ "sun_dbri", | 2222 | /* ID */ "sun_dbri", |
2228 | /* device */ 0, | 2223 | /* device */ 0, |
2229 | /* playback count */ 1, | 2224 | /* playback count */ 1, |
@@ -2234,9 +2229,9 @@ static int __devinit snd_dbri_pcm(struct snd_dbri *dbri) | |||
2234 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_dbri_ops); | 2229 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_dbri_ops); |
2235 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_dbri_ops); | 2230 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_dbri_ops); |
2236 | 2231 | ||
2237 | pcm->private_data = dbri; | 2232 | pcm->private_data = card->private_data; |
2238 | pcm->info_flags = 0; | 2233 | pcm->info_flags = 0; |
2239 | strcpy(pcm->name, dbri->card->shortname); | 2234 | strcpy(pcm->name, card->shortname); |
2240 | 2235 | ||
2241 | if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, | 2236 | if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, |
2242 | SNDRV_DMA_TYPE_CONTINUOUS, | 2237 | SNDRV_DMA_TYPE_CONTINUOUS, |
@@ -2422,14 +2417,14 @@ static struct snd_kcontrol_new dbri_controls[] __devinitdata = { | |||
2422 | CS4215_SINGLE("Mic boost", 4, 4, 1, 1) | 2417 | CS4215_SINGLE("Mic boost", 4, 4, 1, 1) |
2423 | }; | 2418 | }; |
2424 | 2419 | ||
2425 | static int __init snd_dbri_mixer(struct snd_dbri *dbri) | 2420 | static int __devinit snd_dbri_mixer(struct snd_card *card) |
2426 | { | 2421 | { |
2427 | struct snd_card *card; | ||
2428 | int idx, err; | 2422 | int idx, err; |
2423 | struct snd_dbri *dbri; | ||
2429 | 2424 | ||
2430 | snd_assert(dbri != NULL && dbri->card != NULL, return -EINVAL); | 2425 | snd_assert(card != NULL && card->private_data != NULL, return -EINVAL); |
2426 | dbri = card->private_data; | ||
2431 | 2427 | ||
2432 | card = dbri->card; | ||
2433 | strcpy(card->mixername, card->shortname); | 2428 | strcpy(card->mixername, card->shortname); |
2434 | 2429 | ||
2435 | for (idx = 0; idx < ARRAY_SIZE(dbri_controls); idx++) { | 2430 | for (idx = 0; idx < ARRAY_SIZE(dbri_controls); idx++) { |
@@ -2485,15 +2480,16 @@ static void dbri_debug_read(struct snd_info_entry *entry, | |||
2485 | } | 2480 | } |
2486 | #endif | 2481 | #endif |
2487 | 2482 | ||
2488 | void snd_dbri_proc(struct snd_dbri *dbri) | 2483 | void __devinit snd_dbri_proc(struct snd_card *card) |
2489 | { | 2484 | { |
2485 | struct snd_dbri *dbri = card->private_data; | ||
2490 | struct snd_info_entry *entry; | 2486 | struct snd_info_entry *entry; |
2491 | 2487 | ||
2492 | if (!snd_card_proc_new(dbri->card, "regs", &entry)) | 2488 | if (!snd_card_proc_new(card, "regs", &entry)) |
2493 | snd_info_set_text_ops(entry, dbri, dbri_regs_read); | 2489 | snd_info_set_text_ops(entry, dbri, dbri_regs_read); |
2494 | 2490 | ||
2495 | #ifdef DBRI_DEBUG | 2491 | #ifdef DBRI_DEBUG |
2496 | if (!snd_card_proc_new(dbri->card, "debug", &entry)) { | 2492 | if (!snd_card_proc_new(card, "debug", &entry)) { |
2497 | snd_info_set_text_ops(entry, dbri, dbri_debug_read); | 2493 | snd_info_set_text_ops(entry, dbri, dbri_debug_read); |
2498 | entry->mode = S_IFREG | S_IRUGO; /* Readable only. */ | 2494 | entry->mode = S_IFREG | S_IRUGO; /* Readable only. */ |
2499 | } | 2495 | } |
@@ -2507,17 +2503,16 @@ void snd_dbri_proc(struct snd_dbri *dbri) | |||
2507 | */ | 2503 | */ |
2508 | static void snd_dbri_free(struct snd_dbri *dbri); | 2504 | static void snd_dbri_free(struct snd_dbri *dbri); |
2509 | 2505 | ||
2510 | static int __init snd_dbri_create(struct snd_card *card, | 2506 | static int __devinit snd_dbri_create(struct snd_card *card, |
2511 | struct sbus_dev *sdev, | 2507 | struct sbus_dev *sdev, |
2512 | struct linux_prom_irqs *irq, int dev) | 2508 | int irq, int dev) |
2513 | { | 2509 | { |
2514 | struct snd_dbri *dbri = card->private_data; | 2510 | struct snd_dbri *dbri = card->private_data; |
2515 | int err; | 2511 | int err; |
2516 | 2512 | ||
2517 | spin_lock_init(&dbri->lock); | 2513 | spin_lock_init(&dbri->lock); |
2518 | dbri->card = card; | ||
2519 | dbri->sdev = sdev; | 2514 | dbri->sdev = sdev; |
2520 | dbri->irq = irq->pri; | 2515 | dbri->irq = irq; |
2521 | 2516 | ||
2522 | dbri->dma = sbus_alloc_consistent(sdev, sizeof(struct dbri_dma), | 2517 | dbri->dma = sbus_alloc_consistent(sdev, sizeof(struct dbri_dma), |
2523 | &dbri->dma_dvma); | 2518 | &dbri->dma_dvma); |
@@ -2555,9 +2550,6 @@ static int __init snd_dbri_create(struct snd_card *card, | |||
2555 | return err; | 2550 | return err; |
2556 | } | 2551 | } |
2557 | 2552 | ||
2558 | dbri->next = dbri_list; | ||
2559 | dbri_list = dbri; | ||
2560 | |||
2561 | return 0; | 2553 | return 0; |
2562 | } | 2554 | } |
2563 | 2555 | ||
@@ -2577,20 +2569,19 @@ static void snd_dbri_free(struct snd_dbri *dbri) | |||
2577 | (void *)dbri->dma, dbri->dma_dvma); | 2569 | (void *)dbri->dma, dbri->dma_dvma); |
2578 | } | 2570 | } |
2579 | 2571 | ||
2580 | static int __init dbri_attach(int prom_node, struct sbus_dev *sdev) | 2572 | static int __devinit dbri_probe(struct of_device *of_dev, |
2573 | const struct of_device_id *match) | ||
2581 | { | 2574 | { |
2575 | struct sbus_dev *sdev = to_sbus_device(&of_dev->dev); | ||
2582 | struct snd_dbri *dbri; | 2576 | struct snd_dbri *dbri; |
2583 | struct linux_prom_irqs irq; | 2577 | int irq; |
2584 | struct resource *rp; | 2578 | struct resource *rp; |
2585 | struct snd_card *card; | 2579 | struct snd_card *card; |
2586 | static int dev = 0; | 2580 | static int dev = 0; |
2587 | int err; | 2581 | int err; |
2588 | 2582 | ||
2589 | if (sdev->prom_name[9] < 'e') { | 2583 | dprintk(D_GEN, "DBRI: Found %s in SBUS slot %d\n", |
2590 | printk(KERN_ERR "DBRI: unsupported chip version %c found.\n", | 2584 | sdev->prom_name, sdev->slot); |
2591 | sdev->prom_name[9]); | ||
2592 | return -EIO; | ||
2593 | } | ||
2594 | 2585 | ||
2595 | if (dev >= SNDRV_CARDS) | 2586 | if (dev >= SNDRV_CARDS) |
2596 | return -ENODEV; | 2587 | return -ENODEV; |
@@ -2599,10 +2590,9 @@ static int __init dbri_attach(int prom_node, struct sbus_dev *sdev) | |||
2599 | return -ENOENT; | 2590 | return -ENOENT; |
2600 | } | 2591 | } |
2601 | 2592 | ||
2602 | err = prom_getproperty(prom_node, "intr", (char *)&irq, sizeof(irq)); | 2593 | irq = sdev->irqs[0]; |
2603 | if (err < 0) { | 2594 | if (irq <= 0) { |
2604 | printk(KERN_ERR "DBRI-%d: Firmware node lacks IRQ property.\n", | 2595 | printk(KERN_ERR "DBRI-%d: No IRQ.\n", dev); |
2605 | dev); | ||
2606 | return -ENODEV; | 2596 | return -ENODEV; |
2607 | } | 2597 | } |
2608 | 2598 | ||
@@ -2616,24 +2606,26 @@ static int __init dbri_attach(int prom_node, struct sbus_dev *sdev) | |||
2616 | rp = &sdev->resource[0]; | 2606 | rp = &sdev->resource[0]; |
2617 | sprintf(card->longname, "%s at 0x%02lx:0x%016Lx, irq %d", | 2607 | sprintf(card->longname, "%s at 0x%02lx:0x%016Lx, irq %d", |
2618 | card->shortname, | 2608 | card->shortname, |
2619 | rp->flags & 0xffL, (unsigned long long)rp->start, irq.pri); | 2609 | rp->flags & 0xffL, (unsigned long long)rp->start, irq); |
2620 | 2610 | ||
2621 | if ((err = snd_dbri_create(card, sdev, &irq, dev)) < 0) { | 2611 | err = snd_dbri_create(card, sdev, irq, dev); |
2612 | if (err < 0) { | ||
2622 | snd_card_free(card); | 2613 | snd_card_free(card); |
2623 | return err; | 2614 | return err; |
2624 | } | 2615 | } |
2625 | 2616 | ||
2626 | dbri = card->private_data; | 2617 | dbri = card->private_data; |
2627 | err = snd_dbri_pcm(dbri); | 2618 | err = snd_dbri_pcm(card); |
2628 | if (err < 0) | 2619 | if (err < 0) |
2629 | goto _err; | 2620 | goto _err; |
2630 | 2621 | ||
2631 | err = snd_dbri_mixer(dbri); | 2622 | err = snd_dbri_mixer(card); |
2632 | if (err < 0) | 2623 | if (err < 0) |
2633 | goto _err; | 2624 | goto _err; |
2634 | 2625 | ||
2635 | /* /proc file handling */ | 2626 | /* /proc file handling */ |
2636 | snd_dbri_proc(dbri); | 2627 | snd_dbri_proc(card); |
2628 | dev_set_drvdata(&of_dev->dev, card); | ||
2637 | 2629 | ||
2638 | err = snd_card_register(card); | 2630 | err = snd_card_register(card); |
2639 | if (err < 0) | 2631 | if (err < 0) |
@@ -2652,43 +2644,46 @@ _err: | |||
2652 | return err; | 2644 | return err; |
2653 | } | 2645 | } |
2654 | 2646 | ||
2655 | /* Probe for the dbri chip and then attach the driver. */ | 2647 | static int __devexit dbri_remove(struct of_device *dev) |
2656 | static int __init dbri_init(void) | ||
2657 | { | 2648 | { |
2658 | struct sbus_bus *sbus; | 2649 | struct snd_card *card = dev_get_drvdata(&dev->dev); |
2659 | struct sbus_dev *sdev; | ||
2660 | int found = 0; | ||
2661 | |||
2662 | /* Probe each SBUS for the DBRI chip(s). */ | ||
2663 | for_all_sbusdev(sdev, sbus) { | ||
2664 | /* | ||
2665 | * The version is coded in the last character | ||
2666 | */ | ||
2667 | if (!strncmp(sdev->prom_name, "SUNW,DBRI", 9)) { | ||
2668 | dprintk(D_GEN, "DBRI: Found %s in SBUS slot %d\n", | ||
2669 | sdev->prom_name, sdev->slot); | ||
2670 | 2650 | ||
2671 | if (dbri_attach(sdev->prom_node, sdev) == 0) | 2651 | snd_dbri_free(card->private_data); |
2672 | found++; | 2652 | snd_card_free(card); |
2673 | } | ||
2674 | } | ||
2675 | 2653 | ||
2676 | return (found > 0) ? 0 : -EIO; | 2654 | dev_set_drvdata(&dev->dev, NULL); |
2655 | |||
2656 | return 0; | ||
2677 | } | 2657 | } |
2678 | 2658 | ||
2679 | static void __exit dbri_exit(void) | 2659 | static struct of_device_id dbri_match[] = { |
2680 | { | 2660 | { |
2681 | struct snd_dbri *this = dbri_list; | 2661 | .name = "SUNW,DBRIe", |
2662 | }, | ||
2663 | { | ||
2664 | .name = "SUNW,DBRIf", | ||
2665 | }, | ||
2666 | {}, | ||
2667 | }; | ||
2682 | 2668 | ||
2683 | while (this != NULL) { | 2669 | MODULE_DEVICE_TABLE(of, dbri_match); |
2684 | struct snd_dbri *next = this->next; | ||
2685 | struct snd_card *card = this->card; | ||
2686 | 2670 | ||
2687 | snd_dbri_free(this); | 2671 | static struct of_platform_driver dbri_sbus_driver = { |
2688 | snd_card_free(card); | 2672 | .name = "dbri", |
2689 | this = next; | 2673 | .match_table = dbri_match, |
2690 | } | 2674 | .probe = dbri_probe, |
2691 | dbri_list = NULL; | 2675 | .remove = __devexit_p(dbri_remove), |
2676 | }; | ||
2677 | |||
2678 | /* Probe for the dbri chip and then attach the driver. */ | ||
2679 | static int __init dbri_init(void) | ||
2680 | { | ||
2681 | return of_register_driver(&dbri_sbus_driver, &sbus_bus_type); | ||
2682 | } | ||
2683 | |||
2684 | static void __exit dbri_exit(void) | ||
2685 | { | ||
2686 | of_unregister_driver(&dbri_sbus_driver); | ||
2692 | } | 2687 | } |
2693 | 2688 | ||
2694 | module_init(dbri_init); | 2689 | module_init(dbri_init); |