aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/samsung
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2014-08-04 12:28:21 -0400
committerTakashi Iwai <tiwai@suse.de>2014-08-04 12:28:21 -0400
commite9e3bdffe38b256f920eacc455d30deba5e97655 (patch)
treecfa546f6370c117e012c12605da22ce189542127 /sound/soc/samsung
parentf42bb22243d2ae264d721b055f836059fe35321f (diff)
parentae34a78c430c37c06404f032fb04e51315204281 (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/Kconfig40
-rw-r--r--sound/soc/samsung/Makefile6
-rw-r--r--sound/soc/samsung/ac97.c32
-rw-r--r--sound/soc/samsung/dma.c454
-rw-r--r--sound/soc/samsung/dma.h7
-rw-r--r--sound/soc/samsung/dmaengine.c3
-rw-r--r--sound/soc/samsung/i2s.c35
-rw-r--r--sound/soc/samsung/idma.c3
-rw-r--r--sound/soc/samsung/odroidx2_max98090.c177
-rw-r--r--sound/soc/samsung/pcm.c12
-rw-r--r--sound/soc/samsung/s3c-i2s-v2.c19
-rw-r--r--sound/soc/samsung/s3c2412-i2s.c43
-rw-r--r--sound/soc/samsung/s3c24xx-i2s.c58
-rw-r--r--sound/soc/samsung/smdk_wm8580pcm.c2
-rw-r--r--sound/soc/samsung/snow.c4
-rw-r--r--sound/soc/samsung/spdif.c5
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 @@
1config SND_SOC_SAMSUNG 1config 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
14config SND_S3C_DMA
15 tristate
16
17config SND_S3C_DMA_LEGACY
18 tristate
19
20config SND_S3C24XX_I2S 12config SND_S3C24XX_I2S
21 tristate 13 tristate
22 select S3C24XX_DMA
23 14
24config SND_S3C_I2SV2_SOC 15config SND_S3C_I2SV2_SOC
25 tristate 16 tristate
@@ -27,7 +18,6 @@ config SND_S3C_I2SV2_SOC
27config SND_S3C2412_SOC_I2S 18config 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
32config SND_SAMSUNG_PCM 22config SND_SAMSUNG_PCM
33 tristate 23 tristate
@@ -55,7 +45,7 @@ config SND_SOC_SAMSUNG_NEO1973_WM8753
55 45
56config SND_SOC_SAMSUNG_JIVE_WM8750 46config 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
64config SND_SOC_SAMSUNG_SMDK_WM8580 54config 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
83config SND_SOC_SAMSUNG_SMDK2443_WM9710 73config 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
94config SND_SOC_SAMSUNG_LN2440SBC_ALC650 83config 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
155config SND_SOC_SMARTQ 143config 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
179config SND_SOC_SMDK_WM8580_PCM 167config 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
207config SND_SOC_TOBERMORY 195config 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
223config SND_SOC_LOWLAND 211config 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
237config SND_SOC_SNOW 225config 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
235config 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
2snd-soc-s3c-dma-objs := dmaengine.o 2snd-soc-s3c-dma-objs := dmaengine.o
3snd-soc-s3c-dma-legacy-objs := dma.o
4snd-soc-idma-objs := idma.o 3snd-soc-idma-objs := idma.o
5snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o 4snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o
6snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o 5snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o
@@ -10,8 +9,7 @@ snd-soc-samsung-spdif-objs := spdif.o
10snd-soc-pcm-objs := pcm.o 9snd-soc-pcm-objs := pcm.o
11snd-soc-i2s-objs := i2s.o 10snd-soc-i2s-objs := i2s.o
12 11
13obj-$(CONFIG_SND_S3C_DMA) += snd-soc-s3c-dma.o 12obj-$(CONFIG_SND_SOC_SAMSUNG) += snd-soc-s3c-dma.o
14obj-$(CONFIG_SND_S3C_DMA_LEGACY) += snd-soc-s3c-dma-legacy.o
15obj-$(CONFIG_SND_S3C24XX_I2S) += snd-soc-s3c24xx-i2s.o 13obj-$(CONFIG_SND_S3C24XX_I2S) += snd-soc-s3c24xx-i2s.o
16obj-$(CONFIG_SND_SAMSUNG_AC97) += snd-soc-ac97.o 14obj-$(CONFIG_SND_SAMSUNG_AC97) += snd-soc-ac97.o
17obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o 15obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o
@@ -46,6 +44,7 @@ snd-soc-tobermory-objs := tobermory.o
46snd-soc-lowland-objs := lowland.o 44snd-soc-lowland-objs := lowland.o
47snd-soc-littlemill-objs := littlemill.o 45snd-soc-littlemill-objs := littlemill.o
48snd-soc-bells-objs := bells.o 46snd-soc-bells-objs := bells.o
47snd-soc-odroidx2-max98090-objs := odroidx2_max98090.o
49 48
50obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o 49obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o
51obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o 50obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o
@@ -71,3 +70,4 @@ obj-$(CONFIG_SND_SOC_TOBERMORY) += snd-soc-tobermory.o
71obj-$(CONFIG_SND_SOC_LOWLAND) += snd-soc-lowland.o 70obj-$(CONFIG_SND_SOC_LOWLAND) += snd-soc-lowland.o
72obj-$(CONFIG_SND_SOC_LITTLEMILL) += snd-soc-littlemill.o 71obj-$(CONFIG_SND_SOC_LITTLEMILL) += snd-soc-littlemill.o
73obj-$(CONFIG_SND_SOC_BELLS) += snd-soc-bells.o 72obj-$(CONFIG_SND_SOC_BELLS) += snd-soc-bells.o
73obj-$(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};
40static struct s3c_ac97_info s3c_ac97; 39static struct s3c_ac97_info s3c_ac97;
41 40
42static struct s3c_dma_client s3c_dma_client_out = {
43 .name = "AC97 PCMOut"
44};
45
46static struct s3c_dma_client s3c_dma_client_in = {
47 .name = "AC97 PCMIn"
48};
49
50static struct s3c_dma_client s3c_dma_client_micin = {
51 .name = "AC97 MicIn"
52};
53
54static struct s3c_dma_params s3c_ac97_pcm_out = { 41static 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
59static struct s3c_dma_params s3c_ac97_pcm_in = { 45static 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
64static struct s3c_dma_params s3c_ac97_mic_in = { 49static 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
33static 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
46struct 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
57static 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 */
64static 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
115static 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
139static 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
202static 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
220static 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
244static 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
274static snd_pcm_uframes_t
275dma_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
301static 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
321static 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
336static 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
349static 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
361static 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
380static 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
403static 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 }
428out:
429 return ret;
430}
431
432static 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
438void 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}
444EXPORT_SYMBOL_GPL(samsung_asoc_init_dma_data);
445
446int samsung_asoc_dma_platform_register(struct device *dev)
447{
448 return devm_snd_soc_register_platform(dev, &samsung_asoc_platform);
449}
450EXPORT_SYMBOL_GPL(samsung_asoc_dma_platform_register);
451
452MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
453MODULE_DESCRIPTION("Samsung ASoC DMA Driver");
454MODULE_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
17struct s3c_dma_client {
18 char *name;
19};
20
21struct s3c_dma_params { 17struct 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,
261static irqreturn_t iis_irq(int irqno, void *dev_id) 261static 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
16struct 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
24static 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
40static 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
46static 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
51static 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
61static 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
69struct odroidx2_drv_data odroidx2_drvdata = {
70 .dapm_widgets = odroidx2_dapm_widgets,
71 .num_dapm_widgets = ARRAY_SIZE(odroidx2_dapm_widgets),
72};
73
74struct odroidx2_drv_data odroidu3_drvdata = {
75 .dapm_widgets = odroidu3_dapm_widgets,
76 .num_dapm_widgets = ARRAY_SIZE(odroidu3_dapm_widgets),
77};
78
79static 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};
89MODULE_DEVICE_TABLE(of, odroidx2_audio_of_match);
90
91static 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
143err_put_i2s_n:
144 of_node_put(i2s_node);
145err_put_codec_n:
146 of_node_put(codec_node);
147 return ret;
148}
149
150static 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
162static 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};
172module_platform_driver(odroidx2_audio_driver);
173
174MODULE_AUTHOR("Chen Zhen <zhen1.chen@samsung.com>");
175MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
176MODULE_DESCRIPTION("ALSA SoC Odroid X2/U3 Audio Support");
177MODULE_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
134static struct s3c_dma_client s3c_pcm_dma_client_out = {
135 .name = "PCM Stereo out"
136};
137
138static struct s3c_dma_client s3c_pcm_dma_client_in = {
139 .name = "PCM Stereo in"
140};
141
142static struct s3c_dma_params s3c_pcm_stereo_out[] = { 134static 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
153static struct s3c_dma_params s3c_pcm_stereo_in[] = { 143static 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
36static struct s3c_dma_client s3c2412_dma_client_out = {
37 .name = "I2S PCM Stereo out"
38};
39
40static struct s3c_dma_client s3c2412_dma_client_in = {
41 .name = "I2S PCM Stereo in"
42};
43
44static struct s3c_dma_params s3c2412_i2s_pcm_stereo_out = { 36static 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
51static struct s3c_dma_params s3c2412_i2s_pcm_stereo_in = { 42static 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
94static int s3c2412_i2s_remove(struct snd_soc_dai *dai) 86static 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 = {
169static int s3c2412_iis_dev_probe(struct platform_device *pdev) 151static 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
34static struct s3c_dma_client s3c24xx_dma_client_out = {
35 .name = "I2S PCM Stereo out"
36};
37
38static struct s3c_dma_client s3c24xx_dma_client_in = {
39 .name = "I2S PCM Stereo in"
40};
41
42static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_out = { 34static 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
49static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_in = { 40static 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)
422static int s3c24xx_i2s_resume(struct snd_soc_dai *cpu_dai) 401static 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 = {
474static int s3c24xx_iis_dev_probe(struct platform_device *pdev) 453static 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
104static const struct of_device_id snow_of_match[] = { 107static 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
96static struct s3c_dma_client spdif_dma_client_out = {
97 .name = "S/PDIF Stereo out",
98};
99
100static struct s3c_dma_params spdif_stereo_out; 96static struct s3c_dma_params spdif_stereo_out;
101static struct samsung_spdif_info spdif_info; 97static 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