diff options
-rw-r--r-- | sound/soc/fsl/fsl_ssi.c | 61 |
1 files changed, 37 insertions, 24 deletions
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index d48afea5d93d..06ac2b92faf3 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c | |||
@@ -289,16 +289,6 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, | |||
289 | */ | 289 | */ |
290 | if (!ssi_private->playback && !ssi_private->capture) { | 290 | if (!ssi_private->playback && !ssi_private->capture) { |
291 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | 291 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; |
292 | int ret; | ||
293 | |||
294 | /* The 'name' should not have any slashes in it. */ | ||
295 | ret = request_irq(ssi_private->irq, fsl_ssi_isr, 0, | ||
296 | ssi_private->name, ssi_private); | ||
297 | if (ret < 0) { | ||
298 | dev_err(substream->pcm->card->dev, | ||
299 | "could not claim irq %u\n", ssi_private->irq); | ||
300 | return ret; | ||
301 | } | ||
302 | 292 | ||
303 | /* | 293 | /* |
304 | * Section 16.5 of the MPC8610 reference manual says that the | 294 | * Section 16.5 of the MPC8610 reference manual says that the |
@@ -522,15 +512,12 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream, | |||
522 | ssi_private->second_stream = NULL; | 512 | ssi_private->second_stream = NULL; |
523 | 513 | ||
524 | /* | 514 | /* |
525 | * If this is the last active substream, disable the SSI and release | 515 | * If this is the last active substream, disable the SSI. |
526 | * the IRQ. | ||
527 | */ | 516 | */ |
528 | if (!ssi_private->playback && !ssi_private->capture) { | 517 | if (!ssi_private->playback && !ssi_private->capture) { |
529 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | 518 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; |
530 | 519 | ||
531 | clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN); | 520 | clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN); |
532 | |||
533 | free_irq(ssi_private->irq, ssi_private); | ||
534 | } | 521 | } |
535 | } | 522 | } |
536 | 523 | ||
@@ -675,17 +662,30 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev) | |||
675 | ret = of_address_to_resource(np, 0, &res); | 662 | ret = of_address_to_resource(np, 0, &res); |
676 | if (ret) { | 663 | if (ret) { |
677 | dev_err(&pdev->dev, "could not determine device resources\n"); | 664 | dev_err(&pdev->dev, "could not determine device resources\n"); |
678 | kfree(ssi_private); | 665 | goto error_kmalloc; |
679 | return ret; | ||
680 | } | 666 | } |
681 | ssi_private->ssi = of_iomap(np, 0); | 667 | ssi_private->ssi = of_iomap(np, 0); |
682 | if (!ssi_private->ssi) { | 668 | if (!ssi_private->ssi) { |
683 | dev_err(&pdev->dev, "could not map device resources\n"); | 669 | dev_err(&pdev->dev, "could not map device resources\n"); |
684 | kfree(ssi_private); | 670 | ret = -ENOMEM; |
685 | return -ENOMEM; | 671 | goto error_kmalloc; |
686 | } | 672 | } |
687 | ssi_private->ssi_phys = res.start; | 673 | ssi_private->ssi_phys = res.start; |
674 | |||
688 | ssi_private->irq = irq_of_parse_and_map(np, 0); | 675 | ssi_private->irq = irq_of_parse_and_map(np, 0); |
676 | if (ssi_private->irq == NO_IRQ) { | ||
677 | dev_err(&pdev->dev, "no irq for node %s\n", np->full_name); | ||
678 | ret = -ENXIO; | ||
679 | goto error_iomap; | ||
680 | } | ||
681 | |||
682 | /* The 'name' should not have any slashes in it. */ | ||
683 | ret = request_irq(ssi_private->irq, fsl_ssi_isr, 0, ssi_private->name, | ||
684 | ssi_private); | ||
685 | if (ret < 0) { | ||
686 | dev_err(&pdev->dev, "could not claim irq %u\n", ssi_private->irq); | ||
687 | goto error_irqmap; | ||
688 | } | ||
689 | 689 | ||
690 | /* Are the RX and the TX clocks locked? */ | 690 | /* Are the RX and the TX clocks locked? */ |
691 | if (of_find_property(np, "fsl,ssi-asynchronous", NULL)) | 691 | if (of_find_property(np, "fsl,ssi-asynchronous", NULL)) |
@@ -711,7 +711,7 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev) | |||
711 | if (ret) { | 711 | if (ret) { |
712 | dev_err(&pdev->dev, "could not create sysfs %s file\n", | 712 | dev_err(&pdev->dev, "could not create sysfs %s file\n", |
713 | ssi_private->dev_attr.attr.name); | 713 | ssi_private->dev_attr.attr.name); |
714 | goto error; | 714 | goto error_irq; |
715 | } | 715 | } |
716 | 716 | ||
717 | /* Register with ASoC */ | 717 | /* Register with ASoC */ |
@@ -720,7 +720,7 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev) | |||
720 | ret = snd_soc_register_dai(&pdev->dev, &ssi_private->cpu_dai_drv); | 720 | ret = snd_soc_register_dai(&pdev->dev, &ssi_private->cpu_dai_drv); |
721 | if (ret) { | 721 | if (ret) { |
722 | dev_err(&pdev->dev, "failed to register DAI: %d\n", ret); | 722 | dev_err(&pdev->dev, "failed to register DAI: %d\n", ret); |
723 | goto error; | 723 | goto error_dev; |
724 | } | 724 | } |
725 | 725 | ||
726 | /* Trigger the machine driver's probe function. The platform driver | 726 | /* Trigger the machine driver's probe function. The platform driver |
@@ -741,18 +741,28 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev) | |||
741 | if (IS_ERR(ssi_private->pdev)) { | 741 | if (IS_ERR(ssi_private->pdev)) { |
742 | ret = PTR_ERR(ssi_private->pdev); | 742 | ret = PTR_ERR(ssi_private->pdev); |
743 | dev_err(&pdev->dev, "failed to register platform: %d\n", ret); | 743 | dev_err(&pdev->dev, "failed to register platform: %d\n", ret); |
744 | goto error; | 744 | goto error_dai; |
745 | } | 745 | } |
746 | 746 | ||
747 | return 0; | 747 | return 0; |
748 | 748 | ||
749 | error: | 749 | error_dai: |
750 | snd_soc_unregister_dai(&pdev->dev); | 750 | snd_soc_unregister_dai(&pdev->dev); |
751 | |||
752 | error_dev: | ||
751 | dev_set_drvdata(&pdev->dev, NULL); | 753 | dev_set_drvdata(&pdev->dev, NULL); |
752 | if (dev_attr) | 754 | device_remove_file(&pdev->dev, dev_attr); |
753 | device_remove_file(&pdev->dev, dev_attr); | 755 | |
756 | error_irq: | ||
757 | free_irq(ssi_private->irq, ssi_private); | ||
758 | |||
759 | error_irqmap: | ||
754 | irq_dispose_mapping(ssi_private->irq); | 760 | irq_dispose_mapping(ssi_private->irq); |
761 | |||
762 | error_iomap: | ||
755 | iounmap(ssi_private->ssi); | 763 | iounmap(ssi_private->ssi); |
764 | |||
765 | error_kmalloc: | ||
756 | kfree(ssi_private); | 766 | kfree(ssi_private); |
757 | 767 | ||
758 | return ret; | 768 | return ret; |
@@ -766,6 +776,9 @@ static int fsl_ssi_remove(struct platform_device *pdev) | |||
766 | snd_soc_unregister_dai(&pdev->dev); | 776 | snd_soc_unregister_dai(&pdev->dev); |
767 | device_remove_file(&pdev->dev, &ssi_private->dev_attr); | 777 | device_remove_file(&pdev->dev, &ssi_private->dev_attr); |
768 | 778 | ||
779 | free_irq(ssi_private->irq, ssi_private); | ||
780 | irq_dispose_mapping(ssi_private->irq); | ||
781 | |||
769 | kfree(ssi_private); | 782 | kfree(ssi_private); |
770 | dev_set_drvdata(&pdev->dev, NULL); | 783 | dev_set_drvdata(&pdev->dev, NULL); |
771 | 784 | ||