aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-core.c
diff options
context:
space:
mode:
authorLiam Girdwood <lrg@ti.com>2011-06-09 09:45:53 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-06-09 10:07:27 -0400
commitddee627cf6bb601aa980104fc17d4f84201380be (patch)
tree6fac651b4891e65dd4c869fffb672a40933913c1 /sound/soc/soc-core.c
parentbf564ea99797f6e66796d0d0a24a8fe872d5f26e (diff)
ASoC: core - Separate out PCM operations into new file.
In preparation for Dynamic PCM support (AKA DSP support). There will be future patches that add support to allow PCMs to be dynamically routed to multiple DAIs at startup and also during stream runtime. This patch moves the ASoC core PCM operaitions into a new file called soc-pcm.c. This will in simplify the ASoC core features into distinct files. Signed-off-by: Liam Girdwood <lrg@ti.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/soc-core.c')
-rw-r--r--sound/soc/soc-core.c612
1 files changed, 1 insertions, 611 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index df5608db3350..32d7d2f8147c 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -44,7 +44,6 @@
44 44
45#define NAME_SIZE 32 45#define NAME_SIZE 32
46 46
47static DEFINE_MUTEX(pcm_mutex);
48static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq); 47static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq);
49 48
50#ifdef CONFIG_DEBUG_FS 49#ifdef CONFIG_DEBUG_FS
@@ -58,7 +57,7 @@ static LIST_HEAD(dai_list);
58static LIST_HEAD(platform_list); 57static LIST_HEAD(platform_list);
59static LIST_HEAD(codec_list); 58static LIST_HEAD(codec_list);
60 59
61static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num); 60int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num);
62 61
63/* 62/*
64 * This is a timeout to do a DAPM powerdown after a stream is closed(). 63 * This is a timeout to do a DAPM powerdown after a stream is closed().
@@ -485,552 +484,6 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec)
485} 484}
486#endif 485#endif
487 486
488static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)
489{
490 struct snd_soc_pcm_runtime *rtd = substream->private_data;
491 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
492 struct snd_soc_dai *codec_dai = rtd->codec_dai;
493 int ret;
494
495 if (!codec_dai->driver->symmetric_rates &&
496 !cpu_dai->driver->symmetric_rates &&
497 !rtd->dai_link->symmetric_rates)
498 return 0;
499
500 /* This can happen if multiple streams are starting simultaneously -
501 * the second can need to get its constraints before the first has
502 * picked a rate. Complain and allow the application to carry on.
503 */
504 if (!rtd->rate) {
505 dev_warn(&rtd->dev,
506 "Not enforcing symmetric_rates due to race\n");
507 return 0;
508 }
509
510 dev_dbg(&rtd->dev, "Symmetry forces %dHz rate\n", rtd->rate);
511
512 ret = snd_pcm_hw_constraint_minmax(substream->runtime,
513 SNDRV_PCM_HW_PARAM_RATE,
514 rtd->rate, rtd->rate);
515 if (ret < 0) {
516 dev_err(&rtd->dev,
517 "Unable to apply rate symmetry constraint: %d\n", ret);
518 return ret;
519 }
520
521 return 0;
522}
523
524/*
525 * Called by ALSA when a PCM substream is opened, the runtime->hw record is
526 * then initialized and any private data can be allocated. This also calls
527 * startup for the cpu DAI, platform, machine and codec DAI.
528 */
529static int soc_pcm_open(struct snd_pcm_substream *substream)
530{
531 struct snd_soc_pcm_runtime *rtd = substream->private_data;
532 struct snd_pcm_runtime *runtime = substream->runtime;
533 struct snd_soc_platform *platform = rtd->platform;
534 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
535 struct snd_soc_dai *codec_dai = rtd->codec_dai;
536 struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver;
537 struct snd_soc_dai_driver *codec_dai_drv = codec_dai->driver;
538 int ret = 0;
539
540 mutex_lock(&pcm_mutex);
541
542 /* startup the audio subsystem */
543 if (cpu_dai->driver->ops->startup) {
544 ret = cpu_dai->driver->ops->startup(substream, cpu_dai);
545 if (ret < 0) {
546 printk(KERN_ERR "asoc: can't open interface %s\n",
547 cpu_dai->name);
548 goto out;
549 }
550 }
551
552 if (platform->driver->ops && platform->driver->ops->open) {
553 ret = platform->driver->ops->open(substream);
554 if (ret < 0) {
555 printk(KERN_ERR "asoc: can't open platform %s\n", platform->name);
556 goto platform_err;
557 }
558 }
559
560 if (codec_dai->driver->ops->startup) {
561 ret = codec_dai->driver->ops->startup(substream, codec_dai);
562 if (ret < 0) {
563 printk(KERN_ERR "asoc: can't open codec %s\n",
564 codec_dai->name);
565 goto codec_dai_err;
566 }
567 }
568
569 if (rtd->dai_link->ops && rtd->dai_link->ops->startup) {
570 ret = rtd->dai_link->ops->startup(substream);
571 if (ret < 0) {
572 printk(KERN_ERR "asoc: %s startup failed\n", rtd->dai_link->name);
573 goto machine_err;
574 }
575 }
576
577 /* Check that the codec and cpu DAIs are compatible */
578 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
579 runtime->hw.rate_min =
580 max(codec_dai_drv->playback.rate_min,
581 cpu_dai_drv->playback.rate_min);
582 runtime->hw.rate_max =
583 min(codec_dai_drv->playback.rate_max,
584 cpu_dai_drv->playback.rate_max);
585 runtime->hw.channels_min =
586 max(codec_dai_drv->playback.channels_min,
587 cpu_dai_drv->playback.channels_min);
588 runtime->hw.channels_max =
589 min(codec_dai_drv->playback.channels_max,
590 cpu_dai_drv->playback.channels_max);
591 runtime->hw.formats =
592 codec_dai_drv->playback.formats & cpu_dai_drv->playback.formats;
593 runtime->hw.rates =
594 codec_dai_drv->playback.rates & cpu_dai_drv->playback.rates;
595 if (codec_dai_drv->playback.rates
596 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
597 runtime->hw.rates |= cpu_dai_drv->playback.rates;
598 if (cpu_dai_drv->playback.rates
599 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
600 runtime->hw.rates |= codec_dai_drv->playback.rates;
601 } else {
602 runtime->hw.rate_min =
603 max(codec_dai_drv->capture.rate_min,
604 cpu_dai_drv->capture.rate_min);
605 runtime->hw.rate_max =
606 min(codec_dai_drv->capture.rate_max,
607 cpu_dai_drv->capture.rate_max);
608 runtime->hw.channels_min =
609 max(codec_dai_drv->capture.channels_min,
610 cpu_dai_drv->capture.channels_min);
611 runtime->hw.channels_max =
612 min(codec_dai_drv->capture.channels_max,
613 cpu_dai_drv->capture.channels_max);
614 runtime->hw.formats =
615 codec_dai_drv->capture.formats & cpu_dai_drv->capture.formats;
616 runtime->hw.rates =
617 codec_dai_drv->capture.rates & cpu_dai_drv->capture.rates;
618 if (codec_dai_drv->capture.rates
619 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
620 runtime->hw.rates |= cpu_dai_drv->capture.rates;
621 if (cpu_dai_drv->capture.rates
622 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
623 runtime->hw.rates |= codec_dai_drv->capture.rates;
624 }
625
626 ret = -EINVAL;
627 snd_pcm_limit_hw_rates(runtime);
628 if (!runtime->hw.rates) {
629 printk(KERN_ERR "asoc: %s <-> %s No matching rates\n",
630 codec_dai->name, cpu_dai->name);
631 goto config_err;
632 }
633 if (!runtime->hw.formats) {
634 printk(KERN_ERR "asoc: %s <-> %s No matching formats\n",
635 codec_dai->name, cpu_dai->name);
636 goto config_err;
637 }
638 if (!runtime->hw.channels_min || !runtime->hw.channels_max ||
639 runtime->hw.channels_min > runtime->hw.channels_max) {
640 printk(KERN_ERR "asoc: %s <-> %s No matching channels\n",
641 codec_dai->name, cpu_dai->name);
642 goto config_err;
643 }
644
645 /* Symmetry only applies if we've already got an active stream. */
646 if (cpu_dai->active || codec_dai->active) {
647 ret = soc_pcm_apply_symmetry(substream);
648 if (ret != 0)
649 goto config_err;
650 }
651
652 pr_debug("asoc: %s <-> %s info:\n",
653 codec_dai->name, cpu_dai->name);
654 pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates);
655 pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min,
656 runtime->hw.channels_max);
657 pr_debug("asoc: min rate %d max rate %d\n", runtime->hw.rate_min,
658 runtime->hw.rate_max);
659
660 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
661 cpu_dai->playback_active++;
662 codec_dai->playback_active++;
663 } else {
664 cpu_dai->capture_active++;
665 codec_dai->capture_active++;
666 }
667 cpu_dai->active++;
668 codec_dai->active++;
669 rtd->codec->active++;
670 mutex_unlock(&pcm_mutex);
671 return 0;
672
673config_err:
674 if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown)
675 rtd->dai_link->ops->shutdown(substream);
676
677machine_err:
678 if (codec_dai->driver->ops->shutdown)
679 codec_dai->driver->ops->shutdown(substream, codec_dai);
680
681codec_dai_err:
682 if (platform->driver->ops && platform->driver->ops->close)
683 platform->driver->ops->close(substream);
684
685platform_err:
686 if (cpu_dai->driver->ops->shutdown)
687 cpu_dai->driver->ops->shutdown(substream, cpu_dai);
688out:
689 mutex_unlock(&pcm_mutex);
690 return ret;
691}
692
693/*
694 * Power down the audio subsystem pmdown_time msecs after close is called.
695 * This is to ensure there are no pops or clicks in between any music tracks
696 * due to DAPM power cycling.
697 */
698static void close_delayed_work(struct work_struct *work)
699{
700 struct snd_soc_pcm_runtime *rtd =
701 container_of(work, struct snd_soc_pcm_runtime, delayed_work.work);
702 struct snd_soc_dai *codec_dai = rtd->codec_dai;
703
704 mutex_lock(&pcm_mutex);
705
706 pr_debug("pop wq checking: %s status: %s waiting: %s\n",
707 codec_dai->driver->playback.stream_name,
708 codec_dai->playback_active ? "active" : "inactive",
709 codec_dai->pop_wait ? "yes" : "no");
710
711 /* are we waiting on this codec DAI stream */
712 if (codec_dai->pop_wait == 1) {
713 codec_dai->pop_wait = 0;
714 snd_soc_dapm_stream_event(rtd,
715 codec_dai->driver->playback.stream_name,
716 SND_SOC_DAPM_STREAM_STOP);
717 }
718
719 mutex_unlock(&pcm_mutex);
720}
721
722/*
723 * Called by ALSA when a PCM substream is closed. Private data can be
724 * freed here. The cpu DAI, codec DAI, machine and platform are also
725 * shutdown.
726 */
727static int soc_codec_close(struct snd_pcm_substream *substream)
728{
729 struct snd_soc_pcm_runtime *rtd = substream->private_data;
730 struct snd_soc_platform *platform = rtd->platform;
731 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
732 struct snd_soc_dai *codec_dai = rtd->codec_dai;
733 struct snd_soc_codec *codec = rtd->codec;
734
735 mutex_lock(&pcm_mutex);
736
737 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
738 cpu_dai->playback_active--;
739 codec_dai->playback_active--;
740 } else {
741 cpu_dai->capture_active--;
742 codec_dai->capture_active--;
743 }
744
745 cpu_dai->active--;
746 codec_dai->active--;
747 codec->active--;
748
749 /* Muting the DAC suppresses artifacts caused during digital
750 * shutdown, for example from stopping clocks.
751 */
752 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
753 snd_soc_dai_digital_mute(codec_dai, 1);
754
755 if (cpu_dai->driver->ops->shutdown)
756 cpu_dai->driver->ops->shutdown(substream, cpu_dai);
757
758 if (codec_dai->driver->ops->shutdown)
759 codec_dai->driver->ops->shutdown(substream, codec_dai);
760
761 if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown)
762 rtd->dai_link->ops->shutdown(substream);
763
764 if (platform->driver->ops && platform->driver->ops->close)
765 platform->driver->ops->close(substream);
766 cpu_dai->runtime = NULL;
767
768 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
769 /* start delayed pop wq here for playback streams */
770 codec_dai->pop_wait = 1;
771 schedule_delayed_work(&rtd->delayed_work,
772 msecs_to_jiffies(rtd->pmdown_time));
773 } else {
774 /* capture streams can be powered down now */
775 snd_soc_dapm_stream_event(rtd,
776 codec_dai->driver->capture.stream_name,
777 SND_SOC_DAPM_STREAM_STOP);
778 }
779
780 mutex_unlock(&pcm_mutex);
781 return 0;
782}
783
784/*
785 * Called by ALSA when the PCM substream is prepared, can set format, sample
786 * rate, etc. This function is non atomic and can be called multiple times,
787 * it can refer to the runtime info.
788 */
789static int soc_pcm_prepare(struct snd_pcm_substream *substream)
790{
791 struct snd_soc_pcm_runtime *rtd = substream->private_data;
792 struct snd_soc_platform *platform = rtd->platform;
793 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
794 struct snd_soc_dai *codec_dai = rtd->codec_dai;
795 int ret = 0;
796
797 mutex_lock(&pcm_mutex);
798
799 if (rtd->dai_link->ops && rtd->dai_link->ops->prepare) {
800 ret = rtd->dai_link->ops->prepare(substream);
801 if (ret < 0) {
802 printk(KERN_ERR "asoc: machine prepare error\n");
803 goto out;
804 }
805 }
806
807 if (platform->driver->ops && platform->driver->ops->prepare) {
808 ret = platform->driver->ops->prepare(substream);
809 if (ret < 0) {
810 printk(KERN_ERR "asoc: platform prepare error\n");
811 goto out;
812 }
813 }
814
815 if (codec_dai->driver->ops->prepare) {
816 ret = codec_dai->driver->ops->prepare(substream, codec_dai);
817 if (ret < 0) {
818 printk(KERN_ERR "asoc: codec DAI prepare error\n");
819 goto out;
820 }
821 }
822
823 if (cpu_dai->driver->ops->prepare) {
824 ret = cpu_dai->driver->ops->prepare(substream, cpu_dai);
825 if (ret < 0) {
826 printk(KERN_ERR "asoc: cpu DAI prepare error\n");
827 goto out;
828 }
829 }
830
831 /* cancel any delayed stream shutdown that is pending */
832 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
833 codec_dai->pop_wait) {
834 codec_dai->pop_wait = 0;
835 cancel_delayed_work(&rtd->delayed_work);
836 }
837
838 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
839 snd_soc_dapm_stream_event(rtd,
840 codec_dai->driver->playback.stream_name,
841 SND_SOC_DAPM_STREAM_START);
842 else
843 snd_soc_dapm_stream_event(rtd,
844 codec_dai->driver->capture.stream_name,
845 SND_SOC_DAPM_STREAM_START);
846
847 snd_soc_dai_digital_mute(codec_dai, 0);
848
849out:
850 mutex_unlock(&pcm_mutex);
851 return ret;
852}
853
854/*
855 * Called by ALSA when the hardware params are set by application. This
856 * function can also be called multiple times and can allocate buffers
857 * (using snd_pcm_lib_* ). It's non-atomic.
858 */
859static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
860 struct snd_pcm_hw_params *params)
861{
862 struct snd_soc_pcm_runtime *rtd = substream->private_data;
863 struct snd_soc_platform *platform = rtd->platform;
864 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
865 struct snd_soc_dai *codec_dai = rtd->codec_dai;
866 int ret = 0;
867
868 mutex_lock(&pcm_mutex);
869
870 if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) {
871 ret = rtd->dai_link->ops->hw_params(substream, params);
872 if (ret < 0) {
873 printk(KERN_ERR "asoc: machine hw_params failed\n");
874 goto out;
875 }
876 }
877
878 if (codec_dai->driver->ops->hw_params) {
879 ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai);
880 if (ret < 0) {
881 printk(KERN_ERR "asoc: can't set codec %s hw params\n",
882 codec_dai->name);
883 goto codec_err;
884 }
885 }
886
887 if (cpu_dai->driver->ops->hw_params) {
888 ret = cpu_dai->driver->ops->hw_params(substream, params, cpu_dai);
889 if (ret < 0) {
890 printk(KERN_ERR "asoc: interface %s hw params failed\n",
891 cpu_dai->name);
892 goto interface_err;
893 }
894 }
895
896 if (platform->driver->ops && platform->driver->ops->hw_params) {
897 ret = platform->driver->ops->hw_params(substream, params);
898 if (ret < 0) {
899 printk(KERN_ERR "asoc: platform %s hw params failed\n",
900 platform->name);
901 goto platform_err;
902 }
903 }
904
905 rtd->rate = params_rate(params);
906
907out:
908 mutex_unlock(&pcm_mutex);
909 return ret;
910
911platform_err:
912 if (cpu_dai->driver->ops->hw_free)
913 cpu_dai->driver->ops->hw_free(substream, cpu_dai);
914
915interface_err:
916 if (codec_dai->driver->ops->hw_free)
917 codec_dai->driver->ops->hw_free(substream, codec_dai);
918
919codec_err:
920 if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free)
921 rtd->dai_link->ops->hw_free(substream);
922
923 mutex_unlock(&pcm_mutex);
924 return ret;
925}
926
927/*
928 * Frees resources allocated by hw_params, can be called multiple times
929 */
930static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
931{
932 struct snd_soc_pcm_runtime *rtd = substream->private_data;
933 struct snd_soc_platform *platform = rtd->platform;
934 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
935 struct snd_soc_dai *codec_dai = rtd->codec_dai;
936 struct snd_soc_codec *codec = rtd->codec;
937
938 mutex_lock(&pcm_mutex);
939
940 /* apply codec digital mute */
941 if (!codec->active)
942 snd_soc_dai_digital_mute(codec_dai, 1);
943
944 /* free any machine hw params */
945 if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free)
946 rtd->dai_link->ops->hw_free(substream);
947
948 /* free any DMA resources */
949 if (platform->driver->ops && platform->driver->ops->hw_free)
950 platform->driver->ops->hw_free(substream);
951
952 /* now free hw params for the DAIs */
953 if (codec_dai->driver->ops->hw_free)
954 codec_dai->driver->ops->hw_free(substream, codec_dai);
955
956 if (cpu_dai->driver->ops->hw_free)
957 cpu_dai->driver->ops->hw_free(substream, cpu_dai);
958
959 mutex_unlock(&pcm_mutex);
960 return 0;
961}
962
963static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
964{
965 struct snd_soc_pcm_runtime *rtd = substream->private_data;
966 struct snd_soc_platform *platform = rtd->platform;
967 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
968 struct snd_soc_dai *codec_dai = rtd->codec_dai;
969 int ret;
970
971 if (codec_dai->driver->ops->trigger) {
972 ret = codec_dai->driver->ops->trigger(substream, cmd, codec_dai);
973 if (ret < 0)
974 return ret;
975 }
976
977 if (platform->driver->ops && platform->driver->ops->trigger) {
978 ret = platform->driver->ops->trigger(substream, cmd);
979 if (ret < 0)
980 return ret;
981 }
982
983 if (cpu_dai->driver->ops->trigger) {
984 ret = cpu_dai->driver->ops->trigger(substream, cmd, cpu_dai);
985 if (ret < 0)
986 return ret;
987 }
988 return 0;
989}
990
991/*
992 * soc level wrapper for pointer callback
993 * If cpu_dai, codec_dai, platform driver has the delay callback, than
994 * the runtime->delay will be updated accordingly.
995 */
996static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
997{
998 struct snd_soc_pcm_runtime *rtd = substream->private_data;
999 struct snd_soc_platform *platform = rtd->platform;
1000 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1001 struct snd_soc_dai *codec_dai = rtd->codec_dai;
1002 struct snd_pcm_runtime *runtime = substream->runtime;
1003 snd_pcm_uframes_t offset = 0;
1004 snd_pcm_sframes_t delay = 0;
1005
1006 if (platform->driver->ops && platform->driver->ops->pointer)
1007 offset = platform->driver->ops->pointer(substream);
1008
1009 if (cpu_dai->driver->ops->delay)
1010 delay += cpu_dai->driver->ops->delay(substream, cpu_dai);
1011
1012 if (codec_dai->driver->ops->delay)
1013 delay += codec_dai->driver->ops->delay(substream, codec_dai);
1014
1015 if (platform->driver->delay)
1016 delay += platform->driver->delay(substream, codec_dai);
1017
1018 runtime->delay = delay;
1019
1020 return offset;
1021}
1022
1023/* ASoC PCM operations */
1024static struct snd_pcm_ops soc_pcm_ops = {
1025 .open = soc_pcm_open,
1026 .close = soc_codec_close,
1027 .hw_params = soc_pcm_hw_params,
1028 .hw_free = soc_pcm_hw_free,
1029 .prepare = soc_pcm_prepare,
1030 .trigger = soc_pcm_trigger,
1031 .pointer = soc_pcm_pointer,
1032};
1033
1034#ifdef CONFIG_PM_SLEEP 487#ifdef CONFIG_PM_SLEEP
1035/* powers down audio subsystem for suspend */ 488/* powers down audio subsystem for suspend */
1036int snd_soc_suspend(struct device *dev) 489int snd_soc_suspend(struct device *dev)
@@ -1692,9 +1145,6 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
1692 if (order != SND_SOC_COMP_ORDER_LAST) 1145 if (order != SND_SOC_COMP_ORDER_LAST)
1693 return 0; 1146 return 0;
1694 1147
1695 /* DAPM dai link stream work */
1696 INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
1697
1698 ret = soc_post_component_init(card, codec, num, 0); 1148 ret = soc_post_component_init(card, codec, num, 0);
1699 if (ret) 1149 if (ret)
1700 return ret; 1150 return ret;
@@ -2114,66 +1564,6 @@ static struct platform_driver soc_driver = {
2114 .remove = soc_remove, 1564 .remove = soc_remove,
2115}; 1565};
2116 1566
2117/* create a new pcm */
2118static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
2119{
2120 struct snd_soc_codec *codec = rtd->codec;
2121 struct snd_soc_platform *platform = rtd->platform;
2122 struct snd_soc_dai *codec_dai = rtd->codec_dai;
2123 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
2124 struct snd_pcm *pcm;
2125 char new_name[64];
2126 int ret = 0, playback = 0, capture = 0;
2127
2128 /* check client and interface hw capabilities */
2129 snprintf(new_name, sizeof(new_name), "%s %s-%d",
2130 rtd->dai_link->stream_name, codec_dai->name, num);
2131
2132 if (codec_dai->driver->playback.channels_min)
2133 playback = 1;
2134 if (codec_dai->driver->capture.channels_min)
2135 capture = 1;
2136
2137 dev_dbg(rtd->card->dev, "registered pcm #%d %s\n",num,new_name);
2138 ret = snd_pcm_new(rtd->card->snd_card, new_name,
2139 num, playback, capture, &pcm);
2140 if (ret < 0) {
2141 printk(KERN_ERR "asoc: can't create pcm for codec %s\n", codec->name);
2142 return ret;
2143 }
2144
2145 rtd->pcm = pcm;
2146 pcm->private_data = rtd;
2147 if (platform->driver->ops) {
2148 soc_pcm_ops.mmap = platform->driver->ops->mmap;
2149 soc_pcm_ops.pointer = platform->driver->ops->pointer;
2150 soc_pcm_ops.ioctl = platform->driver->ops->ioctl;
2151 soc_pcm_ops.copy = platform->driver->ops->copy;
2152 soc_pcm_ops.silence = platform->driver->ops->silence;
2153 soc_pcm_ops.ack = platform->driver->ops->ack;
2154 soc_pcm_ops.page = platform->driver->ops->page;
2155 }
2156
2157 if (playback)
2158 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops);
2159
2160 if (capture)
2161 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops);
2162
2163 if (platform->driver->pcm_new) {
2164 ret = platform->driver->pcm_new(rtd);
2165 if (ret < 0) {
2166 pr_err("asoc: platform pcm constructor failed\n");
2167 return ret;
2168 }
2169 }
2170
2171 pcm->private_free = platform->driver->pcm_free;
2172 printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name,
2173 cpu_dai->name);
2174 return ret;
2175}
2176
2177/** 1567/**
2178 * snd_soc_codec_volatile_register: Report if a register is volatile. 1568 * snd_soc_codec_volatile_register: Report if a register is volatile.
2179 * 1569 *