diff options
author | Takashi Iwai <tiwai@suse.de> | 2014-08-04 12:28:21 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2014-08-04 12:28:21 -0400 |
commit | e9e3bdffe38b256f920eacc455d30deba5e97655 (patch) | |
tree | cfa546f6370c117e012c12605da22ce189542127 /sound/soc/samsung | |
parent | f42bb22243d2ae264d721b055f836059fe35321f (diff) | |
parent | ae34a78c430c37c06404f032fb04e51315204281 (diff) |
Merge tag 'asoc-v3.17' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Updates for v3.17
This has been a pretty exciting release in terms of the framework, we've
finally got support for multiple CODECs attached to a single DAI link
which has been something there's been interest in as long as I've been
working on ASoC. A big thanks to Benoit and Misael for their work on
this.
Otherwise it's been a fairly standard release for development, including
more componentisation work from Lars-Peter and a good selection of both
CODEC and CPU drivers.
- Support for multiple CODECs attached to a single DAI, enabling
systems with for example multiple DAC/speaker drivers on a single
link, contributed by Benoit Cousson based on work from Misael Lopez
Cruz.
- Support for byte controls larger than 256 bytes based on the use of
TLVs contributed by Omair Mohammed Abdullah.
- More componentisation work from Lars-Peter Clausen.
- The remainder of the conversions of CODEC drivers to params_width()
- Drivers for Cirrus Logic CS4265, Freescale i.MX ASRC blocks, Realtek
RT286 and RT5670, Rockchip RK3xxx I2S controllers and Texas Instruments
TAS2552.
- Lots of updates and fixes, especially to the DaVinci, Intel,
Freescale, Realtek, and rcar drivers.
Diffstat (limited to 'sound/soc/samsung')
-rw-r--r-- | sound/soc/samsung/Kconfig | 40 | ||||
-rw-r--r-- | sound/soc/samsung/Makefile | 6 | ||||
-rw-r--r-- | sound/soc/samsung/ac97.c | 32 | ||||
-rw-r--r-- | sound/soc/samsung/dma.c | 454 | ||||
-rw-r--r-- | sound/soc/samsung/dma.h | 7 | ||||
-rw-r--r-- | sound/soc/samsung/dmaengine.c | 3 | ||||
-rw-r--r-- | sound/soc/samsung/i2s.c | 35 | ||||
-rw-r--r-- | sound/soc/samsung/idma.c | 3 | ||||
-rw-r--r-- | sound/soc/samsung/odroidx2_max98090.c | 177 | ||||
-rw-r--r-- | sound/soc/samsung/pcm.c | 12 | ||||
-rw-r--r-- | sound/soc/samsung/s3c-i2s-v2.c | 19 | ||||
-rw-r--r-- | sound/soc/samsung/s3c2412-i2s.c | 43 | ||||
-rw-r--r-- | sound/soc/samsung/s3c24xx-i2s.c | 58 | ||||
-rw-r--r-- | sound/soc/samsung/smdk_wm8580pcm.c | 2 | ||||
-rw-r--r-- | sound/soc/samsung/snow.c | 4 | ||||
-rw-r--r-- | sound/soc/samsung/spdif.c | 5 |
16 files changed, 267 insertions, 633 deletions
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index 753b8c93ab51..55a38697443d 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig | |||
@@ -1,25 +1,16 @@ | |||
1 | config SND_SOC_SAMSUNG | 1 | config SND_SOC_SAMSUNG |
2 | tristate "ASoC support for Samsung" | 2 | tristate "ASoC support for Samsung" |
3 | depends on PLAT_SAMSUNG | 3 | depends on PLAT_SAMSUNG |
4 | select S3C2410_DMA if ARCH_S3C24XX | 4 | depends on S3C64XX_PL080 || !ARCH_S3C64XX |
5 | select S3C64XX_PL080 if ARCH_S3C64XX | 5 | depends on S3C24XX_DMAC || !ARCH_S3C24XX |
6 | select SND_S3C_DMA if !ARCH_S3C24XX | 6 | select SND_SOC_GENERIC_DMAENGINE_PCM |
7 | select SND_S3C_DMA_LEGACY if ARCH_S3C24XX | ||
8 | select SND_SOC_GENERIC_DMAENGINE_PCM if !ARCH_S3C24XX | ||
9 | help | 7 | help |
10 | Say Y or M if you want to add support for codecs attached to | 8 | Say Y or M if you want to add support for codecs attached to |
11 | the Samsung SoCs' Audio interfaces. You will also need to | 9 | the Samsung SoCs' Audio interfaces. You will also need to |
12 | select the audio interfaces to support below. | 10 | select the audio interfaces to support below. |
13 | 11 | ||
14 | config SND_S3C_DMA | ||
15 | tristate | ||
16 | |||
17 | config SND_S3C_DMA_LEGACY | ||
18 | tristate | ||
19 | |||
20 | config SND_S3C24XX_I2S | 12 | config SND_S3C24XX_I2S |
21 | tristate | 13 | tristate |
22 | select S3C24XX_DMA | ||
23 | 14 | ||
24 | config SND_S3C_I2SV2_SOC | 15 | config SND_S3C_I2SV2_SOC |
25 | tristate | 16 | tristate |
@@ -27,7 +18,6 @@ config SND_S3C_I2SV2_SOC | |||
27 | config SND_S3C2412_SOC_I2S | 18 | config SND_S3C2412_SOC_I2S |
28 | tristate | 19 | tristate |
29 | select SND_S3C_I2SV2_SOC | 20 | select SND_S3C_I2SV2_SOC |
30 | select S3C2410_DMA | ||
31 | 21 | ||
32 | config SND_SAMSUNG_PCM | 22 | config SND_SAMSUNG_PCM |
33 | tristate | 23 | tristate |
@@ -55,7 +45,7 @@ config SND_SOC_SAMSUNG_NEO1973_WM8753 | |||
55 | 45 | ||
56 | config SND_SOC_SAMSUNG_JIVE_WM8750 | 46 | config SND_SOC_SAMSUNG_JIVE_WM8750 |
57 | tristate "SoC I2S Audio support for Jive" | 47 | tristate "SoC I2S Audio support for Jive" |
58 | depends on SND_SOC_SAMSUNG && MACH_JIVE | 48 | depends on SND_SOC_SAMSUNG && MACH_JIVE && I2C |
59 | select SND_SOC_WM8750 | 49 | select SND_SOC_WM8750 |
60 | select SND_S3C2412_SOC_I2S | 50 | select SND_S3C2412_SOC_I2S |
61 | help | 51 | help |
@@ -63,7 +53,7 @@ config SND_SOC_SAMSUNG_JIVE_WM8750 | |||
63 | 53 | ||
64 | config SND_SOC_SAMSUNG_SMDK_WM8580 | 54 | config SND_SOC_SAMSUNG_SMDK_WM8580 |
65 | tristate "SoC I2S Audio support for WM8580 on SMDK" | 55 | tristate "SoC I2S Audio support for WM8580 on SMDK" |
66 | depends on SND_SOC_SAMSUNG && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDK6440 || MACH_SMDK6450 || MACH_SMDKV210 || MACH_SMDKC110) | 56 | depends on SND_SOC_SAMSUNG && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110) |
67 | depends on REGMAP_I2C | 57 | depends on REGMAP_I2C |
68 | select SND_SOC_WM8580 | 58 | select SND_SOC_WM8580 |
69 | select SND_SAMSUNG_I2S | 59 | select SND_SAMSUNG_I2S |
@@ -83,7 +73,6 @@ config SND_SOC_SAMSUNG_SMDK_WM8994 | |||
83 | config SND_SOC_SAMSUNG_SMDK2443_WM9710 | 73 | config SND_SOC_SAMSUNG_SMDK2443_WM9710 |
84 | tristate "SoC AC97 Audio support for SMDK2443 - WM9710" | 74 | tristate "SoC AC97 Audio support for SMDK2443 - WM9710" |
85 | depends on SND_SOC_SAMSUNG && MACH_SMDK2443 | 75 | depends on SND_SOC_SAMSUNG && MACH_SMDK2443 |
86 | select S3C2410_DMA | ||
87 | select AC97_BUS | 76 | select AC97_BUS |
88 | select SND_SOC_AC97_CODEC | 77 | select SND_SOC_AC97_CODEC |
89 | select SND_SAMSUNG_AC97 | 78 | select SND_SAMSUNG_AC97 |
@@ -94,7 +83,6 @@ config SND_SOC_SAMSUNG_SMDK2443_WM9710 | |||
94 | config SND_SOC_SAMSUNG_LN2440SBC_ALC650 | 83 | config SND_SOC_SAMSUNG_LN2440SBC_ALC650 |
95 | tristate "SoC AC97 Audio support for LN2440SBC - ALC650" | 84 | tristate "SoC AC97 Audio support for LN2440SBC - ALC650" |
96 | depends on SND_SOC_SAMSUNG && ARCH_S3C24XX | 85 | depends on SND_SOC_SAMSUNG && ARCH_S3C24XX |
97 | select S3C2410_DMA | ||
98 | select AC97_BUS | 86 | select AC97_BUS |
99 | select SND_SOC_AC97_CODEC | 87 | select SND_SOC_AC97_CODEC |
100 | select SND_SAMSUNG_AC97 | 88 | select SND_SAMSUNG_AC97 |
@@ -154,7 +142,7 @@ config SND_SOC_SAMSUNG_SMDK_WM9713 | |||
154 | 142 | ||
155 | config SND_SOC_SMARTQ | 143 | config SND_SOC_SMARTQ |
156 | tristate "SoC I2S Audio support for SmartQ board" | 144 | tristate "SoC I2S Audio support for SmartQ board" |
157 | depends on SND_SOC_SAMSUNG && MACH_SMARTQ | 145 | depends on SND_SOC_SAMSUNG && MACH_SMARTQ && I2C |
158 | select SND_SAMSUNG_I2S | 146 | select SND_SAMSUNG_I2S |
159 | select SND_SOC_WM8750 | 147 | select SND_SOC_WM8750 |
160 | 148 | ||
@@ -178,7 +166,7 @@ config SND_SOC_SAMSUNG_SMDK_SPDIF | |||
178 | 166 | ||
179 | config SND_SOC_SMDK_WM8580_PCM | 167 | config SND_SOC_SMDK_WM8580_PCM |
180 | tristate "SoC PCM Audio support for WM8580 on SMDK" | 168 | tristate "SoC PCM Audio support for WM8580 on SMDK" |
181 | depends on SND_SOC_SAMSUNG && (MACH_SMDK6450 || MACH_SMDKV210 || MACH_SMDKC110) | 169 | depends on SND_SOC_SAMSUNG && (MACH_SMDKV210 || MACH_SMDKC110) |
182 | depends on REGMAP_I2C | 170 | depends on REGMAP_I2C |
183 | select SND_SOC_WM8580 | 171 | select SND_SOC_WM8580 |
184 | select SND_SAMSUNG_PCM | 172 | select SND_SAMSUNG_PCM |
@@ -206,7 +194,7 @@ config SND_SOC_SPEYSIDE | |||
206 | 194 | ||
207 | config SND_SOC_TOBERMORY | 195 | config SND_SOC_TOBERMORY |
208 | tristate "Audio support for Wolfson Tobermory" | 196 | tristate "Audio support for Wolfson Tobermory" |
209 | depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 && INPUT | 197 | depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 && INPUT && I2C |
210 | select SND_SAMSUNG_I2S | 198 | select SND_SAMSUNG_I2S |
211 | select SND_SOC_WM8962 | 199 | select SND_SOC_WM8962 |
212 | 200 | ||
@@ -222,7 +210,7 @@ config SND_SOC_BELLS | |||
222 | 210 | ||
223 | config SND_SOC_LOWLAND | 211 | config SND_SOC_LOWLAND |
224 | tristate "Audio support for Wolfson Lowland" | 212 | tristate "Audio support for Wolfson Lowland" |
225 | depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 | 213 | depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 && I2C |
226 | select SND_SAMSUNG_I2S | 214 | select SND_SAMSUNG_I2S |
227 | select SND_SOC_WM5100 | 215 | select SND_SOC_WM5100 |
228 | select SND_SOC_WM9081 | 216 | select SND_SOC_WM9081 |
@@ -236,10 +224,18 @@ config SND_SOC_LITTLEMILL | |||
236 | 224 | ||
237 | config SND_SOC_SNOW | 225 | config SND_SOC_SNOW |
238 | tristate "Audio support for Google Snow boards" | 226 | tristate "Audio support for Google Snow boards" |
239 | depends on SND_SOC_SAMSUNG | 227 | depends on SND_SOC_SAMSUNG && I2C |
240 | select SND_SOC_MAX98090 | 228 | select SND_SOC_MAX98090 |
241 | select SND_SOC_MAX98095 | 229 | select SND_SOC_MAX98095 |
242 | select SND_SAMSUNG_I2S | 230 | select SND_SAMSUNG_I2S |
243 | help | 231 | help |
244 | Say Y if you want to add audio support for various Snow | 232 | Say Y if you want to add audio support for various Snow |
245 | boards based on Exynos5 series of SoCs. | 233 | boards based on Exynos5 series of SoCs. |
234 | |||
235 | config SND_SOC_ODROIDX2 | ||
236 | tristate "Audio support for Odroid-X2 and Odroid-U3" | ||
237 | depends on SND_SOC_SAMSUNG | ||
238 | select SND_SOC_MAX98090 | ||
239 | select SND_SAMSUNG_I2S | ||
240 | help | ||
241 | Say Y here to enable audio support for the Odroid-X2/U3. | ||
diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile index 6d0212ba571c..91505ddaaf95 100644 --- a/sound/soc/samsung/Makefile +++ b/sound/soc/samsung/Makefile | |||
@@ -1,6 +1,5 @@ | |||
1 | # S3c24XX Platform Support | 1 | # S3c24XX Platform Support |
2 | snd-soc-s3c-dma-objs := dmaengine.o | 2 | snd-soc-s3c-dma-objs := dmaengine.o |
3 | snd-soc-s3c-dma-legacy-objs := dma.o | ||
4 | snd-soc-idma-objs := idma.o | 3 | snd-soc-idma-objs := idma.o |
5 | snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o | 4 | snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o |
6 | snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o | 5 | snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o |
@@ -10,8 +9,7 @@ snd-soc-samsung-spdif-objs := spdif.o | |||
10 | snd-soc-pcm-objs := pcm.o | 9 | snd-soc-pcm-objs := pcm.o |
11 | snd-soc-i2s-objs := i2s.o | 10 | snd-soc-i2s-objs := i2s.o |
12 | 11 | ||
13 | obj-$(CONFIG_SND_S3C_DMA) += snd-soc-s3c-dma.o | 12 | obj-$(CONFIG_SND_SOC_SAMSUNG) += snd-soc-s3c-dma.o |
14 | obj-$(CONFIG_SND_S3C_DMA_LEGACY) += snd-soc-s3c-dma-legacy.o | ||
15 | obj-$(CONFIG_SND_S3C24XX_I2S) += snd-soc-s3c24xx-i2s.o | 13 | obj-$(CONFIG_SND_S3C24XX_I2S) += snd-soc-s3c24xx-i2s.o |
16 | obj-$(CONFIG_SND_SAMSUNG_AC97) += snd-soc-ac97.o | 14 | obj-$(CONFIG_SND_SAMSUNG_AC97) += snd-soc-ac97.o |
17 | obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o | 15 | obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o |
@@ -46,6 +44,7 @@ snd-soc-tobermory-objs := tobermory.o | |||
46 | snd-soc-lowland-objs := lowland.o | 44 | snd-soc-lowland-objs := lowland.o |
47 | snd-soc-littlemill-objs := littlemill.o | 45 | snd-soc-littlemill-objs := littlemill.o |
48 | snd-soc-bells-objs := bells.o | 46 | snd-soc-bells-objs := bells.o |
47 | snd-soc-odroidx2-max98090-objs := odroidx2_max98090.o | ||
49 | 48 | ||
50 | obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o | 49 | obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o |
51 | obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o | 50 | obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o |
@@ -71,3 +70,4 @@ obj-$(CONFIG_SND_SOC_TOBERMORY) += snd-soc-tobermory.o | |||
71 | obj-$(CONFIG_SND_SOC_LOWLAND) += snd-soc-lowland.o | 70 | obj-$(CONFIG_SND_SOC_LOWLAND) += snd-soc-lowland.o |
72 | obj-$(CONFIG_SND_SOC_LITTLEMILL) += snd-soc-littlemill.o | 71 | obj-$(CONFIG_SND_SOC_LITTLEMILL) += snd-soc-littlemill.o |
73 | obj-$(CONFIG_SND_SOC_BELLS) += snd-soc-bells.o | 72 | obj-$(CONFIG_SND_SOC_BELLS) += snd-soc-bells.o |
73 | obj-$(CONFIG_SND_SOC_ODROIDX2) += snd-soc-odroidx2-max98090.o | ||
diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c index 68d9303047e8..e1615113fd84 100644 --- a/sound/soc/samsung/ac97.c +++ b/sound/soc/samsung/ac97.c | |||
@@ -19,7 +19,6 @@ | |||
19 | 19 | ||
20 | #include <sound/soc.h> | 20 | #include <sound/soc.h> |
21 | 21 | ||
22 | #include <mach/dma.h> | ||
23 | #include "regs-ac97.h" | 22 | #include "regs-ac97.h" |
24 | #include <linux/platform_data/asoc-s3c.h> | 23 | #include <linux/platform_data/asoc-s3c.h> |
25 | 24 | ||
@@ -39,30 +38,15 @@ struct s3c_ac97_info { | |||
39 | }; | 38 | }; |
40 | static struct s3c_ac97_info s3c_ac97; | 39 | static struct s3c_ac97_info s3c_ac97; |
41 | 40 | ||
42 | static struct s3c_dma_client s3c_dma_client_out = { | ||
43 | .name = "AC97 PCMOut" | ||
44 | }; | ||
45 | |||
46 | static struct s3c_dma_client s3c_dma_client_in = { | ||
47 | .name = "AC97 PCMIn" | ||
48 | }; | ||
49 | |||
50 | static struct s3c_dma_client s3c_dma_client_micin = { | ||
51 | .name = "AC97 MicIn" | ||
52 | }; | ||
53 | |||
54 | static struct s3c_dma_params s3c_ac97_pcm_out = { | 41 | static struct s3c_dma_params s3c_ac97_pcm_out = { |
55 | .client = &s3c_dma_client_out, | ||
56 | .dma_size = 4, | 42 | .dma_size = 4, |
57 | }; | 43 | }; |
58 | 44 | ||
59 | static struct s3c_dma_params s3c_ac97_pcm_in = { | 45 | static struct s3c_dma_params s3c_ac97_pcm_in = { |
60 | .client = &s3c_dma_client_in, | ||
61 | .dma_size = 4, | 46 | .dma_size = 4, |
62 | }; | 47 | }; |
63 | 48 | ||
64 | static struct s3c_dma_params s3c_ac97_mic_in = { | 49 | static struct s3c_dma_params s3c_ac97_mic_in = { |
65 | .client = &s3c_dma_client_micin, | ||
66 | .dma_size = 4, | 50 | .dma_size = 4, |
67 | }; | 51 | }; |
68 | 52 | ||
@@ -225,9 +209,6 @@ static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd, | |||
225 | struct snd_soc_dai *dai) | 209 | struct snd_soc_dai *dai) |
226 | { | 210 | { |
227 | u32 ac_glbctrl; | 211 | u32 ac_glbctrl; |
228 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
229 | struct s3c_dma_params *dma_data = | ||
230 | snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
231 | 212 | ||
232 | ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); | 213 | ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); |
233 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | 214 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) |
@@ -253,11 +234,6 @@ static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd, | |||
253 | 234 | ||
254 | writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); | 235 | writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); |
255 | 236 | ||
256 | if (!dma_data->ops) | ||
257 | dma_data->ops = samsung_dma_get_ops(); | ||
258 | |||
259 | dma_data->ops->started(dma_data->channel); | ||
260 | |||
261 | return 0; | 237 | return 0; |
262 | } | 238 | } |
263 | 239 | ||
@@ -265,9 +241,6 @@ static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream, | |||
265 | int cmd, struct snd_soc_dai *dai) | 241 | int cmd, struct snd_soc_dai *dai) |
266 | { | 242 | { |
267 | u32 ac_glbctrl; | 243 | u32 ac_glbctrl; |
268 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
269 | struct s3c_dma_params *dma_data = | ||
270 | snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
271 | 244 | ||
272 | ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); | 245 | ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); |
273 | ac_glbctrl &= ~S3C_AC97_GLBCTRL_MICINTM_MASK; | 246 | ac_glbctrl &= ~S3C_AC97_GLBCTRL_MICINTM_MASK; |
@@ -287,11 +260,6 @@ static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream, | |||
287 | 260 | ||
288 | writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); | 261 | writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); |
289 | 262 | ||
290 | if (!dma_data->ops) | ||
291 | dma_data->ops = samsung_dma_get_ops(); | ||
292 | |||
293 | dma_data->ops->started(dma_data->channel); | ||
294 | |||
295 | return 0; | 263 | return 0; |
296 | } | 264 | } |
297 | 265 | ||
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c deleted file mode 100644 index d9dc7bcc0336..000000000000 --- a/sound/soc/samsung/dma.c +++ /dev/null | |||
@@ -1,454 +0,0 @@ | |||
1 | /* | ||
2 | * dma.c -- ALSA Soc Audio Layer | ||
3 | * | ||
4 | * (c) 2006 Wolfson Microelectronics PLC. | ||
5 | * Graeme Gregory graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com | ||
6 | * | ||
7 | * Copyright 2004-2005 Simtec Electronics | ||
8 | * http://armlinux.simtec.co.uk/ | ||
9 | * Ben Dooks <ben@simtec.co.uk> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
14 | * option) any later version. | ||
15 | */ | ||
16 | |||
17 | #include <linux/slab.h> | ||
18 | #include <linux/dma-mapping.h> | ||
19 | #include <linux/module.h> | ||
20 | |||
21 | #include <sound/soc.h> | ||
22 | #include <sound/pcm_params.h> | ||
23 | |||
24 | #include <asm/dma.h> | ||
25 | #include <mach/hardware.h> | ||
26 | #include <mach/dma.h> | ||
27 | |||
28 | #include "dma.h" | ||
29 | |||
30 | #define ST_RUNNING (1<<0) | ||
31 | #define ST_OPENED (1<<1) | ||
32 | |||
33 | static const struct snd_pcm_hardware dma_hardware = { | ||
34 | .info = SNDRV_PCM_INFO_INTERLEAVED | | ||
35 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
36 | SNDRV_PCM_INFO_MMAP | | ||
37 | SNDRV_PCM_INFO_MMAP_VALID, | ||
38 | .buffer_bytes_max = 128*1024, | ||
39 | .period_bytes_min = PAGE_SIZE, | ||
40 | .period_bytes_max = PAGE_SIZE*2, | ||
41 | .periods_min = 2, | ||
42 | .periods_max = 128, | ||
43 | .fifo_size = 32, | ||
44 | }; | ||
45 | |||
46 | struct runtime_data { | ||
47 | spinlock_t lock; | ||
48 | int state; | ||
49 | unsigned int dma_loaded; | ||
50 | unsigned int dma_period; | ||
51 | dma_addr_t dma_start; | ||
52 | dma_addr_t dma_pos; | ||
53 | dma_addr_t dma_end; | ||
54 | struct s3c_dma_params *params; | ||
55 | }; | ||
56 | |||
57 | static void audio_buffdone(void *data); | ||
58 | |||
59 | /* dma_enqueue | ||
60 | * | ||
61 | * place a dma buffer onto the queue for the dma system | ||
62 | * to handle. | ||
63 | */ | ||
64 | static void dma_enqueue(struct snd_pcm_substream *substream) | ||
65 | { | ||
66 | struct runtime_data *prtd = substream->runtime->private_data; | ||
67 | dma_addr_t pos = prtd->dma_pos; | ||
68 | unsigned int limit; | ||
69 | struct samsung_dma_prep dma_info; | ||
70 | |||
71 | pr_debug("Entered %s\n", __func__); | ||
72 | |||
73 | limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period; | ||
74 | |||
75 | pr_debug("%s: loaded %d, limit %d\n", | ||
76 | __func__, prtd->dma_loaded, limit); | ||
77 | |||
78 | dma_info.cap = (samsung_dma_has_circular() ? DMA_CYCLIC : DMA_SLAVE); | ||
79 | dma_info.direction = | ||
80 | (substream->stream == SNDRV_PCM_STREAM_PLAYBACK | ||
81 | ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM); | ||
82 | dma_info.fp = audio_buffdone; | ||
83 | dma_info.fp_param = substream; | ||
84 | dma_info.period = prtd->dma_period; | ||
85 | dma_info.len = prtd->dma_period*limit; | ||
86 | |||
87 | if (dma_info.cap == DMA_CYCLIC) { | ||
88 | dma_info.buf = pos; | ||
89 | prtd->params->ops->prepare(prtd->params->ch, &dma_info); | ||
90 | prtd->dma_loaded += limit; | ||
91 | return; | ||
92 | } | ||
93 | |||
94 | while (prtd->dma_loaded < limit) { | ||
95 | pr_debug("dma_loaded: %d\n", prtd->dma_loaded); | ||
96 | |||
97 | if ((pos + dma_info.period) > prtd->dma_end) { | ||
98 | dma_info.period = prtd->dma_end - pos; | ||
99 | pr_debug("%s: corrected dma len %ld\n", | ||
100 | __func__, dma_info.period); | ||
101 | } | ||
102 | |||
103 | dma_info.buf = pos; | ||
104 | prtd->params->ops->prepare(prtd->params->ch, &dma_info); | ||
105 | |||
106 | prtd->dma_loaded++; | ||
107 | pos += prtd->dma_period; | ||
108 | if (pos >= prtd->dma_end) | ||
109 | pos = prtd->dma_start; | ||
110 | } | ||
111 | |||
112 | prtd->dma_pos = pos; | ||
113 | } | ||
114 | |||
115 | static void audio_buffdone(void *data) | ||
116 | { | ||
117 | struct snd_pcm_substream *substream = data; | ||
118 | struct runtime_data *prtd = substream->runtime->private_data; | ||
119 | |||
120 | pr_debug("Entered %s\n", __func__); | ||
121 | |||
122 | if (prtd->state & ST_RUNNING) { | ||
123 | prtd->dma_pos += prtd->dma_period; | ||
124 | if (prtd->dma_pos >= prtd->dma_end) | ||
125 | prtd->dma_pos = prtd->dma_start; | ||
126 | |||
127 | if (substream) | ||
128 | snd_pcm_period_elapsed(substream); | ||
129 | |||
130 | spin_lock(&prtd->lock); | ||
131 | if (!samsung_dma_has_circular()) { | ||
132 | prtd->dma_loaded--; | ||
133 | dma_enqueue(substream); | ||
134 | } | ||
135 | spin_unlock(&prtd->lock); | ||
136 | } | ||
137 | } | ||
138 | |||
139 | static int dma_hw_params(struct snd_pcm_substream *substream, | ||
140 | struct snd_pcm_hw_params *params) | ||
141 | { | ||
142 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
143 | struct runtime_data *prtd = runtime->private_data; | ||
144 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
145 | unsigned long totbytes = params_buffer_bytes(params); | ||
146 | struct s3c_dma_params *dma = | ||
147 | snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
148 | struct samsung_dma_req req; | ||
149 | struct samsung_dma_config config; | ||
150 | |||
151 | pr_debug("Entered %s\n", __func__); | ||
152 | |||
153 | /* return if this is a bufferless transfer e.g. | ||
154 | * codec <--> BT codec or GSM modem -- lg FIXME */ | ||
155 | if (!dma) | ||
156 | return 0; | ||
157 | |||
158 | /* this may get called several times by oss emulation | ||
159 | * with different params -HW */ | ||
160 | if (prtd->params == NULL) { | ||
161 | /* prepare DMA */ | ||
162 | prtd->params = dma; | ||
163 | |||
164 | pr_debug("params %p, client %p, channel %d\n", prtd->params, | ||
165 | prtd->params->client, prtd->params->channel); | ||
166 | |||
167 | prtd->params->ops = samsung_dma_get_ops(); | ||
168 | |||
169 | req.cap = (samsung_dma_has_circular() ? | ||
170 | DMA_CYCLIC : DMA_SLAVE); | ||
171 | req.client = prtd->params->client; | ||
172 | config.direction = | ||
173 | (substream->stream == SNDRV_PCM_STREAM_PLAYBACK | ||
174 | ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM); | ||
175 | config.width = prtd->params->dma_size; | ||
176 | config.fifo = prtd->params->dma_addr; | ||
177 | prtd->params->ch = prtd->params->ops->request( | ||
178 | prtd->params->channel, &req, rtd->cpu_dai->dev, | ||
179 | prtd->params->ch_name); | ||
180 | if (!prtd->params->ch) { | ||
181 | pr_err("Failed to allocate DMA channel\n"); | ||
182 | return -ENXIO; | ||
183 | } | ||
184 | prtd->params->ops->config(prtd->params->ch, &config); | ||
185 | } | ||
186 | |||
187 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | ||
188 | |||
189 | runtime->dma_bytes = totbytes; | ||
190 | |||
191 | spin_lock_irq(&prtd->lock); | ||
192 | prtd->dma_loaded = 0; | ||
193 | prtd->dma_period = params_period_bytes(params); | ||
194 | prtd->dma_start = runtime->dma_addr; | ||
195 | prtd->dma_pos = prtd->dma_start; | ||
196 | prtd->dma_end = prtd->dma_start + totbytes; | ||
197 | spin_unlock_irq(&prtd->lock); | ||
198 | |||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | static int dma_hw_free(struct snd_pcm_substream *substream) | ||
203 | { | ||
204 | struct runtime_data *prtd = substream->runtime->private_data; | ||
205 | |||
206 | pr_debug("Entered %s\n", __func__); | ||
207 | |||
208 | snd_pcm_set_runtime_buffer(substream, NULL); | ||
209 | |||
210 | if (prtd->params) { | ||
211 | prtd->params->ops->flush(prtd->params->ch); | ||
212 | prtd->params->ops->release(prtd->params->ch, | ||
213 | prtd->params->client); | ||
214 | prtd->params = NULL; | ||
215 | } | ||
216 | |||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | static int dma_prepare(struct snd_pcm_substream *substream) | ||
221 | { | ||
222 | struct runtime_data *prtd = substream->runtime->private_data; | ||
223 | int ret = 0; | ||
224 | |||
225 | pr_debug("Entered %s\n", __func__); | ||
226 | |||
227 | /* return if this is a bufferless transfer e.g. | ||
228 | * codec <--> BT codec or GSM modem -- lg FIXME */ | ||
229 | if (!prtd->params) | ||
230 | return 0; | ||
231 | |||
232 | /* flush the DMA channel */ | ||
233 | prtd->params->ops->flush(prtd->params->ch); | ||
234 | |||
235 | prtd->dma_loaded = 0; | ||
236 | prtd->dma_pos = prtd->dma_start; | ||
237 | |||
238 | /* enqueue dma buffers */ | ||
239 | dma_enqueue(substream); | ||
240 | |||
241 | return ret; | ||
242 | } | ||
243 | |||
244 | static int dma_trigger(struct snd_pcm_substream *substream, int cmd) | ||
245 | { | ||
246 | struct runtime_data *prtd = substream->runtime->private_data; | ||
247 | int ret = 0; | ||
248 | |||
249 | pr_debug("Entered %s\n", __func__); | ||
250 | |||
251 | spin_lock(&prtd->lock); | ||
252 | |||
253 | switch (cmd) { | ||
254 | case SNDRV_PCM_TRIGGER_START: | ||
255 | prtd->state |= ST_RUNNING; | ||
256 | prtd->params->ops->trigger(prtd->params->ch); | ||
257 | break; | ||
258 | |||
259 | case SNDRV_PCM_TRIGGER_STOP: | ||
260 | prtd->state &= ~ST_RUNNING; | ||
261 | prtd->params->ops->stop(prtd->params->ch); | ||
262 | break; | ||
263 | |||
264 | default: | ||
265 | ret = -EINVAL; | ||
266 | break; | ||
267 | } | ||
268 | |||
269 | spin_unlock(&prtd->lock); | ||
270 | |||
271 | return ret; | ||
272 | } | ||
273 | |||
274 | static snd_pcm_uframes_t | ||
275 | dma_pointer(struct snd_pcm_substream *substream) | ||
276 | { | ||
277 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
278 | struct runtime_data *prtd = runtime->private_data; | ||
279 | unsigned long res; | ||
280 | |||
281 | pr_debug("Entered %s\n", __func__); | ||
282 | |||
283 | res = prtd->dma_pos - prtd->dma_start; | ||
284 | |||
285 | pr_debug("Pointer offset: %lu\n", res); | ||
286 | |||
287 | /* we seem to be getting the odd error from the pcm library due | ||
288 | * to out-of-bounds pointers. this is maybe due to the dma engine | ||
289 | * not having loaded the new values for the channel before being | ||
290 | * called... (todo - fix ) | ||
291 | */ | ||
292 | |||
293 | if (res >= snd_pcm_lib_buffer_bytes(substream)) { | ||
294 | if (res == snd_pcm_lib_buffer_bytes(substream)) | ||
295 | res = 0; | ||
296 | } | ||
297 | |||
298 | return bytes_to_frames(substream->runtime, res); | ||
299 | } | ||
300 | |||
301 | static int dma_open(struct snd_pcm_substream *substream) | ||
302 | { | ||
303 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
304 | struct runtime_data *prtd; | ||
305 | |||
306 | pr_debug("Entered %s\n", __func__); | ||
307 | |||
308 | snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); | ||
309 | snd_soc_set_runtime_hwparams(substream, &dma_hardware); | ||
310 | |||
311 | prtd = kzalloc(sizeof(struct runtime_data), GFP_KERNEL); | ||
312 | if (prtd == NULL) | ||
313 | return -ENOMEM; | ||
314 | |||
315 | spin_lock_init(&prtd->lock); | ||
316 | |||
317 | runtime->private_data = prtd; | ||
318 | return 0; | ||
319 | } | ||
320 | |||
321 | static int dma_close(struct snd_pcm_substream *substream) | ||
322 | { | ||
323 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
324 | struct runtime_data *prtd = runtime->private_data; | ||
325 | |||
326 | pr_debug("Entered %s\n", __func__); | ||
327 | |||
328 | if (!prtd) | ||
329 | pr_debug("dma_close called with prtd == NULL\n"); | ||
330 | |||
331 | kfree(prtd); | ||
332 | |||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | static int dma_mmap(struct snd_pcm_substream *substream, | ||
337 | struct vm_area_struct *vma) | ||
338 | { | ||
339 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
340 | |||
341 | pr_debug("Entered %s\n", __func__); | ||
342 | |||
343 | return dma_mmap_writecombine(substream->pcm->card->dev, vma, | ||
344 | runtime->dma_area, | ||
345 | runtime->dma_addr, | ||
346 | runtime->dma_bytes); | ||
347 | } | ||
348 | |||
349 | static struct snd_pcm_ops dma_ops = { | ||
350 | .open = dma_open, | ||
351 | .close = dma_close, | ||
352 | .ioctl = snd_pcm_lib_ioctl, | ||
353 | .hw_params = dma_hw_params, | ||
354 | .hw_free = dma_hw_free, | ||
355 | .prepare = dma_prepare, | ||
356 | .trigger = dma_trigger, | ||
357 | .pointer = dma_pointer, | ||
358 | .mmap = dma_mmap, | ||
359 | }; | ||
360 | |||
361 | static int preallocate_dma_buffer(struct snd_pcm *pcm, int stream) | ||
362 | { | ||
363 | struct snd_pcm_substream *substream = pcm->streams[stream].substream; | ||
364 | struct snd_dma_buffer *buf = &substream->dma_buffer; | ||
365 | size_t size = dma_hardware.buffer_bytes_max; | ||
366 | |||
367 | pr_debug("Entered %s\n", __func__); | ||
368 | |||
369 | buf->dev.type = SNDRV_DMA_TYPE_DEV; | ||
370 | buf->dev.dev = pcm->card->dev; | ||
371 | buf->private_data = NULL; | ||
372 | buf->area = dma_alloc_writecombine(pcm->card->dev, size, | ||
373 | &buf->addr, GFP_KERNEL); | ||
374 | if (!buf->area) | ||
375 | return -ENOMEM; | ||
376 | buf->bytes = size; | ||
377 | return 0; | ||
378 | } | ||
379 | |||
380 | static void dma_free_dma_buffers(struct snd_pcm *pcm) | ||
381 | { | ||
382 | struct snd_pcm_substream *substream; | ||
383 | struct snd_dma_buffer *buf; | ||
384 | int stream; | ||
385 | |||
386 | pr_debug("Entered %s\n", __func__); | ||
387 | |||
388 | for (stream = 0; stream < 2; stream++) { | ||
389 | substream = pcm->streams[stream].substream; | ||
390 | if (!substream) | ||
391 | continue; | ||
392 | |||
393 | buf = &substream->dma_buffer; | ||
394 | if (!buf->area) | ||
395 | continue; | ||
396 | |||
397 | dma_free_writecombine(pcm->card->dev, buf->bytes, | ||
398 | buf->area, buf->addr); | ||
399 | buf->area = NULL; | ||
400 | } | ||
401 | } | ||
402 | |||
403 | static int dma_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; | ||
408 | |||
409 | pr_debug("Entered %s\n", __func__); | ||
410 | |||
411 | ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); | ||
412 | if (ret) | ||
413 | return ret; | ||
414 | |||
415 | if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { | ||
416 | ret = preallocate_dma_buffer(pcm, | ||
417 | SNDRV_PCM_STREAM_PLAYBACK); | ||
418 | if (ret) | ||
419 | goto out; | ||
420 | } | ||
421 | |||
422 | if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { | ||
423 | ret = preallocate_dma_buffer(pcm, | ||
424 | SNDRV_PCM_STREAM_CAPTURE); | ||
425 | if (ret) | ||
426 | goto out; | ||
427 | } | ||
428 | out: | ||
429 | return ret; | ||
430 | } | ||
431 | |||
432 | static struct snd_soc_platform_driver samsung_asoc_platform = { | ||
433 | .ops = &dma_ops, | ||
434 | .pcm_new = dma_new, | ||
435 | .pcm_free = dma_free_dma_buffers, | ||
436 | }; | ||
437 | |||
438 | void samsung_asoc_init_dma_data(struct snd_soc_dai *dai, | ||
439 | struct s3c_dma_params *playback, | ||
440 | struct s3c_dma_params *capture) | ||
441 | { | ||
442 | snd_soc_dai_init_dma_data(dai, playback, capture); | ||
443 | } | ||
444 | EXPORT_SYMBOL_GPL(samsung_asoc_init_dma_data); | ||
445 | |||
446 | int samsung_asoc_dma_platform_register(struct device *dev) | ||
447 | { | ||
448 | return devm_snd_soc_register_platform(dev, &samsung_asoc_platform); | ||
449 | } | ||
450 | EXPORT_SYMBOL_GPL(samsung_asoc_dma_platform_register); | ||
451 | |||
452 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); | ||
453 | MODULE_DESCRIPTION("Samsung ASoC DMA Driver"); | ||
454 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/samsung/dma.h b/sound/soc/samsung/dma.h index 070ab0f09609..0e85dcfec023 100644 --- a/sound/soc/samsung/dma.h +++ b/sound/soc/samsung/dma.h | |||
@@ -14,17 +14,10 @@ | |||
14 | 14 | ||
15 | #include <sound/dmaengine_pcm.h> | 15 | #include <sound/dmaengine_pcm.h> |
16 | 16 | ||
17 | struct s3c_dma_client { | ||
18 | char *name; | ||
19 | }; | ||
20 | |||
21 | struct s3c_dma_params { | 17 | struct s3c_dma_params { |
22 | struct s3c_dma_client *client; /* stream identifier */ | ||
23 | int channel; /* Channel ID */ | 18 | int channel; /* Channel ID */ |
24 | dma_addr_t dma_addr; | 19 | dma_addr_t dma_addr; |
25 | int dma_size; /* Size of the DMA transfer */ | 20 | int dma_size; /* Size of the DMA transfer */ |
26 | unsigned ch; | ||
27 | struct samsung_dma_ops *ops; | ||
28 | char *ch_name; | 21 | char *ch_name; |
29 | struct snd_dmaengine_dai_dma_data dma_data; | 22 | struct snd_dmaengine_dai_dma_data dma_data; |
30 | }; | 23 | }; |
diff --git a/sound/soc/samsung/dmaengine.c b/sound/soc/samsung/dmaengine.c index a0e4e7948909..506f5bf6d082 100644 --- a/sound/soc/samsung/dmaengine.c +++ b/sound/soc/samsung/dmaengine.c | |||
@@ -17,6 +17,7 @@ | |||
17 | 17 | ||
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | #include <linux/amba/pl08x.h> | 19 | #include <linux/amba/pl08x.h> |
20 | #include <linux/platform_data/dma-s3c24xx.h> | ||
20 | 21 | ||
21 | #include <sound/core.h> | 22 | #include <sound/core.h> |
22 | #include <sound/pcm.h> | 23 | #include <sound/pcm.h> |
@@ -29,6 +30,8 @@ | |||
29 | 30 | ||
30 | #ifdef CONFIG_ARCH_S3C64XX | 31 | #ifdef CONFIG_ARCH_S3C64XX |
31 | #define filter_fn pl08x_filter_id | 32 | #define filter_fn pl08x_filter_id |
33 | #elif defined(CONFIG_ARCH_S3C24XX) | ||
34 | #define filter_fn s3c24xx_dma_filter | ||
32 | #else | 35 | #else |
33 | #define filter_fn NULL | 36 | #define filter_fn NULL |
34 | #endif | 37 | #endif |
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 2ac76fa3e742..03eec22f0f46 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c | |||
@@ -68,6 +68,8 @@ struct i2s_dai { | |||
68 | #define DAI_OPENED (1 << 0) /* Dai is opened */ | 68 | #define DAI_OPENED (1 << 0) /* Dai is opened */ |
69 | #define DAI_MANAGER (1 << 1) /* Dai is the manager */ | 69 | #define DAI_MANAGER (1 << 1) /* Dai is the manager */ |
70 | unsigned mode; | 70 | unsigned mode; |
71 | /* CDCLK pin direction: 0 - input, 1 - output */ | ||
72 | unsigned int cdclk_out:1; | ||
71 | /* Driver for this DAI */ | 73 | /* Driver for this DAI */ |
72 | struct snd_soc_dai_driver i2s_dai_drv; | 74 | struct snd_soc_dai_driver i2s_dai_drv; |
73 | /* DMA parameters */ | 75 | /* DMA parameters */ |
@@ -737,6 +739,9 @@ static int i2s_startup(struct snd_pcm_substream *substream, | |||
737 | 739 | ||
738 | spin_unlock_irqrestore(&lock, flags); | 740 | spin_unlock_irqrestore(&lock, flags); |
739 | 741 | ||
742 | if (!is_opened(other) && i2s->cdclk_out) | ||
743 | i2s_set_sysclk(dai, SAMSUNG_I2S_CDCLK, | ||
744 | 0, SND_SOC_CLOCK_OUT); | ||
740 | return 0; | 745 | return 0; |
741 | } | 746 | } |
742 | 747 | ||
@@ -752,9 +757,13 @@ static void i2s_shutdown(struct snd_pcm_substream *substream, | |||
752 | i2s->mode &= ~DAI_OPENED; | 757 | i2s->mode &= ~DAI_OPENED; |
753 | i2s->mode &= ~DAI_MANAGER; | 758 | i2s->mode &= ~DAI_MANAGER; |
754 | 759 | ||
755 | if (is_opened(other)) | 760 | if (is_opened(other)) { |
756 | other->mode |= DAI_MANAGER; | 761 | other->mode |= DAI_MANAGER; |
757 | 762 | } else { | |
763 | u32 mod = readl(i2s->addr + I2SMOD); | ||
764 | i2s->cdclk_out = !(mod & MOD_CDCLKCON); | ||
765 | other->cdclk_out = i2s->cdclk_out; | ||
766 | } | ||
758 | /* Reset any constraint on RFS and BFS */ | 767 | /* Reset any constraint on RFS and BFS */ |
759 | i2s->rfs = 0; | 768 | i2s->rfs = 0; |
760 | i2s->bfs = 0; | 769 | i2s->bfs = 0; |
@@ -920,11 +929,9 @@ static int i2s_suspend(struct snd_soc_dai *dai) | |||
920 | { | 929 | { |
921 | struct i2s_dai *i2s = to_info(dai); | 930 | struct i2s_dai *i2s = to_info(dai); |
922 | 931 | ||
923 | if (dai->active) { | 932 | i2s->suspend_i2smod = readl(i2s->addr + I2SMOD); |
924 | i2s->suspend_i2smod = readl(i2s->addr + I2SMOD); | 933 | i2s->suspend_i2scon = readl(i2s->addr + I2SCON); |
925 | i2s->suspend_i2scon = readl(i2s->addr + I2SCON); | 934 | i2s->suspend_i2spsr = readl(i2s->addr + I2SPSR); |
926 | i2s->suspend_i2spsr = readl(i2s->addr + I2SPSR); | ||
927 | } | ||
928 | 935 | ||
929 | return 0; | 936 | return 0; |
930 | } | 937 | } |
@@ -933,11 +940,9 @@ static int i2s_resume(struct snd_soc_dai *dai) | |||
933 | { | 940 | { |
934 | struct i2s_dai *i2s = to_info(dai); | 941 | struct i2s_dai *i2s = to_info(dai); |
935 | 942 | ||
936 | if (dai->active) { | 943 | writel(i2s->suspend_i2scon, i2s->addr + I2SCON); |
937 | writel(i2s->suspend_i2scon, i2s->addr + I2SCON); | 944 | writel(i2s->suspend_i2smod, i2s->addr + I2SMOD); |
938 | writel(i2s->suspend_i2smod, i2s->addr + I2SMOD); | 945 | writel(i2s->suspend_i2spsr, i2s->addr + I2SPSR); |
939 | writel(i2s->suspend_i2spsr, i2s->addr + I2SPSR); | ||
940 | } | ||
941 | 946 | ||
942 | return 0; | 947 | return 0; |
943 | } | 948 | } |
@@ -1216,11 +1221,7 @@ static int samsung_i2s_probe(struct platform_device *pdev) | |||
1216 | 1221 | ||
1217 | pri_dai->dma_playback.dma_addr = regs_base + I2STXD; | 1222 | pri_dai->dma_playback.dma_addr = regs_base + I2STXD; |
1218 | pri_dai->dma_capture.dma_addr = regs_base + I2SRXD; | 1223 | pri_dai->dma_capture.dma_addr = regs_base + I2SRXD; |
1219 | pri_dai->dma_playback.client = | ||
1220 | (struct s3c_dma_client *)&pri_dai->dma_playback; | ||
1221 | pri_dai->dma_playback.ch_name = "tx"; | 1224 | pri_dai->dma_playback.ch_name = "tx"; |
1222 | pri_dai->dma_capture.client = | ||
1223 | (struct s3c_dma_client *)&pri_dai->dma_capture; | ||
1224 | pri_dai->dma_capture.ch_name = "rx"; | 1225 | pri_dai->dma_capture.ch_name = "rx"; |
1225 | pri_dai->dma_playback.dma_size = 4; | 1226 | pri_dai->dma_playback.dma_size = 4; |
1226 | pri_dai->dma_capture.dma_size = 4; | 1227 | pri_dai->dma_capture.dma_size = 4; |
@@ -1238,8 +1239,6 @@ static int samsung_i2s_probe(struct platform_device *pdev) | |||
1238 | goto err; | 1239 | goto err; |
1239 | } | 1240 | } |
1240 | sec_dai->dma_playback.dma_addr = regs_base + I2STXDS; | 1241 | sec_dai->dma_playback.dma_addr = regs_base + I2STXDS; |
1241 | sec_dai->dma_playback.client = | ||
1242 | (struct s3c_dma_client *)&sec_dai->dma_playback; | ||
1243 | sec_dai->dma_playback.ch_name = "tx-sec"; | 1242 | sec_dai->dma_playback.ch_name = "tx-sec"; |
1244 | 1243 | ||
1245 | if (!np) { | 1244 | if (!np) { |
diff --git a/sound/soc/samsung/idma.c b/sound/soc/samsung/idma.c index 8cc5770abb39..db6cefa18017 100644 --- a/sound/soc/samsung/idma.c +++ b/sound/soc/samsung/idma.c | |||
@@ -261,10 +261,9 @@ static int idma_mmap(struct snd_pcm_substream *substream, | |||
261 | static irqreturn_t iis_irq(int irqno, void *dev_id) | 261 | static irqreturn_t iis_irq(int irqno, void *dev_id) |
262 | { | 262 | { |
263 | struct idma_ctrl *prtd = (struct idma_ctrl *)dev_id; | 263 | struct idma_ctrl *prtd = (struct idma_ctrl *)dev_id; |
264 | u32 iiscon, iisahb, val, addr; | 264 | u32 iisahb, val, addr; |
265 | 265 | ||
266 | iisahb = readl(idma.regs + I2SAHB); | 266 | iisahb = readl(idma.regs + I2SAHB); |
267 | iiscon = readl(idma.regs + I2SCON); | ||
268 | 267 | ||
269 | val = (iisahb & AHB_LVL0INT) ? AHB_CLRLVL0INT : 0; | 268 | val = (iisahb & AHB_LVL0INT) ? AHB_CLRLVL0INT : 0; |
270 | 269 | ||
diff --git a/sound/soc/samsung/odroidx2_max98090.c b/sound/soc/samsung/odroidx2_max98090.c new file mode 100644 index 000000000000..278edf9e2a87 --- /dev/null +++ b/sound/soc/samsung/odroidx2_max98090.c | |||
@@ -0,0 +1,177 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 Samsung Electronics Co., Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License as published by the | ||
6 | * Free Software Foundation; either version 2 of the License, or (at your | ||
7 | * option) any later version. | ||
8 | */ | ||
9 | |||
10 | #include <linux/of.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <sound/soc.h> | ||
13 | #include <sound/pcm_params.h> | ||
14 | #include "i2s.h" | ||
15 | |||
16 | struct odroidx2_drv_data { | ||
17 | const struct snd_soc_dapm_widget *dapm_widgets; | ||
18 | unsigned int num_dapm_widgets; | ||
19 | }; | ||
20 | |||
21 | /* The I2S CDCLK output clock frequency for the MAX98090 codec */ | ||
22 | #define MAX98090_MCLK 19200000 | ||
23 | |||
24 | static int odroidx2_late_probe(struct snd_soc_card *card) | ||
25 | { | ||
26 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; | ||
27 | struct snd_soc_dai *cpu_dai = card->rtd[0].cpu_dai; | ||
28 | int ret; | ||
29 | |||
30 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, MAX98090_MCLK, | ||
31 | SND_SOC_CLOCK_IN); | ||
32 | if (ret < 0) | ||
33 | return ret; | ||
34 | |||
35 | /* Set the cpu DAI configuration in order to use CDCLK */ | ||
36 | return snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_CDCLK, | ||
37 | 0, SND_SOC_CLOCK_OUT); | ||
38 | } | ||
39 | |||
40 | static const struct snd_soc_dapm_widget odroidx2_dapm_widgets[] = { | ||
41 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | ||
42 | SND_SOC_DAPM_MIC("Mic Jack", NULL), | ||
43 | SND_SOC_DAPM_MIC("DMIC", NULL), | ||
44 | }; | ||
45 | |||
46 | static const struct snd_soc_dapm_widget odroidu3_dapm_widgets[] = { | ||
47 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | ||
48 | SND_SOC_DAPM_SPK("Speakers", NULL), | ||
49 | }; | ||
50 | |||
51 | static struct snd_soc_dai_link odroidx2_dai[] = { | ||
52 | { | ||
53 | .name = "MAX98090", | ||
54 | .stream_name = "MAX98090 PCM", | ||
55 | .codec_dai_name = "HiFi", | ||
56 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
57 | SND_SOC_DAIFMT_CBM_CFM, | ||
58 | } | ||
59 | }; | ||
60 | |||
61 | static struct snd_soc_card odroidx2 = { | ||
62 | .owner = THIS_MODULE, | ||
63 | .dai_link = odroidx2_dai, | ||
64 | .num_links = ARRAY_SIZE(odroidx2_dai), | ||
65 | .fully_routed = true, | ||
66 | .late_probe = odroidx2_late_probe, | ||
67 | }; | ||
68 | |||
69 | struct odroidx2_drv_data odroidx2_drvdata = { | ||
70 | .dapm_widgets = odroidx2_dapm_widgets, | ||
71 | .num_dapm_widgets = ARRAY_SIZE(odroidx2_dapm_widgets), | ||
72 | }; | ||
73 | |||
74 | struct odroidx2_drv_data odroidu3_drvdata = { | ||
75 | .dapm_widgets = odroidu3_dapm_widgets, | ||
76 | .num_dapm_widgets = ARRAY_SIZE(odroidu3_dapm_widgets), | ||
77 | }; | ||
78 | |||
79 | static const struct of_device_id odroidx2_audio_of_match[] = { | ||
80 | { | ||
81 | .compatible = "samsung,odroidx2-audio", | ||
82 | .data = &odroidx2_drvdata, | ||
83 | }, { | ||
84 | .compatible = "samsung,odroidu3-audio", | ||
85 | .data = &odroidu3_drvdata, | ||
86 | }, | ||
87 | { }, | ||
88 | }; | ||
89 | MODULE_DEVICE_TABLE(of, odroidx2_audio_of_match); | ||
90 | |||
91 | static int odroidx2_audio_probe(struct platform_device *pdev) | ||
92 | { | ||
93 | struct device_node *snd_node = pdev->dev.of_node; | ||
94 | struct snd_soc_card *card = &odroidx2; | ||
95 | struct device_node *i2s_node, *codec_node; | ||
96 | struct odroidx2_drv_data *dd; | ||
97 | const struct of_device_id *of_id; | ||
98 | int ret; | ||
99 | |||
100 | of_id = of_match_node(odroidx2_audio_of_match, snd_node); | ||
101 | dd = (struct odroidx2_drv_data *)of_id->data; | ||
102 | |||
103 | card->num_dapm_widgets = dd->num_dapm_widgets; | ||
104 | card->dapm_widgets = dd->dapm_widgets; | ||
105 | |||
106 | card->dev = &pdev->dev; | ||
107 | |||
108 | ret = snd_soc_of_parse_card_name(card, "samsung,model"); | ||
109 | if (ret < 0) | ||
110 | return ret; | ||
111 | |||
112 | ret = snd_soc_of_parse_audio_routing(card, "samsung,audio-routing"); | ||
113 | if (ret < 0) | ||
114 | return ret; | ||
115 | |||
116 | codec_node = of_parse_phandle(snd_node, "samsung,audio-codec", 0); | ||
117 | if (!codec_node) { | ||
118 | dev_err(&pdev->dev, | ||
119 | "Failed parsing samsung,i2s-codec property\n"); | ||
120 | return -EINVAL; | ||
121 | } | ||
122 | |||
123 | i2s_node = of_parse_phandle(snd_node, "samsung,i2s-controller", 0); | ||
124 | if (!i2s_node) { | ||
125 | dev_err(&pdev->dev, | ||
126 | "Failed parsing samsung,i2s-controller property\n"); | ||
127 | ret = -EINVAL; | ||
128 | goto err_put_codec_n; | ||
129 | } | ||
130 | |||
131 | odroidx2_dai[0].codec_of_node = codec_node; | ||
132 | odroidx2_dai[0].cpu_of_node = i2s_node; | ||
133 | odroidx2_dai[0].platform_of_node = i2s_node; | ||
134 | |||
135 | ret = snd_soc_register_card(card); | ||
136 | if (ret) { | ||
137 | dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", | ||
138 | ret); | ||
139 | goto err_put_i2s_n; | ||
140 | } | ||
141 | return 0; | ||
142 | |||
143 | err_put_i2s_n: | ||
144 | of_node_put(i2s_node); | ||
145 | err_put_codec_n: | ||
146 | of_node_put(codec_node); | ||
147 | return ret; | ||
148 | } | ||
149 | |||
150 | static int odroidx2_audio_remove(struct platform_device *pdev) | ||
151 | { | ||
152 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
153 | |||
154 | snd_soc_unregister_card(card); | ||
155 | |||
156 | of_node_put((struct device_node *)odroidx2_dai[0].cpu_of_node); | ||
157 | of_node_put((struct device_node *)odroidx2_dai[0].codec_of_node); | ||
158 | |||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | static struct platform_driver odroidx2_audio_driver = { | ||
163 | .driver = { | ||
164 | .name = "odroidx2-audio", | ||
165 | .owner = THIS_MODULE, | ||
166 | .of_match_table = odroidx2_audio_of_match, | ||
167 | .pm = &snd_soc_pm_ops, | ||
168 | }, | ||
169 | .probe = odroidx2_audio_probe, | ||
170 | .remove = odroidx2_audio_remove, | ||
171 | }; | ||
172 | module_platform_driver(odroidx2_audio_driver); | ||
173 | |||
174 | MODULE_AUTHOR("Chen Zhen <zhen1.chen@samsung.com>"); | ||
175 | MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>"); | ||
176 | MODULE_DESCRIPTION("ALSA SoC Odroid X2/U3 Audio Support"); | ||
177 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c index 4c5f97fe45c8..bac034b15a27 100644 --- a/sound/soc/samsung/pcm.c +++ b/sound/soc/samsung/pcm.c | |||
@@ -131,32 +131,20 @@ struct s3c_pcm_info { | |||
131 | struct s3c_dma_params *dma_capture; | 131 | struct s3c_dma_params *dma_capture; |
132 | }; | 132 | }; |
133 | 133 | ||
134 | static struct s3c_dma_client s3c_pcm_dma_client_out = { | ||
135 | .name = "PCM Stereo out" | ||
136 | }; | ||
137 | |||
138 | static struct s3c_dma_client s3c_pcm_dma_client_in = { | ||
139 | .name = "PCM Stereo in" | ||
140 | }; | ||
141 | |||
142 | static struct s3c_dma_params s3c_pcm_stereo_out[] = { | 134 | static struct s3c_dma_params s3c_pcm_stereo_out[] = { |
143 | [0] = { | 135 | [0] = { |
144 | .client = &s3c_pcm_dma_client_out, | ||
145 | .dma_size = 4, | 136 | .dma_size = 4, |
146 | }, | 137 | }, |
147 | [1] = { | 138 | [1] = { |
148 | .client = &s3c_pcm_dma_client_out, | ||
149 | .dma_size = 4, | 139 | .dma_size = 4, |
150 | }, | 140 | }, |
151 | }; | 141 | }; |
152 | 142 | ||
153 | static struct s3c_dma_params s3c_pcm_stereo_in[] = { | 143 | static struct s3c_dma_params s3c_pcm_stereo_in[] = { |
154 | [0] = { | 144 | [0] = { |
155 | .client = &s3c_pcm_dma_client_in, | ||
156 | .dma_size = 4, | 145 | .dma_size = 4, |
157 | }, | 146 | }, |
158 | [1] = { | 147 | [1] = { |
159 | .client = &s3c_pcm_dma_client_in, | ||
160 | .dma_size = 4, | 148 | .dma_size = 4, |
161 | }, | 149 | }, |
162 | }; | 150 | }; |
diff --git a/sound/soc/samsung/s3c-i2s-v2.c b/sound/soc/samsung/s3c-i2s-v2.c index 0ff4bbe23af3..df65c5b494b1 100644 --- a/sound/soc/samsung/s3c-i2s-v2.c +++ b/sound/soc/samsung/s3c-i2s-v2.c | |||
@@ -22,8 +22,6 @@ | |||
22 | #include <sound/soc.h> | 22 | #include <sound/soc.h> |
23 | #include <sound/pcm_params.h> | 23 | #include <sound/pcm_params.h> |
24 | 24 | ||
25 | #include <mach/dma.h> | ||
26 | |||
27 | #include "regs-i2s-v2.h" | 25 | #include "regs-i2s-v2.h" |
28 | #include "s3c-i2s-v2.h" | 26 | #include "s3c-i2s-v2.h" |
29 | #include "dma.h" | 27 | #include "dma.h" |
@@ -392,8 +390,6 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | |||
392 | int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); | 390 | int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); |
393 | unsigned long irqs; | 391 | unsigned long irqs; |
394 | int ret = 0; | 392 | int ret = 0; |
395 | struct s3c_dma_params *dma_data = | ||
396 | snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
397 | 393 | ||
398 | pr_debug("Entered %s\n", __func__); | 394 | pr_debug("Entered %s\n", __func__); |
399 | 395 | ||
@@ -424,13 +420,6 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | |||
424 | 420 | ||
425 | local_irq_restore(irqs); | 421 | local_irq_restore(irqs); |
426 | 422 | ||
427 | /* | ||
428 | * Load the next buffer to DMA to meet the reqirement | ||
429 | * of the auto reload mechanism of S3C24XX. | ||
430 | * This call won't bother S3C64XX. | ||
431 | */ | ||
432 | s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED); | ||
433 | |||
434 | break; | 423 | break; |
435 | 424 | ||
436 | case SNDRV_PCM_TRIGGER_STOP: | 425 | case SNDRV_PCM_TRIGGER_STOP: |
@@ -644,12 +633,6 @@ int s3c_i2sv2_probe(struct snd_soc_dai *dai, | |||
644 | /* record our i2s structure for later use in the callbacks */ | 633 | /* record our i2s structure for later use in the callbacks */ |
645 | snd_soc_dai_set_drvdata(dai, i2s); | 634 | snd_soc_dai_set_drvdata(dai, i2s); |
646 | 635 | ||
647 | i2s->regs = ioremap(base, 0x100); | ||
648 | if (i2s->regs == NULL) { | ||
649 | dev_err(dev, "cannot ioremap registers\n"); | ||
650 | return -ENXIO; | ||
651 | } | ||
652 | |||
653 | i2s->iis_pclk = clk_get(dev, "iis"); | 636 | i2s->iis_pclk = clk_get(dev, "iis"); |
654 | if (IS_ERR(i2s->iis_pclk)) { | 637 | if (IS_ERR(i2s->iis_pclk)) { |
655 | dev_err(dev, "failed to get iis_clock\n"); | 638 | dev_err(dev, "failed to get iis_clock\n"); |
@@ -729,7 +712,7 @@ int s3c_i2sv2_register_component(struct device *dev, int id, | |||
729 | struct snd_soc_component_driver *cmp_drv, | 712 | struct snd_soc_component_driver *cmp_drv, |
730 | struct snd_soc_dai_driver *dai_drv) | 713 | struct snd_soc_dai_driver *dai_drv) |
731 | { | 714 | { |
732 | struct snd_soc_dai_ops *ops = dai_drv->ops; | 715 | struct snd_soc_dai_ops *ops = (struct snd_soc_dai_ops *)dai_drv->ops; |
733 | 716 | ||
734 | ops->trigger = s3c2412_i2s_trigger; | 717 | ops->trigger = s3c2412_i2s_trigger; |
735 | if (!ops->hw_params) | 718 | if (!ops->hw_params) |
diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c index 08c059be9104..27b339c6580e 100644 --- a/sound/soc/samsung/s3c2412-i2s.c +++ b/sound/soc/samsung/s3c2412-i2s.c | |||
@@ -33,25 +33,15 @@ | |||
33 | #include "regs-i2s-v2.h" | 33 | #include "regs-i2s-v2.h" |
34 | #include "s3c2412-i2s.h" | 34 | #include "s3c2412-i2s.h" |
35 | 35 | ||
36 | static struct s3c_dma_client s3c2412_dma_client_out = { | ||
37 | .name = "I2S PCM Stereo out" | ||
38 | }; | ||
39 | |||
40 | static struct s3c_dma_client s3c2412_dma_client_in = { | ||
41 | .name = "I2S PCM Stereo in" | ||
42 | }; | ||
43 | |||
44 | static struct s3c_dma_params s3c2412_i2s_pcm_stereo_out = { | 36 | static struct s3c_dma_params s3c2412_i2s_pcm_stereo_out = { |
45 | .client = &s3c2412_dma_client_out, | ||
46 | .channel = DMACH_I2S_OUT, | 37 | .channel = DMACH_I2S_OUT, |
47 | .dma_addr = S3C2410_PA_IIS + S3C2412_IISTXD, | 38 | .ch_name = "tx", |
48 | .dma_size = 4, | 39 | .dma_size = 4, |
49 | }; | 40 | }; |
50 | 41 | ||
51 | static struct s3c_dma_params s3c2412_i2s_pcm_stereo_in = { | 42 | static struct s3c_dma_params s3c2412_i2s_pcm_stereo_in = { |
52 | .client = &s3c2412_dma_client_in, | ||
53 | .channel = DMACH_I2S_IN, | 43 | .channel = DMACH_I2S_IN, |
54 | .dma_addr = S3C2410_PA_IIS + S3C2412_IISRXD, | 44 | .ch_name = "rx", |
55 | .dma_size = 4, | 45 | .dma_size = 4, |
56 | }; | 46 | }; |
57 | 47 | ||
@@ -63,6 +53,9 @@ static int s3c2412_i2s_probe(struct snd_soc_dai *dai) | |||
63 | 53 | ||
64 | pr_debug("Entered %s\n", __func__); | 54 | pr_debug("Entered %s\n", __func__); |
65 | 55 | ||
56 | samsung_asoc_init_dma_data(dai, &s3c2412_i2s_pcm_stereo_out, | ||
57 | &s3c2412_i2s_pcm_stereo_in); | ||
58 | |||
66 | ret = s3c_i2sv2_probe(dai, &s3c2412_i2s, S3C2410_PA_IIS); | 59 | ret = s3c_i2sv2_probe(dai, &s3c2412_i2s, S3C2410_PA_IIS); |
67 | if (ret) | 60 | if (ret) |
68 | return ret; | 61 | return ret; |
@@ -70,17 +63,16 @@ static int s3c2412_i2s_probe(struct snd_soc_dai *dai) | |||
70 | s3c2412_i2s.dma_capture = &s3c2412_i2s_pcm_stereo_in; | 63 | s3c2412_i2s.dma_capture = &s3c2412_i2s_pcm_stereo_in; |
71 | s3c2412_i2s.dma_playback = &s3c2412_i2s_pcm_stereo_out; | 64 | s3c2412_i2s.dma_playback = &s3c2412_i2s_pcm_stereo_out; |
72 | 65 | ||
73 | s3c2412_i2s.iis_cclk = clk_get(dai->dev, "i2sclk"); | 66 | s3c2412_i2s.iis_cclk = devm_clk_get(dai->dev, "i2sclk"); |
74 | if (IS_ERR(s3c2412_i2s.iis_cclk)) { | 67 | if (IS_ERR(s3c2412_i2s.iis_cclk)) { |
75 | pr_err("failed to get i2sclk clock\n"); | 68 | pr_err("failed to get i2sclk clock\n"); |
76 | iounmap(s3c2412_i2s.regs); | ||
77 | return PTR_ERR(s3c2412_i2s.iis_cclk); | 69 | return PTR_ERR(s3c2412_i2s.iis_cclk); |
78 | } | 70 | } |
79 | 71 | ||
80 | /* Set MPLL as the source for IIS CLK */ | 72 | /* Set MPLL as the source for IIS CLK */ |
81 | 73 | ||
82 | clk_set_parent(s3c2412_i2s.iis_cclk, clk_get(NULL, "mpll")); | 74 | clk_set_parent(s3c2412_i2s.iis_cclk, clk_get(NULL, "mpll")); |
83 | clk_enable(s3c2412_i2s.iis_cclk); | 75 | clk_prepare_enable(s3c2412_i2s.iis_cclk); |
84 | 76 | ||
85 | s3c2412_i2s.iis_cclk = s3c2412_i2s.iis_pclk; | 77 | s3c2412_i2s.iis_cclk = s3c2412_i2s.iis_pclk; |
86 | 78 | ||
@@ -93,9 +85,7 @@ static int s3c2412_i2s_probe(struct snd_soc_dai *dai) | |||
93 | 85 | ||
94 | static int s3c2412_i2s_remove(struct snd_soc_dai *dai) | 86 | static int s3c2412_i2s_remove(struct snd_soc_dai *dai) |
95 | { | 87 | { |
96 | clk_disable(s3c2412_i2s.iis_cclk); | 88 | clk_disable_unprepare(s3c2412_i2s.iis_cclk); |
97 | clk_put(s3c2412_i2s.iis_cclk); | ||
98 | iounmap(s3c2412_i2s.regs); | ||
99 | 89 | ||
100 | return 0; | 90 | return 0; |
101 | } | 91 | } |
@@ -105,18 +95,10 @@ static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream, | |||
105 | struct snd_soc_dai *cpu_dai) | 95 | struct snd_soc_dai *cpu_dai) |
106 | { | 96 | { |
107 | struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(cpu_dai); | 97 | struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(cpu_dai); |
108 | struct s3c_dma_params *dma_data; | ||
109 | u32 iismod; | 98 | u32 iismod; |
110 | 99 | ||
111 | pr_debug("Entered %s\n", __func__); | 100 | pr_debug("Entered %s\n", __func__); |
112 | 101 | ||
113 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
114 | dma_data = i2s->dma_playback; | ||
115 | else | ||
116 | dma_data = i2s->dma_capture; | ||
117 | |||
118 | snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); | ||
119 | |||
120 | iismod = readl(i2s->regs + S3C2412_IISMOD); | 102 | iismod = readl(i2s->regs + S3C2412_IISMOD); |
121 | pr_debug("%s: r: IISMOD: %x\n", __func__, iismod); | 103 | pr_debug("%s: r: IISMOD: %x\n", __func__, iismod); |
122 | 104 | ||
@@ -169,6 +151,15 @@ static const struct snd_soc_component_driver s3c2412_i2s_component = { | |||
169 | static int s3c2412_iis_dev_probe(struct platform_device *pdev) | 151 | static int s3c2412_iis_dev_probe(struct platform_device *pdev) |
170 | { | 152 | { |
171 | int ret = 0; | 153 | int ret = 0; |
154 | struct resource *res; | ||
155 | |||
156 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
157 | s3c2412_i2s.regs = devm_ioremap_resource(&pdev->dev, res); | ||
158 | if (IS_ERR(s3c2412_i2s.regs)) | ||
159 | return PTR_ERR(s3c2412_i2s.regs); | ||
160 | |||
161 | s3c2412_i2s_pcm_stereo_out.dma_addr = res->start + S3C2412_IISTXD; | ||
162 | s3c2412_i2s_pcm_stereo_in.dma_addr = res->start + S3C2412_IISRXD; | ||
172 | 163 | ||
173 | ret = s3c_i2sv2_register_component(&pdev->dev, -1, | 164 | ret = s3c_i2sv2_register_component(&pdev->dev, -1, |
174 | &s3c2412_i2s_component, | 165 | &s3c2412_i2s_component, |
diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c index 9aba9fb7df0e..e87d9a2053b8 100644 --- a/sound/soc/samsung/s3c24xx-i2s.c +++ b/sound/soc/samsung/s3c24xx-i2s.c | |||
@@ -31,25 +31,15 @@ | |||
31 | #include "dma.h" | 31 | #include "dma.h" |
32 | #include "s3c24xx-i2s.h" | 32 | #include "s3c24xx-i2s.h" |
33 | 33 | ||
34 | static struct s3c_dma_client s3c24xx_dma_client_out = { | ||
35 | .name = "I2S PCM Stereo out" | ||
36 | }; | ||
37 | |||
38 | static struct s3c_dma_client s3c24xx_dma_client_in = { | ||
39 | .name = "I2S PCM Stereo in" | ||
40 | }; | ||
41 | |||
42 | static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_out = { | 34 | static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_out = { |
43 | .client = &s3c24xx_dma_client_out, | ||
44 | .channel = DMACH_I2S_OUT, | 35 | .channel = DMACH_I2S_OUT, |
45 | .dma_addr = S3C2410_PA_IIS + S3C2410_IISFIFO, | 36 | .ch_name = "tx", |
46 | .dma_size = 2, | 37 | .dma_size = 2, |
47 | }; | 38 | }; |
48 | 39 | ||
49 | static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_in = { | 40 | static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_in = { |
50 | .client = &s3c24xx_dma_client_in, | ||
51 | .channel = DMACH_I2S_IN, | 41 | .channel = DMACH_I2S_IN, |
52 | .dma_addr = S3C2410_PA_IIS + S3C2410_IISFIFO, | 42 | .ch_name = "rx", |
53 | .dma_size = 2, | 43 | .dma_size = 2, |
54 | }; | 44 | }; |
55 | 45 | ||
@@ -231,18 +221,12 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
231 | struct snd_pcm_hw_params *params, | 221 | struct snd_pcm_hw_params *params, |
232 | struct snd_soc_dai *dai) | 222 | struct snd_soc_dai *dai) |
233 | { | 223 | { |
234 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 224 | struct snd_dmaengine_dai_dma_data *dma_data; |
235 | struct s3c_dma_params *dma_data; | ||
236 | u32 iismod; | 225 | u32 iismod; |
237 | 226 | ||
238 | pr_debug("Entered %s\n", __func__); | 227 | pr_debug("Entered %s\n", __func__); |
239 | 228 | ||
240 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 229 | dma_data = snd_soc_dai_get_dma_data(dai, substream); |
241 | dma_data = &s3c24xx_i2s_pcm_stereo_out; | ||
242 | else | ||
243 | dma_data = &s3c24xx_i2s_pcm_stereo_in; | ||
244 | |||
245 | snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_data); | ||
246 | 230 | ||
247 | /* Working copies of register */ | 231 | /* Working copies of register */ |
248 | iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); | 232 | iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); |
@@ -251,11 +235,11 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
251 | switch (params_width(params)) { | 235 | switch (params_width(params)) { |
252 | case 8: | 236 | case 8: |
253 | iismod &= ~S3C2410_IISMOD_16BIT; | 237 | iismod &= ~S3C2410_IISMOD_16BIT; |
254 | dma_data->dma_size = 1; | 238 | dma_data->addr_width = 1; |
255 | break; | 239 | break; |
256 | case 16: | 240 | case 16: |
257 | iismod |= S3C2410_IISMOD_16BIT; | 241 | iismod |= S3C2410_IISMOD_16BIT; |
258 | dma_data->dma_size = 2; | 242 | dma_data->addr_width = 2; |
259 | break; | 243 | break; |
260 | default: | 244 | default: |
261 | return -EINVAL; | 245 | return -EINVAL; |
@@ -270,8 +254,6 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | |||
270 | struct snd_soc_dai *dai) | 254 | struct snd_soc_dai *dai) |
271 | { | 255 | { |
272 | int ret = 0; | 256 | int ret = 0; |
273 | struct s3c_dma_params *dma_data = | ||
274 | snd_soc_dai_get_dma_data(dai, substream); | ||
275 | 257 | ||
276 | pr_debug("Entered %s\n", __func__); | 258 | pr_debug("Entered %s\n", __func__); |
277 | 259 | ||
@@ -290,7 +272,6 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | |||
290 | else | 272 | else |
291 | s3c24xx_snd_txctrl(1); | 273 | s3c24xx_snd_txctrl(1); |
292 | 274 | ||
293 | s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED); | ||
294 | break; | 275 | break; |
295 | case SNDRV_PCM_TRIGGER_STOP: | 276 | case SNDRV_PCM_TRIGGER_STOP: |
296 | case SNDRV_PCM_TRIGGER_SUSPEND: | 277 | case SNDRV_PCM_TRIGGER_SUSPEND: |
@@ -380,17 +361,15 @@ static int s3c24xx_i2s_probe(struct snd_soc_dai *dai) | |||
380 | { | 361 | { |
381 | pr_debug("Entered %s\n", __func__); | 362 | pr_debug("Entered %s\n", __func__); |
382 | 363 | ||
383 | s3c24xx_i2s.regs = ioremap(S3C2410_PA_IIS, 0x100); | 364 | samsung_asoc_init_dma_data(dai, &s3c24xx_i2s_pcm_stereo_out, |
384 | if (s3c24xx_i2s.regs == NULL) | 365 | &s3c24xx_i2s_pcm_stereo_in); |
385 | return -ENXIO; | ||
386 | 366 | ||
387 | s3c24xx_i2s.iis_clk = clk_get(dai->dev, "iis"); | 367 | s3c24xx_i2s.iis_clk = devm_clk_get(dai->dev, "iis"); |
388 | if (IS_ERR(s3c24xx_i2s.iis_clk)) { | 368 | if (IS_ERR(s3c24xx_i2s.iis_clk)) { |
389 | pr_err("failed to get iis_clock\n"); | 369 | pr_err("failed to get iis_clock\n"); |
390 | iounmap(s3c24xx_i2s.regs); | ||
391 | return PTR_ERR(s3c24xx_i2s.iis_clk); | 370 | return PTR_ERR(s3c24xx_i2s.iis_clk); |
392 | } | 371 | } |
393 | clk_enable(s3c24xx_i2s.iis_clk); | 372 | clk_prepare_enable(s3c24xx_i2s.iis_clk); |
394 | 373 | ||
395 | /* Configure the I2S pins (GPE0...GPE4) in correct mode */ | 374 | /* Configure the I2S pins (GPE0...GPE4) in correct mode */ |
396 | s3c_gpio_cfgall_range(S3C2410_GPE(0), 5, S3C_GPIO_SFN(2), | 375 | s3c_gpio_cfgall_range(S3C2410_GPE(0), 5, S3C_GPIO_SFN(2), |
@@ -414,7 +393,7 @@ static int s3c24xx_i2s_suspend(struct snd_soc_dai *cpu_dai) | |||
414 | s3c24xx_i2s.iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON); | 393 | s3c24xx_i2s.iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON); |
415 | s3c24xx_i2s.iispsr = readl(s3c24xx_i2s.regs + S3C2410_IISPSR); | 394 | s3c24xx_i2s.iispsr = readl(s3c24xx_i2s.regs + S3C2410_IISPSR); |
416 | 395 | ||
417 | clk_disable(s3c24xx_i2s.iis_clk); | 396 | clk_disable_unprepare(s3c24xx_i2s.iis_clk); |
418 | 397 | ||
419 | return 0; | 398 | return 0; |
420 | } | 399 | } |
@@ -422,7 +401,7 @@ static int s3c24xx_i2s_suspend(struct snd_soc_dai *cpu_dai) | |||
422 | static int s3c24xx_i2s_resume(struct snd_soc_dai *cpu_dai) | 401 | static int s3c24xx_i2s_resume(struct snd_soc_dai *cpu_dai) |
423 | { | 402 | { |
424 | pr_debug("Entered %s\n", __func__); | 403 | pr_debug("Entered %s\n", __func__); |
425 | clk_enable(s3c24xx_i2s.iis_clk); | 404 | clk_prepare_enable(s3c24xx_i2s.iis_clk); |
426 | 405 | ||
427 | writel(s3c24xx_i2s.iiscon, s3c24xx_i2s.regs + S3C2410_IISCON); | 406 | writel(s3c24xx_i2s.iiscon, s3c24xx_i2s.regs + S3C2410_IISCON); |
428 | writel(s3c24xx_i2s.iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); | 407 | writel(s3c24xx_i2s.iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); |
@@ -474,6 +453,19 @@ static const struct snd_soc_component_driver s3c24xx_i2s_component = { | |||
474 | static int s3c24xx_iis_dev_probe(struct platform_device *pdev) | 453 | static int s3c24xx_iis_dev_probe(struct platform_device *pdev) |
475 | { | 454 | { |
476 | int ret = 0; | 455 | int ret = 0; |
456 | struct resource *res; | ||
457 | |||
458 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
459 | if (!res) { | ||
460 | dev_err(&pdev->dev, "Can't get IO resource.\n"); | ||
461 | return -ENOENT; | ||
462 | } | ||
463 | s3c24xx_i2s.regs = devm_ioremap_resource(&pdev->dev, res); | ||
464 | if (s3c24xx_i2s.regs == NULL) | ||
465 | return -ENXIO; | ||
466 | |||
467 | s3c24xx_i2s_pcm_stereo_out.dma_addr = res->start + S3C2410_IISFIFO; | ||
468 | s3c24xx_i2s_pcm_stereo_in.dma_addr = res->start + S3C2410_IISFIFO; | ||
477 | 469 | ||
478 | ret = devm_snd_soc_register_component(&pdev->dev, | 470 | ret = devm_snd_soc_register_component(&pdev->dev, |
479 | &s3c24xx_i2s_component, &s3c24xx_i2s_dai, 1); | 471 | &s3c24xx_i2s_component, &s3c24xx_i2s_dai, 1); |
diff --git a/sound/soc/samsung/smdk_wm8580pcm.c b/sound/soc/samsung/smdk_wm8580pcm.c index e119aaa91c28..63d079303561 100644 --- a/sound/soc/samsung/smdk_wm8580pcm.c +++ b/sound/soc/samsung/smdk_wm8580pcm.c | |||
@@ -25,7 +25,7 @@ | |||
25 | * o '0' means 'OFF' | 25 | * o '0' means 'OFF' |
26 | * o 'X' means 'Don't care' | 26 | * o 'X' means 'Don't care' |
27 | * | 27 | * |
28 | * SMDK6410, SMDK6440, SMDK6450 Base B/D: CFG1-0000, CFG2-1111 | 28 | * SMDK6410 Base B/D: CFG1-0000, CFG2-1111 |
29 | * SMDKC110, SMDKV210: CFGB11-100100, CFGB12-0000 | 29 | * SMDKC110, SMDKV210: CFGB11-100100, CFGB12-0000 |
30 | */ | 30 | */ |
31 | 31 | ||
diff --git a/sound/soc/samsung/snow.c b/sound/soc/samsung/snow.c index 014c177840ba..0acf5d0eed53 100644 --- a/sound/soc/samsung/snow.c +++ b/sound/soc/samsung/snow.c | |||
@@ -92,6 +92,9 @@ static int snow_probe(struct platform_device *pdev) | |||
92 | 92 | ||
93 | card->dev = &pdev->dev; | 93 | card->dev = &pdev->dev; |
94 | 94 | ||
95 | /* Update card-name if provided through DT, else use default name */ | ||
96 | snd_soc_of_parse_card_name(card, "samsung,model"); | ||
97 | |||
95 | ret = devm_snd_soc_register_card(&pdev->dev, card); | 98 | ret = devm_snd_soc_register_card(&pdev->dev, card); |
96 | if (ret) { | 99 | if (ret) { |
97 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); | 100 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); |
@@ -103,6 +106,7 @@ static int snow_probe(struct platform_device *pdev) | |||
103 | 106 | ||
104 | static const struct of_device_id snow_of_match[] = { | 107 | static const struct of_device_id snow_of_match[] = { |
105 | { .compatible = "google,snow-audio-max98090", }, | 108 | { .compatible = "google,snow-audio-max98090", }, |
109 | { .compatible = "google,snow-audio-max98091", }, | ||
106 | { .compatible = "google,snow-audio-max98095", }, | 110 | { .compatible = "google,snow-audio-max98095", }, |
107 | {}, | 111 | {}, |
108 | }; | 112 | }; |
diff --git a/sound/soc/samsung/spdif.c b/sound/soc/samsung/spdif.c index d9ffc48fce5e..d7d2e208f486 100644 --- a/sound/soc/samsung/spdif.c +++ b/sound/soc/samsung/spdif.c | |||
@@ -93,10 +93,6 @@ struct samsung_spdif_info { | |||
93 | struct s3c_dma_params *dma_playback; | 93 | struct s3c_dma_params *dma_playback; |
94 | }; | 94 | }; |
95 | 95 | ||
96 | static struct s3c_dma_client spdif_dma_client_out = { | ||
97 | .name = "S/PDIF Stereo out", | ||
98 | }; | ||
99 | |||
100 | static struct s3c_dma_params spdif_stereo_out; | 96 | static struct s3c_dma_params spdif_stereo_out; |
101 | static struct samsung_spdif_info spdif_info; | 97 | static struct samsung_spdif_info spdif_info; |
102 | 98 | ||
@@ -435,7 +431,6 @@ static int spdif_probe(struct platform_device *pdev) | |||
435 | } | 431 | } |
436 | 432 | ||
437 | spdif_stereo_out.dma_size = 2; | 433 | spdif_stereo_out.dma_size = 2; |
438 | spdif_stereo_out.client = &spdif_dma_client_out; | ||
439 | spdif_stereo_out.dma_addr = mem_res->start + DATA_OUTBUF; | 434 | spdif_stereo_out.dma_addr = mem_res->start + DATA_OUTBUF; |
440 | spdif_stereo_out.channel = dma_res->start; | 435 | spdif_stereo_out.channel = dma_res->start; |
441 | 436 | ||