aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2012-03-06 08:04:16 -0500
committerTakashi Iwai <tiwai@suse.de>2012-03-06 08:04:16 -0500
commit303076342b8a30aa98f8a53b539155d0b81ff0c3 (patch)
tree09197f8d7409d2ccd4a98ea6052634fc9f3a7757 /sound/soc
parent650d6e25cde82fda425995ba77ed4b0ad3be5b8d (diff)
parent9d5ef2663fe220a88412a7190942b7d933da0333 (diff)
Merge tag 'asoc-3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into topic/asoc
A few more ASoC updates, the main one is the move of the audmux driver from arch/arm into sound/soc. There's also some general driver specific tweaks and fixes.
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/codecs/wm8804.c6
-rw-r--r--sound/soc/codecs/wm8962.c18
-rw-r--r--sound/soc/codecs/wm8994.c77
-rw-r--r--sound/soc/codecs/wm8994.h1
-rw-r--r--sound/soc/imx/Kconfig21
-rw-r--r--sound/soc/imx/Makefile15
-rw-r--r--sound/soc/imx/eukrea-tlv320.c40
-rw-r--r--sound/soc/imx/imx-audmux.c314
-rw-r--r--sound/soc/imx/imx-audmux.h60
-rw-r--r--sound/soc/imx/imx-pcm-dma-mx2.c2
-rw-r--r--sound/soc/imx/imx-pcm.c105
-rw-r--r--sound/soc/imx/imx-pcm.h32
-rw-r--r--sound/soc/imx/imx-ssi.c88
-rw-r--r--sound/soc/imx/imx-ssi.h16
-rw-r--r--sound/soc/imx/mx27vis-aic32x4.c20
-rw-r--r--sound/soc/imx/phycore-ac97.c27
-rw-r--r--sound/soc/imx/wm1133-ev1.c25
-rw-r--r--sound/soc/soc-dapm.c5
18 files changed, 687 insertions, 185 deletions
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c
index 7ee8dcf1fe32..6bd1b767b138 100644
--- a/sound/soc/codecs/wm8804.c
+++ b/sound/soc/codecs/wm8804.c
@@ -755,6 +755,12 @@ static __devinit int wm8804_i2c_probe(struct i2c_client *i2c,
755 if (!wm8804) 755 if (!wm8804)
756 return -ENOMEM; 756 return -ENOMEM;
757 757
758 wm8804->regmap = regmap_init_i2c(i2c, &wm8804_regmap_config);
759 if (IS_ERR(wm8804->regmap)) {
760 ret = PTR_ERR(wm8804->regmap);
761 return ret;
762 }
763
758 i2c_set_clientdata(i2c, wm8804); 764 i2c_set_clientdata(i2c, wm8804);
759 765
760 ret = snd_soc_register_codec(&i2c->dev, 766 ret = snd_soc_register_codec(&i2c->dev,
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index 445d2090661c..5bcb350bacc1 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -116,11 +116,11 @@ static struct reg_default wm8962_reg[] = {
116 { 1, 0x049F }, /* R1 - Right Input volume */ 116 { 1, 0x049F }, /* R1 - Right Input volume */
117 { 2, 0x0000 }, /* R2 - HPOUTL volume */ 117 { 2, 0x0000 }, /* R2 - HPOUTL volume */
118 { 3, 0x0000 }, /* R3 - HPOUTR volume */ 118 { 3, 0x0000 }, /* R3 - HPOUTR volume */
119 { 4, 0x0020 }, /* R4 - Clocking1 */ 119
120 { 5, 0x0018 }, /* R5 - ADC & DAC Control 1 */ 120 { 5, 0x0018 }, /* R5 - ADC & DAC Control 1 */
121 { 6, 0x2008 }, /* R6 - ADC & DAC Control 2 */ 121 { 6, 0x2008 }, /* R6 - ADC & DAC Control 2 */
122 { 7, 0x000A }, /* R7 - Audio Interface 0 */ 122 { 7, 0x000A }, /* R7 - Audio Interface 0 */
123 { 8, 0x01E4 }, /* R8 - Clocking2 */ 123
124 { 9, 0x0300 }, /* R9 - Audio Interface 1 */ 124 { 9, 0x0300 }, /* R9 - Audio Interface 1 */
125 { 10, 0x00C0 }, /* R10 - Left DAC volume */ 125 { 10, 0x00C0 }, /* R10 - Left DAC volume */
126 { 11, 0x00C0 }, /* R11 - Right DAC volume */ 126 { 11, 0x00C0 }, /* R11 - Right DAC volume */
@@ -129,7 +129,7 @@ static struct reg_default wm8962_reg[] = {
129 { 15, 0x6243 }, /* R15 - Software Reset */ 129 { 15, 0x6243 }, /* R15 - Software Reset */
130 130
131 { 17, 0x007B }, /* R17 - ALC1 */ 131 { 17, 0x007B }, /* R17 - ALC1 */
132 { 18, 0x0000 }, /* R18 - ALC2 */ 132
133 { 19, 0x1C32 }, /* R19 - ALC3 */ 133 { 19, 0x1C32 }, /* R19 - ALC3 */
134 { 20, 0x3200 }, /* R20 - Noise Gate */ 134 { 20, 0x3200 }, /* R20 - Noise Gate */
135 { 21, 0x00C0 }, /* R21 - Left ADC volume */ 135 { 21, 0x00C0 }, /* R21 - Left ADC volume */
@@ -153,10 +153,6 @@ static struct reg_default wm8962_reg[] = {
153 { 40, 0x0000 }, /* R40 - SPKOUTL volume */ 153 { 40, 0x0000 }, /* R40 - SPKOUTL volume */
154 { 41, 0x0000 }, /* R41 - SPKOUTR volume */ 154 { 41, 0x0000 }, /* R41 - SPKOUTR volume */
155 155
156 { 47, 0x0000 }, /* R47 - Thermal Shutdown Status */
157 { 48, 0x8027 }, /* R48 - Additional Control (4) */
158 { 49, 0x0010 }, /* R49 - Class D Control 1 */
159
160 { 51, 0x0003 }, /* R51 - Class D Control 2 */ 156 { 51, 0x0003 }, /* R51 - Class D Control 2 */
161 157
162 { 56, 0x0506 }, /* R56 - Clocking 4 */ 158 { 56, 0x0506 }, /* R56 - Clocking 4 */
@@ -168,8 +164,6 @@ static struct reg_default wm8962_reg[] = {
168 164
169 { 64, 0x0810 }, /* R64 - DC Servo 4 */ 165 { 64, 0x0810 }, /* R64 - DC Servo 4 */
170 166
171 { 66, 0x0000 }, /* R66 - DC Servo 6 */
172
173 { 68, 0x001B }, /* R68 - Analogue PGA Bias */ 167 { 68, 0x001B }, /* R68 - Analogue PGA Bias */
174 { 69, 0x0000 }, /* R69 - Analogue HP 0 */ 168 { 69, 0x0000 }, /* R69 - Analogue HP 0 */
175 169
@@ -302,9 +296,6 @@ static struct reg_default wm8962_reg[] = {
302 { 516, 0x8100 }, /* R516 - GPIO 5 */ 296 { 516, 0x8100 }, /* R516 - GPIO 5 */
303 { 517, 0x8100 }, /* R517 - GPIO 6 */ 297 { 517, 0x8100 }, /* R517 - GPIO 6 */
304 298
305 { 560, 0x0000 }, /* R560 - Interrupt Status 1 */
306 { 561, 0x0000 }, /* R561 - Interrupt Status 2 */
307
308 { 568, 0x0030 }, /* R568 - Interrupt Status 1 Mask */ 299 { 568, 0x0030 }, /* R568 - Interrupt Status 1 Mask */
309 { 569, 0xFFED }, /* R569 - Interrupt Status 2 Mask */ 300 { 569, 0xFFED }, /* R569 - Interrupt Status 2 Mask */
310 301
@@ -316,8 +307,6 @@ static struct reg_default wm8962_reg[] = {
316 307
317 { 768, 0x1C00 }, /* R768 - DSP2 Power Management */ 308 { 768, 0x1C00 }, /* R768 - DSP2 Power Management */
318 309
319 { 1037, 0x0000 }, /* R1037 - DSP2_ExecControl */
320
321 { 8192, 0x0000 }, /* R8192 - DSP2 Instruction RAM 0 */ 310 { 8192, 0x0000 }, /* R8192 - DSP2 Instruction RAM 0 */
322 311
323 { 9216, 0x0030 }, /* R9216 - DSP2 Address RAM 2 */ 312 { 9216, 0x0030 }, /* R9216 - DSP2 Address RAM 2 */
@@ -3673,7 +3662,6 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
3673 ret); 3662 ret);
3674 } 3663 }
3675 3664
3676 pm_runtime_set_active(&i2c->dev);
3677 pm_runtime_enable(&i2c->dev); 3665 pm_runtime_enable(&i2c->dev);
3678 pm_request_idle(&i2c->dev); 3666 pm_request_idle(&i2c->dev);
3679 3667
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index 2417ef9316ed..bc12d097ef0d 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -685,8 +685,6 @@ SOC_SINGLE_TLV("MIXINL IN1RP Boost Volume", WM8994_INPUT_MIXER_1, 8, 1, 0,
685static void wm1811_jackdet_set_mode(struct snd_soc_codec *codec, u16 mode) 685static void wm1811_jackdet_set_mode(struct snd_soc_codec *codec, u16 mode)
686{ 686{
687 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); 687 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
688 u16 old = snd_soc_read(codec, WM8994_ANTIPOP_2)
689 & WM1811_JACKDET_MODE_MASK;
690 688
691 if (!wm8994->jackdet || !wm8994->jack_cb) 689 if (!wm8994->jackdet || !wm8994->jack_cb)
692 return; 690 return;
@@ -694,28 +692,17 @@ static void wm1811_jackdet_set_mode(struct snd_soc_codec *codec, u16 mode)
694 if (wm8994->active_refcount) 692 if (wm8994->active_refcount)
695 mode = WM1811_JACKDET_MODE_AUDIO; 693 mode = WM1811_JACKDET_MODE_AUDIO;
696 694
697 if (mode == old) 695 if (mode == wm8994->jackdet_mode)
698 return; 696 return;
699 697
700 snd_soc_update_bits(codec, WM8994_ANTIPOP_2, 698 wm8994->jackdet_mode = mode;
701 WM1811_JACKDET_MODE_MASK, mode);
702
703 switch (mode) {
704 case WM1811_JACKDET_MODE_MIC:
705 case WM1811_JACKDET_MODE_AUDIO:
706 switch (old) {
707 case WM1811_JACKDET_MODE_MIC:
708 case WM1811_JACKDET_MODE_AUDIO:
709 break;
710 default:
711 msleep(2);
712 break;
713 }
714 699
715 default: 700 /* Always use audio mode to detect while the system is active */
716 break; 701 if (mode != WM1811_JACKDET_MODE_NONE)
717 } 702 mode = WM1811_JACKDET_MODE_AUDIO;
718 703
704 snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
705 WM1811_JACKDET_MODE_MASK, mode);
719} 706}
720 707
721static void active_reference(struct snd_soc_codec *codec) 708static void active_reference(struct snd_soc_codec *codec)
@@ -2749,7 +2736,7 @@ static struct snd_soc_dai_driver wm8994_dai[] = {
2749}; 2736};
2750 2737
2751#ifdef CONFIG_PM 2738#ifdef CONFIG_PM
2752static int wm8994_suspend(struct snd_soc_codec *codec) 2739static int wm8994_codec_suspend(struct snd_soc_codec *codec)
2753{ 2740{
2754 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); 2741 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
2755 struct wm8994 *control = wm8994->wm8994; 2742 struct wm8994 *control = wm8994->wm8994;
@@ -2783,7 +2770,7 @@ static int wm8994_suspend(struct snd_soc_codec *codec)
2783 return 0; 2770 return 0;
2784} 2771}
2785 2772
2786static int wm8994_resume(struct snd_soc_codec *codec) 2773static int wm8994_codec_resume(struct snd_soc_codec *codec)
2787{ 2774{
2788 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); 2775 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
2789 struct wm8994 *control = wm8994->wm8994; 2776 struct wm8994 *control = wm8994->wm8994;
@@ -2842,8 +2829,8 @@ static int wm8994_resume(struct snd_soc_codec *codec)
2842 return 0; 2829 return 0;
2843} 2830}
2844#else 2831#else
2845#define wm8994_suspend NULL 2832#define wm8994_codec_suspend NULL
2846#define wm8994_resume NULL 2833#define wm8994_codec_resume NULL
2847#endif 2834#endif
2848 2835
2849static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) 2836static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994)
@@ -3955,8 +3942,8 @@ static int wm8994_codec_remove(struct snd_soc_codec *codec)
3955static struct snd_soc_codec_driver soc_codec_dev_wm8994 = { 3942static struct snd_soc_codec_driver soc_codec_dev_wm8994 = {
3956 .probe = wm8994_codec_probe, 3943 .probe = wm8994_codec_probe,
3957 .remove = wm8994_codec_remove, 3944 .remove = wm8994_codec_remove,
3958 .suspend = wm8994_suspend, 3945 .suspend = wm8994_codec_suspend,
3959 .resume = wm8994_resume, 3946 .resume = wm8994_codec_resume,
3960 .set_bias_level = wm8994_set_bias_level, 3947 .set_bias_level = wm8994_set_bias_level,
3961}; 3948};
3962 3949
@@ -3983,11 +3970,43 @@ static int __devexit wm8994_remove(struct platform_device *pdev)
3983 return 0; 3970 return 0;
3984} 3971}
3985 3972
3973#ifdef CONFIG_PM_SLEEP
3974static int wm8994_suspend(struct device *dev)
3975{
3976 struct wm8994_priv *wm8994 = dev_get_drvdata(dev);
3977
3978 /* Drop down to power saving mode when system is suspended */
3979 if (wm8994->jackdet && !wm8994->active_refcount)
3980 regmap_update_bits(wm8994->wm8994->regmap, WM8994_ANTIPOP_2,
3981 WM1811_JACKDET_MODE_MASK,
3982 wm8994->jackdet_mode);
3983
3984 return 0;
3985}
3986
3987static int wm8994_resume(struct device *dev)
3988{
3989 struct wm8994_priv *wm8994 = dev_get_drvdata(dev);
3990
3991 if (wm8994->jackdet && wm8994->jack_cb)
3992 regmap_update_bits(wm8994->wm8994->regmap, WM8994_ANTIPOP_2,
3993 WM1811_JACKDET_MODE_MASK,
3994 WM1811_JACKDET_MODE_AUDIO);
3995
3996 return 0;
3997}
3998#endif
3999
4000static const struct dev_pm_ops wm8994_pm_ops = {
4001 SET_SYSTEM_SLEEP_PM_OPS(wm8994_suspend, wm8994_resume)
4002};
4003
3986static struct platform_driver wm8994_codec_driver = { 4004static struct platform_driver wm8994_codec_driver = {
3987 .driver = { 4005 .driver = {
3988 .name = "wm8994-codec", 4006 .name = "wm8994-codec",
3989 .owner = THIS_MODULE, 4007 .owner = THIS_MODULE,
3990 }, 4008 .pm = &wm8994_pm_ops,
4009 },
3991 .probe = wm8994_probe, 4010 .probe = wm8994_probe,
3992 .remove = __devexit_p(wm8994_remove), 4011 .remove = __devexit_p(wm8994_remove),
3993}; 4012};
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h
index f996d14766d9..2f4d2d12a452 100644
--- a/sound/soc/codecs/wm8994.h
+++ b/sound/soc/codecs/wm8994.h
@@ -122,6 +122,7 @@ struct wm8994_priv {
122 bool jack_mic; 122 bool jack_mic;
123 int btn_mask; 123 int btn_mask;
124 bool jackdet; 124 bool jackdet;
125 int jackdet_mode;
125 126
126 wm8958_micdet_cb jack_cb; 127 wm8958_micdet_cb jack_cb;
127 void *jack_cb_data; 128 void *jack_cb_data;
diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig
index aa4294bf49b2..810acaa09009 100644
--- a/sound/soc/imx/Kconfig
+++ b/sound/soc/imx/Kconfig
@@ -8,19 +8,32 @@ menuconfig SND_IMX_SOC
8 8
9if SND_IMX_SOC 9if SND_IMX_SOC
10 10
11config SND_SOC_IMX_SSI
12 tristate
13
14config SND_SOC_IMX_PCM
15 tristate
16
11config SND_MXC_SOC_FIQ 17config SND_MXC_SOC_FIQ
12 select FIQ
13 tristate 18 tristate
19 select FIQ
20 select SND_SOC_IMX_PCM
14 21
15config SND_MXC_SOC_MX2 22config SND_MXC_SOC_MX2
16 select SND_SOC_DMAENGINE_PCM 23 select SND_SOC_DMAENGINE_PCM
17 tristate 24 tristate
25 select SND_SOC_IMX_PCM
26
27config SND_SOC_IMX_AUDMUX
28 tristate
18 29
19config SND_MXC_SOC_WM1133_EV1 30config SND_MXC_SOC_WM1133_EV1
20 tristate "Audio on the the i.MX31ADS with WM1133-EV1 fitted" 31 tristate "Audio on the the i.MX31ADS with WM1133-EV1 fitted"
21 depends on MACH_MX31ADS_WM1133_EV1 && EXPERIMENTAL 32 depends on MACH_MX31ADS_WM1133_EV1 && EXPERIMENTAL
22 select SND_SOC_WM8350 33 select SND_SOC_WM8350
23 select SND_MXC_SOC_FIQ 34 select SND_MXC_SOC_FIQ
35 select SND_SOC_IMX_AUDMUX
36 select SND_SOC_IMX_SSI
24 help 37 help
25 Enable support for audio on the i.MX31ADS with the WM1133-EV1 38 Enable support for audio on the i.MX31ADS with the WM1133-EV1
26 PMIC board with WM8835x fitted. 39 PMIC board with WM8835x fitted.
@@ -30,6 +43,8 @@ config SND_SOC_MX27VIS_AIC32X4
30 depends on MACH_IMX27_VISSTRIM_M10 && I2C 43 depends on MACH_IMX27_VISSTRIM_M10 && I2C
31 select SND_SOC_TLV320AIC32X4 44 select SND_SOC_TLV320AIC32X4
32 select SND_MXC_SOC_MX2 45 select SND_MXC_SOC_MX2
46 select SND_SOC_IMX_AUDMUX
47 select SND_SOC_IMX_SSI
33 help 48 help
34 Say Y if you want to add support for SoC audio on Visstrim SM10 49 Say Y if you want to add support for SoC audio on Visstrim SM10
35 board with TLV320AIC32X4 codec. 50 board with TLV320AIC32X4 codec.
@@ -40,6 +55,8 @@ config SND_SOC_PHYCORE_AC97
40 select SND_SOC_AC97_BUS 55 select SND_SOC_AC97_BUS
41 select SND_SOC_WM9712 56 select SND_SOC_WM9712
42 select SND_MXC_SOC_FIQ 57 select SND_MXC_SOC_FIQ
58 select SND_SOC_IMX_AUDMUX
59 select SND_SOC_IMX_SSI
43 help 60 help
44 Say Y if you want to add support for SoC audio on Phytec phyCORE 61 Say Y if you want to add support for SoC audio on Phytec phyCORE
45 and phyCARD boards in AC97 mode 62 and phyCARD boards in AC97 mode
@@ -53,6 +70,8 @@ config SND_SOC_EUKREA_TLV320
53 depends on I2C 70 depends on I2C
54 select SND_SOC_TLV320AIC23 71 select SND_SOC_TLV320AIC23
55 select SND_MXC_SOC_FIQ 72 select SND_MXC_SOC_FIQ
73 select SND_SOC_IMX_AUDMUX
74 select SND_SOC_IMX_SSI
56 help 75 help
57 Enable I2S based access to the TLV320AIC23B codec attached 76 Enable I2S based access to the TLV320AIC23B codec attached
58 to the SSI interface 77 to the SSI interface
diff --git a/sound/soc/imx/Makefile b/sound/soc/imx/Makefile
index d6d609ba7e24..f5db3e92d0d1 100644
--- a/sound/soc/imx/Makefile
+++ b/sound/soc/imx/Makefile
@@ -1,11 +1,14 @@
1# i.MX Platform Support 1# i.MX Platform Support
2snd-soc-imx-objs := imx-ssi.o 2snd-soc-imx-ssi-objs := imx-ssi.o
3snd-soc-imx-fiq-objs := imx-pcm-fiq.o 3snd-soc-imx-audmux-objs := imx-audmux.o
4snd-soc-imx-mx2-objs := imx-pcm-dma-mx2.o
5 4
6obj-$(CONFIG_SND_IMX_SOC) += snd-soc-imx.o 5obj-$(CONFIG_SND_SOC_IMX_SSI) += snd-soc-imx-ssi.o
7obj-$(CONFIG_SND_MXC_SOC_FIQ) += snd-soc-imx-fiq.o 6obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o
8obj-$(CONFIG_SND_MXC_SOC_MX2) += snd-soc-imx-mx2.o 7
8obj-$(CONFIG_SND_SOC_IMX_PCM) += snd-soc-imx-pcm.o
9snd-soc-imx-pcm-y := imx-pcm.o
10snd-soc-imx-pcm-$(CONFIG_SND_MXC_SOC_FIQ) += imx-pcm-fiq.o
11snd-soc-imx-pcm-$(CONFIG_SND_MXC_SOC_MX2) += imx-pcm-dma-mx2.o
9 12
10# i.MX Machine Support 13# i.MX Machine Support
11snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o 14snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o
diff --git a/sound/soc/imx/eukrea-tlv320.c b/sound/soc/imx/eukrea-tlv320.c
index 1c1fdd10f73f..7d4475cfdb24 100644
--- a/sound/soc/imx/eukrea-tlv320.c
+++ b/sound/soc/imx/eukrea-tlv320.c
@@ -26,6 +26,7 @@
26 26
27#include "../codecs/tlv320aic23.h" 27#include "../codecs/tlv320aic23.h"
28#include "imx-ssi.h" 28#include "imx-ssi.h"
29#include "imx-audmux.h"
29 30
30#define CODEC_CLOCK 12000000 31#define CODEC_CLOCK 12000000
31 32
@@ -97,12 +98,43 @@ static struct platform_device *eukrea_tlv320_snd_device;
97static int __init eukrea_tlv320_init(void) 98static int __init eukrea_tlv320_init(void)
98{ 99{
99 int ret; 100 int ret;
100 101 int int_port = 0, ext_port;
101 if (!machine_is_eukrea_cpuimx27() && !machine_is_eukrea_cpuimx25sd() 102
102 && !machine_is_eukrea_cpuimx35sd() 103 if (machine_is_eukrea_cpuimx27()) {
103 && !machine_is_eukrea_cpuimx51sd()) 104 imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0,
105 IMX_AUDMUX_V1_PCR_SYN |
106 IMX_AUDMUX_V1_PCR_TFSDIR |
107 IMX_AUDMUX_V1_PCR_TCLKDIR |
108 IMX_AUDMUX_V1_PCR_RFSDIR |
109 IMX_AUDMUX_V1_PCR_RCLKDIR |
110 IMX_AUDMUX_V1_PCR_TFCSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) |
111 IMX_AUDMUX_V1_PCR_RFCSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) |
112 IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4)
113 );
114 imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR3_SSI_PINS_4,
115 IMX_AUDMUX_V1_PCR_SYN |
116 IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0)
117 );
118 } else if (machine_is_eukrea_cpuimx25sd() ||
119 machine_is_eukrea_cpuimx35sd() ||
120 machine_is_eukrea_cpuimx51sd()) {
121 ext_port = machine_is_eukrea_cpuimx25sd() ? 4 : 3;
122 imx_audmux_v2_configure_port(int_port,
123 IMX_AUDMUX_V2_PTCR_SYN |
124 IMX_AUDMUX_V2_PTCR_TFSDIR |
125 IMX_AUDMUX_V2_PTCR_TFSEL(ext_port) |
126 IMX_AUDMUX_V2_PTCR_TCLKDIR |
127 IMX_AUDMUX_V2_PTCR_TCSEL(ext_port),
128 IMX_AUDMUX_V2_PDCR_RXDSEL(ext_port)
129 );
130 imx_audmux_v2_configure_port(ext_port,
131 IMX_AUDMUX_V2_PTCR_SYN,
132 IMX_AUDMUX_V2_PDCR_RXDSEL(int_port)
133 );
134 } else {
104 /* return happy. We might run on a totally different machine */ 135 /* return happy. We might run on a totally different machine */
105 return 0; 136 return 0;
137 }
106 138
107 eukrea_tlv320_snd_device = platform_device_alloc("soc-audio", -1); 139 eukrea_tlv320_snd_device = platform_device_alloc("soc-audio", -1);
108 if (!eukrea_tlv320_snd_device) 140 if (!eukrea_tlv320_snd_device)
diff --git a/sound/soc/imx/imx-audmux.c b/sound/soc/imx/imx-audmux.c
new file mode 100644
index 000000000000..b83699d905bb
--- /dev/null
+++ b/sound/soc/imx/imx-audmux.c
@@ -0,0 +1,314 @@
1/*
2 * Copyright 2012 Freescale Semiconductor, Inc.
3 * Copyright 2012 Linaro Ltd.
4 * Copyright 2009 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
5 *
6 * Initial development of this code was funded by
7 * Phytec Messtechnik GmbH, http://www.phytec.de
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 */
19
20#include <linux/clk.h>
21#include <linux/debugfs.h>
22#include <linux/err.h>
23#include <linux/io.h>
24#include <linux/module.h>
25#include <linux/of.h>
26#include <linux/of_device.h>
27#include <linux/platform_device.h>
28#include <linux/slab.h>
29
30#include "imx-audmux.h"
31
32#define DRIVER_NAME "imx-audmux"
33
34static struct clk *audmux_clk;
35static void __iomem *audmux_base;
36
37#define IMX_AUDMUX_V2_PTCR(x) ((x) * 8)
38#define IMX_AUDMUX_V2_PDCR(x) ((x) * 8 + 4)
39
40#ifdef CONFIG_DEBUG_FS
41static struct dentry *audmux_debugfs_root;
42
43static int audmux_open_file(struct inode *inode, struct file *file)
44{
45 file->private_data = inode->i_private;
46 return 0;
47}
48
49/* There is an annoying discontinuity in the SSI numbering with regard
50 * to the Linux number of the devices */
51static const char *audmux_port_string(int port)
52{
53 switch (port) {
54 case MX31_AUDMUX_PORT1_SSI0:
55 return "imx-ssi.0";
56 case MX31_AUDMUX_PORT2_SSI1:
57 return "imx-ssi.1";
58 case MX31_AUDMUX_PORT3_SSI_PINS_3:
59 return "SSI3";
60 case MX31_AUDMUX_PORT4_SSI_PINS_4:
61 return "SSI4";
62 case MX31_AUDMUX_PORT5_SSI_PINS_5:
63 return "SSI5";
64 case MX31_AUDMUX_PORT6_SSI_PINS_6:
65 return "SSI6";
66 default:
67 return "UNKNOWN";
68 }
69}
70
71static ssize_t audmux_read_file(struct file *file, char __user *user_buf,
72 size_t count, loff_t *ppos)
73{
74 ssize_t ret;
75 char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
76 int port = (int)file->private_data;
77 u32 pdcr, ptcr;
78
79 if (!buf)
80 return -ENOMEM;
81
82 if (audmux_clk)
83 clk_enable(audmux_clk);
84
85 ptcr = readl(audmux_base + IMX_AUDMUX_V2_PTCR(port));
86 pdcr = readl(audmux_base + IMX_AUDMUX_V2_PDCR(port));
87
88 if (audmux_clk)
89 clk_disable(audmux_clk);
90
91 ret = snprintf(buf, PAGE_SIZE, "PDCR: %08x\nPTCR: %08x\n",
92 pdcr, ptcr);
93
94 if (ptcr & IMX_AUDMUX_V2_PTCR_TFSDIR)
95 ret += snprintf(buf + ret, PAGE_SIZE - ret,
96 "TxFS output from %s, ",
97 audmux_port_string((ptcr >> 27) & 0x7));
98 else
99 ret += snprintf(buf + ret, PAGE_SIZE - ret,
100 "TxFS input, ");
101
102 if (ptcr & IMX_AUDMUX_V2_PTCR_TCLKDIR)
103 ret += snprintf(buf + ret, PAGE_SIZE - ret,
104 "TxClk output from %s",
105 audmux_port_string((ptcr >> 22) & 0x7));
106 else
107 ret += snprintf(buf + ret, PAGE_SIZE - ret,
108 "TxClk input");
109
110 ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
111
112 if (ptcr & IMX_AUDMUX_V2_PTCR_SYN) {
113 ret += snprintf(buf + ret, PAGE_SIZE - ret,
114 "Port is symmetric");
115 } else {
116 if (ptcr & IMX_AUDMUX_V2_PTCR_RFSDIR)
117 ret += snprintf(buf + ret, PAGE_SIZE - ret,
118 "RxFS output from %s, ",
119 audmux_port_string((ptcr >> 17) & 0x7));
120 else
121 ret += snprintf(buf + ret, PAGE_SIZE - ret,
122 "RxFS input, ");
123
124 if (ptcr & IMX_AUDMUX_V2_PTCR_RCLKDIR)
125 ret += snprintf(buf + ret, PAGE_SIZE - ret,
126 "RxClk output from %s",
127 audmux_port_string((ptcr >> 12) & 0x7));
128 else
129 ret += snprintf(buf + ret, PAGE_SIZE - ret,
130 "RxClk input");
131 }
132
133 ret += snprintf(buf + ret, PAGE_SIZE - ret,
134 "\nData received from %s\n",
135 audmux_port_string((pdcr >> 13) & 0x7));
136
137 ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
138
139 kfree(buf);
140
141 return ret;
142}
143
144static const struct file_operations audmux_debugfs_fops = {
145 .open = audmux_open_file,
146 .read = audmux_read_file,
147 .llseek = default_llseek,
148};
149
150static void __init audmux_debugfs_init(void)
151{
152 int i;
153 char buf[20];
154
155 audmux_debugfs_root = debugfs_create_dir("audmux", NULL);
156 if (!audmux_debugfs_root) {
157 pr_warning("Failed to create AUDMUX debugfs root\n");
158 return;
159 }
160
161 for (i = 1; i < 8; i++) {
162 snprintf(buf, sizeof(buf), "ssi%d", i);
163 if (!debugfs_create_file(buf, 0444, audmux_debugfs_root,
164 (void *)i, &audmux_debugfs_fops))
165 pr_warning("Failed to create AUDMUX port %d debugfs file\n",
166 i);
167 }
168}
169
170static void __exit audmux_debugfs_remove(void)
171{
172 debugfs_remove_recursive(audmux_debugfs_root);
173}
174#else
175static inline void audmux_debugfs_init(void)
176{
177}
178
179static inline void audmux_debugfs_remove(void)
180{
181}
182#endif
183
184enum imx_audmux_type {
185 IMX21_AUDMUX,
186 IMX31_AUDMUX,
187} audmux_type;
188
189static struct platform_device_id imx_audmux_ids[] = {
190 {
191 .name = "imx21-audmux",
192 .driver_data = IMX21_AUDMUX,
193 }, {
194 .name = "imx31-audmux",
195 .driver_data = IMX31_AUDMUX,
196 }, {
197 /* sentinel */
198 }
199};
200MODULE_DEVICE_TABLE(platform, imx_audmux_ids);
201
202static const struct of_device_id imx_audmux_dt_ids[] = {
203 { .compatible = "fsl,imx21-audmux", .data = &imx_audmux_ids[0], },
204 { .compatible = "fsl,imx31-audmux", .data = &imx_audmux_ids[1], },
205 { /* sentinel */ }
206};
207MODULE_DEVICE_TABLE(of, imx_audmux_dt_ids);
208
209static const uint8_t port_mapping[] = {
210 0x0, 0x4, 0x8, 0x10, 0x14, 0x1c,
211};
212
213int imx_audmux_v1_configure_port(unsigned int port, unsigned int pcr)
214{
215 if (audmux_type != IMX21_AUDMUX)
216 return -EINVAL;
217
218 if (!audmux_base)
219 return -ENOSYS;
220
221 if (port >= ARRAY_SIZE(port_mapping))
222 return -EINVAL;
223
224 writel(pcr, audmux_base + port_mapping[port]);
225
226 return 0;
227}
228EXPORT_SYMBOL_GPL(imx_audmux_v1_configure_port);
229
230int imx_audmux_v2_configure_port(unsigned int port, unsigned int ptcr,
231 unsigned int pdcr)
232{
233 if (audmux_type != IMX31_AUDMUX)
234 return -EINVAL;
235
236 if (!audmux_base)
237 return -ENOSYS;
238
239 if (audmux_clk)
240 clk_enable(audmux_clk);
241
242 writel(ptcr, audmux_base + IMX_AUDMUX_V2_PTCR(port));
243 writel(pdcr, audmux_base + IMX_AUDMUX_V2_PDCR(port));
244
245 if (audmux_clk)
246 clk_disable(audmux_clk);
247
248 return 0;
249}
250EXPORT_SYMBOL_GPL(imx_audmux_v2_configure_port);
251
252static int __init imx_audmux_probe(struct platform_device *pdev)
253{
254 struct resource *res;
255 const struct of_device_id *of_id =
256 of_match_device(imx_audmux_dt_ids, &pdev->dev);
257
258 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
259 audmux_base = devm_request_and_ioremap(&pdev->dev, res);
260 if (!audmux_base)
261 return -EADDRNOTAVAIL;
262
263 audmux_clk = clk_get(&pdev->dev, "audmux");
264 if (IS_ERR(audmux_clk)) {
265 dev_dbg(&pdev->dev, "cannot get clock: %ld\n",
266 PTR_ERR(audmux_clk));
267 audmux_clk = NULL;
268 }
269
270 if (of_id)
271 pdev->id_entry = of_id->data;
272 audmux_type = pdev->id_entry->driver_data;
273 if (audmux_type == IMX31_AUDMUX)
274 audmux_debugfs_init();
275
276 return 0;
277}
278
279static int __exit imx_audmux_remove(struct platform_device *pdev)
280{
281 if (audmux_type == IMX31_AUDMUX)
282 audmux_debugfs_remove();
283 clk_put(audmux_clk);
284
285 return 0;
286}
287
288static struct platform_driver imx_audmux_driver = {
289 .probe = imx_audmux_probe,
290 .remove = __exit_p(imx_audmux_remove),
291 .id_table = imx_audmux_ids,
292 .driver = {
293 .name = DRIVER_NAME,
294 .owner = THIS_MODULE,
295 .of_match_table = imx_audmux_dt_ids,
296 }
297};
298
299static int __init imx_audmux_init(void)
300{
301 return platform_driver_register(&imx_audmux_driver);
302}
303subsys_initcall(imx_audmux_init);
304
305static void __exit imx_audmux_exit(void)
306{
307 platform_driver_unregister(&imx_audmux_driver);
308}
309module_exit(imx_audmux_exit);
310
311MODULE_DESCRIPTION("Freescale i.MX AUDMUX driver");
312MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
313MODULE_LICENSE("GPL v2");
314MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/sound/soc/imx/imx-audmux.h b/sound/soc/imx/imx-audmux.h
new file mode 100644
index 000000000000..04ebbab8d7b9
--- /dev/null
+++ b/sound/soc/imx/imx-audmux.h
@@ -0,0 +1,60 @@
1#ifndef __IMX_AUDMUX_H
2#define __IMX_AUDMUX_H
3
4#define MX27_AUDMUX_HPCR1_SSI0 0
5#define MX27_AUDMUX_HPCR2_SSI1 1
6#define MX27_AUDMUX_HPCR3_SSI_PINS_4 2
7#define MX27_AUDMUX_PPCR1_SSI_PINS_1 3
8#define MX27_AUDMUX_PPCR2_SSI_PINS_2 4
9#define MX27_AUDMUX_PPCR3_SSI_PINS_3 5
10
11#define MX31_AUDMUX_PORT1_SSI0 0
12#define MX31_AUDMUX_PORT2_SSI1 1
13#define MX31_AUDMUX_PORT3_SSI_PINS_3 2
14#define MX31_AUDMUX_PORT4_SSI_PINS_4 3
15#define MX31_AUDMUX_PORT5_SSI_PINS_5 4
16#define MX31_AUDMUX_PORT6_SSI_PINS_6 5
17
18#define MX51_AUDMUX_PORT1_SSI0 0
19#define MX51_AUDMUX_PORT2_SSI1 1
20#define MX51_AUDMUX_PORT3 2
21#define MX51_AUDMUX_PORT4 3
22#define MX51_AUDMUX_PORT5 4
23#define MX51_AUDMUX_PORT6 5
24#define MX51_AUDMUX_PORT7 6
25
26/* Register definitions for the i.MX21/27 Digital Audio Multiplexer */
27#define IMX_AUDMUX_V1_PCR_INMMASK(x) ((x) & 0xff)
28#define IMX_AUDMUX_V1_PCR_INMEN (1 << 8)
29#define IMX_AUDMUX_V1_PCR_TXRXEN (1 << 10)
30#define IMX_AUDMUX_V1_PCR_SYN (1 << 12)
31#define IMX_AUDMUX_V1_PCR_RXDSEL(x) (((x) & 0x7) << 13)
32#define IMX_AUDMUX_V1_PCR_RFCSEL(x) (((x) & 0xf) << 20)
33#define IMX_AUDMUX_V1_PCR_RCLKDIR (1 << 24)
34#define IMX_AUDMUX_V1_PCR_RFSDIR (1 << 25)
35#define IMX_AUDMUX_V1_PCR_TFCSEL(x) (((x) & 0xf) << 26)
36#define IMX_AUDMUX_V1_PCR_TCLKDIR (1 << 30)
37#define IMX_AUDMUX_V1_PCR_TFSDIR (1 << 31)
38
39/* Register definitions for the i.MX25/31/35/51 Digital Audio Multiplexer */
40#define IMX_AUDMUX_V2_PTCR_TFSDIR (1 << 31)
41#define IMX_AUDMUX_V2_PTCR_TFSEL(x) (((x) & 0xf) << 27)
42#define IMX_AUDMUX_V2_PTCR_TCLKDIR (1 << 26)
43#define IMX_AUDMUX_V2_PTCR_TCSEL(x) (((x) & 0xf) << 22)
44#define IMX_AUDMUX_V2_PTCR_RFSDIR (1 << 21)
45#define IMX_AUDMUX_V2_PTCR_RFSEL(x) (((x) & 0xf) << 17)
46#define IMX_AUDMUX_V2_PTCR_RCLKDIR (1 << 16)
47#define IMX_AUDMUX_V2_PTCR_RCSEL(x) (((x) & 0xf) << 12)
48#define IMX_AUDMUX_V2_PTCR_SYN (1 << 11)
49
50#define IMX_AUDMUX_V2_PDCR_RXDSEL(x) (((x) & 0x7) << 13)
51#define IMX_AUDMUX_V2_PDCR_TXRXEN (1 << 12)
52#define IMX_AUDMUX_V2_PDCR_MODE(x) (((x) & 0x3) << 8)
53#define IMX_AUDMUX_V2_PDCR_INMMASK(x) ((x) & 0xff)
54
55int imx_audmux_v1_configure_port(unsigned int port, unsigned int pcr);
56
57int imx_audmux_v2_configure_port(unsigned int port, unsigned int ptcr,
58 unsigned int pdcr);
59
60#endif /* __IMX_AUDMUX_H */
diff --git a/sound/soc/imx/imx-pcm-dma-mx2.c b/sound/soc/imx/imx-pcm-dma-mx2.c
index 471e2218c971..e43c8fa2788b 100644
--- a/sound/soc/imx/imx-pcm-dma-mx2.c
+++ b/sound/soc/imx/imx-pcm-dma-mx2.c
@@ -31,7 +31,7 @@
31 31
32#include <mach/dma.h> 32#include <mach/dma.h>
33 33
34#include "imx-ssi.h" 34#include "imx-pcm.h"
35 35
36static bool filter(struct dma_chan *chan, void *param) 36static bool filter(struct dma_chan *chan, void *param)
37{ 37{
diff --git a/sound/soc/imx/imx-pcm.c b/sound/soc/imx/imx-pcm.c
new file mode 100644
index 000000000000..93dc360b1777
--- /dev/null
+++ b/sound/soc/imx/imx-pcm.c
@@ -0,0 +1,105 @@
1/*
2 * Copyright 2009 Sascha Hauer <s.hauer@pengutronix.de>
3 *
4 * This code is based on code copyrighted by Freescale,
5 * Liam Girdwood, Javier Martin and probably others.
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#include <linux/dma-mapping.h>
14#include <linux/module.h>
15#include <sound/pcm.h>
16#include <sound/soc.h>
17#include "imx-pcm.h"
18
19int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
20 struct vm_area_struct *vma)
21{
22 struct snd_pcm_runtime *runtime = substream->runtime;
23 int ret;
24
25 ret = dma_mmap_writecombine(substream->pcm->card->dev, vma,
26 runtime->dma_area, runtime->dma_addr, runtime->dma_bytes);
27
28 pr_debug("%s: ret: %d %p 0x%08x 0x%08x\n", __func__, ret,
29 runtime->dma_area,
30 runtime->dma_addr,
31 runtime->dma_bytes);
32 return ret;
33}
34EXPORT_SYMBOL_GPL(snd_imx_pcm_mmap);
35
36static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
37{
38 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
39 struct snd_dma_buffer *buf = &substream->dma_buffer;
40 size_t size = IMX_SSI_DMABUF_SIZE;
41
42 buf->dev.type = SNDRV_DMA_TYPE_DEV;
43 buf->dev.dev = pcm->card->dev;
44 buf->private_data = NULL;
45 buf->area = dma_alloc_writecombine(pcm->card->dev, size,
46 &buf->addr, GFP_KERNEL);
47 if (!buf->area)
48 return -ENOMEM;
49 buf->bytes = size;
50
51 return 0;
52}
53
54static u64 imx_pcm_dmamask = DMA_BIT_MASK(32);
55
56int imx_pcm_new(struct snd_soc_pcm_runtime *rtd)
57{
58 struct snd_card *card = rtd->card->snd_card;
59 struct snd_pcm *pcm = rtd->pcm;
60 int ret = 0;
61
62 if (!card->dev->dma_mask)
63 card->dev->dma_mask = &imx_pcm_dmamask;
64 if (!card->dev->coherent_dma_mask)
65 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
66 if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
67 ret = imx_pcm_preallocate_dma_buffer(pcm,
68 SNDRV_PCM_STREAM_PLAYBACK);
69 if (ret)
70 goto out;
71 }
72
73 if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
74 ret = imx_pcm_preallocate_dma_buffer(pcm,
75 SNDRV_PCM_STREAM_CAPTURE);
76 if (ret)
77 goto out;
78 }
79
80out:
81 return ret;
82}
83EXPORT_SYMBOL_GPL(imx_pcm_new);
84
85void imx_pcm_free(struct snd_pcm *pcm)
86{
87 struct snd_pcm_substream *substream;
88 struct snd_dma_buffer *buf;
89 int stream;
90
91 for (stream = 0; stream < 2; stream++) {
92 substream = pcm->streams[stream].substream;
93 if (!substream)
94 continue;
95
96 buf = &substream->dma_buffer;
97 if (!buf->area)
98 continue;
99
100 dma_free_writecombine(pcm->card->dev, buf->bytes,
101 buf->area, buf->addr);
102 buf->area = NULL;
103 }
104}
105EXPORT_SYMBOL_GPL(imx_pcm_free);
diff --git a/sound/soc/imx/imx-pcm.h b/sound/soc/imx/imx-pcm.h
new file mode 100644
index 000000000000..b5f5c3acf34d
--- /dev/null
+++ b/sound/soc/imx/imx-pcm.h
@@ -0,0 +1,32 @@
1/*
2 * Copyright 2009 Sascha Hauer <s.hauer@pengutronix.de>
3 *
4 * This code is based on code copyrighted by Freescale,
5 * Liam Girdwood, Javier Martin and probably others.
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#ifndef _IMX_PCM_H
14#define _IMX_PCM_H
15
16/*
17 * Do not change this as the FIQ handler depends on this size
18 */
19#define IMX_SSI_DMABUF_SIZE (64 * 1024)
20
21struct imx_pcm_dma_params {
22 int dma;
23 unsigned long dma_addr;
24 int burstsize;
25};
26
27int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
28 struct vm_area_struct *vma);
29int imx_pcm_new(struct snd_soc_pcm_runtime *rtd);
30void imx_pcm_free(struct snd_pcm *pcm);
31
32#endif /* _IMX_PCM_H */
diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c
index 25c623115a9f..9203cdd0a154 100644
--- a/sound/soc/imx/imx-ssi.c
+++ b/sound/soc/imx/imx-ssi.c
@@ -363,94 +363,6 @@ static const struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = {
363 .trigger = imx_ssi_trigger, 363 .trigger = imx_ssi_trigger,
364}; 364};
365 365
366int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
367 struct vm_area_struct *vma)
368{
369 struct snd_pcm_runtime *runtime = substream->runtime;
370 int ret;
371
372 ret = dma_mmap_writecombine(substream->pcm->card->dev, vma,
373 runtime->dma_area, runtime->dma_addr, runtime->dma_bytes);
374
375 pr_debug("%s: ret: %d %p 0x%08x 0x%08x\n", __func__, ret,
376 runtime->dma_area,
377 runtime->dma_addr,
378 runtime->dma_bytes);
379 return ret;
380}
381EXPORT_SYMBOL_GPL(snd_imx_pcm_mmap);
382
383static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
384{
385 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
386 struct snd_dma_buffer *buf = &substream->dma_buffer;
387 size_t size = IMX_SSI_DMABUF_SIZE;
388
389 buf->dev.type = SNDRV_DMA_TYPE_DEV;
390 buf->dev.dev = pcm->card->dev;
391 buf->private_data = NULL;
392 buf->area = dma_alloc_writecombine(pcm->card->dev, size,
393 &buf->addr, GFP_KERNEL);
394 if (!buf->area)
395 return -ENOMEM;
396 buf->bytes = size;
397
398 return 0;
399}
400
401static u64 imx_pcm_dmamask = DMA_BIT_MASK(32);
402
403int imx_pcm_new(struct snd_soc_pcm_runtime *rtd)
404{
405 struct snd_card *card = rtd->card->snd_card;
406 struct snd_pcm *pcm = rtd->pcm;
407 int ret = 0;
408
409 if (!card->dev->dma_mask)
410 card->dev->dma_mask = &imx_pcm_dmamask;
411 if (!card->dev->coherent_dma_mask)
412 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
413 if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
414 ret = imx_pcm_preallocate_dma_buffer(pcm,
415 SNDRV_PCM_STREAM_PLAYBACK);
416 if (ret)
417 goto out;
418 }
419
420 if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
421 ret = imx_pcm_preallocate_dma_buffer(pcm,
422 SNDRV_PCM_STREAM_CAPTURE);
423 if (ret)
424 goto out;
425 }
426
427out:
428 return ret;
429}
430EXPORT_SYMBOL_GPL(imx_pcm_new);
431
432void imx_pcm_free(struct snd_pcm *pcm)
433{
434 struct snd_pcm_substream *substream;
435 struct snd_dma_buffer *buf;
436 int stream;
437
438 for (stream = 0; stream < 2; stream++) {
439 substream = pcm->streams[stream].substream;
440 if (!substream)
441 continue;
442
443 buf = &substream->dma_buffer;
444 if (!buf->area)
445 continue;
446
447 dma_free_writecombine(pcm->card->dev, buf->bytes,
448 buf->area, buf->addr);
449 buf->area = NULL;
450 }
451}
452EXPORT_SYMBOL_GPL(imx_pcm_free);
453
454static int imx_ssi_dai_probe(struct snd_soc_dai *dai) 366static int imx_ssi_dai_probe(struct snd_soc_dai *dai)
455{ 367{
456 struct imx_ssi *ssi = dev_get_drvdata(dai->dev); 368 struct imx_ssi *ssi = dev_get_drvdata(dai->dev);
diff --git a/sound/soc/imx/imx-ssi.h b/sound/soc/imx/imx-ssi.h
index 1072dfb53e47..5744e86ca878 100644
--- a/sound/soc/imx/imx-ssi.h
+++ b/sound/soc/imx/imx-ssi.h
@@ -187,12 +187,7 @@
187 187
188#include <linux/dmaengine.h> 188#include <linux/dmaengine.h>
189#include <mach/dma.h> 189#include <mach/dma.h>
190 190#include "imx-pcm.h"
191struct imx_pcm_dma_params {
192 int dma;
193 unsigned long dma_addr;
194 int burstsize;
195};
196 191
197struct imx_ssi { 192struct imx_ssi {
198 struct platform_device *ac97_dev; 193 struct platform_device *ac97_dev;
@@ -218,13 +213,4 @@ struct imx_ssi {
218 struct platform_device *soc_platform_pdev_fiq; 213 struct platform_device *soc_platform_pdev_fiq;
219}; 214};
220 215
221int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma);
222int imx_pcm_new(struct snd_soc_pcm_runtime *rtd);
223void imx_pcm_free(struct snd_pcm *pcm);
224
225/*
226 * Do not change this as the FIQ handler depends on this size
227 */
228#define IMX_SSI_DMABUF_SIZE (64 * 1024)
229
230#endif /* _IMX_SSI_H */ 216#endif /* _IMX_SSI_H */
diff --git a/sound/soc/imx/mx27vis-aic32x4.c b/sound/soc/imx/mx27vis-aic32x4.c
index 155899c08c0c..976f857151f0 100644
--- a/sound/soc/imx/mx27vis-aic32x4.c
+++ b/sound/soc/imx/mx27vis-aic32x4.c
@@ -32,11 +32,11 @@
32#include <sound/soc-dapm.h> 32#include <sound/soc-dapm.h>
33#include <sound/tlv.h> 33#include <sound/tlv.h>
34#include <asm/mach-types.h> 34#include <asm/mach-types.h>
35#include <mach/audmux.h>
36#include <mach/iomux-mx27.h> 35#include <mach/iomux-mx27.h>
37 36
38#include "../codecs/tlv320aic32x4.h" 37#include "../codecs/tlv320aic32x4.h"
39#include "imx-ssi.h" 38#include "imx-ssi.h"
39#include "imx-audmux.h"
40 40
41#define MX27VIS_AMP_GAIN 0 41#define MX27VIS_AMP_GAIN 0
42#define MX27VIS_AMP_MUTE 1 42#define MX27VIS_AMP_MUTE 1
@@ -207,16 +207,16 @@ static int __init mx27vis_aic32x4_init(void)
207 } 207 }
208 208
209 /* Connect SSI0 as clock slave to SSI1 external pins */ 209 /* Connect SSI0 as clock slave to SSI1 external pins */
210 mxc_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0, 210 imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0,
211 MXC_AUDMUX_V1_PCR_SYN | 211 IMX_AUDMUX_V1_PCR_SYN |
212 MXC_AUDMUX_V1_PCR_TFSDIR | 212 IMX_AUDMUX_V1_PCR_TFSDIR |
213 MXC_AUDMUX_V1_PCR_TCLKDIR | 213 IMX_AUDMUX_V1_PCR_TCLKDIR |
214 MXC_AUDMUX_V1_PCR_TFCSEL(MX27_AUDMUX_PPCR1_SSI_PINS_1) | 214 IMX_AUDMUX_V1_PCR_TFCSEL(MX27_AUDMUX_PPCR1_SSI_PINS_1) |
215 MXC_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_PPCR1_SSI_PINS_1) 215 IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_PPCR1_SSI_PINS_1)
216 ); 216 );
217 mxc_audmux_v1_configure_port(MX27_AUDMUX_PPCR1_SSI_PINS_1, 217 imx_audmux_v1_configure_port(MX27_AUDMUX_PPCR1_SSI_PINS_1,
218 MXC_AUDMUX_V1_PCR_SYN | 218 IMX_AUDMUX_V1_PCR_SYN |
219 MXC_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0) 219 IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0)
220 ); 220 );
221 221
222 ret = mxc_gpio_setup_multiple_pins(mx27vis_amp_pins, 222 ret = mxc_gpio_setup_multiple_pins(mx27vis_amp_pins,
diff --git a/sound/soc/imx/phycore-ac97.c b/sound/soc/imx/phycore-ac97.c
index 6ac12111de6a..f8da6dd115ed 100644
--- a/sound/soc/imx/phycore-ac97.c
+++ b/sound/soc/imx/phycore-ac97.c
@@ -19,6 +19,8 @@
19#include <sound/soc.h> 19#include <sound/soc.h>
20#include <asm/mach-types.h> 20#include <asm/mach-types.h>
21 21
22#include "imx-audmux.h"
23
22static struct snd_soc_card imx_phycore; 24static struct snd_soc_card imx_phycore;
23 25
24static struct snd_soc_ops imx_phycore_hifi_ops = { 26static struct snd_soc_ops imx_phycore_hifi_ops = {
@@ -50,9 +52,32 @@ static int __init imx_phycore_init(void)
50{ 52{
51 int ret; 53 int ret;
52 54
53 if (!machine_is_pcm043() && !machine_is_pca100()) 55 if (machine_is_pca100()) {
56 imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0,
57 IMX_AUDMUX_V1_PCR_SYN | /* 4wire mode */
58 IMX_AUDMUX_V1_PCR_TFCSEL(3) |
59 IMX_AUDMUX_V1_PCR_TCLKDIR | /* clock is output */
60 IMX_AUDMUX_V1_PCR_RXDSEL(3));
61 imx_audmux_v1_configure_port(3,
62 IMX_AUDMUX_V1_PCR_SYN | /* 4wire mode */
63 IMX_AUDMUX_V1_PCR_TFCSEL(0) |
64 IMX_AUDMUX_V1_PCR_TFSDIR |
65 IMX_AUDMUX_V1_PCR_RXDSEL(0));
66 } else if (machine_is_pcm043()) {
67 imx_audmux_v2_configure_port(3,
68 IMX_AUDMUX_V2_PTCR_SYN | /* 4wire mode */
69 IMX_AUDMUX_V2_PTCR_TFSEL(0) |
70 IMX_AUDMUX_V2_PTCR_TFSDIR,
71 IMX_AUDMUX_V2_PDCR_RXDSEL(0));
72 imx_audmux_v2_configure_port(0,
73 IMX_AUDMUX_V2_PTCR_SYN | /* 4wire mode */
74 IMX_AUDMUX_V2_PTCR_TCSEL(3) |
75 IMX_AUDMUX_V2_PTCR_TCLKDIR, /* clock is output */
76 IMX_AUDMUX_V2_PDCR_RXDSEL(3));
77 } else {
54 /* return happy. We might run on a totally different machine */ 78 /* return happy. We might run on a totally different machine */
55 return 0; 79 return 0;
80 }
56 81
57 imx_phycore_snd_ac97_device = platform_device_alloc("soc-audio", -1); 82 imx_phycore_snd_ac97_device = platform_device_alloc("soc-audio", -1);
58 if (!imx_phycore_snd_ac97_device) 83 if (!imx_phycore_snd_ac97_device)
diff --git a/sound/soc/imx/wm1133-ev1.c b/sound/soc/imx/wm1133-ev1.c
index 37480c90e997..fe54a69073e5 100644
--- a/sound/soc/imx/wm1133-ev1.c
+++ b/sound/soc/imx/wm1133-ev1.c
@@ -21,10 +21,9 @@
21#include <sound/pcm_params.h> 21#include <sound/pcm_params.h>
22#include <sound/soc.h> 22#include <sound/soc.h>
23 23
24#include <mach/audmux.h>
25
26#include "imx-ssi.h" 24#include "imx-ssi.h"
27#include "../codecs/wm8350.h" 25#include "../codecs/wm8350.h"
26#include "imx-audmux.h"
28 27
29/* There is a silicon mic on the board optionally connected via a solder pad 28/* There is a silicon mic on the board optionally connected via a solder pad
30 * SP1. Define this to enable it. 29 * SP1. Define this to enable it.
@@ -268,17 +267,17 @@ static int __init wm1133_ev1_audio_init(void)
268 unsigned int ptcr, pdcr; 267 unsigned int ptcr, pdcr;
269 268
270 /* SSI0 mastered by port 5 */ 269 /* SSI0 mastered by port 5 */
271 ptcr = MXC_AUDMUX_V2_PTCR_SYN | 270 ptcr = IMX_AUDMUX_V2_PTCR_SYN |
272 MXC_AUDMUX_V2_PTCR_TFSDIR | 271 IMX_AUDMUX_V2_PTCR_TFSDIR |
273 MXC_AUDMUX_V2_PTCR_TFSEL(MX31_AUDMUX_PORT5_SSI_PINS_5) | 272 IMX_AUDMUX_V2_PTCR_TFSEL(MX31_AUDMUX_PORT5_SSI_PINS_5) |
274 MXC_AUDMUX_V2_PTCR_TCLKDIR | 273 IMX_AUDMUX_V2_PTCR_TCLKDIR |
275 MXC_AUDMUX_V2_PTCR_TCSEL(MX31_AUDMUX_PORT5_SSI_PINS_5); 274 IMX_AUDMUX_V2_PTCR_TCSEL(MX31_AUDMUX_PORT5_SSI_PINS_5);
276 pdcr = MXC_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT5_SSI_PINS_5); 275 pdcr = IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT5_SSI_PINS_5);
277 mxc_audmux_v2_configure_port(MX31_AUDMUX_PORT1_SSI0, ptcr, pdcr); 276 imx_audmux_v2_configure_port(MX31_AUDMUX_PORT1_SSI0, ptcr, pdcr);
278 277
279 ptcr = MXC_AUDMUX_V2_PTCR_SYN; 278 ptcr = IMX_AUDMUX_V2_PTCR_SYN;
280 pdcr = MXC_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT1_SSI0); 279 pdcr = IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT1_SSI0);
281 mxc_audmux_v2_configure_port(MX31_AUDMUX_PORT5_SSI_PINS_5, ptcr, pdcr); 280 imx_audmux_v2_configure_port(MX31_AUDMUX_PORT5_SSI_PINS_5, ptcr, pdcr);
282 281
283 wm1133_ev1_snd_device = platform_device_alloc("soc-audio", -1); 282 wm1133_ev1_snd_device = platform_device_alloc("soc-audio", -1);
284 if (!wm1133_ev1_snd_device) 283 if (!wm1133_ev1_snd_device)
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index c9b088dab1cf..a4d4aa1e6c49 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -1569,8 +1569,9 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
1569 out = is_connected_output_ep(w); 1569 out = is_connected_output_ep(w);
1570 dapm_clear_walk(w->dapm); 1570 dapm_clear_walk(w->dapm);
1571 1571
1572 ret = snprintf(buf, PAGE_SIZE, "%s: %s in %d out %d", 1572 ret = snprintf(buf, PAGE_SIZE, "%s: %s%s in %d out %d",
1573 w->name, w->power ? "On" : "Off", in, out); 1573 w->name, w->power ? "On" : "Off",
1574 w->force ? " (forced)" : "", in, out);
1574 1575
1575 if (w->reg >= 0) 1576 if (w->reg >= 0)
1576 ret += snprintf(buf + ret, PAGE_SIZE - ret, 1577 ret += snprintf(buf + ret, PAGE_SIZE - ret,