diff options
Diffstat (limited to 'sound/soc/sh/siu_dai.c')
-rw-r--r-- | sound/soc/sh/siu_dai.c | 97 |
1 files changed, 58 insertions, 39 deletions
diff --git a/sound/soc/sh/siu_dai.c b/sound/soc/sh/siu_dai.c index eeed5edd722b..af53b64d8af2 100644 --- a/sound/soc/sh/siu_dai.c +++ b/sound/soc/sh/siu_dai.c | |||
@@ -71,6 +71,8 @@ struct port_flag { | |||
71 | struct format_flag capture; | 71 | struct format_flag capture; |
72 | }; | 72 | }; |
73 | 73 | ||
74 | struct siu_info *siu_i2s_data; | ||
75 | |||
74 | static struct port_flag siu_flags[SIU_PORT_NUM] = { | 76 | static struct port_flag siu_flags[SIU_PORT_NUM] = { |
75 | [SIU_PORT_A] = { | 77 | [SIU_PORT_A] = { |
76 | .playback = { | 78 | .playback = { |
@@ -104,13 +106,13 @@ static struct port_flag siu_flags[SIU_PORT_NUM] = { | |||
104 | 106 | ||
105 | static void siu_dai_start(struct siu_port *port_info) | 107 | static void siu_dai_start(struct siu_port *port_info) |
106 | { | 108 | { |
107 | struct siu_info *info = siu_i2s_dai.private_data; | 109 | struct siu_info *info = siu_i2s_data; |
108 | u32 __iomem *base = info->reg; | 110 | u32 __iomem *base = info->reg; |
109 | 111 | ||
110 | dev_dbg(port_info->pcm->card->dev, "%s\n", __func__); | 112 | dev_dbg(port_info->pcm->card->dev, "%s\n", __func__); |
111 | 113 | ||
112 | /* Turn on SIU clock */ | 114 | /* Turn on SIU clock */ |
113 | pm_runtime_get_sync(siu_i2s_dai.dev); | 115 | pm_runtime_get_sync(info->dev); |
114 | 116 | ||
115 | /* Issue software reset to siu */ | 117 | /* Issue software reset to siu */ |
116 | siu_write32(base + SIU_SRCTL, 0); | 118 | siu_write32(base + SIU_SRCTL, 0); |
@@ -148,21 +150,21 @@ static void siu_dai_start(struct siu_port *port_info) | |||
148 | siu_write32(base + SIU_SBDVCB, port_info->capture.volume); | 150 | siu_write32(base + SIU_SBDVCB, port_info->capture.volume); |
149 | } | 151 | } |
150 | 152 | ||
151 | static void siu_dai_stop(void) | 153 | static void siu_dai_stop(struct siu_port *port_info) |
152 | { | 154 | { |
153 | struct siu_info *info = siu_i2s_dai.private_data; | 155 | struct siu_info *info = siu_i2s_data; |
154 | u32 __iomem *base = info->reg; | 156 | u32 __iomem *base = info->reg; |
155 | 157 | ||
156 | /* SIU software reset */ | 158 | /* SIU software reset */ |
157 | siu_write32(base + SIU_SRCTL, 0); | 159 | siu_write32(base + SIU_SRCTL, 0); |
158 | 160 | ||
159 | /* Turn off SIU clock */ | 161 | /* Turn off SIU clock */ |
160 | pm_runtime_put_sync(siu_i2s_dai.dev); | 162 | pm_runtime_put_sync(info->dev); |
161 | } | 163 | } |
162 | 164 | ||
163 | static void siu_dai_spbAselect(struct siu_port *port_info) | 165 | static void siu_dai_spbAselect(struct siu_port *port_info) |
164 | { | 166 | { |
165 | struct siu_info *info = siu_i2s_dai.private_data; | 167 | struct siu_info *info = siu_i2s_data; |
166 | struct siu_firmware *fw = &info->fw; | 168 | struct siu_firmware *fw = &info->fw; |
167 | u32 *ydef = fw->yram0; | 169 | u32 *ydef = fw->yram0; |
168 | u32 idx; | 170 | u32 idx; |
@@ -187,7 +189,7 @@ static void siu_dai_spbAselect(struct siu_port *port_info) | |||
187 | 189 | ||
188 | static void siu_dai_spbBselect(struct siu_port *port_info) | 190 | static void siu_dai_spbBselect(struct siu_port *port_info) |
189 | { | 191 | { |
190 | struct siu_info *info = siu_i2s_dai.private_data; | 192 | struct siu_info *info = siu_i2s_data; |
191 | struct siu_firmware *fw = &info->fw; | 193 | struct siu_firmware *fw = &info->fw; |
192 | u32 *ydef = fw->yram0; | 194 | u32 *ydef = fw->yram0; |
193 | u32 idx; | 195 | u32 idx; |
@@ -207,7 +209,7 @@ static void siu_dai_spbBselect(struct siu_port *port_info) | |||
207 | 209 | ||
208 | static void siu_dai_open(struct siu_stream *siu_stream) | 210 | static void siu_dai_open(struct siu_stream *siu_stream) |
209 | { | 211 | { |
210 | struct siu_info *info = siu_i2s_dai.private_data; | 212 | struct siu_info *info = siu_i2s_data; |
211 | u32 __iomem *base = info->reg; | 213 | u32 __iomem *base = info->reg; |
212 | u32 srctl, ifctl; | 214 | u32 srctl, ifctl; |
213 | 215 | ||
@@ -238,7 +240,7 @@ static void siu_dai_open(struct siu_stream *siu_stream) | |||
238 | */ | 240 | */ |
239 | static void siu_dai_pcmdatapack(struct siu_stream *siu_stream) | 241 | static void siu_dai_pcmdatapack(struct siu_stream *siu_stream) |
240 | { | 242 | { |
241 | struct siu_info *info = siu_i2s_dai.private_data; | 243 | struct siu_info *info = siu_i2s_data; |
242 | u32 __iomem *base = info->reg; | 244 | u32 __iomem *base = info->reg; |
243 | u32 dpak; | 245 | u32 dpak; |
244 | 246 | ||
@@ -258,7 +260,7 @@ static void siu_dai_pcmdatapack(struct siu_stream *siu_stream) | |||
258 | 260 | ||
259 | static int siu_dai_spbstart(struct siu_port *port_info) | 261 | static int siu_dai_spbstart(struct siu_port *port_info) |
260 | { | 262 | { |
261 | struct siu_info *info = siu_i2s_dai.private_data; | 263 | struct siu_info *info = siu_i2s_data; |
262 | u32 __iomem *base = info->reg; | 264 | u32 __iomem *base = info->reg; |
263 | struct siu_firmware *fw = &info->fw; | 265 | struct siu_firmware *fw = &info->fw; |
264 | u32 *ydef = fw->yram0; | 266 | u32 *ydef = fw->yram0; |
@@ -323,7 +325,7 @@ static int siu_dai_spbstart(struct siu_port *port_info) | |||
323 | 325 | ||
324 | static void siu_dai_spbstop(struct siu_port *port_info) | 326 | static void siu_dai_spbstop(struct siu_port *port_info) |
325 | { | 327 | { |
326 | struct siu_info *info = siu_i2s_dai.private_data; | 328 | struct siu_info *info = siu_i2s_data; |
327 | u32 __iomem *base = info->reg; | 329 | u32 __iomem *base = info->reg; |
328 | 330 | ||
329 | siu_write32(base + SIU_SBACTIV, 0); | 331 | siu_write32(base + SIU_SBACTIV, 0); |
@@ -402,7 +404,7 @@ static int siu_dai_put_volume(struct snd_kcontrol *kctrl, | |||
402 | { | 404 | { |
403 | struct siu_port *port_info = snd_kcontrol_chip(kctrl); | 405 | struct siu_port *port_info = snd_kcontrol_chip(kctrl); |
404 | struct device *dev = port_info->pcm->card->dev; | 406 | struct device *dev = port_info->pcm->card->dev; |
405 | struct siu_info *info = siu_i2s_dai.private_data; | 407 | struct siu_info *info = siu_i2s_data; |
406 | u32 __iomem *base = info->reg; | 408 | u32 __iomem *base = info->reg; |
407 | u32 new_vol; | 409 | u32 new_vol; |
408 | u32 cur_vol; | 410 | u32 cur_vol; |
@@ -510,7 +512,7 @@ void siu_free_port(struct siu_port *port_info) | |||
510 | static int siu_dai_startup(struct snd_pcm_substream *substream, | 512 | static int siu_dai_startup(struct snd_pcm_substream *substream, |
511 | struct snd_soc_dai *dai) | 513 | struct snd_soc_dai *dai) |
512 | { | 514 | { |
513 | struct siu_info *info = siu_i2s_dai.private_data; | 515 | struct siu_info *info = snd_soc_dai_get_drvdata(dai); |
514 | struct snd_pcm_runtime *rt = substream->runtime; | 516 | struct snd_pcm_runtime *rt = substream->runtime; |
515 | struct siu_port *port_info = siu_port_info(substream); | 517 | struct siu_port *port_info = siu_port_info(substream); |
516 | int ret; | 518 | int ret; |
@@ -532,7 +534,7 @@ static int siu_dai_startup(struct snd_pcm_substream *substream, | |||
532 | static void siu_dai_shutdown(struct snd_pcm_substream *substream, | 534 | static void siu_dai_shutdown(struct snd_pcm_substream *substream, |
533 | struct snd_soc_dai *dai) | 535 | struct snd_soc_dai *dai) |
534 | { | 536 | { |
535 | struct siu_info *info = siu_i2s_dai.private_data; | 537 | struct siu_info *info = snd_soc_dai_get_drvdata(dai); |
536 | struct siu_port *port_info = siu_port_info(substream); | 538 | struct siu_port *port_info = siu_port_info(substream); |
537 | 539 | ||
538 | dev_dbg(substream->pcm->card->dev, "%s: port=%d@%p\n", __func__, | 540 | dev_dbg(substream->pcm->card->dev, "%s: port=%d@%p\n", __func__, |
@@ -548,7 +550,7 @@ static void siu_dai_shutdown(struct snd_pcm_substream *substream, | |||
548 | /* during stmread or stmwrite ? */ | 550 | /* during stmread or stmwrite ? */ |
549 | BUG_ON(port_info->playback.rw_flg || port_info->capture.rw_flg); | 551 | BUG_ON(port_info->playback.rw_flg || port_info->capture.rw_flg); |
550 | siu_dai_spbstop(port_info); | 552 | siu_dai_spbstop(port_info); |
551 | siu_dai_stop(); | 553 | siu_dai_stop(port_info); |
552 | } | 554 | } |
553 | } | 555 | } |
554 | 556 | ||
@@ -556,7 +558,7 @@ static void siu_dai_shutdown(struct snd_pcm_substream *substream, | |||
556 | static int siu_dai_prepare(struct snd_pcm_substream *substream, | 558 | static int siu_dai_prepare(struct snd_pcm_substream *substream, |
557 | struct snd_soc_dai *dai) | 559 | struct snd_soc_dai *dai) |
558 | { | 560 | { |
559 | struct siu_info *info = siu_i2s_dai.private_data; | 561 | struct siu_info *info = snd_soc_dai_get_drvdata(dai); |
560 | struct snd_pcm_runtime *rt = substream->runtime; | 562 | struct snd_pcm_runtime *rt = substream->runtime; |
561 | struct siu_port *port_info = siu_port_info(substream); | 563 | struct siu_port *port_info = siu_port_info(substream); |
562 | struct siu_stream *siu_stream; | 564 | struct siu_stream *siu_stream; |
@@ -605,7 +607,7 @@ fail: | |||
605 | static int siu_dai_set_fmt(struct snd_soc_dai *dai, | 607 | static int siu_dai_set_fmt(struct snd_soc_dai *dai, |
606 | unsigned int fmt) | 608 | unsigned int fmt) |
607 | { | 609 | { |
608 | struct siu_info *info = siu_i2s_dai.private_data; | 610 | struct siu_info *info = snd_soc_dai_get_drvdata(dai); |
609 | u32 __iomem *base = info->reg; | 611 | u32 __iomem *base = info->reg; |
610 | u32 ifctl; | 612 | u32 ifctl; |
611 | 613 | ||
@@ -671,21 +673,37 @@ static int siu_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, | |||
671 | return -EINVAL; | 673 | return -EINVAL; |
672 | } | 674 | } |
673 | 675 | ||
674 | siu_clk = clk_get(siu_i2s_dai.dev, siu_name); | 676 | siu_clk = clk_get(dai->dev, siu_name); |
675 | if (IS_ERR(siu_clk)) | 677 | if (IS_ERR(siu_clk)) { |
678 | dev_err(dai->dev, "%s: cannot get a SIU clock: %ld\n", __func__, | ||
679 | PTR_ERR(siu_clk)); | ||
676 | return PTR_ERR(siu_clk); | 680 | return PTR_ERR(siu_clk); |
681 | } | ||
682 | |||
683 | parent_clk = clk_get(dai->dev, parent_name); | ||
684 | if (IS_ERR(parent_clk)) { | ||
685 | ret = PTR_ERR(parent_clk); | ||
686 | dev_err(dai->dev, "cannot get a SIU clock parent: %d\n", ret); | ||
687 | goto epclkget; | ||
688 | } | ||
677 | 689 | ||
678 | parent_clk = clk_get(siu_i2s_dai.dev, parent_name); | 690 | ret = clk_set_parent(siu_clk, parent_clk); |
679 | if (!IS_ERR(parent_clk)) { | 691 | if (ret < 0) { |
680 | ret = clk_set_parent(siu_clk, parent_clk); | 692 | dev_err(dai->dev, "cannot reparent the SIU clock: %d\n", ret); |
681 | if (!ret) | 693 | goto eclksetp; |
682 | clk_set_rate(siu_clk, freq); | ||
683 | clk_put(parent_clk); | ||
684 | } | 694 | } |
685 | 695 | ||
696 | ret = clk_set_rate(siu_clk, freq); | ||
697 | if (ret < 0) | ||
698 | dev_err(dai->dev, "cannot set SIU clock rate: %d\n", ret); | ||
699 | |||
700 | /* TODO: when clkdev gets reference counting we'll move these to siu_dai_shutdown() */ | ||
701 | eclksetp: | ||
702 | clk_put(parent_clk); | ||
703 | epclkget: | ||
686 | clk_put(siu_clk); | 704 | clk_put(siu_clk); |
687 | 705 | ||
688 | return 0; | 706 | return ret; |
689 | } | 707 | } |
690 | 708 | ||
691 | static struct snd_soc_dai_ops siu_dai_ops = { | 709 | static struct snd_soc_dai_ops siu_dai_ops = { |
@@ -696,9 +714,8 @@ static struct snd_soc_dai_ops siu_dai_ops = { | |||
696 | .set_fmt = siu_dai_set_fmt, | 714 | .set_fmt = siu_dai_set_fmt, |
697 | }; | 715 | }; |
698 | 716 | ||
699 | struct snd_soc_dai siu_i2s_dai = { | 717 | static struct snd_soc_dai_driver siu_i2s_dai = { |
700 | .name = "sh-siu", | 718 | .name = "siu-i2s-dai", |
701 | .id = 0, | ||
702 | .playback = { | 719 | .playback = { |
703 | .channels_min = 2, | 720 | .channels_min = 2, |
704 | .channels_max = 2, | 721 | .channels_max = 2, |
@@ -713,7 +730,6 @@ struct snd_soc_dai siu_i2s_dai = { | |||
713 | }, | 730 | }, |
714 | .ops = &siu_dai_ops, | 731 | .ops = &siu_dai_ops, |
715 | }; | 732 | }; |
716 | EXPORT_SYMBOL_GPL(siu_i2s_dai); | ||
717 | 733 | ||
718 | static int __devinit siu_probe(struct platform_device *pdev) | 734 | static int __devinit siu_probe(struct platform_device *pdev) |
719 | { | 735 | { |
@@ -725,6 +741,8 @@ static int __devinit siu_probe(struct platform_device *pdev) | |||
725 | info = kmalloc(sizeof(*info), GFP_KERNEL); | 741 | info = kmalloc(sizeof(*info), GFP_KERNEL); |
726 | if (!info) | 742 | if (!info) |
727 | return -ENOMEM; | 743 | return -ENOMEM; |
744 | siu_i2s_data = info; | ||
745 | info->dev = &pdev->dev; | ||
728 | 746 | ||
729 | ret = request_firmware(&fw_entry, "siu_spb.bin", &pdev->dev); | 747 | ret = request_firmware(&fw_entry, "siu_spb.bin", &pdev->dev); |
730 | if (ret) | 748 | if (ret) |
@@ -767,14 +785,14 @@ static int __devinit siu_probe(struct platform_device *pdev) | |||
767 | if (!info->reg) | 785 | if (!info->reg) |
768 | goto emapreg; | 786 | goto emapreg; |
769 | 787 | ||
770 | siu_i2s_dai.dev = &pdev->dev; | 788 | dev_set_drvdata(&pdev->dev, info); |
771 | siu_i2s_dai.private_data = info; | ||
772 | 789 | ||
773 | ret = snd_soc_register_dais(&siu_i2s_dai, 1); | 790 | /* register using ARRAY version so we can keep dai name */ |
791 | ret = snd_soc_register_dais(&pdev->dev, &siu_i2s_dai, 1); | ||
774 | if (ret < 0) | 792 | if (ret < 0) |
775 | goto edaiinit; | 793 | goto edaiinit; |
776 | 794 | ||
777 | ret = snd_soc_register_platform(&siu_platform); | 795 | ret = snd_soc_register_platform(&pdev->dev, &siu_platform); |
778 | if (ret < 0) | 796 | if (ret < 0) |
779 | goto esocregp; | 797 | goto esocregp; |
780 | 798 | ||
@@ -783,7 +801,7 @@ static int __devinit siu_probe(struct platform_device *pdev) | |||
783 | return ret; | 801 | return ret; |
784 | 802 | ||
785 | esocregp: | 803 | esocregp: |
786 | snd_soc_unregister_dais(&siu_i2s_dai, 1); | 804 | snd_soc_unregister_dai(&pdev->dev); |
787 | edaiinit: | 805 | edaiinit: |
788 | iounmap(info->reg); | 806 | iounmap(info->reg); |
789 | emapreg: | 807 | emapreg: |
@@ -804,13 +822,13 @@ ereqfw: | |||
804 | 822 | ||
805 | static int __devexit siu_remove(struct platform_device *pdev) | 823 | static int __devexit siu_remove(struct platform_device *pdev) |
806 | { | 824 | { |
807 | struct siu_info *info = siu_i2s_dai.private_data; | 825 | struct siu_info *info = dev_get_drvdata(&pdev->dev); |
808 | struct resource *res; | 826 | struct resource *res; |
809 | 827 | ||
810 | pm_runtime_disable(&pdev->dev); | 828 | pm_runtime_disable(&pdev->dev); |
811 | 829 | ||
812 | snd_soc_unregister_platform(&siu_platform); | 830 | snd_soc_unregister_platform(&pdev->dev); |
813 | snd_soc_unregister_dais(&siu_i2s_dai, 1); | 831 | snd_soc_unregister_dai(&pdev->dev); |
814 | 832 | ||
815 | iounmap(info->reg); | 833 | iounmap(info->reg); |
816 | iounmap(info->yram); | 834 | iounmap(info->yram); |
@@ -826,7 +844,8 @@ static int __devexit siu_remove(struct platform_device *pdev) | |||
826 | 844 | ||
827 | static struct platform_driver siu_driver = { | 845 | static struct platform_driver siu_driver = { |
828 | .driver = { | 846 | .driver = { |
829 | .name = "sh_siu", | 847 | .owner = THIS_MODULE, |
848 | .name = "siu-pcm-audio", | ||
830 | }, | 849 | }, |
831 | .probe = siu_probe, | 850 | .probe = siu_probe, |
832 | .remove = __devexit_p(siu_remove), | 851 | .remove = __devexit_p(siu_remove), |