aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/s3c24xx
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/s3c24xx')
-rw-r--r--sound/soc/s3c24xx/Kconfig171
-rw-r--r--sound/soc/s3c24xx/Makefile55
-rw-r--r--sound/soc/s3c24xx/aquila_wm8994.c295
-rw-r--r--sound/soc/s3c24xx/goni_wm8994.c298
-rw-r--r--sound/soc/s3c24xx/jive_wm8750.c191
-rw-r--r--sound/soc/s3c24xx/lm4857.h32
-rw-r--r--sound/soc/s3c24xx/ln2440sbc_alc650.c78
-rw-r--r--sound/soc/s3c24xx/neo1973_gta02_wm8753.c504
-rw-r--r--sound/soc/s3c24xx/neo1973_wm8753.c704
-rw-r--r--sound/soc/s3c24xx/regs-i2s-v2.h115
-rw-r--r--sound/soc/s3c24xx/rx1950_uda1380.c319
-rw-r--r--sound/soc/s3c24xx/s3c-ac97.c520
-rw-r--r--sound/soc/s3c24xx/s3c-ac97.h21
-rw-r--r--sound/soc/s3c24xx/s3c-dma.c502
-rw-r--r--sound/soc/s3c24xx/s3c-dma.h30
-rw-r--r--sound/soc/s3c24xx/s3c-i2s-v2.c757
-rw-r--r--sound/soc/s3c24xx/s3c-i2s-v2.h106
-rw-r--r--sound/soc/s3c24xx/s3c-pcm.c552
-rw-r--r--sound/soc/s3c24xx/s3c-pcm.h124
-rw-r--r--sound/soc/s3c24xx/s3c2412-i2s.c212
-rw-r--r--sound/soc/s3c24xx/s3c2412-i2s.h27
-rw-r--r--sound/soc/s3c24xx/s3c24xx-i2s.c519
-rw-r--r--sound/soc/s3c24xx/s3c24xx-i2s.h35
-rw-r--r--sound/soc/s3c24xx/s3c24xx_simtec.c395
-rw-r--r--sound/soc/s3c24xx/s3c24xx_simtec.h22
-rw-r--r--sound/soc/s3c24xx/s3c24xx_simtec_hermes.c146
-rw-r--r--sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c134
-rw-r--r--sound/soc/s3c24xx/s3c24xx_uda134x.c368
-rw-r--r--sound/soc/s3c24xx/s3c64xx-i2s-v4.c230
-rw-r--r--sound/soc/s3c24xx/s3c64xx-i2s.c242
-rw-r--r--sound/soc/s3c24xx/s3c64xx-i2s.h41
-rw-r--r--sound/soc/s3c24xx/smartq_wm8987.c290
-rw-r--r--sound/soc/s3c24xx/smdk2443_wm9710.c74
-rw-r--r--sound/soc/s3c24xx/smdk64xx_wm8580.c272
-rw-r--r--sound/soc/s3c24xx/smdk_spdif.c223
-rw-r--r--sound/soc/s3c24xx/smdk_wm9713.c107
-rw-r--r--sound/soc/s3c24xx/spdif.c501
-rw-r--r--sound/soc/s3c24xx/spdif.h19
38 files changed, 0 insertions, 9231 deletions
diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig
deleted file mode 100644
index d85bf8a0abb2..000000000000
--- a/sound/soc/s3c24xx/Kconfig
+++ /dev/null
@@ -1,171 +0,0 @@
1config SND_S3C24XX_SOC
2 tristate "SoC Audio for the Samsung S3CXXXX chips"
3 depends on ARCH_S3C2410 || ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210
4 select S3C64XX_DMA if ARCH_S3C64XX
5 select S3C2410_DMA if ARCH_S3C2410
6 help
7 Say Y or M if you want to add support for codecs attached to
8 the S3C24XX AC97 or I2S interfaces. You will also need to
9 select the audio interfaces to support below.
10
11config SND_S3C24XX_SOC_I2S
12 tristate
13 select S3C2410_DMA
14
15config SND_S3C_I2SV2_SOC
16 tristate
17
18config SND_S3C2412_SOC_I2S
19 tristate
20 select SND_S3C_I2SV2_SOC
21 select S3C2410_DMA
22
23config SND_S3C64XX_SOC_I2S
24 tristate
25 select SND_S3C_I2SV2_SOC
26 select S3C64XX_DMA
27
28config SND_S3C64XX_SOC_I2S_V4
29 tristate
30 select SND_S3C_I2SV2_SOC
31 select S3C64XX_DMA
32
33config SND_S3C_SOC_PCM
34 tristate
35
36config SND_S3C_SOC_AC97
37 tristate
38 select SND_SOC_AC97_BUS
39
40config SND_S5P_SOC_SPDIF
41 tristate
42 select SND_SOC_SPDIF
43
44config SND_S3C24XX_SOC_NEO1973_WM8753
45 tristate "SoC I2S Audio support for NEO1973 - WM8753"
46 depends on SND_S3C24XX_SOC && MACH_NEO1973_GTA01
47 select SND_S3C24XX_SOC_I2S
48 select SND_SOC_WM8753
49 help
50 Say Y if you want to add support for SoC audio on smdk2440
51 with the WM8753.
52
53config SND_S3C24XX_SOC_NEO1973_GTA02_WM8753
54 tristate "Audio support for the Openmoko Neo FreeRunner (GTA02)"
55 depends on SND_S3C24XX_SOC && MACH_NEO1973_GTA02
56 select SND_S3C24XX_SOC_I2S
57 select SND_SOC_WM8753
58 help
59 This driver provides audio support for the Openmoko Neo FreeRunner
60 smartphone.
61
62config SND_S3C24XX_SOC_JIVE_WM8750
63 tristate "SoC I2S Audio support for Jive"
64 depends on SND_S3C24XX_SOC && MACH_JIVE
65 select SND_SOC_WM8750
66 select SND_S3C2412_SOC_I2S
67 help
68 Sat Y if you want to add support for SoC audio on the Jive.
69
70config SND_S3C64XX_SOC_WM8580
71 tristate "SoC I2S Audio support for WM8580 on SMDK64XX"
72 depends on SND_S3C24XX_SOC && MACH_SMDK6410
73 select SND_SOC_WM8580
74 select SND_S3C64XX_SOC_I2S_V4
75 help
76 Say Y if you want to add support for SoC audio on the SMDK6410.
77
78config SND_S3C24XX_SOC_SMDK2443_WM9710
79 tristate "SoC AC97 Audio support for SMDK2443 - WM9710"
80 depends on SND_S3C24XX_SOC && MACH_SMDK2443
81 select S3C2410_DMA
82 select AC97_BUS
83 select SND_SOC_AC97_CODEC
84 select SND_S3C_SOC_AC97
85 help
86 Say Y if you want to add support for SoC audio on smdk2443
87 with the WM9710.
88
89config SND_S3C24XX_SOC_LN2440SBC_ALC650
90 tristate "SoC AC97 Audio support for LN2440SBC - ALC650"
91 depends on SND_S3C24XX_SOC && ARCH_S3C2410
92 select S3C2410_DMA
93 select AC97_BUS
94 select SND_SOC_AC97_CODEC
95 select SND_S3C_SOC_AC97
96 help
97 Say Y if you want to add support for SoC audio on ln2440sbc
98 with the ALC650.
99
100config SND_S3C24XX_SOC_S3C24XX_UDA134X
101 tristate "SoC I2S Audio support UDA134X wired to a S3C24XX"
102 depends on SND_S3C24XX_SOC && ARCH_S3C2410
103 select SND_S3C24XX_SOC_I2S
104 select SND_SOC_L3
105 select SND_SOC_UDA134X
106
107config SND_S3C24XX_SOC_SIMTEC
108 tristate
109 help
110 Internal node for common S3C24XX/Simtec suppor
111
112config SND_S3C24XX_SOC_SIMTEC_TLV320AIC23
113 tristate "SoC I2S Audio support for TLV320AIC23 on Simtec boards"
114 depends on SND_S3C24XX_SOC && ARCH_S3C2410
115 select SND_S3C24XX_SOC_I2S
116 select SND_SOC_TLV320AIC23
117 select SND_S3C24XX_SOC_SIMTEC
118
119config SND_S3C24XX_SOC_SIMTEC_HERMES
120 tristate "SoC I2S Audio support for Simtec Hermes board"
121 depends on SND_S3C24XX_SOC && ARCH_S3C2410
122 select SND_S3C24XX_SOC_I2S
123 select SND_SOC_TLV320AIC3X
124 select SND_S3C24XX_SOC_SIMTEC
125
126config SND_S3C24XX_SOC_RX1950_UDA1380
127 tristate "Audio support for the HP iPAQ RX1950"
128 depends on SND_S3C24XX_SOC && MACH_RX1950
129 select SND_S3C24XX_SOC_I2S
130 select SND_SOC_UDA1380
131 help
132 This driver provides audio support for HP iPAQ RX1950 PDA.
133
134config SND_SOC_SMDK_WM9713
135 tristate "SoC AC97 Audio support for SMDK with WM9713"
136 depends on SND_S3C24XX_SOC && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110)
137 select SND_SOC_WM9713
138 select SND_S3C_SOC_AC97
139 help
140 Sat Y if you want to add support for SoC audio on the SMDK.
141
142config SND_S3C64XX_SOC_SMARTQ
143 tristate "SoC I2S Audio support for SmartQ board"
144 depends on SND_S3C24XX_SOC && MACH_SMARTQ
145 select SND_S3C64XX_SOC_I2S
146 select SND_SOC_WM8750
147
148config SND_S5PC110_SOC_AQUILA_WM8994
149 tristate "SoC I2S Audio support for AQUILA - WM8994"
150 depends on SND_S3C24XX_SOC && MACH_AQUILA
151 select SND_S3C64XX_SOC_I2S_V4
152 select SND_SOC_WM8994
153 help
154 Say Y if you want to add support for SoC audio on aquila
155 with the WM8994.
156
157config SND_S5PV210_SOC_GONI_WM8994
158 tristate "SoC I2S Audio support for GONI - WM8994"
159 depends on SND_S3C24XX_SOC && MACH_GONI
160 select SND_S3C64XX_SOC_I2S_V4
161 select SND_SOC_WM8994
162 help
163 Say Y if you want to add support for SoC audio on goni
164 with the WM8994.
165
166config SND_SOC_SMDK_SPDIF
167 tristate "SoC S/PDIF Audio support for SMDK"
168 depends on SND_S3C24XX_SOC && (MACH_SMDKC100 || MACH_SMDKC110 || MACH_SMDKV210)
169 select SND_S5P_SOC_SPDIF
170 help
171 Say Y if you want to add support for SoC S/PDIF audio on the SMDK.
diff --git a/sound/soc/s3c24xx/Makefile b/sound/soc/s3c24xx/Makefile
deleted file mode 100644
index ee8f41d6df99..000000000000
--- a/sound/soc/s3c24xx/Makefile
+++ /dev/null
@@ -1,55 +0,0 @@
1# S3c24XX Platform Support
2snd-soc-s3c24xx-objs := s3c-dma.o
3snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o
4snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o
5snd-soc-s3c64xx-i2s-objs := s3c64xx-i2s.o
6snd-soc-s3c-ac97-objs := s3c-ac97.o
7snd-soc-s3c64xx-i2s-v4-objs := s3c64xx-i2s-v4.o
8snd-soc-s3c-i2s-v2-objs := s3c-i2s-v2.o
9snd-soc-s3c-pcm-objs := s3c-pcm.o
10snd-soc-samsung-spdif-objs := spdif.o
11
12obj-$(CONFIG_SND_S3C24XX_SOC) += snd-soc-s3c24xx.o
13obj-$(CONFIG_SND_S3C24XX_SOC_I2S) += snd-soc-s3c24xx-i2s.o
14obj-$(CONFIG_SND_S3C_SOC_AC97) += snd-soc-s3c-ac97.o
15obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o
16obj-$(CONFIG_SND_S3C64XX_SOC_I2S) += snd-soc-s3c64xx-i2s.o
17obj-$(CONFIG_SND_S3C64XX_SOC_I2S_V4) += snd-soc-s3c64xx-i2s-v4.o
18obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-v2.o
19obj-$(CONFIG_SND_S3C_SOC_PCM) += snd-soc-s3c-pcm.o
20obj-$(CONFIG_SND_S5P_SOC_SPDIF) += snd-soc-samsung-spdif.o
21
22# S3C24XX Machine Support
23snd-soc-jive-wm8750-objs := jive_wm8750.o
24snd-soc-neo1973-wm8753-objs := neo1973_wm8753.o
25snd-soc-neo1973-gta02-wm8753-objs := neo1973_gta02_wm8753.o
26snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o
27snd-soc-ln2440sbc-alc650-objs := ln2440sbc_alc650.o
28snd-soc-s3c24xx-uda134x-objs := s3c24xx_uda134x.o
29snd-soc-s3c24xx-simtec-objs := s3c24xx_simtec.o
30snd-soc-s3c24xx-simtec-hermes-objs := s3c24xx_simtec_hermes.o
31snd-soc-s3c24xx-simtec-tlv320aic23-objs := s3c24xx_simtec_tlv320aic23.o
32snd-soc-rx1950-uda1380-objs := rx1950_uda1380.o
33snd-soc-smdk64xx-wm8580-objs := smdk64xx_wm8580.o
34snd-soc-smdk-wm9713-objs := smdk_wm9713.o
35snd-soc-s3c64xx-smartq-wm8987-objs := smartq_wm8987.o
36snd-soc-aquila-wm8994-objs := aquila_wm8994.o
37snd-soc-goni-wm8994-objs := goni_wm8994.o
38snd-soc-smdk-spdif-objs := smdk_spdif.o
39
40obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o
41obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o
42obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_GTA02_WM8753) += snd-soc-neo1973-gta02-wm8753.o
43obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o
44obj-$(CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650) += snd-soc-ln2440sbc-alc650.o
45obj-$(CONFIG_SND_S3C24XX_SOC_S3C24XX_UDA134X) += snd-soc-s3c24xx-uda134x.o
46obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC) += snd-soc-s3c24xx-simtec.o
47obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC_HERMES) += snd-soc-s3c24xx-simtec-hermes.o
48obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC_TLV320AIC23) += snd-soc-s3c24xx-simtec-tlv320aic23.o
49obj-$(CONFIG_SND_S3C24XX_SOC_RX1950_UDA1380) += snd-soc-rx1950-uda1380.o
50obj-$(CONFIG_SND_S3C64XX_SOC_WM8580) += snd-soc-smdk64xx-wm8580.o
51obj-$(CONFIG_SND_SOC_SMDK_WM9713) += snd-soc-smdk-wm9713.o
52obj-$(CONFIG_SND_S3C64XX_SOC_SMARTQ) += snd-soc-s3c64xx-smartq-wm8987.o
53obj-$(CONFIG_SND_S5PC110_SOC_AQUILA_WM8994) += snd-soc-aquila-wm8994.o
54obj-$(CONFIG_SND_S5PV210_SOC_GONI_WM8994) += snd-soc-goni-wm8994.o
55obj-$(CONFIG_SND_SOC_SMDK_SPDIF) += snd-soc-smdk-spdif.o
diff --git a/sound/soc/s3c24xx/aquila_wm8994.c b/sound/soc/s3c24xx/aquila_wm8994.c
deleted file mode 100644
index 235d1973f7d0..000000000000
--- a/sound/soc/s3c24xx/aquila_wm8994.c
+++ /dev/null
@@ -1,295 +0,0 @@
1/*
2 * aquila_wm8994.c
3 *
4 * Copyright (C) 2010 Samsung Electronics Co.Ltd
5 * Author: Chanwoo Choi <cw00.choi@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 */
13
14#include <linux/module.h>
15#include <linux/moduleparam.h>
16#include <linux/io.h>
17#include <linux/platform_device.h>
18#include <sound/soc.h>
19#include <sound/soc-dapm.h>
20#include <sound/jack.h>
21#include <asm/mach-types.h>
22#include <mach/gpio.h>
23#include <mach/regs-clock.h>
24
25#include <linux/mfd/wm8994/core.h>
26#include <linux/mfd/wm8994/registers.h>
27#include "../codecs/wm8994.h"
28#include "s3c-dma.h"
29#include "s3c64xx-i2s.h"
30
31static struct snd_soc_card aquila;
32static struct platform_device *aquila_snd_device;
33
34/* 3.5 pie jack */
35static struct snd_soc_jack jack;
36
37/* 3.5 pie jack detection DAPM pins */
38static struct snd_soc_jack_pin jack_pins[] = {
39 {
40 .pin = "Headset Mic",
41 .mask = SND_JACK_MICROPHONE,
42 }, {
43 .pin = "Headset Stereophone",
44 .mask = SND_JACK_HEADPHONE | SND_JACK_MECHANICAL |
45 SND_JACK_AVOUT,
46 },
47};
48
49/* 3.5 pie jack detection gpios */
50static struct snd_soc_jack_gpio jack_gpios[] = {
51 {
52 .gpio = S5PV210_GPH0(6),
53 .name = "DET_3.5",
54 .report = SND_JACK_HEADSET | SND_JACK_MECHANICAL |
55 SND_JACK_AVOUT,
56 .debounce_time = 200,
57 },
58};
59
60static const struct snd_soc_dapm_widget aquila_dapm_widgets[] = {
61 SND_SOC_DAPM_SPK("Ext Spk", NULL),
62 SND_SOC_DAPM_SPK("Ext Rcv", NULL),
63 SND_SOC_DAPM_HP("Headset Stereophone", NULL),
64 SND_SOC_DAPM_MIC("Headset Mic", NULL),
65 SND_SOC_DAPM_MIC("Main Mic", NULL),
66 SND_SOC_DAPM_MIC("2nd Mic", NULL),
67 SND_SOC_DAPM_LINE("Radio In", NULL),
68};
69
70static const struct snd_soc_dapm_route aquila_dapm_routes[] = {
71 {"Ext Spk", NULL, "SPKOUTLP"},
72 {"Ext Spk", NULL, "SPKOUTLN"},
73
74 {"Ext Rcv", NULL, "HPOUT2N"},
75 {"Ext Rcv", NULL, "HPOUT2P"},
76
77 {"Headset Stereophone", NULL, "HPOUT1L"},
78 {"Headset Stereophone", NULL, "HPOUT1R"},
79
80 {"IN1RN", NULL, "Headset Mic"},
81 {"IN1RP", NULL, "Headset Mic"},
82
83 {"IN1RN", NULL, "2nd Mic"},
84 {"IN1RP", NULL, "2nd Mic"},
85
86 {"IN1LN", NULL, "Main Mic"},
87 {"IN1LP", NULL, "Main Mic"},
88
89 {"IN2LN", NULL, "Radio In"},
90 {"IN2RN", NULL, "Radio In"},
91};
92
93static int aquila_wm8994_init(struct snd_soc_pcm_runtime *rtd)
94{
95 struct snd_soc_codec *codec = rtd->codec;
96 int ret;
97
98 /* add aquila specific widgets */
99 snd_soc_dapm_new_controls(codec, aquila_dapm_widgets,
100 ARRAY_SIZE(aquila_dapm_widgets));
101
102 /* set up aquila specific audio routes */
103 snd_soc_dapm_add_routes(codec, aquila_dapm_routes,
104 ARRAY_SIZE(aquila_dapm_routes));
105
106 /* set endpoints to not connected */
107 snd_soc_dapm_nc_pin(codec, "IN2LP:VXRN");
108 snd_soc_dapm_nc_pin(codec, "IN2RP:VXRP");
109 snd_soc_dapm_nc_pin(codec, "LINEOUT1N");
110 snd_soc_dapm_nc_pin(codec, "LINEOUT1P");
111 snd_soc_dapm_nc_pin(codec, "LINEOUT2N");
112 snd_soc_dapm_nc_pin(codec, "LINEOUT2P");
113 snd_soc_dapm_nc_pin(codec, "SPKOUTRN");
114 snd_soc_dapm_nc_pin(codec, "SPKOUTRP");
115
116 snd_soc_dapm_sync(codec);
117
118 /* Headset jack detection */
119 ret = snd_soc_jack_new(&aquila, "Headset Jack",
120 SND_JACK_HEADSET | SND_JACK_MECHANICAL | SND_JACK_AVOUT,
121 &jack);
122 if (ret)
123 return ret;
124
125 ret = snd_soc_jack_add_pins(&jack, ARRAY_SIZE(jack_pins), jack_pins);
126 if (ret)
127 return ret;
128
129 ret = snd_soc_jack_add_gpios(&jack, ARRAY_SIZE(jack_gpios), jack_gpios);
130 if (ret)
131 return ret;
132
133 return 0;
134}
135
136static int aquila_hifi_hw_params(struct snd_pcm_substream *substream,
137 struct snd_pcm_hw_params *params)
138{
139 struct snd_soc_pcm_runtime *rtd = substream->private_data;
140 struct snd_soc_dai *codec_dai = rtd->codec_dai;
141 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
142 unsigned int pll_out = 24000000;
143 int ret = 0;
144
145 /* set the cpu DAI configuration */
146 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
147 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
148 if (ret < 0)
149 return ret;
150
151 /* set the cpu system clock */
152 ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_PCLK,
153 0, SND_SOC_CLOCK_IN);
154 if (ret < 0)
155 return ret;
156
157 /* set codec DAI configuration */
158 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
159 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
160 if (ret < 0)
161 return ret;
162
163 /* set the codec FLL */
164 ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, 0, pll_out,
165 params_rate(params) * 256);
166 if (ret < 0)
167 return ret;
168
169 /* set the codec system clock */
170 ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL1,
171 params_rate(params) * 256, SND_SOC_CLOCK_IN);
172 if (ret < 0)
173 return ret;
174
175 return 0;
176}
177
178static struct snd_soc_ops aquila_hifi_ops = {
179 .hw_params = aquila_hifi_hw_params,
180};
181
182static int aquila_voice_hw_params(struct snd_pcm_substream *substream,
183 struct snd_pcm_hw_params *params)
184{
185 struct snd_soc_pcm_runtime *rtd = substream->private_data;
186 struct snd_soc_dai *codec_dai = rtd->codec_dai;
187 unsigned int pll_out = 24000000;
188 int ret = 0;
189
190 if (params_rate(params) != 8000)
191 return -EINVAL;
192
193 /* set codec DAI configuration */
194 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_LEFT_J |
195 SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
196 if (ret < 0)
197 return ret;
198
199 /* set the codec FLL */
200 ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL2, 0, pll_out,
201 params_rate(params) * 256);
202 if (ret < 0)
203 return ret;
204
205 /* set the codec system clock */
206 ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL2,
207 params_rate(params) * 256, SND_SOC_CLOCK_IN);
208 if (ret < 0)
209 return ret;
210
211 return 0;
212}
213
214static struct snd_soc_dai_driver voice_dai = {
215 .name = "aquila-voice-dai",
216 .playback = {
217 .channels_min = 1,
218 .channels_max = 2,
219 .rates = SNDRV_PCM_RATE_8000,
220 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
221 .capture = {
222 .channels_min = 1,
223 .channels_max = 2,
224 .rates = SNDRV_PCM_RATE_8000,
225 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
226};
227
228static struct snd_soc_ops aquila_voice_ops = {
229 .hw_params = aquila_voice_hw_params,
230};
231
232static struct snd_soc_dai_link aquila_dai[] = {
233{
234 .name = "WM8994",
235 .stream_name = "WM8994 HiFi",
236 .cpu_dai_name = "s3c64xx-i2s-v4",
237 .codec_dai_name = "wm8994-hifi",
238 .platform_name = "s3c24xx-pcm-audio",
239 .codec_name = "wm8994-codec.0-0x1a",
240 .init = aquila_wm8994_init,
241 .ops = &aquila_hifi_ops,
242}, {
243 .name = "WM8994 Voice",
244 .stream_name = "Voice",
245 .cpu_dai_name = "aquila-voice-dai",
246 .codec_dai_name = "wm8994-voice",
247 .platform_name = "s3c24xx-pcm-audio",
248 .codec_name = "wm8994-codec.0-0x1a",
249 .ops = &aquila_voice_ops,
250},
251};
252
253static struct snd_soc_card aquila = {
254 .name = "aquila",
255 .dai_link = aquila_dai,
256 .num_links = ARRAY_SIZE(aquila_dai),
257};
258
259static int __init aquila_init(void)
260{
261 int ret;
262
263 if (!machine_is_aquila())
264 return -ENODEV;
265
266 aquila_snd_device = platform_device_alloc("soc-audio", -1);
267 if (!aquila_snd_device)
268 return -ENOMEM;
269
270 /* register voice DAI here */
271 ret = snd_soc_register_dai(&aquila_snd_device->dev, &voice_dai);
272 if (ret)
273 return ret;
274
275 platform_set_drvdata(aquila_snd_device, &aquila);
276 ret = platform_device_add(aquila_snd_device);
277
278 if (ret)
279 platform_device_put(aquila_snd_device);
280
281 return ret;
282}
283
284static void __exit aquila_exit(void)
285{
286 platform_device_unregister(aquila_snd_device);
287}
288
289module_init(aquila_init);
290module_exit(aquila_exit);
291
292/* Module information */
293MODULE_DESCRIPTION("ALSA SoC WM8994 Aquila(S5PC110)");
294MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
295MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/goni_wm8994.c b/sound/soc/s3c24xx/goni_wm8994.c
deleted file mode 100644
index 694f702cc8e2..000000000000
--- a/sound/soc/s3c24xx/goni_wm8994.c
+++ /dev/null
@@ -1,298 +0,0 @@
1/*
2 * goni_wm8994.c
3 *
4 * Copyright (C) 2010 Samsung Electronics Co.Ltd
5 * Author: Chanwoo Choi <cw00.choi@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 */
13
14#include <linux/module.h>
15#include <linux/moduleparam.h>
16#include <linux/io.h>
17#include <linux/platform_device.h>
18#include <sound/soc.h>
19#include <sound/soc-dapm.h>
20#include <sound/jack.h>
21#include <asm/mach-types.h>
22#include <mach/gpio.h>
23#include <mach/regs-clock.h>
24
25#include <linux/mfd/wm8994/core.h>
26#include <linux/mfd/wm8994/registers.h>
27#include "../codecs/wm8994.h"
28#include "s3c-dma.h"
29#include "s3c64xx-i2s.h"
30
31static struct snd_soc_card goni;
32static struct platform_device *goni_snd_device;
33
34/* 3.5 pie jack */
35static struct snd_soc_jack jack;
36
37/* 3.5 pie jack detection DAPM pins */
38static struct snd_soc_jack_pin jack_pins[] = {
39 {
40 .pin = "Headset Mic",
41 .mask = SND_JACK_MICROPHONE,
42 }, {
43 .pin = "Headset Stereophone",
44 .mask = SND_JACK_HEADPHONE | SND_JACK_MECHANICAL |
45 SND_JACK_AVOUT,
46 },
47};
48
49/* 3.5 pie jack detection gpios */
50static struct snd_soc_jack_gpio jack_gpios[] = {
51 {
52 .gpio = S5PV210_GPH0(6),
53 .name = "DET_3.5",
54 .report = SND_JACK_HEADSET | SND_JACK_MECHANICAL |
55 SND_JACK_AVOUT,
56 .debounce_time = 200,
57 },
58};
59
60static const struct snd_soc_dapm_widget goni_dapm_widgets[] = {
61 SND_SOC_DAPM_SPK("Ext Left Spk", NULL),
62 SND_SOC_DAPM_SPK("Ext Right Spk", NULL),
63 SND_SOC_DAPM_SPK("Ext Rcv", NULL),
64 SND_SOC_DAPM_HP("Headset Stereophone", NULL),
65 SND_SOC_DAPM_MIC("Headset Mic", NULL),
66 SND_SOC_DAPM_MIC("Main Mic", NULL),
67 SND_SOC_DAPM_MIC("2nd Mic", NULL),
68 SND_SOC_DAPM_LINE("Radio In", NULL),
69};
70
71static const struct snd_soc_dapm_route goni_dapm_routes[] = {
72 {"Ext Left Spk", NULL, "SPKOUTLP"},
73 {"Ext Left Spk", NULL, "SPKOUTLN"},
74
75 {"Ext Right Spk", NULL, "SPKOUTRP"},
76 {"Ext Right Spk", NULL, "SPKOUTRN"},
77
78 {"Ext Rcv", NULL, "HPOUT2N"},
79 {"Ext Rcv", NULL, "HPOUT2P"},
80
81 {"Headset Stereophone", NULL, "HPOUT1L"},
82 {"Headset Stereophone", NULL, "HPOUT1R"},
83
84 {"IN1RN", NULL, "Headset Mic"},
85 {"IN1RP", NULL, "Headset Mic"},
86
87 {"IN1RN", NULL, "2nd Mic"},
88 {"IN1RP", NULL, "2nd Mic"},
89
90 {"IN1LN", NULL, "Main Mic"},
91 {"IN1LP", NULL, "Main Mic"},
92
93 {"IN2LN", NULL, "Radio In"},
94 {"IN2RN", NULL, "Radio In"},
95};
96
97static int goni_wm8994_init(struct snd_soc_pcm_runtime *rtd)
98{
99 struct snd_soc_codec *codec = rtd->codec;
100 int ret;
101
102 /* add goni specific widgets */
103 snd_soc_dapm_new_controls(codec, goni_dapm_widgets,
104 ARRAY_SIZE(goni_dapm_widgets));
105
106 /* set up goni specific audio routes */
107 snd_soc_dapm_add_routes(codec, goni_dapm_routes,
108 ARRAY_SIZE(goni_dapm_routes));
109
110 /* set endpoints to not connected */
111 snd_soc_dapm_nc_pin(codec, "IN2LP:VXRN");
112 snd_soc_dapm_nc_pin(codec, "IN2RP:VXRP");
113 snd_soc_dapm_nc_pin(codec, "LINEOUT1N");
114 snd_soc_dapm_nc_pin(codec, "LINEOUT1P");
115 snd_soc_dapm_nc_pin(codec, "LINEOUT2N");
116 snd_soc_dapm_nc_pin(codec, "LINEOUT2P");
117
118 snd_soc_dapm_sync(codec);
119
120 /* Headset jack detection */
121 ret = snd_soc_jack_new(&goni, "Headset Jack",
122 SND_JACK_HEADSET | SND_JACK_MECHANICAL | SND_JACK_AVOUT,
123 &jack);
124 if (ret)
125 return ret;
126
127 ret = snd_soc_jack_add_pins(&jack, ARRAY_SIZE(jack_pins), jack_pins);
128 if (ret)
129 return ret;
130
131 ret = snd_soc_jack_add_gpios(&jack, ARRAY_SIZE(jack_gpios), jack_gpios);
132 if (ret)
133 return ret;
134
135 return 0;
136}
137
138static int goni_hifi_hw_params(struct snd_pcm_substream *substream,
139 struct snd_pcm_hw_params *params)
140{
141 struct snd_soc_pcm_runtime *rtd = substream->private_data;
142 struct snd_soc_dai *codec_dai = rtd->codec_dai;
143 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
144 unsigned int pll_out = 24000000;
145 int ret = 0;
146
147 /* set the cpu DAI configuration */
148 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
149 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
150 if (ret < 0)
151 return ret;
152
153 /* set the cpu system clock */
154 ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_PCLK,
155 0, SND_SOC_CLOCK_IN);
156 if (ret < 0)
157 return ret;
158
159 /* set codec DAI configuration */
160 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
161 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
162 if (ret < 0)
163 return ret;
164
165 /* set the codec FLL */
166 ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, 0, pll_out,
167 params_rate(params) * 256);
168 if (ret < 0)
169 return ret;
170
171 /* set the codec system clock */
172 ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL1,
173 params_rate(params) * 256, SND_SOC_CLOCK_IN);
174 if (ret < 0)
175 return ret;
176
177 return 0;
178}
179
180static struct snd_soc_ops goni_hifi_ops = {
181 .hw_params = goni_hifi_hw_params,
182};
183
184static int goni_voice_hw_params(struct snd_pcm_substream *substream,
185 struct snd_pcm_hw_params *params)
186{
187 struct snd_soc_pcm_runtime *rtd = substream->private_data;
188 struct snd_soc_dai *codec_dai = rtd->codec_dai;
189 unsigned int pll_out = 24000000;
190 int ret = 0;
191
192 if (params_rate(params) != 8000)
193 return -EINVAL;
194
195 /* set codec DAI configuration */
196 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_LEFT_J |
197 SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
198 if (ret < 0)
199 return ret;
200
201 /* set the codec FLL */
202 ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL2, 0, pll_out,
203 params_rate(params) * 256);
204 if (ret < 0)
205 return ret;
206
207 /* set the codec system clock */
208 ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL2,
209 params_rate(params) * 256, SND_SOC_CLOCK_IN);
210 if (ret < 0)
211 return ret;
212
213 return 0;
214}
215
216static struct snd_soc_dai_driver voice_dai = {
217 .name = "goni-voice-dai",
218 .id = 0,
219 .playback = {
220 .channels_min = 1,
221 .channels_max = 2,
222 .rates = SNDRV_PCM_RATE_8000,
223 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
224 .capture = {
225 .channels_min = 1,
226 .channels_max = 2,
227 .rates = SNDRV_PCM_RATE_8000,
228 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
229};
230
231static struct snd_soc_ops goni_voice_ops = {
232 .hw_params = goni_voice_hw_params,
233};
234
235static struct snd_soc_dai_link goni_dai[] = {
236{
237 .name = "WM8994",
238 .stream_name = "WM8994 HiFi",
239 .cpu_dai_name = "s3c64xx-i2s-v4",
240 .codec_dai_name = "wm8994-hifi",
241 .platform_name = "s3c24xx-pcm-audio",
242 .codec_name = "wm8994-codec.0-0x1a",
243 .init = goni_wm8994_init,
244 .ops = &goni_hifi_ops,
245}, {
246 .name = "WM8994 Voice",
247 .stream_name = "Voice",
248 .cpu_dai_name = "goni-voice-dai",
249 .codec_dai_name = "wm8994-voice",
250 .platform_name = "s3c24xx-pcm-audio",
251 .codec_name = "wm8994-codec.0-0x1a",
252 .ops = &goni_voice_ops,
253},
254};
255
256static struct snd_soc_card goni = {
257 .name = "goni",
258 .dai_link = goni_dai,
259 .num_links = ARRAY_SIZE(goni_dai),
260};
261
262static int __init goni_init(void)
263{
264 int ret;
265
266 if (!machine_is_goni())
267 return -ENODEV;
268
269 goni_snd_device = platform_device_alloc("soc-audio", -1);
270 if (!goni_snd_device)
271 return -ENOMEM;
272
273 /* register voice DAI here */
274 ret = snd_soc_register_dai(&goni_snd_device->dev, &voice_dai);
275 if (ret)
276 return ret;
277
278 platform_set_drvdata(goni_snd_device, &goni);
279 ret = platform_device_add(goni_snd_device);
280
281 if (ret)
282 platform_device_put(goni_snd_device);
283
284 return ret;
285}
286
287static void __exit goni_exit(void)
288{
289 platform_device_unregister(goni_snd_device);
290}
291
292module_init(goni_init);
293module_exit(goni_exit);
294
295/* Module information */
296MODULE_DESCRIPTION("ALSA SoC WM8994 GONI(S5PV210)");
297MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
298MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/jive_wm8750.c b/sound/soc/s3c24xx/jive_wm8750.c
deleted file mode 100644
index 49605cd83947..000000000000
--- a/sound/soc/s3c24xx/jive_wm8750.c
+++ /dev/null
@@ -1,191 +0,0 @@
1/* sound/soc/s3c24xx/jive_wm8750.c
2 *
3 * Copyright 2007,2008 Simtec Electronics
4 *
5 * Based on sound/soc/pxa/spitz.c
6 * Copyright 2005 Wolfson Microelectronics PLC.
7 * Copyright 2005 Openedhand Ltd.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12*/
13
14#include <linux/module.h>
15#include <linux/moduleparam.h>
16#include <linux/timer.h>
17#include <linux/interrupt.h>
18#include <linux/platform_device.h>
19#include <linux/clk.h>
20
21#include <sound/core.h>
22#include <sound/pcm.h>
23#include <sound/soc.h>
24#include <sound/soc-dapm.h>
25
26#include <asm/mach-types.h>
27
28#include "s3c-dma.h"
29#include "s3c2412-i2s.h"
30
31#include "../codecs/wm8750.h"
32
33static const struct snd_soc_dapm_route audio_map[] = {
34 { "Headphone Jack", NULL, "LOUT1" },
35 { "Headphone Jack", NULL, "ROUT1" },
36 { "Internal Speaker", NULL, "LOUT2" },
37 { "Internal Speaker", NULL, "ROUT2" },
38 { "LINPUT1", NULL, "Line Input" },
39 { "RINPUT1", NULL, "Line Input" },
40};
41
42static const struct snd_soc_dapm_widget wm8750_dapm_widgets[] = {
43 SND_SOC_DAPM_HP("Headphone Jack", NULL),
44 SND_SOC_DAPM_SPK("Internal Speaker", NULL),
45 SND_SOC_DAPM_LINE("Line In", NULL),
46};
47
48static int jive_hw_params(struct snd_pcm_substream *substream,
49 struct snd_pcm_hw_params *params)
50{
51 struct snd_soc_pcm_runtime *rtd = substream->private_data;
52 struct snd_soc_dai *codec_dai = rtd->codec_dai;
53 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
54 struct s3c_i2sv2_rate_calc div;
55 unsigned int clk = 0;
56 int ret = 0;
57
58 switch (params_rate(params)) {
59 case 8000:
60 case 16000:
61 case 48000:
62 case 96000:
63 clk = 12288000;
64 break;
65 case 11025:
66 case 22050:
67 case 44100:
68 clk = 11289600;
69 break;
70 }
71
72 s3c_i2sv2_iis_calc_rate(&div, NULL, params_rate(params),
73 s3c_i2sv2_get_clock(cpu_dai));
74
75 /* set codec DAI configuration */
76 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
77 SND_SOC_DAIFMT_NB_NF |
78 SND_SOC_DAIFMT_CBS_CFS);
79 if (ret < 0)
80 return ret;
81
82 /* set cpu DAI configuration */
83 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
84 SND_SOC_DAIFMT_NB_NF |
85 SND_SOC_DAIFMT_CBS_CFS);
86 if (ret < 0)
87 return ret;
88
89 /* set the codec system clock for DAC and ADC */
90 ret = snd_soc_dai_set_sysclk(codec_dai, WM8750_SYSCLK, clk,
91 SND_SOC_CLOCK_IN);
92 if (ret < 0)
93 return ret;
94
95 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C2412_DIV_RCLK, div.fs_div);
96 if (ret < 0)
97 return ret;
98
99 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C2412_DIV_PRESCALER,
100 div.clk_div - 1);
101 if (ret < 0)
102 return ret;
103
104 return 0;
105}
106
107static struct snd_soc_ops jive_ops = {
108 .hw_params = jive_hw_params,
109};
110
111static int jive_wm8750_init(struct snd_soc_pcm_runtime *rtd)
112{
113 struct snd_soc_codec *codec = rtd->codec;
114 int err;
115
116 /* These endpoints are not being used. */
117 snd_soc_dapm_nc_pin(codec, "LINPUT2");
118 snd_soc_dapm_nc_pin(codec, "RINPUT2");
119 snd_soc_dapm_nc_pin(codec, "LINPUT3");
120 snd_soc_dapm_nc_pin(codec, "RINPUT3");
121 snd_soc_dapm_nc_pin(codec, "OUT3");
122 snd_soc_dapm_nc_pin(codec, "MONO");
123
124 /* Add jive specific widgets */
125 err = snd_soc_dapm_new_controls(codec, wm8750_dapm_widgets,
126 ARRAY_SIZE(wm8750_dapm_widgets));
127 if (err) {
128 printk(KERN_ERR "%s: failed to add widgets (%d)\n",
129 __func__, err);
130 return err;
131 }
132
133 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
134 snd_soc_dapm_sync(codec);
135
136 return 0;
137}
138
139static struct snd_soc_dai_link jive_dai = {
140 .name = "wm8750",
141 .stream_name = "WM8750",
142 .cpu_dai_name = "s3c2412-i2s",
143 .codec_dai_name = "wm8750-hifi",
144 .platform_name = "s3c24xx-pcm-audio",
145 .codec_name = "wm8750-codec.0-0x1a",
146 .init = jive_wm8750_init,
147 .ops = &jive_ops,
148};
149
150/* jive audio machine driver */
151static struct snd_soc_card snd_soc_machine_jive = {
152 .name = "Jive",
153 .dai_link = &jive_dai,
154 .num_links = 1,
155};
156
157static struct platform_device *jive_snd_device;
158
159static int __init jive_init(void)
160{
161 int ret;
162
163 if (!machine_is_jive())
164 return 0;
165
166 printk("JIVE WM8750 Audio support\n");
167
168 jive_snd_device = platform_device_alloc("soc-audio", -1);
169 if (!jive_snd_device)
170 return -ENOMEM;
171
172 platform_set_drvdata(jive_snd_device, &snd_soc_machine_jive);
173 ret = platform_device_add(jive_snd_device);
174
175 if (ret)
176 platform_device_put(jive_snd_device);
177
178 return ret;
179}
180
181static void __exit jive_exit(void)
182{
183 platform_device_unregister(jive_snd_device);
184}
185
186module_init(jive_init);
187module_exit(jive_exit);
188
189MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
190MODULE_DESCRIPTION("ALSA SoC Jive Audio support");
191MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/lm4857.h b/sound/soc/s3c24xx/lm4857.h
deleted file mode 100644
index 0cf5b7011d6f..000000000000
--- a/sound/soc/s3c24xx/lm4857.h
+++ /dev/null
@@ -1,32 +0,0 @@
1/*
2 * lm4857.h -- ALSA Soc Audio Layer
3 *
4 * Copyright 2007 Wolfson Microelectronics PLC.
5 * Author: Graeme Gregory
6 * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * Revision history
14 * 18th Jun 2007 Initial version.
15 */
16
17#ifndef LM4857_H_
18#define LM4857_H_
19
20/* The register offsets in the cache array */
21#define LM4857_MVOL 0
22#define LM4857_LVOL 1
23#define LM4857_RVOL 2
24#define LM4857_CTRL 3
25
26/* the shifts required to set these bits */
27#define LM4857_3D 5
28#define LM4857_WAKEUP 5
29#define LM4857_EPGAIN 4
30
31#endif /*LM4857_H_*/
32
diff --git a/sound/soc/s3c24xx/ln2440sbc_alc650.c b/sound/soc/s3c24xx/ln2440sbc_alc650.c
deleted file mode 100644
index abe64abe8c84..000000000000
--- a/sound/soc/s3c24xx/ln2440sbc_alc650.c
+++ /dev/null
@@ -1,78 +0,0 @@
1/*
2 * SoC audio for ln2440sbc
3 *
4 * Copyright 2007 KonekTel, a.s.
5 * Author: Ivan Kuten
6 * ivan.kuten@promwad.com
7 *
8 * Heavily based on smdk2443_wm9710.c
9 * Copyright 2007 Wolfson Microelectronics PLC.
10 * Author: Graeme Gregory
11 * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
16 *
17 */
18
19#include <linux/module.h>
20#include <linux/device.h>
21#include <sound/core.h>
22#include <sound/pcm.h>
23#include <sound/soc.h>
24#include <sound/soc-dapm.h>
25
26#include "s3c-dma.h"
27#include "s3c-ac97.h"
28
29static struct snd_soc_card ln2440sbc;
30
31static struct snd_soc_dai_link ln2440sbc_dai[] = {
32{
33 .name = "AC97",
34 .stream_name = "AC97 HiFi",
35 .cpu_dai_name = "s3c-ac97",
36 .codec_dai_name = "ac97-hifi",
37 .codec_name = "ac97-codec",
38 .platform_name = "s3c24xx-pcm-audio",
39},
40};
41
42static struct snd_soc_card ln2440sbc = {
43 .name = "LN2440SBC",
44 .dai_link = ln2440sbc_dai,
45 .num_links = ARRAY_SIZE(ln2440sbc_dai),
46};
47
48static struct platform_device *ln2440sbc_snd_ac97_device;
49
50static int __init ln2440sbc_init(void)
51{
52 int ret;
53
54 ln2440sbc_snd_ac97_device = platform_device_alloc("soc-audio", -1);
55 if (!ln2440sbc_snd_ac97_device)
56 return -ENOMEM;
57
58 platform_set_drvdata(ln2440sbc_snd_ac97_device, &ln2440sbc);
59 ret = platform_device_add(ln2440sbc_snd_ac97_device);
60
61 if (ret)
62 platform_device_put(ln2440sbc_snd_ac97_device);
63
64 return ret;
65}
66
67static void __exit ln2440sbc_exit(void)
68{
69 platform_device_unregister(ln2440sbc_snd_ac97_device);
70}
71
72module_init(ln2440sbc_init);
73module_exit(ln2440sbc_exit);
74
75/* Module information */
76MODULE_AUTHOR("Ivan Kuten");
77MODULE_DESCRIPTION("ALSA SoC ALC650 LN2440SBC");
78MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/neo1973_gta02_wm8753.c b/sound/soc/s3c24xx/neo1973_gta02_wm8753.c
deleted file mode 100644
index e97bdf150a03..000000000000
--- a/sound/soc/s3c24xx/neo1973_gta02_wm8753.c
+++ /dev/null
@@ -1,504 +0,0 @@
1/*
2 * neo1973_gta02_wm8753.c -- SoC audio for Openmoko Freerunner(GTA02)
3 *
4 * Copyright 2007 Openmoko Inc
5 * Author: Graeme Gregory <graeme@openmoko.org>
6 * Copyright 2007 Wolfson Microelectronics PLC.
7 * Author: Graeme Gregory <linux@wolfsonmicro.com>
8 * Copyright 2009 Wolfson Microelectronics
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 */
15
16#include <linux/module.h>
17#include <linux/moduleparam.h>
18#include <linux/timer.h>
19#include <linux/interrupt.h>
20#include <linux/platform_device.h>
21#include <linux/gpio.h>
22#include <sound/core.h>
23#include <sound/pcm.h>
24#include <sound/soc.h>
25#include <sound/soc-dapm.h>
26
27#include <asm/mach-types.h>
28
29#include <plat/regs-iis.h>
30
31#include <mach/regs-clock.h>
32#include <asm/io.h>
33#include <mach/gta02.h>
34#include "../codecs/wm8753.h"
35#include "s3c-dma.h"
36#include "s3c24xx-i2s.h"
37
38static struct snd_soc_card neo1973_gta02;
39
40static int neo1973_gta02_hifi_hw_params(struct snd_pcm_substream *substream,
41 struct snd_pcm_hw_params *params)
42{
43 struct snd_soc_pcm_runtime *rtd = substream->private_data;
44 struct snd_soc_dai *codec_dai = rtd->codec_dai;
45 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
46 unsigned int pll_out = 0, bclk = 0;
47 int ret = 0;
48 unsigned long iis_clkrate;
49
50 iis_clkrate = s3c24xx_i2s_get_clockrate();
51
52 switch (params_rate(params)) {
53 case 8000:
54 case 16000:
55 pll_out = 12288000;
56 break;
57 case 48000:
58 bclk = WM8753_BCLK_DIV_4;
59 pll_out = 12288000;
60 break;
61 case 96000:
62 bclk = WM8753_BCLK_DIV_2;
63 pll_out = 12288000;
64 break;
65 case 11025:
66 bclk = WM8753_BCLK_DIV_16;
67 pll_out = 11289600;
68 break;
69 case 22050:
70 bclk = WM8753_BCLK_DIV_8;
71 pll_out = 11289600;
72 break;
73 case 44100:
74 bclk = WM8753_BCLK_DIV_4;
75 pll_out = 11289600;
76 break;
77 case 88200:
78 bclk = WM8753_BCLK_DIV_2;
79 pll_out = 11289600;
80 break;
81 }
82
83 /* set codec DAI configuration */
84 ret = snd_soc_dai_set_fmt(codec_dai,
85 SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
86 SND_SOC_DAIFMT_CBM_CFM);
87 if (ret < 0)
88 return ret;
89
90 /* set cpu DAI configuration */
91 ret = snd_soc_dai_set_fmt(cpu_dai,
92 SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
93 SND_SOC_DAIFMT_CBM_CFM);
94 if (ret < 0)
95 return ret;
96
97 /* set the codec system clock for DAC and ADC */
98 ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_MCLK, pll_out,
99 SND_SOC_CLOCK_IN);
100 if (ret < 0)
101 return ret;
102
103 /* set MCLK division for sample rate */
104 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK,
105 S3C2410_IISMOD_32FS);
106 if (ret < 0)
107 return ret;
108
109 /* set codec BCLK division for sample rate */
110 ret = snd_soc_dai_set_clkdiv(codec_dai,
111 WM8753_BCLKDIV, bclk);
112 if (ret < 0)
113 return ret;
114
115 /* set prescaler division for sample rate */
116 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
117 S3C24XX_PRESCALE(4, 4));
118 if (ret < 0)
119 return ret;
120
121 /* codec PLL input is PCLK/4 */
122 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0,
123 iis_clkrate / 4, pll_out);
124 if (ret < 0)
125 return ret;
126
127 return 0;
128}
129
130static int neo1973_gta02_hifi_hw_free(struct snd_pcm_substream *substream)
131{
132 struct snd_soc_pcm_runtime *rtd = substream->private_data;
133 struct snd_soc_dai *codec_dai = rtd->codec_dai;
134
135 /* disable the PLL */
136 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0, 0);
137}
138
139/*
140 * Neo1973 WM8753 HiFi DAI opserations.
141 */
142static struct snd_soc_ops neo1973_gta02_hifi_ops = {
143 .hw_params = neo1973_gta02_hifi_hw_params,
144 .hw_free = neo1973_gta02_hifi_hw_free,
145};
146
147static int neo1973_gta02_voice_hw_params(
148 struct snd_pcm_substream *substream,
149 struct snd_pcm_hw_params *params)
150{
151 struct snd_soc_pcm_runtime *rtd = substream->private_data;
152 struct snd_soc_dai *codec_dai = rtd->codec_dai;
153 unsigned int pcmdiv = 0;
154 int ret = 0;
155 unsigned long iis_clkrate;
156
157 iis_clkrate = s3c24xx_i2s_get_clockrate();
158
159 if (params_rate(params) != 8000)
160 return -EINVAL;
161 if (params_channels(params) != 1)
162 return -EINVAL;
163
164 pcmdiv = WM8753_PCM_DIV_6; /* 2.048 MHz */
165
166 /* todo: gg check mode (DSP_B) against CSR datasheet */
167 /* set codec DAI configuration */
168 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B |
169 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
170 if (ret < 0)
171 return ret;
172
173 /* set the codec system clock for DAC and ADC */
174 ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_PCMCLK,
175 12288000, SND_SOC_CLOCK_IN);
176 if (ret < 0)
177 return ret;
178
179 /* set codec PCM division for sample rate */
180 ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_PCMDIV,
181 pcmdiv);
182 if (ret < 0)
183 return ret;
184
185 /* configure and enable PLL for 12.288MHz output */
186 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0,
187 iis_clkrate / 4, 12288000);
188 if (ret < 0)
189 return ret;
190
191 return 0;
192}
193
194static int neo1973_gta02_voice_hw_free(struct snd_pcm_substream *substream)
195{
196 struct snd_soc_pcm_runtime *rtd = substream->private_data;
197 struct snd_soc_dai *codec_dai = rtd->codec_dai;
198
199 /* disable the PLL */
200 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0, 0);
201}
202
203static struct snd_soc_ops neo1973_gta02_voice_ops = {
204 .hw_params = neo1973_gta02_voice_hw_params,
205 .hw_free = neo1973_gta02_voice_hw_free,
206};
207
208#define LM4853_AMP 1
209#define LM4853_SPK 2
210
211static u8 lm4853_state;
212
213/* This has no effect, it exists only to maintain compatibility with
214 * existing ALSA state files.
215 */
216static int lm4853_set_state(struct snd_kcontrol *kcontrol,
217 struct snd_ctl_elem_value *ucontrol)
218{
219 int val = ucontrol->value.integer.value[0];
220
221 if (val)
222 lm4853_state |= LM4853_AMP;
223 else
224 lm4853_state &= ~LM4853_AMP;
225
226 return 0;
227}
228
229static int lm4853_get_state(struct snd_kcontrol *kcontrol,
230 struct snd_ctl_elem_value *ucontrol)
231{
232 ucontrol->value.integer.value[0] = lm4853_state & LM4853_AMP;
233
234 return 0;
235}
236
237static int lm4853_set_spk(struct snd_kcontrol *kcontrol,
238 struct snd_ctl_elem_value *ucontrol)
239{
240 int val = ucontrol->value.integer.value[0];
241
242 if (val) {
243 lm4853_state |= LM4853_SPK;
244 gpio_set_value(GTA02_GPIO_HP_IN, 0);
245 } else {
246 lm4853_state &= ~LM4853_SPK;
247 gpio_set_value(GTA02_GPIO_HP_IN, 1);
248 }
249
250 return 0;
251}
252
253static int lm4853_get_spk(struct snd_kcontrol *kcontrol,
254 struct snd_ctl_elem_value *ucontrol)
255{
256 ucontrol->value.integer.value[0] = (lm4853_state & LM4853_SPK) >> 1;
257
258 return 0;
259}
260
261static int lm4853_event(struct snd_soc_dapm_widget *w,
262 struct snd_kcontrol *k,
263 int event)
264{
265 gpio_set_value(GTA02_GPIO_AMP_SHUT, SND_SOC_DAPM_EVENT_OFF(event));
266
267 return 0;
268}
269
270static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] = {
271 SND_SOC_DAPM_SPK("Stereo Out", lm4853_event),
272 SND_SOC_DAPM_LINE("GSM Line Out", NULL),
273 SND_SOC_DAPM_LINE("GSM Line In", NULL),
274 SND_SOC_DAPM_MIC("Headset Mic", NULL),
275 SND_SOC_DAPM_MIC("Handset Mic", NULL),
276 SND_SOC_DAPM_SPK("Handset Spk", NULL),
277};
278
279
280/* example machine audio_mapnections */
281static const struct snd_soc_dapm_route audio_map[] = {
282
283 /* Connections to the lm4853 amp */
284 {"Stereo Out", NULL, "LOUT1"},
285 {"Stereo Out", NULL, "ROUT1"},
286
287 /* Connections to the GSM Module */
288 {"GSM Line Out", NULL, "MONO1"},
289 {"GSM Line Out", NULL, "MONO2"},
290 {"RXP", NULL, "GSM Line In"},
291 {"RXN", NULL, "GSM Line In"},
292
293 /* Connections to Headset */
294 {"MIC1", NULL, "Mic Bias"},
295 {"Mic Bias", NULL, "Headset Mic"},
296
297 /* Call Mic */
298 {"MIC2", NULL, "Mic Bias"},
299 {"MIC2N", NULL, "Mic Bias"},
300 {"Mic Bias", NULL, "Handset Mic"},
301
302 /* Call Speaker */
303 {"Handset Spk", NULL, "LOUT2"},
304 {"Handset Spk", NULL, "ROUT2"},
305
306 /* Connect the ALC pins */
307 {"ACIN", NULL, "ACOP"},
308};
309
310static const struct snd_kcontrol_new wm8753_neo1973_gta02_controls[] = {
311 SOC_DAPM_PIN_SWITCH("Stereo Out"),
312 SOC_DAPM_PIN_SWITCH("GSM Line Out"),
313 SOC_DAPM_PIN_SWITCH("GSM Line In"),
314 SOC_DAPM_PIN_SWITCH("Headset Mic"),
315 SOC_DAPM_PIN_SWITCH("Handset Mic"),
316 SOC_DAPM_PIN_SWITCH("Handset Spk"),
317
318 /* This has no effect, it exists only to maintain compatibility with
319 * existing ALSA state files.
320 */
321 SOC_SINGLE_EXT("Amp State Switch", 6, 0, 1, 0,
322 lm4853_get_state,
323 lm4853_set_state),
324 SOC_SINGLE_EXT("Amp Spk Switch", 7, 0, 1, 0,
325 lm4853_get_spk,
326 lm4853_set_spk),
327};
328
329/*
330 * This is an example machine initialisation for a wm8753 connected to a
331 * neo1973 GTA02.
332 */
333static int neo1973_gta02_wm8753_init(struct snd_soc_pcm_runtime *rtd)
334{
335 struct snd_soc_codec *codec = rtd->codec;
336 int err;
337
338 /* set up NC codec pins */
339 snd_soc_dapm_nc_pin(codec, "OUT3");
340 snd_soc_dapm_nc_pin(codec, "OUT4");
341 snd_soc_dapm_nc_pin(codec, "LINE1");
342 snd_soc_dapm_nc_pin(codec, "LINE2");
343
344 /* Add neo1973 gta02 specific widgets */
345 snd_soc_dapm_new_controls(codec, wm8753_dapm_widgets,
346 ARRAY_SIZE(wm8753_dapm_widgets));
347
348 /* add neo1973 gta02 specific controls */
349 err = snd_soc_add_controls(codec, wm8753_neo1973_gta02_controls,
350 ARRAY_SIZE(wm8753_neo1973_gta02_controls));
351
352 if (err < 0)
353 return err;
354
355 /* set up neo1973 gta02 specific audio path audio_map */
356 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
357
358 /* set endpoints to default off mode */
359 snd_soc_dapm_disable_pin(codec, "Stereo Out");
360 snd_soc_dapm_disable_pin(codec, "GSM Line Out");
361 snd_soc_dapm_disable_pin(codec, "GSM Line In");
362 snd_soc_dapm_disable_pin(codec, "Headset Mic");
363 snd_soc_dapm_disable_pin(codec, "Handset Mic");
364 snd_soc_dapm_disable_pin(codec, "Handset Spk");
365
366 /* allow audio paths from the GSM modem to run during suspend */
367 snd_soc_dapm_ignore_suspend(codec, "Stereo Out");
368 snd_soc_dapm_ignore_suspend(codec, "GSM Line Out");
369 snd_soc_dapm_ignore_suspend(codec, "GSM Line In");
370 snd_soc_dapm_ignore_suspend(codec, "Headset Mic");
371 snd_soc_dapm_ignore_suspend(codec, "Handset Mic");
372 snd_soc_dapm_ignore_suspend(codec, "Handset Spk");
373
374 snd_soc_dapm_sync(codec);
375
376 return 0;
377}
378
379/*
380 * BT Codec DAI
381 */
382static struct snd_soc_dai_driver bt_dai = {
383 .name = "bluetooth-dai",
384 .playback = {
385 .channels_min = 1,
386 .channels_max = 1,
387 .rates = SNDRV_PCM_RATE_8000,
388 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
389 .capture = {
390 .channels_min = 1,
391 .channels_max = 1,
392 .rates = SNDRV_PCM_RATE_8000,
393 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
394};
395
396static struct snd_soc_dai_link neo1973_gta02_dai[] = {
397{ /* Hifi Playback - for similatious use with voice below */
398 .name = "WM8753",
399 .stream_name = "WM8753 HiFi",
400 .cpu_dai_name = "s3c24xx-i2s",
401 .codec_dai_name = "wm8753-hifi",
402 .init = neo1973_gta02_wm8753_init,
403 .platform_name = "s3c24xx-pcm-audio",
404 .codec_name = "wm8753-codec.0-0x1a",
405 .ops = &neo1973_gta02_hifi_ops,
406},
407{ /* Voice via BT */
408 .name = "Bluetooth",
409 .stream_name = "Voice",
410 .cpu_dai_name = "bluetooth-dai",
411 .codec_dai_name = "wm8753-voice",
412 .ops = &neo1973_gta02_voice_ops,
413 .codec_name = "wm8753-codec.0-0x1a",
414 .platform_name = "s3c24xx-pcm-audio",
415},
416};
417
418static struct snd_soc_card neo1973_gta02 = {
419 .name = "neo1973-gta02",
420 .dai_link = neo1973_gta02_dai,
421 .num_links = ARRAY_SIZE(neo1973_gta02_dai),
422};
423
424static struct platform_device *neo1973_gta02_snd_device;
425
426static int __init neo1973_gta02_init(void)
427{
428 int ret;
429
430 if (!machine_is_neo1973_gta02()) {
431 printk(KERN_INFO
432 "Only GTA02 is supported by this ASoC driver\n");
433 return -ENODEV;
434 }
435
436 neo1973_gta02_snd_device = platform_device_alloc("soc-audio", -1);
437 if (!neo1973_gta02_snd_device)
438 return -ENOMEM;
439
440 /* register bluetooth DAI here */
441 ret = snd_soc_register_dai(&neo1973_gta02_snd_device->dev, -1, &bt_dai);
442 if (ret) {
443 platform_device_put(neo1973_gta02_snd_device);
444 return ret;
445 }
446
447 platform_set_drvdata(neo1973_gta02_snd_device, &neo1973_gta02);
448 ret = platform_device_add(neo1973_gta02_snd_device);
449
450 if (ret) {
451 platform_device_put(neo1973_gta02_snd_device);
452 return ret;
453 }
454
455 /* Initialise GPIOs used by amp */
456 ret = gpio_request(GTA02_GPIO_HP_IN, "GTA02_HP_IN");
457 if (ret) {
458 pr_err("gta02_wm8753: Failed to register GPIO %d\n", GTA02_GPIO_HP_IN);
459 goto err_unregister_device;
460 }
461
462 ret = gpio_direction_output(GTA02_GPIO_HP_IN, 1);
463 if (ret) {
464 pr_err("gta02_wm8753: Failed to configure GPIO %d\n", GTA02_GPIO_HP_IN);
465 goto err_free_gpio_hp_in;
466 }
467
468 ret = gpio_request(GTA02_GPIO_AMP_SHUT, "GTA02_AMP_SHUT");
469 if (ret) {
470 pr_err("gta02_wm8753: Failed to register GPIO %d\n", GTA02_GPIO_AMP_SHUT);
471 goto err_free_gpio_hp_in;
472 }
473
474 ret = gpio_direction_output(GTA02_GPIO_AMP_SHUT, 1);
475 if (ret) {
476 pr_err("gta02_wm8753: Failed to configure GPIO %d\n", GTA02_GPIO_AMP_SHUT);
477 goto err_free_gpio_amp_shut;
478 }
479
480 return 0;
481
482err_free_gpio_amp_shut:
483 gpio_free(GTA02_GPIO_AMP_SHUT);
484err_free_gpio_hp_in:
485 gpio_free(GTA02_GPIO_HP_IN);
486err_unregister_device:
487 platform_device_unregister(neo1973_gta02_snd_device);
488 return ret;
489}
490module_init(neo1973_gta02_init);
491
492static void __exit neo1973_gta02_exit(void)
493{
494 snd_soc_unregister_dai(&neo1973_gta02_snd_device->dev, -1);
495 platform_device_unregister(neo1973_gta02_snd_device);
496 gpio_free(GTA02_GPIO_HP_IN);
497 gpio_free(GTA02_GPIO_AMP_SHUT);
498}
499module_exit(neo1973_gta02_exit);
500
501/* Module information */
502MODULE_AUTHOR("Graeme Gregory, graeme@openmoko.org");
503MODULE_DESCRIPTION("ALSA SoC WM8753 Neo1973 GTA02");
504MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/neo1973_wm8753.c b/sound/soc/s3c24xx/neo1973_wm8753.c
deleted file mode 100644
index f4f2ee731f01..000000000000
--- a/sound/soc/s3c24xx/neo1973_wm8753.c
+++ /dev/null
@@ -1,704 +0,0 @@
1/*
2 * neo1973_wm8753.c -- SoC audio for Neo1973
3 *
4 * Copyright 2007 Wolfson Microelectronics PLC.
5 * Author: Graeme Gregory
6 * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 */
14
15#include <linux/module.h>
16#include <linux/moduleparam.h>
17#include <linux/timer.h>
18#include <linux/interrupt.h>
19#include <linux/platform_device.h>
20#include <linux/i2c.h>
21#include <sound/core.h>
22#include <sound/pcm.h>
23#include <sound/soc.h>
24#include <sound/soc-dapm.h>
25#include <sound/tlv.h>
26
27#include <asm/mach-types.h>
28#include <asm/hardware/scoop.h>
29#include <mach/regs-clock.h>
30#include <mach/regs-gpio.h>
31#include <mach/hardware.h>
32#include <linux/io.h>
33#include <mach/spi-gpio.h>
34
35#include <plat/regs-iis.h>
36
37#include "../codecs/wm8753.h"
38#include "lm4857.h"
39#include "s3c-dma.h"
40#include "s3c24xx-i2s.h"
41
42/* define the scenarios */
43#define NEO_AUDIO_OFF 0
44#define NEO_GSM_CALL_AUDIO_HANDSET 1
45#define NEO_GSM_CALL_AUDIO_HEADSET 2
46#define NEO_GSM_CALL_AUDIO_BLUETOOTH 3
47#define NEO_STEREO_TO_SPEAKERS 4
48#define NEO_STEREO_TO_HEADPHONES 5
49#define NEO_CAPTURE_HANDSET 6
50#define NEO_CAPTURE_HEADSET 7
51#define NEO_CAPTURE_BLUETOOTH 8
52
53static struct snd_soc_card neo1973;
54static struct i2c_client *i2c;
55
56static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream,
57 struct snd_pcm_hw_params *params)
58{
59 struct snd_soc_pcm_runtime *rtd = substream->private_data;
60 struct snd_soc_dai *codec_dai = rtd->codec_dai;
61 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
62 unsigned int pll_out = 0, bclk = 0;
63 int ret = 0;
64 unsigned long iis_clkrate;
65
66 pr_debug("Entered %s\n", __func__);
67
68 iis_clkrate = s3c24xx_i2s_get_clockrate();
69
70 switch (params_rate(params)) {
71 case 8000:
72 case 16000:
73 pll_out = 12288000;
74 break;
75 case 48000:
76 bclk = WM8753_BCLK_DIV_4;
77 pll_out = 12288000;
78 break;
79 case 96000:
80 bclk = WM8753_BCLK_DIV_2;
81 pll_out = 12288000;
82 break;
83 case 11025:
84 bclk = WM8753_BCLK_DIV_16;
85 pll_out = 11289600;
86 break;
87 case 22050:
88 bclk = WM8753_BCLK_DIV_8;
89 pll_out = 11289600;
90 break;
91 case 44100:
92 bclk = WM8753_BCLK_DIV_4;
93 pll_out = 11289600;
94 break;
95 case 88200:
96 bclk = WM8753_BCLK_DIV_2;
97 pll_out = 11289600;
98 break;
99 }
100
101 /* set codec DAI configuration */
102 ret = snd_soc_dai_set_fmt(codec_dai,
103 SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
104 SND_SOC_DAIFMT_CBM_CFM);
105 if (ret < 0)
106 return ret;
107
108 /* set cpu DAI configuration */
109 ret = snd_soc_dai_set_fmt(cpu_dai,
110 SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
111 SND_SOC_DAIFMT_CBM_CFM);
112 if (ret < 0)
113 return ret;
114
115 /* set the codec system clock for DAC and ADC */
116 ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_MCLK, pll_out,
117 SND_SOC_CLOCK_IN);
118 if (ret < 0)
119 return ret;
120
121 /* set MCLK division for sample rate */
122 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK,
123 S3C2410_IISMOD_32FS);
124 if (ret < 0)
125 return ret;
126
127 /* set codec BCLK division for sample rate */
128 ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_BCLKDIV, bclk);
129 if (ret < 0)
130 return ret;
131
132 /* set prescaler division for sample rate */
133 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
134 S3C24XX_PRESCALE(4, 4));
135 if (ret < 0)
136 return ret;
137
138 /* codec PLL input is PCLK/4 */
139 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0,
140 iis_clkrate / 4, pll_out);
141 if (ret < 0)
142 return ret;
143
144 return 0;
145}
146
147static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream)
148{
149 struct snd_soc_pcm_runtime *rtd = substream->private_data;
150 struct snd_soc_dai *codec_dai = rtd->codec_dai;
151
152 pr_debug("Entered %s\n", __func__);
153
154 /* disable the PLL */
155 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0, 0);
156}
157
158/*
159 * Neo1973 WM8753 HiFi DAI opserations.
160 */
161static struct snd_soc_ops neo1973_hifi_ops = {
162 .hw_params = neo1973_hifi_hw_params,
163 .hw_free = neo1973_hifi_hw_free,
164};
165
166static int neo1973_voice_hw_params(struct snd_pcm_substream *substream,
167 struct snd_pcm_hw_params *params)
168{
169 struct snd_soc_pcm_runtime *rtd = substream->private_data;
170 struct snd_soc_dai *codec_dai = rtd->codec_dai;
171 unsigned int pcmdiv = 0;
172 int ret = 0;
173 unsigned long iis_clkrate;
174
175 pr_debug("Entered %s\n", __func__);
176
177 iis_clkrate = s3c24xx_i2s_get_clockrate();
178
179 if (params_rate(params) != 8000)
180 return -EINVAL;
181 if (params_channels(params) != 1)
182 return -EINVAL;
183
184 pcmdiv = WM8753_PCM_DIV_6; /* 2.048 MHz */
185
186 /* todo: gg check mode (DSP_B) against CSR datasheet */
187 /* set codec DAI configuration */
188 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B |
189 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
190 if (ret < 0)
191 return ret;
192
193 /* set the codec system clock for DAC and ADC */
194 ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_PCMCLK, 12288000,
195 SND_SOC_CLOCK_IN);
196 if (ret < 0)
197 return ret;
198
199 /* set codec PCM division for sample rate */
200 ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_PCMDIV, pcmdiv);
201 if (ret < 0)
202 return ret;
203
204 /* configure and enable PLL for 12.288MHz output */
205 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0,
206 iis_clkrate / 4, 12288000);
207 if (ret < 0)
208 return ret;
209
210 return 0;
211}
212
213static int neo1973_voice_hw_free(struct snd_pcm_substream *substream)
214{
215 struct snd_soc_pcm_runtime *rtd = substream->private_data;
216 struct snd_soc_dai *codec_dai = rtd->codec_dai;
217
218 pr_debug("Entered %s\n", __func__);
219
220 /* disable the PLL */
221 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0, 0);
222}
223
224static struct snd_soc_ops neo1973_voice_ops = {
225 .hw_params = neo1973_voice_hw_params,
226 .hw_free = neo1973_voice_hw_free,
227};
228
229static int neo1973_scenario;
230
231static int neo1973_get_scenario(struct snd_kcontrol *kcontrol,
232 struct snd_ctl_elem_value *ucontrol)
233{
234 ucontrol->value.integer.value[0] = neo1973_scenario;
235 return 0;
236}
237
238static int set_scenario_endpoints(struct snd_soc_codec *codec, int scenario)
239{
240 pr_debug("Entered %s\n", __func__);
241
242 switch (neo1973_scenario) {
243 case NEO_AUDIO_OFF:
244 snd_soc_dapm_disable_pin(codec, "Audio Out");
245 snd_soc_dapm_disable_pin(codec, "GSM Line Out");
246 snd_soc_dapm_disable_pin(codec, "GSM Line In");
247 snd_soc_dapm_disable_pin(codec, "Headset Mic");
248 snd_soc_dapm_disable_pin(codec, "Call Mic");
249 break;
250 case NEO_GSM_CALL_AUDIO_HANDSET:
251 snd_soc_dapm_enable_pin(codec, "Audio Out");
252 snd_soc_dapm_enable_pin(codec, "GSM Line Out");
253 snd_soc_dapm_enable_pin(codec, "GSM Line In");
254 snd_soc_dapm_disable_pin(codec, "Headset Mic");
255 snd_soc_dapm_enable_pin(codec, "Call Mic");
256 break;
257 case NEO_GSM_CALL_AUDIO_HEADSET:
258 snd_soc_dapm_enable_pin(codec, "Audio Out");
259 snd_soc_dapm_enable_pin(codec, "GSM Line Out");
260 snd_soc_dapm_enable_pin(codec, "GSM Line In");
261 snd_soc_dapm_enable_pin(codec, "Headset Mic");
262 snd_soc_dapm_disable_pin(codec, "Call Mic");
263 break;
264 case NEO_GSM_CALL_AUDIO_BLUETOOTH:
265 snd_soc_dapm_disable_pin(codec, "Audio Out");
266 snd_soc_dapm_enable_pin(codec, "GSM Line Out");
267 snd_soc_dapm_enable_pin(codec, "GSM Line In");
268 snd_soc_dapm_disable_pin(codec, "Headset Mic");
269 snd_soc_dapm_disable_pin(codec, "Call Mic");
270 break;
271 case NEO_STEREO_TO_SPEAKERS:
272 snd_soc_dapm_enable_pin(codec, "Audio Out");
273 snd_soc_dapm_disable_pin(codec, "GSM Line Out");
274 snd_soc_dapm_disable_pin(codec, "GSM Line In");
275 snd_soc_dapm_disable_pin(codec, "Headset Mic");
276 snd_soc_dapm_disable_pin(codec, "Call Mic");
277 break;
278 case NEO_STEREO_TO_HEADPHONES:
279 snd_soc_dapm_enable_pin(codec, "Audio Out");
280 snd_soc_dapm_disable_pin(codec, "GSM Line Out");
281 snd_soc_dapm_disable_pin(codec, "GSM Line In");
282 snd_soc_dapm_disable_pin(codec, "Headset Mic");
283 snd_soc_dapm_disable_pin(codec, "Call Mic");
284 break;
285 case NEO_CAPTURE_HANDSET:
286 snd_soc_dapm_disable_pin(codec, "Audio Out");
287 snd_soc_dapm_disable_pin(codec, "GSM Line Out");
288 snd_soc_dapm_disable_pin(codec, "GSM Line In");
289 snd_soc_dapm_disable_pin(codec, "Headset Mic");
290 snd_soc_dapm_enable_pin(codec, "Call Mic");
291 break;
292 case NEO_CAPTURE_HEADSET:
293 snd_soc_dapm_disable_pin(codec, "Audio Out");
294 snd_soc_dapm_disable_pin(codec, "GSM Line Out");
295 snd_soc_dapm_disable_pin(codec, "GSM Line In");
296 snd_soc_dapm_enable_pin(codec, "Headset Mic");
297 snd_soc_dapm_disable_pin(codec, "Call Mic");
298 break;
299 case NEO_CAPTURE_BLUETOOTH:
300 snd_soc_dapm_disable_pin(codec, "Audio Out");
301 snd_soc_dapm_disable_pin(codec, "GSM Line Out");
302 snd_soc_dapm_disable_pin(codec, "GSM Line In");
303 snd_soc_dapm_disable_pin(codec, "Headset Mic");
304 snd_soc_dapm_disable_pin(codec, "Call Mic");
305 break;
306 default:
307 snd_soc_dapm_disable_pin(codec, "Audio Out");
308 snd_soc_dapm_disable_pin(codec, "GSM Line Out");
309 snd_soc_dapm_disable_pin(codec, "GSM Line In");
310 snd_soc_dapm_disable_pin(codec, "Headset Mic");
311 snd_soc_dapm_disable_pin(codec, "Call Mic");
312 }
313
314 snd_soc_dapm_sync(codec);
315
316 return 0;
317}
318
319static int neo1973_set_scenario(struct snd_kcontrol *kcontrol,
320 struct snd_ctl_elem_value *ucontrol)
321{
322 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
323
324 pr_debug("Entered %s\n", __func__);
325
326 if (neo1973_scenario == ucontrol->value.integer.value[0])
327 return 0;
328
329 neo1973_scenario = ucontrol->value.integer.value[0];
330 set_scenario_endpoints(codec, neo1973_scenario);
331 return 1;
332}
333
334static u8 lm4857_regs[4] = {0x00, 0x40, 0x80, 0xC0};
335
336static void lm4857_write_regs(void)
337{
338 pr_debug("Entered %s\n", __func__);
339
340 if (i2c_master_send(i2c, lm4857_regs, 4) != 4)
341 printk(KERN_ERR "lm4857: i2c write failed\n");
342}
343
344static int lm4857_get_reg(struct snd_kcontrol *kcontrol,
345 struct snd_ctl_elem_value *ucontrol)
346{
347 struct soc_mixer_control *mc =
348 (struct soc_mixer_control *)kcontrol->private_value;
349 int reg = mc->reg;
350 int shift = mc->shift;
351 int mask = mc->max;
352
353 pr_debug("Entered %s\n", __func__);
354
355 ucontrol->value.integer.value[0] = (lm4857_regs[reg] >> shift) & mask;
356 return 0;
357}
358
359static int lm4857_set_reg(struct snd_kcontrol *kcontrol,
360 struct snd_ctl_elem_value *ucontrol)
361{
362 struct soc_mixer_control *mc =
363 (struct soc_mixer_control *)kcontrol->private_value;
364 int reg = mc->reg;
365 int shift = mc->shift;
366 int mask = mc->max;
367
368 if (((lm4857_regs[reg] >> shift) & mask) ==
369 ucontrol->value.integer.value[0])
370 return 0;
371
372 lm4857_regs[reg] &= ~(mask << shift);
373 lm4857_regs[reg] |= ucontrol->value.integer.value[0] << shift;
374 lm4857_write_regs();
375 return 1;
376}
377
378static int lm4857_get_mode(struct snd_kcontrol *kcontrol,
379 struct snd_ctl_elem_value *ucontrol)
380{
381 u8 value = lm4857_regs[LM4857_CTRL] & 0x0F;
382
383 pr_debug("Entered %s\n", __func__);
384
385 if (value)
386 value -= 5;
387
388 ucontrol->value.integer.value[0] = value;
389 return 0;
390}
391
392static int lm4857_set_mode(struct snd_kcontrol *kcontrol,
393 struct snd_ctl_elem_value *ucontrol)
394{
395 u8 value = ucontrol->value.integer.value[0];
396
397 pr_debug("Entered %s\n", __func__);
398
399 if (value)
400 value += 5;
401
402 if ((lm4857_regs[LM4857_CTRL] & 0x0F) == value)
403 return 0;
404
405 lm4857_regs[LM4857_CTRL] &= 0xF0;
406 lm4857_regs[LM4857_CTRL] |= value;
407 lm4857_write_regs();
408 return 1;
409}
410
411static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] = {
412 SND_SOC_DAPM_LINE("Audio Out", NULL),
413 SND_SOC_DAPM_LINE("GSM Line Out", NULL),
414 SND_SOC_DAPM_LINE("GSM Line In", NULL),
415 SND_SOC_DAPM_MIC("Headset Mic", NULL),
416 SND_SOC_DAPM_MIC("Call Mic", NULL),
417};
418
419
420static const struct snd_soc_dapm_route dapm_routes[] = {
421
422 /* Connections to the lm4857 amp */
423 {"Audio Out", NULL, "LOUT1"},
424 {"Audio Out", NULL, "ROUT1"},
425
426 /* Connections to the GSM Module */
427 {"GSM Line Out", NULL, "MONO1"},
428 {"GSM Line Out", NULL, "MONO2"},
429 {"RXP", NULL, "GSM Line In"},
430 {"RXN", NULL, "GSM Line In"},
431
432 /* Connections to Headset */
433 {"MIC1", NULL, "Mic Bias"},
434 {"Mic Bias", NULL, "Headset Mic"},
435
436 /* Call Mic */
437 {"MIC2", NULL, "Mic Bias"},
438 {"MIC2N", NULL, "Mic Bias"},
439 {"Mic Bias", NULL, "Call Mic"},
440
441 /* Connect the ALC pins */
442 {"ACIN", NULL, "ACOP"},
443};
444
445static const char *lm4857_mode[] = {
446 "Off",
447 "Call Speaker",
448 "Stereo Speakers",
449 "Stereo Speakers + Headphones",
450 "Headphones"
451};
452
453static const struct soc_enum lm4857_mode_enum[] = {
454 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(lm4857_mode), lm4857_mode),
455};
456
457static const char *neo_scenarios[] = {
458 "Off",
459 "GSM Handset",
460 "GSM Headset",
461 "GSM Bluetooth",
462 "Speakers",
463 "Headphones",
464 "Capture Handset",
465 "Capture Headset",
466 "Capture Bluetooth"
467};
468
469static const struct soc_enum neo_scenario_enum[] = {
470 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(neo_scenarios), neo_scenarios),
471};
472
473static const DECLARE_TLV_DB_SCALE(stereo_tlv, -4050, 150, 0);
474static const DECLARE_TLV_DB_SCALE(mono_tlv, -3450, 150, 0);
475
476static const struct snd_kcontrol_new wm8753_neo1973_controls[] = {
477 SOC_SINGLE_EXT_TLV("Amp Left Playback Volume", LM4857_LVOL, 0, 31, 0,
478 lm4857_get_reg, lm4857_set_reg, stereo_tlv),
479 SOC_SINGLE_EXT_TLV("Amp Right Playback Volume", LM4857_RVOL, 0, 31, 0,
480 lm4857_get_reg, lm4857_set_reg, stereo_tlv),
481 SOC_SINGLE_EXT_TLV("Amp Mono Playback Volume", LM4857_MVOL, 0, 31, 0,
482 lm4857_get_reg, lm4857_set_reg, mono_tlv),
483 SOC_ENUM_EXT("Amp Mode", lm4857_mode_enum[0],
484 lm4857_get_mode, lm4857_set_mode),
485 SOC_ENUM_EXT("Neo Mode", neo_scenario_enum[0],
486 neo1973_get_scenario, neo1973_set_scenario),
487 SOC_SINGLE_EXT("Amp Spk 3D Playback Switch", LM4857_LVOL, 5, 1, 0,
488 lm4857_get_reg, lm4857_set_reg),
489 SOC_SINGLE_EXT("Amp HP 3d Playback Switch", LM4857_RVOL, 5, 1, 0,
490 lm4857_get_reg, lm4857_set_reg),
491 SOC_SINGLE_EXT("Amp Fast Wakeup Playback Switch", LM4857_CTRL, 5, 1, 0,
492 lm4857_get_reg, lm4857_set_reg),
493 SOC_SINGLE_EXT("Amp Earpiece 6dB Playback Switch", LM4857_CTRL, 4, 1, 0,
494 lm4857_get_reg, lm4857_set_reg),
495};
496
497/*
498 * This is an example machine initialisation for a wm8753 connected to a
499 * neo1973 II. It is missing logic to detect hp/mic insertions and logic
500 * to re-route the audio in such an event.
501 */
502static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
503{
504 struct snd_soc_codec *codec = rtd->codec;
505 int err;
506
507 pr_debug("Entered %s\n", __func__);
508
509 /* set up NC codec pins */
510 snd_soc_dapm_nc_pin(codec, "LOUT2");
511 snd_soc_dapm_nc_pin(codec, "ROUT2");
512 snd_soc_dapm_nc_pin(codec, "OUT3");
513 snd_soc_dapm_nc_pin(codec, "OUT4");
514 snd_soc_dapm_nc_pin(codec, "LINE1");
515 snd_soc_dapm_nc_pin(codec, "LINE2");
516
517 /* Add neo1973 specific widgets */
518 snd_soc_dapm_new_controls(codec, wm8753_dapm_widgets,
519 ARRAY_SIZE(wm8753_dapm_widgets));
520
521 /* set endpoints to default mode */
522 set_scenario_endpoints(codec, NEO_AUDIO_OFF);
523
524 /* add neo1973 specific controls */
525 err = snd_soc_add_controls(codec, wm8753_neo1973_controls,
526 ARRAY_SIZE(8753_neo1973_controls));
527 if (err < 0)
528 return err;
529
530 /* set up neo1973 specific audio routes */
531 err = snd_soc_dapm_add_routes(codec, dapm_routes,
532 ARRAY_SIZE(dapm_routes));
533
534 snd_soc_dapm_sync(codec);
535 return 0;
536}
537
538/*
539 * BT Codec DAI
540 */
541static struct snd_soc_dai bt_dai = {
542 .name = "bluetooth-dai",
543 .playback = {
544 .channels_min = 1,
545 .channels_max = 1,
546 .rates = SNDRV_PCM_RATE_8000,
547 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
548 .capture = {
549 .channels_min = 1,
550 .channels_max = 1,
551 .rates = SNDRV_PCM_RATE_8000,
552 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
553};
554
555static struct snd_soc_dai_link neo1973_dai[] = {
556{ /* Hifi Playback - for similatious use with voice below */
557 .name = "WM8753",
558 .stream_name = "WM8753 HiFi",
559 .platform_name = "s3c24xx-pcm-audio",
560 .cpu_dai_name = "s3c24xx-i2s",
561 .codec_dai_name = "wm8753-hifi",
562 .codec_name = "wm8753-codec.0-0x1a",
563 .init = neo1973_wm8753_init,
564 .ops = &neo1973_hifi_ops,
565},
566{ /* Voice via BT */
567 .name = "Bluetooth",
568 .stream_name = "Voice",
569 .platform_name = "s3c24xx-pcm-audio",
570 .cpu_dai_name = "bluetooth-dai",
571 .codec_dai_name = "wm8753-voice",
572 .codec_name = "wm8753-codec.0-0x1a",
573 .ops = &neo1973_voice_ops,
574},
575};
576
577static struct snd_soc_card neo1973 = {
578 .name = "neo1973",
579 .dai_link = neo1973_dai,
580 .num_links = ARRAY_SIZE(neo1973_dai),
581};
582
583static int lm4857_i2c_probe(struct i2c_client *client,
584 const struct i2c_device_id *id)
585{
586 pr_debug("Entered %s\n", __func__);
587
588 i2c = client;
589
590 lm4857_write_regs();
591 return 0;
592}
593
594static int lm4857_i2c_remove(struct i2c_client *client)
595{
596 pr_debug("Entered %s\n", __func__);
597
598 i2c = NULL;
599
600 return 0;
601}
602
603static u8 lm4857_state;
604
605static int lm4857_suspend(struct i2c_client *dev, pm_message_t state)
606{
607 pr_debug("Entered %s\n", __func__);
608
609 dev_dbg(&dev->dev, "lm4857_suspend\n");
610 lm4857_state = lm4857_regs[LM4857_CTRL] & 0xf;
611 if (lm4857_state) {
612 lm4857_regs[LM4857_CTRL] &= 0xf0;
613 lm4857_write_regs();
614 }
615 return 0;
616}
617
618static int lm4857_resume(struct i2c_client *dev)
619{
620 pr_debug("Entered %s\n", __func__);
621
622 if (lm4857_state) {
623 lm4857_regs[LM4857_CTRL] |= (lm4857_state & 0x0f);
624 lm4857_write_regs();
625 }
626 return 0;
627}
628
629static void lm4857_shutdown(struct i2c_client *dev)
630{
631 pr_debug("Entered %s\n", __func__);
632
633 dev_dbg(&dev->dev, "lm4857_shutdown\n");
634 lm4857_regs[LM4857_CTRL] &= 0xf0;
635 lm4857_write_regs();
636}
637
638static const struct i2c_device_id lm4857_i2c_id[] = {
639 { "neo1973_lm4857", 0 },
640 { }
641};
642
643static struct i2c_driver lm4857_i2c_driver = {
644 .driver = {
645 .name = "LM4857 I2C Amp",
646 .owner = THIS_MODULE,
647 },
648 .suspend = lm4857_suspend,
649 .resume = lm4857_resume,
650 .shutdown = lm4857_shutdown,
651 .probe = lm4857_i2c_probe,
652 .remove = lm4857_i2c_remove,
653 .id_table = lm4857_i2c_id,
654};
655
656static struct platform_device *neo1973_snd_device;
657
658static int __init neo1973_init(void)
659{
660 int ret;
661
662 pr_debug("Entered %s\n", __func__);
663
664 if (!machine_is_neo1973_gta01()) {
665 printk(KERN_INFO
666 "Only GTA01 hardware supported by ASoC driver\n");
667 return -ENODEV;
668 }
669
670 neo1973_snd_device = platform_device_alloc("soc-audio", -1);
671 if (!neo1973_snd_device)
672 return -ENOMEM;
673
674 platform_set_drvdata(neo1973_snd_device, &neo1973);
675 ret = platform_device_add(neo1973_snd_device);
676
677 if (ret) {
678 platform_device_put(neo1973_snd_device);
679 return ret;
680 }
681
682 ret = i2c_add_driver(&lm4857_i2c_driver);
683
684 if (ret != 0)
685 platform_device_unregister(neo1973_snd_device);
686
687 return ret;
688}
689
690static void __exit neo1973_exit(void)
691{
692 pr_debug("Entered %s\n", __func__);
693
694 i2c_del_driver(&lm4857_i2c_driver);
695 platform_device_unregister(neo1973_snd_device);
696}
697
698module_init(neo1973_init);
699module_exit(neo1973_exit);
700
701/* Module information */
702MODULE_AUTHOR("Graeme Gregory, graeme@openmoko.org, www.openmoko.org");
703MODULE_DESCRIPTION("ALSA SoC WM8753 Neo1973");
704MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/regs-i2s-v2.h b/sound/soc/s3c24xx/regs-i2s-v2.h
deleted file mode 100644
index 5e5e5680580b..000000000000
--- a/sound/soc/s3c24xx/regs-i2s-v2.h
+++ /dev/null
@@ -1,115 +0,0 @@
1/* linux/include/asm-arm/plat-s3c24xx/regs-s3c2412-iis.h
2 *
3 * Copyright 2007 Simtec Electronics <linux@simtec.co.uk>
4 * http://armlinux.simtec.co.uk/
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * S3C2412 IIS register definition
11*/
12
13#ifndef __ASM_ARCH_REGS_S3C2412_IIS_H
14#define __ASM_ARCH_REGS_S3C2412_IIS_H
15
16#define S3C2412_IISCON (0x00)
17#define S3C2412_IISMOD (0x04)
18#define S3C2412_IISFIC (0x08)
19#define S3C2412_IISPSR (0x0C)
20#define S3C2412_IISTXD (0x10)
21#define S3C2412_IISRXD (0x14)
22
23#define S5PC1XX_IISFICS 0x18
24#define S5PC1XX_IISTXDS 0x1C
25
26#define S5PC1XX_IISCON_SW_RST (1 << 31)
27#define S5PC1XX_IISCON_FRXOFSTATUS (1 << 26)
28#define S5PC1XX_IISCON_FRXORINTEN (1 << 25)
29#define S5PC1XX_IISCON_FTXSURSTAT (1 << 24)
30#define S5PC1XX_IISCON_FTXSURINTEN (1 << 23)
31#define S5PC1XX_IISCON_TXSDMAPAUSE (1 << 20)
32#define S5PC1XX_IISCON_TXSDMACTIVE (1 << 18)
33
34#define S3C64XX_IISCON_FTXURSTATUS (1 << 17)
35#define S3C64XX_IISCON_FTXURINTEN (1 << 16)
36#define S3C64XX_IISCON_TXFIFO2_EMPTY (1 << 15)
37#define S3C64XX_IISCON_TXFIFO1_EMPTY (1 << 14)
38#define S3C64XX_IISCON_TXFIFO2_FULL (1 << 13)
39#define S3C64XX_IISCON_TXFIFO1_FULL (1 << 12)
40
41#define S3C2412_IISCON_LRINDEX (1 << 11)
42#define S3C2412_IISCON_TXFIFO_EMPTY (1 << 10)
43#define S3C2412_IISCON_RXFIFO_EMPTY (1 << 9)
44#define S3C2412_IISCON_TXFIFO_FULL (1 << 8)
45#define S3C2412_IISCON_RXFIFO_FULL (1 << 7)
46#define S3C2412_IISCON_TXDMA_PAUSE (1 << 6)
47#define S3C2412_IISCON_RXDMA_PAUSE (1 << 5)
48#define S3C2412_IISCON_TXCH_PAUSE (1 << 4)
49#define S3C2412_IISCON_RXCH_PAUSE (1 << 3)
50#define S3C2412_IISCON_TXDMA_ACTIVE (1 << 2)
51#define S3C2412_IISCON_RXDMA_ACTIVE (1 << 1)
52#define S3C2412_IISCON_IIS_ACTIVE (1 << 0)
53
54#define S5PC1XX_IISMOD_OPCLK_CDCLK_OUT (0 << 30)
55#define S5PC1XX_IISMOD_OPCLK_CDCLK_IN (1 << 30)
56#define S5PC1XX_IISMOD_OPCLK_BCLK_OUT (2 << 30)
57#define S5PC1XX_IISMOD_OPCLK_PCLK (3 << 30)
58#define S5PC1XX_IISMOD_OPCLK_MASK (3 << 30)
59#define S5PC1XX_IISMOD_TXS_IDMA (1 << 28) /* Sec_TXFIFO use I-DMA */
60#define S5PC1XX_IISMOD_BLCS_MASK 0x3
61#define S5PC1XX_IISMOD_BLCS_SHIFT 26
62#define S5PC1XX_IISMOD_BLCP_MASK 0x3
63#define S5PC1XX_IISMOD_BLCP_SHIFT 24
64
65#define S3C64XX_IISMOD_C2DD_HHALF (1 << 21) /* Discard Higher-half */
66#define S3C64XX_IISMOD_C2DD_LHALF (1 << 20) /* Discard Lower-half */
67#define S3C64XX_IISMOD_C1DD_HHALF (1 << 19)
68#define S3C64XX_IISMOD_C1DD_LHALF (1 << 18)
69#define S3C64XX_IISMOD_DC2_EN (1 << 17)
70#define S3C64XX_IISMOD_DC1_EN (1 << 16)
71#define S3C64XX_IISMOD_BLC_16BIT (0 << 13)
72#define S3C64XX_IISMOD_BLC_8BIT (1 << 13)
73#define S3C64XX_IISMOD_BLC_24BIT (2 << 13)
74#define S3C64XX_IISMOD_BLC_MASK (3 << 13)
75
76#define S3C2412_IISMOD_IMS_SYSMUX (1 << 10)
77#define S3C2412_IISMOD_SLAVE (1 << 11)
78#define S3C2412_IISMOD_MODE_TXONLY (0 << 8)
79#define S3C2412_IISMOD_MODE_RXONLY (1 << 8)
80#define S3C2412_IISMOD_MODE_TXRX (2 << 8)
81#define S3C2412_IISMOD_MODE_MASK (3 << 8)
82#define S3C2412_IISMOD_LR_LLOW (0 << 7)
83#define S3C2412_IISMOD_LR_RLOW (1 << 7)
84#define S3C2412_IISMOD_SDF_IIS (0 << 5)
85#define S3C2412_IISMOD_SDF_MSB (1 << 5)
86#define S3C2412_IISMOD_SDF_LSB (2 << 5)
87#define S3C2412_IISMOD_SDF_MASK (3 << 5)
88#define S3C2412_IISMOD_RCLK_256FS (0 << 3)
89#define S3C2412_IISMOD_RCLK_512FS (1 << 3)
90#define S3C2412_IISMOD_RCLK_384FS (2 << 3)
91#define S3C2412_IISMOD_RCLK_768FS (3 << 3)
92#define S3C2412_IISMOD_RCLK_MASK (3 << 3)
93#define S3C2412_IISMOD_BCLK_32FS (0 << 1)
94#define S3C2412_IISMOD_BCLK_48FS (1 << 1)
95#define S3C2412_IISMOD_BCLK_16FS (2 << 1)
96#define S3C2412_IISMOD_BCLK_24FS (3 << 1)
97#define S3C2412_IISMOD_BCLK_MASK (3 << 1)
98#define S3C2412_IISMOD_8BIT (1 << 0)
99
100#define S3C64XX_IISMOD_CDCLKCON (1 << 12)
101
102#define S3C2412_IISPSR_PSREN (1 << 15)
103
104#define S3C64XX_IISFIC_TX2COUNT(x) (((x) >> 24) & 0xf)
105#define S3C64XX_IISFIC_TX1COUNT(x) (((x) >> 16) & 0xf)
106
107#define S3C2412_IISFIC_TXFLUSH (1 << 15)
108#define S3C2412_IISFIC_RXFLUSH (1 << 7)
109#define S3C2412_IISFIC_TXCOUNT(x) (((x) >> 8) & 0xf)
110#define S3C2412_IISFIC_RXCOUNT(x) (((x) >> 0) & 0xf)
111
112#define S5PC1XX_IISFICS_TXFLUSH (1 << 15)
113#define S5PC1XX_IISFICS_TXCOUNT(x) (((x) >> 8) & 0x7f)
114
115#endif /* __ASM_ARCH_REGS_S3C2412_IIS_H */
diff --git a/sound/soc/s3c24xx/rx1950_uda1380.c b/sound/soc/s3c24xx/rx1950_uda1380.c
deleted file mode 100644
index 468cc11fdf47..000000000000
--- a/sound/soc/s3c24xx/rx1950_uda1380.c
+++ /dev/null
@@ -1,319 +0,0 @@
1/*
2 * rx1950.c -- ALSA Soc Audio Layer
3 *
4 * Copyright (c) 2010 Vasily Khoruzhick <anarsoul@gmail.com>
5 *
6 * Based on smdk2440.c and magician.c
7 *
8 * Authors: Graeme Gregory graeme.gregory@wolfsonmicro.com
9 * Philipp Zabel <philipp.zabel@gmail.com>
10 * Denis Grigoriev <dgreenday@gmail.com>
11 * Vasily Khoruzhick <anarsoul@gmail.com>
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version.
17 *
18 */
19
20#include <linux/module.h>
21#include <linux/moduleparam.h>
22#include <linux/platform_device.h>
23#include <linux/i2c.h>
24#include <linux/gpio.h>
25#include <linux/clk.h>
26
27#include <sound/soc.h>
28#include <sound/soc-dapm.h>
29#include <sound/uda1380.h>
30#include <sound/jack.h>
31
32#include <plat/regs-iis.h>
33
34#include <mach/regs-clock.h>
35
36#include <asm/mach-types.h>
37
38#include "s3c-dma.h"
39#include "s3c24xx-i2s.h"
40#include "../codecs/uda1380.h"
41
42static int rx1950_uda1380_init(struct snd_soc_pcm_runtime *rtd);
43static int rx1950_startup(struct snd_pcm_substream *substream);
44static int rx1950_hw_params(struct snd_pcm_substream *substream,
45 struct snd_pcm_hw_params *params);
46static int rx1950_spk_power(struct snd_soc_dapm_widget *w,
47 struct snd_kcontrol *kcontrol, int event);
48
49static unsigned int rates[] = {
50 16000,
51 44100,
52 48000,
53};
54
55static struct snd_pcm_hw_constraint_list hw_rates = {
56 .count = ARRAY_SIZE(rates),
57 .list = rates,
58 .mask = 0,
59};
60
61static struct snd_soc_jack hp_jack;
62
63static struct snd_soc_jack_pin hp_jack_pins[] = {
64 {
65 .pin = "Headphone Jack",
66 .mask = SND_JACK_HEADPHONE,
67 },
68 {
69 .pin = "Speaker",
70 .mask = SND_JACK_HEADPHONE,
71 .invert = 1,
72 },
73};
74
75static struct snd_soc_jack_gpio hp_jack_gpios[] = {
76 [0] = {
77 .gpio = S3C2410_GPG(12),
78 .name = "hp-gpio",
79 .report = SND_JACK_HEADPHONE,
80 .invert = 1,
81 .debounce_time = 200,
82 },
83};
84
85static struct snd_soc_ops rx1950_ops = {
86 .startup = rx1950_startup,
87 .hw_params = rx1950_hw_params,
88};
89
90/* s3c24xx digital audio interface glue - connects codec <--> CPU */
91static struct snd_soc_dai_link rx1950_uda1380_dai[] = {
92 {
93 .name = "uda1380",
94 .stream_name = "UDA1380 Duplex",
95 .cpu_dai_name = "s3c24xx-iis",
96 .codec_dai_name = "uda1380-hifi",
97 .init = rx1950_uda1380_init,
98 .platform_name = "s3c24xx-pcm-audio",
99 .codec_name = "uda1380-codec.0-001a",
100 .ops = &rx1950_ops,
101 },
102};
103
104static struct snd_soc_card rx1950_asoc = {
105 .name = "rx1950",
106 .dai_link = rx1950_uda1380_dai,
107 .num_links = ARRAY_SIZE(rx1950_uda1380_dai),
108};
109
110/* rx1950 machine dapm widgets */
111static const struct snd_soc_dapm_widget uda1380_dapm_widgets[] = {
112 SND_SOC_DAPM_HP("Headphone Jack", NULL),
113 SND_SOC_DAPM_MIC("Mic Jack", NULL),
114 SND_SOC_DAPM_SPK("Speaker", rx1950_spk_power),
115};
116
117/* rx1950 machine audio_map */
118static const struct snd_soc_dapm_route audio_map[] = {
119 /* headphone connected to VOUTLHP, VOUTRHP */
120 {"Headphone Jack", NULL, "VOUTLHP"},
121 {"Headphone Jack", NULL, "VOUTRHP"},
122
123 /* ext speaker connected to VOUTL, VOUTR */
124 {"Speaker", NULL, "VOUTL"},
125 {"Speaker", NULL, "VOUTR"},
126
127 /* mic is connected to VINM */
128 {"VINM", NULL, "Mic Jack"},
129};
130
131static struct platform_device *s3c24xx_snd_device;
132
133static int rx1950_startup(struct snd_pcm_substream *substream)
134{
135 struct snd_pcm_runtime *runtime = substream->runtime;
136
137 runtime->hw.rate_min = hw_rates.list[0];
138 runtime->hw.rate_max = hw_rates.list[hw_rates.count - 1];
139 runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
140
141 return snd_pcm_hw_constraint_list(runtime, 0,
142 SNDRV_PCM_HW_PARAM_RATE,
143 &hw_rates);
144}
145
146static int rx1950_spk_power(struct snd_soc_dapm_widget *w,
147 struct snd_kcontrol *kcontrol, int event)
148{
149 if (SND_SOC_DAPM_EVENT_ON(event))
150 gpio_set_value(S3C2410_GPA(1), 1);
151 else
152 gpio_set_value(S3C2410_GPA(1), 0);
153
154 return 0;
155}
156
157static int rx1950_hw_params(struct snd_pcm_substream *substream,
158 struct snd_pcm_hw_params *params)
159{
160 struct snd_soc_pcm_runtime *rtd = substream->private_data;
161 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
162 struct snd_soc_dai *codec_dai = rtd->codec_dai;
163 int div;
164 int ret;
165 unsigned int rate = params_rate(params);
166 int clk_source, fs_mode;
167
168 switch (rate) {
169 case 16000:
170 case 48000:
171 clk_source = S3C24XX_CLKSRC_PCLK;
172 fs_mode = S3C2410_IISMOD_256FS;
173 div = s3c24xx_i2s_get_clockrate() / (256 * rate);
174 if (s3c24xx_i2s_get_clockrate() % (256 * rate) > (128 * rate))
175 div++;
176 break;
177 case 44100:
178 case 88200:
179 clk_source = S3C24XX_CLKSRC_MPLL;
180 fs_mode = S3C2410_IISMOD_384FS;
181 div = 1;
182 break;
183 default:
184 printk(KERN_ERR "%s: rate %d is not supported\n",
185 __func__, rate);
186 return -EINVAL;
187 }
188
189 /* set codec DAI configuration */
190 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
191 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
192 if (ret < 0)
193 return ret;
194
195 /* set cpu DAI configuration */
196 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
197 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
198 if (ret < 0)
199 return ret;
200
201 /* select clock source */
202 ret = snd_soc_dai_set_sysclk(cpu_dai, clk_source, rate,
203 SND_SOC_CLOCK_OUT);
204 if (ret < 0)
205 return ret;
206
207 /* set MCLK division for sample rate */
208 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK,
209 fs_mode);
210 if (ret < 0)
211 return ret;
212
213 /* set BCLK division for sample rate */
214 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_BCLK,
215 S3C2410_IISMOD_32FS);
216 if (ret < 0)
217 return ret;
218
219 /* set prescaler division for sample rate */
220 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
221 S3C24XX_PRESCALE(div, div));
222 if (ret < 0)
223 return ret;
224
225 return 0;
226}
227
228static int rx1950_uda1380_init(struct snd_soc_pcm_runtime *rtd)
229{
230 struct snd_soc_codec *codec = rtd->codec;
231 int err;
232
233 /* Add rx1950 specific widgets */
234 err = snd_soc_dapm_new_controls(codec, uda1380_dapm_widgets,
235 ARRAY_SIZE(uda1380_dapm_widgets));
236
237 if (err)
238 return err;
239
240 /* Set up rx1950 specific audio path audio_mapnects */
241 err = snd_soc_dapm_add_routes(codec, audio_map,
242 ARRAY_SIZE(audio_map));
243
244 if (err)
245 return err;
246
247 snd_soc_dapm_enable_pin(codec, "Headphone Jack");
248 snd_soc_dapm_enable_pin(codec, "Speaker");
249
250 snd_soc_dapm_sync(codec);
251
252 snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE,
253 &hp_jack);
254
255 snd_soc_jack_add_pins(&hp_jack, ARRAY_SIZE(hp_jack_pins),
256 hp_jack_pins);
257
258 snd_soc_jack_add_gpios(&hp_jack, ARRAY_SIZE(hp_jack_gpios),
259 hp_jack_gpios);
260
261 return 0;
262}
263
264static int __init rx1950_init(void)
265{
266 int ret;
267
268 if (!machine_is_rx1950())
269 return -ENODEV;
270
271 /* configure some gpios */
272 ret = gpio_request(S3C2410_GPA(1), "speaker-power");
273 if (ret)
274 goto err_gpio;
275
276 ret = gpio_direction_output(S3C2410_GPA(1), 0);
277 if (ret)
278 goto err_gpio_conf;
279
280 s3c24xx_snd_device = platform_device_alloc("soc-audio", -1);
281 if (!s3c24xx_snd_device) {
282 ret = -ENOMEM;
283 goto err_plat_alloc;
284 }
285
286 platform_set_drvdata(s3c24xx_snd_device, &rx1950_asoc);
287 ret = platform_device_add(s3c24xx_snd_device);
288
289 if (ret) {
290 platform_device_put(s3c24xx_snd_device);
291 goto err_plat_add;
292 }
293
294 return 0;
295
296err_plat_add:
297err_plat_alloc:
298err_gpio_conf:
299 gpio_free(S3C2410_GPA(1));
300
301err_gpio:
302 return ret;
303}
304
305static void __exit rx1950_exit(void)
306{
307 platform_device_unregister(s3c24xx_snd_device);
308 snd_soc_jack_free_gpios(&hp_jack, ARRAY_SIZE(hp_jack_gpios),
309 hp_jack_gpios);
310 gpio_free(S3C2410_GPA(1));
311}
312
313module_init(rx1950_init);
314module_exit(rx1950_exit);
315
316/* Module information */
317MODULE_AUTHOR("Vasily Khoruzhick");
318MODULE_DESCRIPTION("ALSA SoC RX1950");
319MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/s3c-ac97.c b/sound/soc/s3c24xx/s3c-ac97.c
deleted file mode 100644
index f891eb79b575..000000000000
--- a/sound/soc/s3c24xx/s3c-ac97.c
+++ /dev/null
@@ -1,520 +0,0 @@
1/* sound/soc/s3c24xx/s3c-ac97.c
2 *
3 * ALSA SoC Audio Layer - S3C AC97 Controller driver
4 * Evolved from s3c2443-ac97.c
5 *
6 * Copyright (c) 2010 Samsung Electronics Co. Ltd
7 * Author: Jaswinder Singh <jassi.brar@samsung.com>
8 * Credits: Graeme Gregory, Sean Choi
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/init.h>
16#include <linux/module.h>
17#include <linux/io.h>
18#include <linux/delay.h>
19#include <linux/clk.h>
20
21#include <sound/soc.h>
22
23#include <plat/regs-ac97.h>
24#include <mach/dma.h>
25#include <plat/audio.h>
26
27#include "s3c-dma.h"
28#include "s3c-ac97.h"
29
30#define AC_CMD_ADDR(x) (x << 16)
31#define AC_CMD_DATA(x) (x & 0xffff)
32
33struct s3c_ac97_info {
34 struct clk *ac97_clk;
35 void __iomem *regs;
36 struct mutex lock;
37 struct completion done;
38};
39static struct s3c_ac97_info s3c_ac97;
40
41static struct s3c2410_dma_client s3c_dma_client_out = {
42 .name = "AC97 PCMOut"
43};
44
45static struct s3c2410_dma_client s3c_dma_client_in = {
46 .name = "AC97 PCMIn"
47};
48
49static struct s3c2410_dma_client s3c_dma_client_micin = {
50 .name = "AC97 MicIn"
51};
52
53static struct s3c_dma_params s3c_ac97_pcm_out = {
54 .client = &s3c_dma_client_out,
55 .dma_size = 4,
56};
57
58static struct s3c_dma_params s3c_ac97_pcm_in = {
59 .client = &s3c_dma_client_in,
60 .dma_size = 4,
61};
62
63static struct s3c_dma_params s3c_ac97_mic_in = {
64 .client = &s3c_dma_client_micin,
65 .dma_size = 4,
66};
67
68static void s3c_ac97_activate(struct snd_ac97 *ac97)
69{
70 u32 ac_glbctrl, stat;
71
72 stat = readl(s3c_ac97.regs + S3C_AC97_GLBSTAT) & 0x7;
73 if (stat == S3C_AC97_GLBSTAT_MAINSTATE_ACTIVE)
74 return; /* Return if already active */
75
76 INIT_COMPLETION(s3c_ac97.done);
77
78 ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL);
79 ac_glbctrl = S3C_AC97_GLBCTRL_ACLINKON;
80 writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
81 msleep(1);
82
83 ac_glbctrl |= S3C_AC97_GLBCTRL_TRANSFERDATAENABLE;
84 writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
85 msleep(1);
86
87 ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL);
88 ac_glbctrl |= S3C_AC97_GLBCTRL_CODECREADYIE;
89 writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
90
91 if (!wait_for_completion_timeout(&s3c_ac97.done, HZ))
92 pr_err("AC97: Unable to activate!");
93}
94
95static unsigned short s3c_ac97_read(struct snd_ac97 *ac97,
96 unsigned short reg)
97{
98 u32 ac_glbctrl, ac_codec_cmd;
99 u32 stat, addr, data;
100
101 mutex_lock(&s3c_ac97.lock);
102
103 s3c_ac97_activate(ac97);
104
105 INIT_COMPLETION(s3c_ac97.done);
106
107 ac_codec_cmd = readl(s3c_ac97.regs + S3C_AC97_CODEC_CMD);
108 ac_codec_cmd = S3C_AC97_CODEC_CMD_READ | AC_CMD_ADDR(reg);
109 writel(ac_codec_cmd, s3c_ac97.regs + S3C_AC97_CODEC_CMD);
110
111 udelay(50);
112
113 ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL);
114 ac_glbctrl |= S3C_AC97_GLBCTRL_CODECREADYIE;
115 writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
116
117 if (!wait_for_completion_timeout(&s3c_ac97.done, HZ))
118 pr_err("AC97: Unable to read!");
119
120 stat = readl(s3c_ac97.regs + S3C_AC97_STAT);
121 addr = (stat >> 16) & 0x7f;
122 data = (stat & 0xffff);
123
124 if (addr != reg)
125 pr_err("s3c-ac97: req addr = %02x, rep addr = %02x\n",
126 reg, addr);
127
128 mutex_unlock(&s3c_ac97.lock);
129
130 return (unsigned short)data;
131}
132
133static void s3c_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
134 unsigned short val)
135{
136 u32 ac_glbctrl, ac_codec_cmd;
137
138 mutex_lock(&s3c_ac97.lock);
139
140 s3c_ac97_activate(ac97);
141
142 INIT_COMPLETION(s3c_ac97.done);
143
144 ac_codec_cmd = readl(s3c_ac97.regs + S3C_AC97_CODEC_CMD);
145 ac_codec_cmd = AC_CMD_ADDR(reg) | AC_CMD_DATA(val);
146 writel(ac_codec_cmd, s3c_ac97.regs + S3C_AC97_CODEC_CMD);
147
148 udelay(50);
149
150 ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL);
151 ac_glbctrl |= S3C_AC97_GLBCTRL_CODECREADYIE;
152 writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
153
154 if (!wait_for_completion_timeout(&s3c_ac97.done, HZ))
155 pr_err("AC97: Unable to write!");
156
157 ac_codec_cmd = readl(s3c_ac97.regs + S3C_AC97_CODEC_CMD);
158 ac_codec_cmd |= S3C_AC97_CODEC_CMD_READ;
159 writel(ac_codec_cmd, s3c_ac97.regs + S3C_AC97_CODEC_CMD);
160
161 mutex_unlock(&s3c_ac97.lock);
162}
163
164static void s3c_ac97_cold_reset(struct snd_ac97 *ac97)
165{
166 pr_debug("AC97: Cold reset\n");
167 writel(S3C_AC97_GLBCTRL_COLDRESET,
168 s3c_ac97.regs + S3C_AC97_GLBCTRL);
169 msleep(1);
170
171 writel(0, s3c_ac97.regs + S3C_AC97_GLBCTRL);
172 msleep(1);
173}
174
175static void s3c_ac97_warm_reset(struct snd_ac97 *ac97)
176{
177 u32 stat;
178
179 stat = readl(s3c_ac97.regs + S3C_AC97_GLBSTAT) & 0x7;
180 if (stat == S3C_AC97_GLBSTAT_MAINSTATE_ACTIVE)
181 return; /* Return if already active */
182
183 pr_debug("AC97: Warm reset\n");
184
185 writel(S3C_AC97_GLBCTRL_WARMRESET, s3c_ac97.regs + S3C_AC97_GLBCTRL);
186 msleep(1);
187
188 writel(0, s3c_ac97.regs + S3C_AC97_GLBCTRL);
189 msleep(1);
190
191 s3c_ac97_activate(ac97);
192}
193
194static irqreturn_t s3c_ac97_irq(int irq, void *dev_id)
195{
196 u32 ac_glbctrl, ac_glbstat;
197
198 ac_glbstat = readl(s3c_ac97.regs + S3C_AC97_GLBSTAT);
199
200 if (ac_glbstat & S3C_AC97_GLBSTAT_CODECREADY) {
201
202 ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL);
203 ac_glbctrl &= ~S3C_AC97_GLBCTRL_CODECREADYIE;
204 writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
205
206 complete(&s3c_ac97.done);
207 }
208
209 ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL);
210 ac_glbctrl |= (1<<30); /* Clear interrupt */
211 writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
212
213 return IRQ_HANDLED;
214}
215
216struct snd_ac97_bus_ops soc_ac97_ops = {
217 .read = s3c_ac97_read,
218 .write = s3c_ac97_write,
219 .warm_reset = s3c_ac97_warm_reset,
220 .reset = s3c_ac97_cold_reset,
221};
222EXPORT_SYMBOL_GPL(soc_ac97_ops);
223
224static int s3c_ac97_hw_params(struct snd_pcm_substream *substream,
225 struct snd_pcm_hw_params *params,
226 struct snd_soc_dai *dai)
227{
228 struct snd_soc_pcm_runtime *rtd = substream->private_data;
229 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
230 struct s3c_dma_params *dma_data;
231
232 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
233 dma_data = &s3c_ac97_pcm_out;
234 else
235 dma_data = &s3c_ac97_pcm_in;
236
237 snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
238
239 return 0;
240}
241
242static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
243 struct snd_soc_dai *dai)
244{
245 u32 ac_glbctrl;
246 struct snd_soc_pcm_runtime *rtd = substream->private_data;
247 struct s3c_dma_params *dma_data =
248 snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
249
250 ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL);
251 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
252 ac_glbctrl &= ~S3C_AC97_GLBCTRL_PCMINTM_MASK;
253 else
254 ac_glbctrl &= ~S3C_AC97_GLBCTRL_PCMOUTTM_MASK;
255
256 switch (cmd) {
257 case SNDRV_PCM_TRIGGER_START:
258 case SNDRV_PCM_TRIGGER_RESUME:
259 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
260 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
261 ac_glbctrl |= S3C_AC97_GLBCTRL_PCMINTM_DMA;
262 else
263 ac_glbctrl |= S3C_AC97_GLBCTRL_PCMOUTTM_DMA;
264 break;
265
266 case SNDRV_PCM_TRIGGER_STOP:
267 case SNDRV_PCM_TRIGGER_SUSPEND:
268 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
269 break;
270 }
271
272 writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
273
274 s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED);
275
276 return 0;
277}
278
279static int s3c_ac97_hw_mic_params(struct snd_pcm_substream *substream,
280 struct snd_pcm_hw_params *params,
281 struct snd_soc_dai *dai)
282{
283 struct snd_soc_pcm_runtime *rtd = substream->private_data;
284 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
285
286 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
287 return -ENODEV;
288 else
289 snd_soc_dai_set_dma_data(cpu_dai, substream, &s3c_ac97_mic_in);
290
291 return 0;
292}
293
294static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream,
295 int cmd, struct snd_soc_dai *dai)
296{
297 u32 ac_glbctrl;
298 struct snd_soc_pcm_runtime *rtd = substream->private_data;
299 struct s3c_dma_params *dma_data =
300 snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
301
302 ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL);
303 ac_glbctrl &= ~S3C_AC97_GLBCTRL_MICINTM_MASK;
304
305 switch (cmd) {
306 case SNDRV_PCM_TRIGGER_START:
307 case SNDRV_PCM_TRIGGER_RESUME:
308 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
309 ac_glbctrl |= S3C_AC97_GLBCTRL_MICINTM_DMA;
310 break;
311
312 case SNDRV_PCM_TRIGGER_STOP:
313 case SNDRV_PCM_TRIGGER_SUSPEND:
314 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
315 break;
316 }
317
318 writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
319
320 s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED);
321
322 return 0;
323}
324
325static struct snd_soc_dai_ops s3c_ac97_dai_ops = {
326 .hw_params = s3c_ac97_hw_params,
327 .trigger = s3c_ac97_trigger,
328};
329
330static struct snd_soc_dai_ops s3c_ac97_mic_dai_ops = {
331 .hw_params = s3c_ac97_hw_mic_params,
332 .trigger = s3c_ac97_mic_trigger,
333};
334
335static struct snd_soc_dai_driver s3c_ac97_dai[] = {
336 [S3C_AC97_DAI_PCM] = {
337 .name = "s3c-ac97",
338 .ac97_control = 1,
339 .playback = {
340 .stream_name = "AC97 Playback",
341 .channels_min = 2,
342 .channels_max = 2,
343 .rates = SNDRV_PCM_RATE_8000_48000,
344 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
345 .capture = {
346 .stream_name = "AC97 Capture",
347 .channels_min = 2,
348 .channels_max = 2,
349 .rates = SNDRV_PCM_RATE_8000_48000,
350 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
351 .ops = &s3c_ac97_dai_ops,
352 },
353 [S3C_AC97_DAI_MIC] = {
354 .name = "s3c-ac97-mic",
355 .ac97_control = 1,
356 .capture = {
357 .stream_name = "AC97 Mic Capture",
358 .channels_min = 1,
359 .channels_max = 1,
360 .rates = SNDRV_PCM_RATE_8000_48000,
361 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
362 .ops = &s3c_ac97_mic_dai_ops,
363 },
364};
365
366static __devinit int s3c_ac97_probe(struct platform_device *pdev)
367{
368 struct resource *mem_res, *dmatx_res, *dmarx_res, *dmamic_res, *irq_res;
369 struct s3c_audio_pdata *ac97_pdata;
370 int ret;
371
372 ac97_pdata = pdev->dev.platform_data;
373 if (!ac97_pdata || !ac97_pdata->cfg_gpio) {
374 dev_err(&pdev->dev, "cfg_gpio callback not provided!\n");
375 return -EINVAL;
376 }
377
378 /* Check for availability of necessary resource */
379 dmatx_res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
380 if (!dmatx_res) {
381 dev_err(&pdev->dev, "Unable to get AC97-TX dma resource\n");
382 return -ENXIO;
383 }
384
385 dmarx_res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
386 if (!dmarx_res) {
387 dev_err(&pdev->dev, "Unable to get AC97-RX dma resource\n");
388 return -ENXIO;
389 }
390
391 dmamic_res = platform_get_resource(pdev, IORESOURCE_DMA, 2);
392 if (!dmamic_res) {
393 dev_err(&pdev->dev, "Unable to get AC97-MIC dma resource\n");
394 return -ENXIO;
395 }
396
397 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
398 if (!mem_res) {
399 dev_err(&pdev->dev, "Unable to get register resource\n");
400 return -ENXIO;
401 }
402
403 irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
404 if (!irq_res) {
405 dev_err(&pdev->dev, "AC97 IRQ not provided!\n");
406 return -ENXIO;
407 }
408
409 if (!request_mem_region(mem_res->start,
410 resource_size(mem_res), "s3c-ac97")) {
411 dev_err(&pdev->dev, "Unable to request register region\n");
412 return -EBUSY;
413 }
414
415 s3c_ac97_pcm_out.channel = dmatx_res->start;
416 s3c_ac97_pcm_out.dma_addr = mem_res->start + S3C_AC97_PCM_DATA;
417 s3c_ac97_pcm_in.channel = dmarx_res->start;
418 s3c_ac97_pcm_in.dma_addr = mem_res->start + S3C_AC97_PCM_DATA;
419 s3c_ac97_mic_in.channel = dmamic_res->start;
420 s3c_ac97_mic_in.dma_addr = mem_res->start + S3C_AC97_MIC_DATA;
421
422 init_completion(&s3c_ac97.done);
423 mutex_init(&s3c_ac97.lock);
424
425 s3c_ac97.regs = ioremap(mem_res->start, resource_size(mem_res));
426 if (s3c_ac97.regs == NULL) {
427 dev_err(&pdev->dev, "Unable to ioremap register region\n");
428 ret = -ENXIO;
429 goto err1;
430 }
431
432 s3c_ac97.ac97_clk = clk_get(&pdev->dev, "ac97");
433 if (IS_ERR(s3c_ac97.ac97_clk)) {
434 dev_err(&pdev->dev, "s3c-ac97 failed to get ac97_clock\n");
435 ret = -ENODEV;
436 goto err2;
437 }
438 clk_enable(s3c_ac97.ac97_clk);
439
440 if (ac97_pdata->cfg_gpio(pdev)) {
441 dev_err(&pdev->dev, "Unable to configure gpio\n");
442 ret = -EINVAL;
443 goto err3;
444 }
445
446 ret = request_irq(irq_res->start, s3c_ac97_irq,
447 IRQF_DISABLED, "AC97", NULL);
448 if (ret < 0) {
449 dev_err(&pdev->dev, "s3c-ac97: interrupt request failed.\n");
450 goto err4;
451 }
452
453 ret = snd_soc_register_dais(&pdev->dev, s3c_ac97_dai,
454 ARRAY_SIZE(s3c_ac97_dai));
455 if (ret)
456 goto err5;
457
458 return 0;
459
460err5:
461 free_irq(irq_res->start, NULL);
462err4:
463err3:
464 clk_disable(s3c_ac97.ac97_clk);
465 clk_put(s3c_ac97.ac97_clk);
466err2:
467 iounmap(s3c_ac97.regs);
468err1:
469 release_mem_region(mem_res->start, resource_size(mem_res));
470
471 return ret;
472}
473
474static __devexit int s3c_ac97_remove(struct platform_device *pdev)
475{
476 struct resource *mem_res, *irq_res;
477
478 snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(s3c_ac97_dai));
479
480 irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
481 if (irq_res)
482 free_irq(irq_res->start, NULL);
483
484 clk_disable(s3c_ac97.ac97_clk);
485 clk_put(s3c_ac97.ac97_clk);
486
487 iounmap(s3c_ac97.regs);
488
489 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
490 if (mem_res)
491 release_mem_region(mem_res->start, resource_size(mem_res));
492
493 return 0;
494}
495
496static struct platform_driver s3c_ac97_driver = {
497 .probe = s3c_ac97_probe,
498 .remove = s3c_ac97_remove,
499 .driver = {
500 .name = "s3c-ac97",
501 .owner = THIS_MODULE,
502 },
503};
504
505static int __init s3c_ac97_init(void)
506{
507 return platform_driver_register(&s3c_ac97_driver);
508}
509module_init(s3c_ac97_init);
510
511static void __exit s3c_ac97_exit(void)
512{
513 platform_driver_unregister(&s3c_ac97_driver);
514}
515module_exit(s3c_ac97_exit);
516
517MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");
518MODULE_DESCRIPTION("AC97 driver for the Samsung SoC");
519MODULE_LICENSE("GPL");
520MODULE_ALIAS("platform:s3c-ac97");
diff --git a/sound/soc/s3c24xx/s3c-ac97.h b/sound/soc/s3c24xx/s3c-ac97.h
deleted file mode 100644
index 5dcedd07fdbb..000000000000
--- a/sound/soc/s3c24xx/s3c-ac97.h
+++ /dev/null
@@ -1,21 +0,0 @@
1/* sound/soc/s3c24xx/s3c-ac97.h
2 *
3 * ALSA SoC Audio Layer - S3C AC97 Controller driver
4 * Evolved from s3c2443-ac97.h
5 *
6 * Copyright (c) 2010 Samsung Electronics Co. Ltd
7 * Author: Jaswinder Singh <jassi.brar@samsung.com>
8 * Credits: Graeme Gregory, Sean Choi
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#ifndef __S3C_AC97_H_
16#define __S3C_AC97_H_
17
18#define S3C_AC97_DAI_PCM 0
19#define S3C_AC97_DAI_MIC 1
20
21#endif /* __S3C_AC97_H_ */
diff --git a/sound/soc/s3c24xx/s3c-dma.c b/sound/soc/s3c24xx/s3c-dma.c
deleted file mode 100644
index 243f79bf43bb..000000000000
--- a/sound/soc/s3c24xx/s3c-dma.c
+++ /dev/null
@@ -1,502 +0,0 @@
1/*
2 * s3c-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/module.h>
18#include <linux/init.h>
19#include <linux/io.h>
20#include <linux/platform_device.h>
21#include <linux/slab.h>
22#include <linux/dma-mapping.h>
23
24#include <sound/core.h>
25#include <sound/pcm.h>
26#include <sound/pcm_params.h>
27#include <sound/soc.h>
28
29#include <asm/dma.h>
30#include <mach/hardware.h>
31#include <mach/dma.h>
32
33#include "s3c-dma.h"
34
35static const struct snd_pcm_hardware s3c_dma_hardware = {
36 .info = SNDRV_PCM_INFO_INTERLEAVED |
37 SNDRV_PCM_INFO_BLOCK_TRANSFER |
38 SNDRV_PCM_INFO_MMAP |
39 SNDRV_PCM_INFO_MMAP_VALID |
40 SNDRV_PCM_INFO_PAUSE |
41 SNDRV_PCM_INFO_RESUME,
42 .formats = SNDRV_PCM_FMTBIT_S16_LE |
43 SNDRV_PCM_FMTBIT_U16_LE |
44 SNDRV_PCM_FMTBIT_U8 |
45 SNDRV_PCM_FMTBIT_S8,
46 .channels_min = 2,
47 .channels_max = 2,
48 .buffer_bytes_max = 128*1024,
49 .period_bytes_min = PAGE_SIZE,
50 .period_bytes_max = PAGE_SIZE*2,
51 .periods_min = 2,
52 .periods_max = 128,
53 .fifo_size = 32,
54};
55
56struct s3c24xx_runtime_data {
57 spinlock_t lock;
58 int state;
59 unsigned int dma_loaded;
60 unsigned int dma_limit;
61 unsigned int dma_period;
62 dma_addr_t dma_start;
63 dma_addr_t dma_pos;
64 dma_addr_t dma_end;
65 struct s3c_dma_params *params;
66};
67
68/* s3c_dma_enqueue
69 *
70 * place a dma buffer onto the queue for the dma system
71 * to handle.
72*/
73static void s3c_dma_enqueue(struct snd_pcm_substream *substream)
74{
75 struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
76 dma_addr_t pos = prtd->dma_pos;
77 unsigned int limit;
78 int ret;
79
80 pr_debug("Entered %s\n", __func__);
81
82 if (s3c_dma_has_circular())
83 limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period;
84 else
85 limit = prtd->dma_limit;
86
87 pr_debug("%s: loaded %d, limit %d\n",
88 __func__, prtd->dma_loaded, limit);
89
90 while (prtd->dma_loaded < limit) {
91 unsigned long len = prtd->dma_period;
92
93 pr_debug("dma_loaded: %d\n", prtd->dma_loaded);
94
95 if ((pos + len) > prtd->dma_end) {
96 len = prtd->dma_end - pos;
97 pr_debug("%s: corrected dma len %ld\n", __func__, len);
98 }
99
100 ret = s3c2410_dma_enqueue(prtd->params->channel,
101 substream, pos, len);
102
103 if (ret == 0) {
104 prtd->dma_loaded++;
105 pos += prtd->dma_period;
106 if (pos >= prtd->dma_end)
107 pos = prtd->dma_start;
108 } else
109 break;
110 }
111
112 prtd->dma_pos = pos;
113}
114
115static void s3c24xx_audio_buffdone(struct s3c2410_dma_chan *channel,
116 void *dev_id, int size,
117 enum s3c2410_dma_buffresult result)
118{
119 struct snd_pcm_substream *substream = dev_id;
120 struct s3c24xx_runtime_data *prtd;
121
122 pr_debug("Entered %s\n", __func__);
123
124 if (result == S3C2410_RES_ABORT || result == S3C2410_RES_ERR)
125 return;
126
127 prtd = substream->runtime->private_data;
128
129 if (substream)
130 snd_pcm_period_elapsed(substream);
131
132 spin_lock(&prtd->lock);
133 if (prtd->state & ST_RUNNING && !s3c_dma_has_circular()) {
134 prtd->dma_loaded--;
135 s3c_dma_enqueue(substream);
136 }
137
138 spin_unlock(&prtd->lock);
139}
140
141static int s3c_dma_hw_params(struct snd_pcm_substream *substream,
142 struct snd_pcm_hw_params *params)
143{
144 struct snd_pcm_runtime *runtime = substream->runtime;
145 struct s3c24xx_runtime_data *prtd = runtime->private_data;
146 struct snd_soc_pcm_runtime *rtd = substream->private_data;
147 unsigned long totbytes = params_buffer_bytes(params);
148 struct s3c_dma_params *dma =
149 snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
150 int ret = 0;
151
152
153 pr_debug("Entered %s\n", __func__);
154
155 /* return if this is a bufferless transfer e.g.
156 * codec <--> BT codec or GSM modem -- lg FIXME */
157 if (!dma)
158 return 0;
159
160 /* this may get called several times by oss emulation
161 * with different params -HW */
162 if (prtd->params == NULL) {
163 /* prepare DMA */
164 prtd->params = dma;
165
166 pr_debug("params %p, client %p, channel %d\n", prtd->params,
167 prtd->params->client, prtd->params->channel);
168
169 ret = s3c2410_dma_request(prtd->params->channel,
170 prtd->params->client, NULL);
171
172 if (ret < 0) {
173 printk(KERN_ERR "failed to get dma channel\n");
174 return ret;
175 }
176
177 /* use the circular buffering if we have it available. */
178 if (s3c_dma_has_circular())
179 s3c2410_dma_setflags(prtd->params->channel,
180 S3C2410_DMAF_CIRCULAR);
181 }
182
183 s3c2410_dma_set_buffdone_fn(prtd->params->channel,
184 s3c24xx_audio_buffdone);
185
186 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
187
188 runtime->dma_bytes = totbytes;
189
190 spin_lock_irq(&prtd->lock);
191 prtd->dma_loaded = 0;
192 prtd->dma_limit = runtime->hw.periods_min;
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 s3c_dma_hw_free(struct snd_pcm_substream *substream)
203{
204 struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
205
206 pr_debug("Entered %s\n", __func__);
207
208 /* TODO - do we need to ensure DMA flushed */
209 snd_pcm_set_runtime_buffer(substream, NULL);
210
211 if (prtd->params) {
212 s3c2410_dma_free(prtd->params->channel, prtd->params->client);
213 prtd->params = NULL;
214 }
215
216 return 0;
217}
218
219static int s3c_dma_prepare(struct snd_pcm_substream *substream)
220{
221 struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
222 int ret = 0;
223
224 pr_debug("Entered %s\n", __func__);
225
226 /* return if this is a bufferless transfer e.g.
227 * codec <--> BT codec or GSM modem -- lg FIXME */
228 if (!prtd->params)
229 return 0;
230
231 /* channel needs configuring for mem=>device, increment memory addr,
232 * sync to pclk, half-word transfers to the IIS-FIFO. */
233 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
234 s3c2410_dma_devconfig(prtd->params->channel,
235 S3C2410_DMASRC_MEM,
236 prtd->params->dma_addr);
237 } else {
238 s3c2410_dma_devconfig(prtd->params->channel,
239 S3C2410_DMASRC_HW,
240 prtd->params->dma_addr);
241 }
242
243 s3c2410_dma_config(prtd->params->channel,
244 prtd->params->dma_size);
245
246 /* flush the DMA channel */
247 s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_FLUSH);
248 prtd->dma_loaded = 0;
249 prtd->dma_pos = prtd->dma_start;
250
251 /* enqueue dma buffers */
252 s3c_dma_enqueue(substream);
253
254 return ret;
255}
256
257static int s3c_dma_trigger(struct snd_pcm_substream *substream, int cmd)
258{
259 struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
260 int ret = 0;
261
262 pr_debug("Entered %s\n", __func__);
263
264 spin_lock(&prtd->lock);
265
266 switch (cmd) {
267 case SNDRV_PCM_TRIGGER_START:
268 case SNDRV_PCM_TRIGGER_RESUME:
269 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
270 prtd->state |= ST_RUNNING;
271 s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_START);
272 break;
273
274 case SNDRV_PCM_TRIGGER_STOP:
275 case SNDRV_PCM_TRIGGER_SUSPEND:
276 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
277 prtd->state &= ~ST_RUNNING;
278 s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_STOP);
279 break;
280
281 default:
282 ret = -EINVAL;
283 break;
284 }
285
286 spin_unlock(&prtd->lock);
287
288 return ret;
289}
290
291static snd_pcm_uframes_t
292s3c_dma_pointer(struct snd_pcm_substream *substream)
293{
294 struct snd_pcm_runtime *runtime = substream->runtime;
295 struct s3c24xx_runtime_data *prtd = runtime->private_data;
296 unsigned long res;
297 dma_addr_t src, dst;
298
299 pr_debug("Entered %s\n", __func__);
300
301 spin_lock(&prtd->lock);
302 s3c2410_dma_getposition(prtd->params->channel, &src, &dst);
303
304 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
305 res = dst - prtd->dma_start;
306 else
307 res = src - prtd->dma_start;
308
309 spin_unlock(&prtd->lock);
310
311 pr_debug("Pointer %x %x\n", src, dst);
312
313 /* we seem to be getting the odd error from the pcm library due
314 * to out-of-bounds pointers. this is maybe due to the dma engine
315 * not having loaded the new values for the channel before being
316 * callled... (todo - fix )
317 */
318
319 if (res >= snd_pcm_lib_buffer_bytes(substream)) {
320 if (res == snd_pcm_lib_buffer_bytes(substream))
321 res = 0;
322 }
323
324 return bytes_to_frames(substream->runtime, res);
325}
326
327static int s3c_dma_open(struct snd_pcm_substream *substream)
328{
329 struct snd_pcm_runtime *runtime = substream->runtime;
330 struct s3c24xx_runtime_data *prtd;
331
332 pr_debug("Entered %s\n", __func__);
333
334 snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
335 snd_soc_set_runtime_hwparams(substream, &s3c_dma_hardware);
336
337 prtd = kzalloc(sizeof(struct s3c24xx_runtime_data), GFP_KERNEL);
338 if (prtd == NULL)
339 return -ENOMEM;
340
341 spin_lock_init(&prtd->lock);
342
343 runtime->private_data = prtd;
344 return 0;
345}
346
347static int s3c_dma_close(struct snd_pcm_substream *substream)
348{
349 struct snd_pcm_runtime *runtime = substream->runtime;
350 struct s3c24xx_runtime_data *prtd = runtime->private_data;
351
352 pr_debug("Entered %s\n", __func__);
353
354 if (!prtd)
355 pr_debug("s3c_dma_close called with prtd == NULL\n");
356
357 kfree(prtd);
358
359 return 0;
360}
361
362static int s3c_dma_mmap(struct snd_pcm_substream *substream,
363 struct vm_area_struct *vma)
364{
365 struct snd_pcm_runtime *runtime = substream->runtime;
366
367 pr_debug("Entered %s\n", __func__);
368
369 return dma_mmap_writecombine(substream->pcm->card->dev, vma,
370 runtime->dma_area,
371 runtime->dma_addr,
372 runtime->dma_bytes);
373}
374
375static struct snd_pcm_ops s3c_dma_ops = {
376 .open = s3c_dma_open,
377 .close = s3c_dma_close,
378 .ioctl = snd_pcm_lib_ioctl,
379 .hw_params = s3c_dma_hw_params,
380 .hw_free = s3c_dma_hw_free,
381 .prepare = s3c_dma_prepare,
382 .trigger = s3c_dma_trigger,
383 .pointer = s3c_dma_pointer,
384 .mmap = s3c_dma_mmap,
385};
386
387static int s3c_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
388{
389 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
390 struct snd_dma_buffer *buf = &substream->dma_buffer;
391 size_t size = s3c_dma_hardware.buffer_bytes_max;
392
393 pr_debug("Entered %s\n", __func__);
394
395 buf->dev.type = SNDRV_DMA_TYPE_DEV;
396 buf->dev.dev = pcm->card->dev;
397 buf->private_data = NULL;
398 buf->area = dma_alloc_writecombine(pcm->card->dev, size,
399 &buf->addr, GFP_KERNEL);
400 if (!buf->area)
401 return -ENOMEM;
402 buf->bytes = size;
403 return 0;
404}
405
406static void s3c_dma_free_dma_buffers(struct snd_pcm *pcm)
407{
408 struct snd_pcm_substream *substream;
409 struct snd_dma_buffer *buf;
410 int stream;
411
412 pr_debug("Entered %s\n", __func__);
413
414 for (stream = 0; stream < 2; stream++) {
415 substream = pcm->streams[stream].substream;
416 if (!substream)
417 continue;
418
419 buf = &substream->dma_buffer;
420 if (!buf->area)
421 continue;
422
423 dma_free_writecombine(pcm->card->dev, buf->bytes,
424 buf->area, buf->addr);
425 buf->area = NULL;
426 }
427}
428
429static u64 s3c_dma_mask = DMA_BIT_MASK(32);
430
431static int s3c_dma_new(struct snd_card *card,
432 struct snd_soc_dai *dai, struct snd_pcm *pcm)
433{
434 int ret = 0;
435
436 pr_debug("Entered %s\n", __func__);
437
438 if (!card->dev->dma_mask)
439 card->dev->dma_mask = &s3c_dma_mask;
440 if (!card->dev->coherent_dma_mask)
441 card->dev->coherent_dma_mask = 0xffffffff;
442
443 if (dai->driver->playback.channels_min) {
444 ret = s3c_preallocate_dma_buffer(pcm,
445 SNDRV_PCM_STREAM_PLAYBACK);
446 if (ret)
447 goto out;
448 }
449
450 if (dai->driver->capture.channels_min) {
451 ret = s3c_preallocate_dma_buffer(pcm,
452 SNDRV_PCM_STREAM_CAPTURE);
453 if (ret)
454 goto out;
455 }
456 out:
457 return ret;
458}
459
460static struct snd_soc_platform_driver s3c24xx_soc_platform = {
461 .ops = &s3c_dma_ops,
462 .pcm_new = s3c_dma_new,
463 .pcm_free = s3c_dma_free_dma_buffers,
464};
465
466static int __devinit s3c24xx_soc_platform_probe(struct platform_device *pdev)
467{
468 return snd_soc_register_platform(&pdev->dev, &s3c24xx_soc_platform);
469}
470
471static int __devexit s3c24xx_soc_platform_remove(struct platform_device *pdev)
472{
473 snd_soc_unregister_platform(&pdev->dev);
474 return 0;
475}
476
477static struct platform_driver s3c24xx_pcm_driver = {
478 .driver = {
479 .name = "s3c24xx-pcm-audio",
480 .owner = THIS_MODULE,
481 },
482
483 .probe = s3c24xx_soc_platform_probe,
484 .remove = __devexit_p(s3c24xx_soc_platform_remove),
485};
486
487static int __init snd_s3c24xx_pcm_init(void)
488{
489 return platform_driver_register(&s3c24xx_pcm_driver);
490}
491module_init(snd_s3c24xx_pcm_init);
492
493static void __exit snd_s3c24xx_pcm_exit(void)
494{
495 platform_driver_unregister(&s3c24xx_pcm_driver);
496}
497module_exit(snd_s3c24xx_pcm_exit);
498
499MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
500MODULE_DESCRIPTION("Samsung S3C Audio DMA module");
501MODULE_LICENSE("GPL");
502MODULE_ALIAS("platform:s3c24xx-pcm-audio");
diff --git a/sound/soc/s3c24xx/s3c-dma.h b/sound/soc/s3c24xx/s3c-dma.h
deleted file mode 100644
index 748c07d7c075..000000000000
--- a/sound/soc/s3c24xx/s3c-dma.h
+++ /dev/null
@@ -1,30 +0,0 @@
1/*
2 * s3c-dma.h --
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 * ALSA PCM interface for the Samsung S3C24xx CPU
10 */
11
12#ifndef _S3C_AUDIO_H
13#define _S3C_AUDIO_H
14
15#define ST_RUNNING (1<<0)
16#define ST_OPENED (1<<1)
17
18struct s3c_dma_params {
19 struct s3c2410_dma_client *client; /* stream identifier */
20 int channel; /* Channel ID */
21 dma_addr_t dma_addr;
22 int dma_size; /* Size of the DMA transfer */
23};
24
25#define S3C24XX_DAI_I2S 0
26
27/* platform data */
28extern struct snd_ac97_bus_ops s3c24xx_ac97_ops;
29
30#endif
diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.c b/sound/soc/s3c24xx/s3c-i2s-v2.c
deleted file mode 100644
index b3866d5b19e9..000000000000
--- a/sound/soc/s3c24xx/s3c-i2s-v2.c
+++ /dev/null
@@ -1,757 +0,0 @@
1/* sound/soc/s3c24xx/s3c-i2c-v2.c
2 *
3 * ALSA Soc Audio Layer - I2S core for newer Samsung SoCs.
4 *
5 * Copyright (c) 2006 Wolfson Microelectronics PLC.
6 * Graeme Gregory graeme.gregory@wolfsonmicro.com
7 * linux@wolfsonmicro.com
8 *
9 * Copyright (c) 2008, 2007, 2004-2005 Simtec Electronics
10 * http://armlinux.simtec.co.uk/
11 * Ben Dooks <ben@simtec.co.uk>
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version.
17 */
18
19#include <linux/delay.h>
20#include <linux/clk.h>
21#include <linux/io.h>
22
23#include <sound/pcm.h>
24#include <sound/pcm_params.h>
25#include <sound/soc.h>
26
27#include <mach/dma.h>
28
29#include "regs-i2s-v2.h"
30#include "s3c-i2s-v2.h"
31#include "s3c-dma.h"
32
33#undef S3C_IIS_V2_SUPPORTED
34
35#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413) \
36 || defined(CONFIG_CPU_S5PV210)
37#define S3C_IIS_V2_SUPPORTED
38#endif
39
40#ifdef CONFIG_PLAT_S3C64XX
41#define S3C_IIS_V2_SUPPORTED
42#endif
43
44#ifndef S3C_IIS_V2_SUPPORTED
45#error Unsupported CPU model
46#endif
47
48#define S3C2412_I2S_DEBUG_CON 0
49
50static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai)
51{
52 return snd_soc_dai_get_drvdata(cpu_dai);
53}
54
55#define bit_set(v, b) (((v) & (b)) ? 1 : 0)
56
57#if S3C2412_I2S_DEBUG_CON
58static void dbg_showcon(const char *fn, u32 con)
59{
60 printk(KERN_DEBUG "%s: LRI=%d, TXFEMPT=%d, RXFEMPT=%d, TXFFULL=%d, RXFFULL=%d\n", fn,
61 bit_set(con, S3C2412_IISCON_LRINDEX),
62 bit_set(con, S3C2412_IISCON_TXFIFO_EMPTY),
63 bit_set(con, S3C2412_IISCON_RXFIFO_EMPTY),
64 bit_set(con, S3C2412_IISCON_TXFIFO_FULL),
65 bit_set(con, S3C2412_IISCON_RXFIFO_FULL));
66
67 printk(KERN_DEBUG "%s: PAUSE: TXDMA=%d, RXDMA=%d, TXCH=%d, RXCH=%d\n",
68 fn,
69 bit_set(con, S3C2412_IISCON_TXDMA_PAUSE),
70 bit_set(con, S3C2412_IISCON_RXDMA_PAUSE),
71 bit_set(con, S3C2412_IISCON_TXCH_PAUSE),
72 bit_set(con, S3C2412_IISCON_RXCH_PAUSE));
73 printk(KERN_DEBUG "%s: ACTIVE: TXDMA=%d, RXDMA=%d, IIS=%d\n", fn,
74 bit_set(con, S3C2412_IISCON_TXDMA_ACTIVE),
75 bit_set(con, S3C2412_IISCON_RXDMA_ACTIVE),
76 bit_set(con, S3C2412_IISCON_IIS_ACTIVE));
77}
78#else
79static inline void dbg_showcon(const char *fn, u32 con)
80{
81}
82#endif
83
84
85/* Turn on or off the transmission path. */
86static void s3c2412_snd_txctrl(struct s3c_i2sv2_info *i2s, int on)
87{
88 void __iomem *regs = i2s->regs;
89 u32 fic, con, mod;
90
91 pr_debug("%s(%d)\n", __func__, on);
92
93 fic = readl(regs + S3C2412_IISFIC);
94 con = readl(regs + S3C2412_IISCON);
95 mod = readl(regs + S3C2412_IISMOD);
96
97 pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
98
99 if (on) {
100 con |= S3C2412_IISCON_TXDMA_ACTIVE | S3C2412_IISCON_IIS_ACTIVE;
101 con &= ~S3C2412_IISCON_TXDMA_PAUSE;
102 con &= ~S3C2412_IISCON_TXCH_PAUSE;
103
104 switch (mod & S3C2412_IISMOD_MODE_MASK) {
105 case S3C2412_IISMOD_MODE_TXONLY:
106 case S3C2412_IISMOD_MODE_TXRX:
107 /* do nothing, we are in the right mode */
108 break;
109
110 case S3C2412_IISMOD_MODE_RXONLY:
111 mod &= ~S3C2412_IISMOD_MODE_MASK;
112 mod |= S3C2412_IISMOD_MODE_TXRX;
113 break;
114
115 default:
116 dev_err(i2s->dev, "TXEN: Invalid MODE %x in IISMOD\n",
117 mod & S3C2412_IISMOD_MODE_MASK);
118 break;
119 }
120
121 writel(con, regs + S3C2412_IISCON);
122 writel(mod, regs + S3C2412_IISMOD);
123 } else {
124 /* Note, we do not have any indication that the FIFO problems
125 * tha the S3C2410/2440 had apply here, so we should be able
126 * to disable the DMA and TX without resetting the FIFOS.
127 */
128
129 con |= S3C2412_IISCON_TXDMA_PAUSE;
130 con |= S3C2412_IISCON_TXCH_PAUSE;
131 con &= ~S3C2412_IISCON_TXDMA_ACTIVE;
132
133 switch (mod & S3C2412_IISMOD_MODE_MASK) {
134 case S3C2412_IISMOD_MODE_TXRX:
135 mod &= ~S3C2412_IISMOD_MODE_MASK;
136 mod |= S3C2412_IISMOD_MODE_RXONLY;
137 break;
138
139 case S3C2412_IISMOD_MODE_TXONLY:
140 mod &= ~S3C2412_IISMOD_MODE_MASK;
141 con &= ~S3C2412_IISCON_IIS_ACTIVE;
142 break;
143
144 default:
145 dev_err(i2s->dev, "TXDIS: Invalid MODE %x in IISMOD\n",
146 mod & S3C2412_IISMOD_MODE_MASK);
147 break;
148 }
149
150 writel(mod, regs + S3C2412_IISMOD);
151 writel(con, regs + S3C2412_IISCON);
152 }
153
154 fic = readl(regs + S3C2412_IISFIC);
155 dbg_showcon(__func__, con);
156 pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
157}
158
159static void s3c2412_snd_rxctrl(struct s3c_i2sv2_info *i2s, int on)
160{
161 void __iomem *regs = i2s->regs;
162 u32 fic, con, mod;
163
164 pr_debug("%s(%d)\n", __func__, on);
165
166 fic = readl(regs + S3C2412_IISFIC);
167 con = readl(regs + S3C2412_IISCON);
168 mod = readl(regs + S3C2412_IISMOD);
169
170 pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
171
172 if (on) {
173 con |= S3C2412_IISCON_RXDMA_ACTIVE | S3C2412_IISCON_IIS_ACTIVE;
174 con &= ~S3C2412_IISCON_RXDMA_PAUSE;
175 con &= ~S3C2412_IISCON_RXCH_PAUSE;
176
177 switch (mod & S3C2412_IISMOD_MODE_MASK) {
178 case S3C2412_IISMOD_MODE_TXRX:
179 case S3C2412_IISMOD_MODE_RXONLY:
180 /* do nothing, we are in the right mode */
181 break;
182
183 case S3C2412_IISMOD_MODE_TXONLY:
184 mod &= ~S3C2412_IISMOD_MODE_MASK;
185 mod |= S3C2412_IISMOD_MODE_TXRX;
186 break;
187
188 default:
189 dev_err(i2s->dev, "RXEN: Invalid MODE %x in IISMOD\n",
190 mod & S3C2412_IISMOD_MODE_MASK);
191 }
192
193 writel(mod, regs + S3C2412_IISMOD);
194 writel(con, regs + S3C2412_IISCON);
195 } else {
196 /* See txctrl notes on FIFOs. */
197
198 con &= ~S3C2412_IISCON_RXDMA_ACTIVE;
199 con |= S3C2412_IISCON_RXDMA_PAUSE;
200 con |= S3C2412_IISCON_RXCH_PAUSE;
201
202 switch (mod & S3C2412_IISMOD_MODE_MASK) {
203 case S3C2412_IISMOD_MODE_RXONLY:
204 con &= ~S3C2412_IISCON_IIS_ACTIVE;
205 mod &= ~S3C2412_IISMOD_MODE_MASK;
206 break;
207
208 case S3C2412_IISMOD_MODE_TXRX:
209 mod &= ~S3C2412_IISMOD_MODE_MASK;
210 mod |= S3C2412_IISMOD_MODE_TXONLY;
211 break;
212
213 default:
214 dev_err(i2s->dev, "RXDIS: Invalid MODE %x in IISMOD\n",
215 mod & S3C2412_IISMOD_MODE_MASK);
216 }
217
218 writel(con, regs + S3C2412_IISCON);
219 writel(mod, regs + S3C2412_IISMOD);
220 }
221
222 fic = readl(regs + S3C2412_IISFIC);
223 pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
224}
225
226#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
227
228/*
229 * Wait for the LR signal to allow synchronisation to the L/R clock
230 * from the codec. May only be needed for slave mode.
231 */
232static int s3c2412_snd_lrsync(struct s3c_i2sv2_info *i2s)
233{
234 u32 iiscon;
235 unsigned long loops = msecs_to_loops(5);
236
237 pr_debug("Entered %s\n", __func__);
238
239 while (--loops) {
240 iiscon = readl(i2s->regs + S3C2412_IISCON);
241 if (iiscon & S3C2412_IISCON_LRINDEX)
242 break;
243
244 cpu_relax();
245 }
246
247 if (!loops) {
248 printk(KERN_ERR "%s: timeout\n", __func__);
249 return -ETIMEDOUT;
250 }
251
252 return 0;
253}
254
255/*
256 * Set S3C2412 I2S DAI format
257 */
258static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
259 unsigned int fmt)
260{
261 struct s3c_i2sv2_info *i2s = to_info(cpu_dai);
262 u32 iismod;
263
264 pr_debug("Entered %s\n", __func__);
265
266 iismod = readl(i2s->regs + S3C2412_IISMOD);
267 pr_debug("hw_params r: IISMOD: %x \n", iismod);
268
269 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
270 case SND_SOC_DAIFMT_CBM_CFM:
271 i2s->master = 0;
272 iismod |= S3C2412_IISMOD_SLAVE;
273 break;
274 case SND_SOC_DAIFMT_CBS_CFS:
275 i2s->master = 1;
276 iismod &= ~S3C2412_IISMOD_SLAVE;
277 break;
278 default:
279 pr_err("unknwon master/slave format\n");
280 return -EINVAL;
281 }
282
283 iismod &= ~S3C2412_IISMOD_SDF_MASK;
284
285 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
286 case SND_SOC_DAIFMT_RIGHT_J:
287 iismod |= S3C2412_IISMOD_LR_RLOW;
288 iismod |= S3C2412_IISMOD_SDF_MSB;
289 break;
290 case SND_SOC_DAIFMT_LEFT_J:
291 iismod |= S3C2412_IISMOD_LR_RLOW;
292 iismod |= S3C2412_IISMOD_SDF_LSB;
293 break;
294 case SND_SOC_DAIFMT_I2S:
295 iismod &= ~S3C2412_IISMOD_LR_RLOW;
296 iismod |= S3C2412_IISMOD_SDF_IIS;
297 break;
298 default:
299 pr_err("Unknown data format\n");
300 return -EINVAL;
301 }
302
303 writel(iismod, i2s->regs + S3C2412_IISMOD);
304 pr_debug("hw_params w: IISMOD: %x \n", iismod);
305 return 0;
306}
307
308static int s3c_i2sv2_hw_params(struct snd_pcm_substream *substream,
309 struct snd_pcm_hw_params *params,
310 struct snd_soc_dai *dai)
311{
312 struct s3c_i2sv2_info *i2s = to_info(dai);
313 struct s3c_dma_params *dma_data;
314 u32 iismod;
315
316 pr_debug("Entered %s\n", __func__);
317
318 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
319 dma_data = i2s->dma_playback;
320 else
321 dma_data = i2s->dma_capture;
322
323 snd_soc_dai_set_dma_data(dai, substream, dma_data);
324
325 /* Working copies of register */
326 iismod = readl(i2s->regs + S3C2412_IISMOD);
327 pr_debug("%s: r: IISMOD: %x\n", __func__, iismod);
328
329 iismod &= ~S3C64XX_IISMOD_BLC_MASK;
330 /* Sample size */
331 switch (params_format(params)) {
332 case SNDRV_PCM_FORMAT_S8:
333 iismod |= S3C64XX_IISMOD_BLC_8BIT;
334 break;
335 case SNDRV_PCM_FORMAT_S16_LE:
336 break;
337 case SNDRV_PCM_FORMAT_S24_LE:
338 iismod |= S3C64XX_IISMOD_BLC_24BIT;
339 break;
340 }
341
342 writel(iismod, i2s->regs + S3C2412_IISMOD);
343 pr_debug("%s: w: IISMOD: %x\n", __func__, iismod);
344
345 return 0;
346}
347
348static int s3c_i2sv2_set_sysclk(struct snd_soc_dai *cpu_dai,
349 int clk_id, unsigned int freq, int dir)
350{
351 struct s3c_i2sv2_info *i2s = to_info(cpu_dai);
352 u32 iismod = readl(i2s->regs + S3C2412_IISMOD);
353
354 pr_debug("Entered %s\n", __func__);
355 pr_debug("%s r: IISMOD: %x\n", __func__, iismod);
356
357 switch (clk_id) {
358 case S3C_I2SV2_CLKSRC_PCLK:
359 iismod &= ~S3C2412_IISMOD_IMS_SYSMUX;
360 break;
361
362 case S3C_I2SV2_CLKSRC_AUDIOBUS:
363 iismod |= S3C2412_IISMOD_IMS_SYSMUX;
364 break;
365
366 case S3C_I2SV2_CLKSRC_CDCLK:
367 /* Error if controller doesn't have the CDCLKCON bit */
368 if (!(i2s->feature & S3C_FEATURE_CDCLKCON))
369 return -EINVAL;
370
371 switch (dir) {
372 case SND_SOC_CLOCK_IN:
373 iismod |= S3C64XX_IISMOD_CDCLKCON;
374 break;
375 case SND_SOC_CLOCK_OUT:
376 iismod &= ~S3C64XX_IISMOD_CDCLKCON;
377 break;
378 default:
379 return -EINVAL;
380 }
381 break;
382
383 default:
384 return -EINVAL;
385 }
386
387 writel(iismod, i2s->regs + S3C2412_IISMOD);
388 pr_debug("%s w: IISMOD: %x\n", __func__, iismod);
389
390 return 0;
391}
392
393static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
394 struct snd_soc_dai *dai)
395{
396 struct snd_soc_pcm_runtime *rtd = substream->private_data;
397 struct s3c_i2sv2_info *i2s = to_info(rtd->cpu_dai);
398 int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
399 unsigned long irqs;
400 int ret = 0;
401 struct s3c_dma_params *dma_data =
402 snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
403
404 pr_debug("Entered %s\n", __func__);
405
406 switch (cmd) {
407 case SNDRV_PCM_TRIGGER_START:
408 /* On start, ensure that the FIFOs are cleared and reset. */
409
410 writel(capture ? S3C2412_IISFIC_RXFLUSH : S3C2412_IISFIC_TXFLUSH,
411 i2s->regs + S3C2412_IISFIC);
412
413 /* clear again, just in case */
414 writel(0x0, i2s->regs + S3C2412_IISFIC);
415
416 case SNDRV_PCM_TRIGGER_RESUME:
417 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
418 if (!i2s->master) {
419 ret = s3c2412_snd_lrsync(i2s);
420 if (ret)
421 goto exit_err;
422 }
423
424 local_irq_save(irqs);
425
426 if (capture)
427 s3c2412_snd_rxctrl(i2s, 1);
428 else
429 s3c2412_snd_txctrl(i2s, 1);
430
431 local_irq_restore(irqs);
432
433 /*
434 * Load the next buffer to DMA to meet the reqirement
435 * of the auto reload mechanism of S3C24XX.
436 * This call won't bother S3C64XX.
437 */
438 s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED);
439
440 break;
441
442 case SNDRV_PCM_TRIGGER_STOP:
443 case SNDRV_PCM_TRIGGER_SUSPEND:
444 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
445 local_irq_save(irqs);
446
447 if (capture)
448 s3c2412_snd_rxctrl(i2s, 0);
449 else
450 s3c2412_snd_txctrl(i2s, 0);
451
452 local_irq_restore(irqs);
453 break;
454 default:
455 ret = -EINVAL;
456 break;
457 }
458
459exit_err:
460 return ret;
461}
462
463/*
464 * Set S3C2412 Clock dividers
465 */
466static int s3c2412_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai,
467 int div_id, int div)
468{
469 struct s3c_i2sv2_info *i2s = to_info(cpu_dai);
470 u32 reg;
471
472 pr_debug("%s(%p, %d, %d)\n", __func__, cpu_dai, div_id, div);
473
474 switch (div_id) {
475 case S3C_I2SV2_DIV_BCLK:
476 switch (div) {
477 case 16:
478 div = S3C2412_IISMOD_BCLK_16FS;
479 break;
480
481 case 32:
482 div = S3C2412_IISMOD_BCLK_32FS;
483 break;
484
485 case 24:
486 div = S3C2412_IISMOD_BCLK_24FS;
487 break;
488
489 case 48:
490 div = S3C2412_IISMOD_BCLK_48FS;
491 break;
492
493 default:
494 return -EINVAL;
495 }
496
497 reg = readl(i2s->regs + S3C2412_IISMOD);
498 reg &= ~S3C2412_IISMOD_BCLK_MASK;
499 writel(reg | div, i2s->regs + S3C2412_IISMOD);
500
501 pr_debug("%s: MOD=%08x\n", __func__, readl(i2s->regs + S3C2412_IISMOD));
502 break;
503
504 case S3C_I2SV2_DIV_RCLK:
505 switch (div) {
506 case 256:
507 div = S3C2412_IISMOD_RCLK_256FS;
508 break;
509
510 case 384:
511 div = S3C2412_IISMOD_RCLK_384FS;
512 break;
513
514 case 512:
515 div = S3C2412_IISMOD_RCLK_512FS;
516 break;
517
518 case 768:
519 div = S3C2412_IISMOD_RCLK_768FS;
520 break;
521
522 default:
523 return -EINVAL;
524 }
525
526 reg = readl(i2s->regs + S3C2412_IISMOD);
527 reg &= ~S3C2412_IISMOD_RCLK_MASK;
528 writel(reg | div, i2s->regs + S3C2412_IISMOD);
529 pr_debug("%s: MOD=%08x\n", __func__, readl(i2s->regs + S3C2412_IISMOD));
530 break;
531
532 case S3C_I2SV2_DIV_PRESCALER:
533 if (div >= 0) {
534 writel((div << 8) | S3C2412_IISPSR_PSREN,
535 i2s->regs + S3C2412_IISPSR);
536 } else {
537 writel(0x0, i2s->regs + S3C2412_IISPSR);
538 }
539 pr_debug("%s: PSR=%08x\n", __func__, readl(i2s->regs + S3C2412_IISPSR));
540 break;
541
542 default:
543 return -EINVAL;
544 }
545
546 return 0;
547}
548
549static snd_pcm_sframes_t s3c2412_i2s_delay(struct snd_pcm_substream *substream,
550 struct snd_soc_dai *dai)
551{
552 struct s3c_i2sv2_info *i2s = to_info(dai);
553 u32 reg = readl(i2s->regs + S3C2412_IISFIC);
554 snd_pcm_sframes_t delay;
555
556 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
557 delay = S3C2412_IISFIC_TXCOUNT(reg);
558 else
559 delay = S3C2412_IISFIC_RXCOUNT(reg);
560
561 return delay;
562}
563
564struct clk *s3c_i2sv2_get_clock(struct snd_soc_dai *cpu_dai)
565{
566 struct s3c_i2sv2_info *i2s = to_info(cpu_dai);
567 u32 iismod = readl(i2s->regs + S3C2412_IISMOD);
568
569 if (iismod & S3C2412_IISMOD_IMS_SYSMUX)
570 return i2s->iis_cclk;
571 else
572 return i2s->iis_pclk;
573}
574EXPORT_SYMBOL_GPL(s3c_i2sv2_get_clock);
575
576/* default table of all avaialable root fs divisors */
577static unsigned int iis_fs_tab[] = { 256, 512, 384, 768 };
578
579int s3c_i2sv2_iis_calc_rate(struct s3c_i2sv2_rate_calc *info,
580 unsigned int *fstab,
581 unsigned int rate, struct clk *clk)
582{
583 unsigned long clkrate = clk_get_rate(clk);
584 unsigned int div;
585 unsigned int fsclk;
586 unsigned int actual;
587 unsigned int fs;
588 unsigned int fsdiv;
589 signed int deviation = 0;
590 unsigned int best_fs = 0;
591 unsigned int best_div = 0;
592 unsigned int best_rate = 0;
593 unsigned int best_deviation = INT_MAX;
594
595 pr_debug("Input clock rate %ldHz\n", clkrate);
596
597 if (fstab == NULL)
598 fstab = iis_fs_tab;
599
600 for (fs = 0; fs < ARRAY_SIZE(iis_fs_tab); fs++) {
601 fsdiv = iis_fs_tab[fs];
602
603 fsclk = clkrate / fsdiv;
604 div = fsclk / rate;
605
606 if ((fsclk % rate) > (rate / 2))
607 div++;
608
609 if (div <= 1)
610 continue;
611
612 actual = clkrate / (fsdiv * div);
613 deviation = actual - rate;
614
615 printk(KERN_DEBUG "%ufs: div %u => result %u, deviation %d\n",
616 fsdiv, div, actual, deviation);
617
618 deviation = abs(deviation);
619
620 if (deviation < best_deviation) {
621 best_fs = fsdiv;
622 best_div = div;
623 best_rate = actual;
624 best_deviation = deviation;
625 }
626
627 if (deviation == 0)
628 break;
629 }
630
631 printk(KERN_DEBUG "best: fs=%u, div=%u, rate=%u\n",
632 best_fs, best_div, best_rate);
633
634 info->fs_div = best_fs;
635 info->clk_div = best_div;
636
637 return 0;
638}
639EXPORT_SYMBOL_GPL(s3c_i2sv2_iis_calc_rate);
640
641int s3c_i2sv2_probe(struct snd_soc_dai *dai,
642 struct s3c_i2sv2_info *i2s,
643 unsigned long base)
644{
645 struct device *dev = dai->dev;
646 unsigned int iismod;
647
648 i2s->dev = dev;
649
650 /* record our i2s structure for later use in the callbacks */
651 snd_soc_dai_set_drvdata(dai, i2s);
652
653 i2s->regs = ioremap(base, 0x100);
654 if (i2s->regs == NULL) {
655 dev_err(dev, "cannot ioremap registers\n");
656 return -ENXIO;
657 }
658
659 i2s->iis_pclk = clk_get(dev, "iis");
660 if (IS_ERR(i2s->iis_pclk)) {
661 dev_err(dev, "failed to get iis_clock\n");
662 iounmap(i2s->regs);
663 return -ENOENT;
664 }
665
666 clk_enable(i2s->iis_pclk);
667
668 /* Mark ourselves as in TXRX mode so we can run through our cleanup
669 * process without warnings. */
670 iismod = readl(i2s->regs + S3C2412_IISMOD);
671 iismod |= S3C2412_IISMOD_MODE_TXRX;
672 writel(iismod, i2s->regs + S3C2412_IISMOD);
673 s3c2412_snd_txctrl(i2s, 0);
674 s3c2412_snd_rxctrl(i2s, 0);
675
676 return 0;
677}
678EXPORT_SYMBOL_GPL(s3c_i2sv2_probe);
679
680#ifdef CONFIG_PM
681static int s3c2412_i2s_suspend(struct snd_soc_dai *dai)
682{
683 struct s3c_i2sv2_info *i2s = to_info(dai);
684 u32 iismod;
685
686 if (dai->active) {
687 i2s->suspend_iismod = readl(i2s->regs + S3C2412_IISMOD);
688 i2s->suspend_iiscon = readl(i2s->regs + S3C2412_IISCON);
689 i2s->suspend_iispsr = readl(i2s->regs + S3C2412_IISPSR);
690
691 /* some basic suspend checks */
692
693 iismod = readl(i2s->regs + S3C2412_IISMOD);
694
695 if (iismod & S3C2412_IISCON_RXDMA_ACTIVE)
696 pr_warning("%s: RXDMA active?\n", __func__);
697
698 if (iismod & S3C2412_IISCON_TXDMA_ACTIVE)
699 pr_warning("%s: TXDMA active?\n", __func__);
700
701 if (iismod & S3C2412_IISCON_IIS_ACTIVE)
702 pr_warning("%s: IIS active\n", __func__);
703 }
704
705 return 0;
706}
707
708static int s3c2412_i2s_resume(struct snd_soc_dai *dai)
709{
710 struct s3c_i2sv2_info *i2s = to_info(dai);
711
712 pr_info("dai_active %d, IISMOD %08x, IISCON %08x\n",
713 dai->active, i2s->suspend_iismod, i2s->suspend_iiscon);
714
715 if (dai->active) {
716 writel(i2s->suspend_iiscon, i2s->regs + S3C2412_IISCON);
717 writel(i2s->suspend_iismod, i2s->regs + S3C2412_IISMOD);
718 writel(i2s->suspend_iispsr, i2s->regs + S3C2412_IISPSR);
719
720 writel(S3C2412_IISFIC_RXFLUSH | S3C2412_IISFIC_TXFLUSH,
721 i2s->regs + S3C2412_IISFIC);
722
723 ndelay(250);
724 writel(0x0, i2s->regs + S3C2412_IISFIC);
725 }
726
727 return 0;
728}
729#else
730#define s3c2412_i2s_suspend NULL
731#define s3c2412_i2s_resume NULL
732#endif
733
734int s3c_i2sv2_register_dai(struct device *dev, int id,
735 struct snd_soc_dai_driver *drv)
736{
737 struct snd_soc_dai_ops *ops = drv->ops;
738
739 ops->trigger = s3c2412_i2s_trigger;
740 if (!ops->hw_params)
741 ops->hw_params = s3c_i2sv2_hw_params;
742 ops->set_fmt = s3c2412_i2s_set_fmt;
743 ops->set_clkdiv = s3c2412_i2s_set_clkdiv;
744 ops->set_sysclk = s3c_i2sv2_set_sysclk;
745
746 /* Allow overriding by (for example) IISv4 */
747 if (!ops->delay)
748 ops->delay = s3c2412_i2s_delay;
749
750 drv->suspend = s3c2412_i2s_suspend;
751 drv->resume = s3c2412_i2s_resume;
752
753 return snd_soc_register_dai(dev, drv);
754}
755EXPORT_SYMBOL_GPL(s3c_i2sv2_register_dai);
756
757MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.h b/sound/soc/s3c24xx/s3c-i2s-v2.h
deleted file mode 100644
index d45830151484..000000000000
--- a/sound/soc/s3c24xx/s3c-i2s-v2.h
+++ /dev/null
@@ -1,106 +0,0 @@
1/* sound/soc/s3c24xx/s3c-i2s-v2.h
2 *
3 * ALSA Soc Audio Layer - S3C_I2SV2 I2S driver
4 *
5 * Copyright (c) 2007 Simtec Electronics
6 * http://armlinux.simtec.co.uk/
7 * Ben Dooks <ben@simtec.co.uk>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13*/
14
15/* This code is the core support for the I2S block found in a number of
16 * Samsung SoC devices which is unofficially named I2S-V2. Currently the
17 * S3C2412 and the S3C64XX series use this block to provide 1 or 2 I2S
18 * channels via configurable GPIO.
19 */
20
21#ifndef __SND_SOC_S3C24XX_S3C_I2SV2_I2S_H
22#define __SND_SOC_S3C24XX_S3C_I2SV2_I2S_H __FILE__
23
24#define S3C_I2SV2_DIV_BCLK (1)
25#define S3C_I2SV2_DIV_RCLK (2)
26#define S3C_I2SV2_DIV_PRESCALER (3)
27
28#define S3C_I2SV2_CLKSRC_PCLK 0
29#define S3C_I2SV2_CLKSRC_AUDIOBUS 1
30#define S3C_I2SV2_CLKSRC_CDCLK 2
31
32/* Set this flag for I2S controllers that have the bit IISMOD[12]
33 * bridge/break RCLK signal and external Xi2sCDCLK pin.
34 */
35#define S3C_FEATURE_CDCLKCON (1 << 0)
36
37/**
38 * struct s3c_i2sv2_info - S3C I2S-V2 information
39 * @dev: The parent device passed to use from the probe.
40 * @regs: The pointer to the device registe block.
41 * @feature: Set of bit-flags indicating features of the controller.
42 * @master: True if the I2S core is the I2S bit clock master.
43 * @dma_playback: DMA information for playback channel.
44 * @dma_capture: DMA information for capture channel.
45 * @suspend_iismod: PM save for the IISMOD register.
46 * @suspend_iiscon: PM save for the IISCON register.
47 * @suspend_iispsr: PM save for the IISPSR register.
48 *
49 * This is the private codec state for the hardware associated with an
50 * I2S channel such as the register mappings and clock sources.
51 */
52struct s3c_i2sv2_info {
53 struct device *dev;
54 void __iomem *regs;
55
56 u32 feature;
57
58 struct clk *iis_pclk;
59 struct clk *iis_cclk;
60
61 unsigned char master;
62
63 struct s3c_dma_params *dma_playback;
64 struct s3c_dma_params *dma_capture;
65
66 u32 suspend_iismod;
67 u32 suspend_iiscon;
68 u32 suspend_iispsr;
69
70 unsigned long base;
71};
72
73extern struct clk *s3c_i2sv2_get_clock(struct snd_soc_dai *cpu_dai);
74
75struct s3c_i2sv2_rate_calc {
76 unsigned int clk_div; /* for prescaler */
77 unsigned int fs_div; /* for root frame clock */
78};
79
80extern int s3c_i2sv2_iis_calc_rate(struct s3c_i2sv2_rate_calc *info,
81 unsigned int *fstab,
82 unsigned int rate, struct clk *clk);
83
84/**
85 * s3c_i2sv2_probe - probe for i2s device helper
86 * @dai: The ASoC DAI structure supplied to the original probe.
87 * @i2s: Our local i2s structure to fill in.
88 * @base: The base address for the registers.
89 */
90extern int s3c_i2sv2_probe(struct snd_soc_dai *dai,
91 struct s3c_i2sv2_info *i2s,
92 unsigned long base);
93
94/**
95 * s3c_i2sv2_register_dai - register dai with soc core
96 * @dev: DAI device
97 * @id: DAI ID
98 * @drv: The driver structure to register
99 *
100 * Fill in any missing fields and then register the given dai with the
101 * soc core.
102 */
103extern int s3c_i2sv2_register_dai(struct device *dev, int id,
104 struct snd_soc_dai_driver *drv);
105
106#endif /* __SND_SOC_S3C24XX_S3C_I2SV2_I2S_H */
diff --git a/sound/soc/s3c24xx/s3c-pcm.c b/sound/soc/s3c24xx/s3c-pcm.c
deleted file mode 100644
index 2e020e1b4eab..000000000000
--- a/sound/soc/s3c24xx/s3c-pcm.c
+++ /dev/null
@@ -1,552 +0,0 @@
1/* sound/soc/s3c24xx/s3c-pcm.c
2 *
3 * ALSA SoC Audio Layer - S3C PCM-Controller driver
4 *
5 * Copyright (c) 2009 Samsung Electronics Co. Ltd
6 * Author: Jaswinder Singh <jassi.brar@samsung.com>
7 * based upon I2S drivers by Ben Dooks.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/init.h>
15#include <linux/module.h>
16#include <linux/device.h>
17#include <linux/delay.h>
18#include <linux/clk.h>
19#include <linux/kernel.h>
20#include <linux/gpio.h>
21#include <linux/io.h>
22
23#include <sound/core.h>
24#include <sound/pcm.h>
25#include <sound/pcm_params.h>
26#include <sound/initval.h>
27#include <sound/soc.h>
28
29#include <plat/audio.h>
30#include <plat/dma.h>
31
32#include "s3c-dma.h"
33#include "s3c-pcm.h"
34
35static struct s3c2410_dma_client s3c_pcm_dma_client_out = {
36 .name = "PCM Stereo out"
37};
38
39static struct s3c2410_dma_client s3c_pcm_dma_client_in = {
40 .name = "PCM Stereo in"
41};
42
43static struct s3c_dma_params s3c_pcm_stereo_out[] = {
44 [0] = {
45 .client = &s3c_pcm_dma_client_out,
46 .dma_size = 4,
47 },
48 [1] = {
49 .client = &s3c_pcm_dma_client_out,
50 .dma_size = 4,
51 },
52};
53
54static struct s3c_dma_params s3c_pcm_stereo_in[] = {
55 [0] = {
56 .client = &s3c_pcm_dma_client_in,
57 .dma_size = 4,
58 },
59 [1] = {
60 .client = &s3c_pcm_dma_client_in,
61 .dma_size = 4,
62 },
63};
64
65static struct s3c_pcm_info s3c_pcm[2];
66
67static void s3c_pcm_snd_txctrl(struct s3c_pcm_info *pcm, int on)
68{
69 void __iomem *regs = pcm->regs;
70 u32 ctl, clkctl;
71
72 clkctl = readl(regs + S3C_PCM_CLKCTL);
73 ctl = readl(regs + S3C_PCM_CTL);
74 ctl &= ~(S3C_PCM_CTL_TXDIPSTICK_MASK
75 << S3C_PCM_CTL_TXDIPSTICK_SHIFT);
76
77 if (on) {
78 ctl |= S3C_PCM_CTL_TXDMA_EN;
79 ctl |= S3C_PCM_CTL_TXFIFO_EN;
80 ctl |= S3C_PCM_CTL_ENABLE;
81 ctl |= (0x4<<S3C_PCM_CTL_TXDIPSTICK_SHIFT);
82 clkctl |= S3C_PCM_CLKCTL_SERCLK_EN;
83 } else {
84 ctl &= ~S3C_PCM_CTL_TXDMA_EN;
85 ctl &= ~S3C_PCM_CTL_TXFIFO_EN;
86
87 if (!(ctl & S3C_PCM_CTL_RXFIFO_EN)) {
88 ctl &= ~S3C_PCM_CTL_ENABLE;
89 if (!pcm->idleclk)
90 clkctl |= S3C_PCM_CLKCTL_SERCLK_EN;
91 }
92 }
93
94 writel(clkctl, regs + S3C_PCM_CLKCTL);
95 writel(ctl, regs + S3C_PCM_CTL);
96}
97
98static void s3c_pcm_snd_rxctrl(struct s3c_pcm_info *pcm, int on)
99{
100 void __iomem *regs = pcm->regs;
101 u32 ctl, clkctl;
102
103 ctl = readl(regs + S3C_PCM_CTL);
104 clkctl = readl(regs + S3C_PCM_CLKCTL);
105 ctl &= ~(S3C_PCM_CTL_RXDIPSTICK_MASK
106 << S3C_PCM_CTL_RXDIPSTICK_SHIFT);
107
108 if (on) {
109 ctl |= S3C_PCM_CTL_RXDMA_EN;
110 ctl |= S3C_PCM_CTL_RXFIFO_EN;
111 ctl |= S3C_PCM_CTL_ENABLE;
112 ctl |= (0x20<<S3C_PCM_CTL_RXDIPSTICK_SHIFT);
113 clkctl |= S3C_PCM_CLKCTL_SERCLK_EN;
114 } else {
115 ctl &= ~S3C_PCM_CTL_RXDMA_EN;
116 ctl &= ~S3C_PCM_CTL_RXFIFO_EN;
117
118 if (!(ctl & S3C_PCM_CTL_TXFIFO_EN)) {
119 ctl &= ~S3C_PCM_CTL_ENABLE;
120 if (!pcm->idleclk)
121 clkctl |= S3C_PCM_CLKCTL_SERCLK_EN;
122 }
123 }
124
125 writel(clkctl, regs + S3C_PCM_CLKCTL);
126 writel(ctl, regs + S3C_PCM_CTL);
127}
128
129static int s3c_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
130 struct snd_soc_dai *dai)
131{
132 struct snd_soc_pcm_runtime *rtd = substream->private_data;
133 struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(rtd->cpu_dai);
134 unsigned long flags;
135
136 dev_dbg(pcm->dev, "Entered %s\n", __func__);
137
138 switch (cmd) {
139 case SNDRV_PCM_TRIGGER_START:
140 case SNDRV_PCM_TRIGGER_RESUME:
141 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
142 spin_lock_irqsave(&pcm->lock, flags);
143
144 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
145 s3c_pcm_snd_rxctrl(pcm, 1);
146 else
147 s3c_pcm_snd_txctrl(pcm, 1);
148
149 spin_unlock_irqrestore(&pcm->lock, flags);
150 break;
151
152 case SNDRV_PCM_TRIGGER_STOP:
153 case SNDRV_PCM_TRIGGER_SUSPEND:
154 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
155 spin_lock_irqsave(&pcm->lock, flags);
156
157 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
158 s3c_pcm_snd_rxctrl(pcm, 0);
159 else
160 s3c_pcm_snd_txctrl(pcm, 0);
161
162 spin_unlock_irqrestore(&pcm->lock, flags);
163 break;
164
165 default:
166 return -EINVAL;
167 }
168
169 return 0;
170}
171
172static int s3c_pcm_hw_params(struct snd_pcm_substream *substream,
173 struct snd_pcm_hw_params *params,
174 struct snd_soc_dai *socdai)
175{
176 struct snd_soc_pcm_runtime *rtd = substream->private_data;
177 struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(rtd->cpu_dai);
178 struct s3c_dma_params *dma_data;
179 void __iomem *regs = pcm->regs;
180 struct clk *clk;
181 int sclk_div, sync_div;
182 unsigned long flags;
183 u32 clkctl;
184
185 dev_dbg(pcm->dev, "Entered %s\n", __func__);
186
187 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
188 dma_data = pcm->dma_playback;
189 else
190 dma_data = pcm->dma_capture;
191
192 snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_data);
193
194 /* Strictly check for sample size */
195 switch (params_format(params)) {
196 case SNDRV_PCM_FORMAT_S16_LE:
197 break;
198 default:
199 return -EINVAL;
200 }
201
202 spin_lock_irqsave(&pcm->lock, flags);
203
204 /* Get hold of the PCMSOURCE_CLK */
205 clkctl = readl(regs + S3C_PCM_CLKCTL);
206 if (clkctl & S3C_PCM_CLKCTL_SERCLKSEL_PCLK)
207 clk = pcm->pclk;
208 else
209 clk = pcm->cclk;
210
211 /* Set the SCLK divider */
212 sclk_div = clk_get_rate(clk) / pcm->sclk_per_fs /
213 params_rate(params) / 2 - 1;
214
215 clkctl &= ~(S3C_PCM_CLKCTL_SCLKDIV_MASK
216 << S3C_PCM_CLKCTL_SCLKDIV_SHIFT);
217 clkctl |= ((sclk_div & S3C_PCM_CLKCTL_SCLKDIV_MASK)
218 << S3C_PCM_CLKCTL_SCLKDIV_SHIFT);
219
220 /* Set the SYNC divider */
221 sync_div = pcm->sclk_per_fs - 1;
222
223 clkctl &= ~(S3C_PCM_CLKCTL_SYNCDIV_MASK
224 << S3C_PCM_CLKCTL_SYNCDIV_SHIFT);
225 clkctl |= ((sync_div & S3C_PCM_CLKCTL_SYNCDIV_MASK)
226 << S3C_PCM_CLKCTL_SYNCDIV_SHIFT);
227
228 writel(clkctl, regs + S3C_PCM_CLKCTL);
229
230 spin_unlock_irqrestore(&pcm->lock, flags);
231
232 dev_dbg(pcm->dev, "PCMSOURCE_CLK-%lu SCLK=%ufs SCLK_DIV=%d SYNC_DIV=%d\n",
233 clk_get_rate(clk), pcm->sclk_per_fs,
234 sclk_div, sync_div);
235
236 return 0;
237}
238
239static int s3c_pcm_set_fmt(struct snd_soc_dai *cpu_dai,
240 unsigned int fmt)
241{
242 struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(cpu_dai);
243 void __iomem *regs = pcm->regs;
244 unsigned long flags;
245 int ret = 0;
246 u32 ctl;
247
248 dev_dbg(pcm->dev, "Entered %s\n", __func__);
249
250 spin_lock_irqsave(&pcm->lock, flags);
251
252 ctl = readl(regs + S3C_PCM_CTL);
253
254 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
255 case SND_SOC_DAIFMT_NB_NF:
256 /* Nothing to do, NB_NF by default */
257 break;
258 default:
259 dev_err(pcm->dev, "Unsupported clock inversion!\n");
260 ret = -EINVAL;
261 goto exit;
262 }
263
264 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
265 case SND_SOC_DAIFMT_CBS_CFS:
266 /* Nothing to do, Master by default */
267 break;
268 default:
269 dev_err(pcm->dev, "Unsupported master/slave format!\n");
270 ret = -EINVAL;
271 goto exit;
272 }
273
274 switch (fmt & SND_SOC_DAIFMT_CLOCK_MASK) {
275 case SND_SOC_DAIFMT_CONT:
276 pcm->idleclk = 1;
277 break;
278 case SND_SOC_DAIFMT_GATED:
279 pcm->idleclk = 0;
280 break;
281 default:
282 dev_err(pcm->dev, "Invalid Clock gating request!\n");
283 ret = -EINVAL;
284 goto exit;
285 }
286
287 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
288 case SND_SOC_DAIFMT_DSP_A:
289 ctl |= S3C_PCM_CTL_TXMSB_AFTER_FSYNC;
290 ctl |= S3C_PCM_CTL_RXMSB_AFTER_FSYNC;
291 break;
292 case SND_SOC_DAIFMT_DSP_B:
293 ctl &= ~S3C_PCM_CTL_TXMSB_AFTER_FSYNC;
294 ctl &= ~S3C_PCM_CTL_RXMSB_AFTER_FSYNC;
295 break;
296 default:
297 dev_err(pcm->dev, "Unsupported data format!\n");
298 ret = -EINVAL;
299 goto exit;
300 }
301
302 writel(ctl, regs + S3C_PCM_CTL);
303
304exit:
305 spin_unlock_irqrestore(&pcm->lock, flags);
306
307 return ret;
308}
309
310static int s3c_pcm_set_clkdiv(struct snd_soc_dai *cpu_dai,
311 int div_id, int div)
312{
313 struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(cpu_dai);
314
315 switch (div_id) {
316 case S3C_PCM_SCLK_PER_FS:
317 pcm->sclk_per_fs = div;
318 break;
319
320 default:
321 return -EINVAL;
322 }
323
324 return 0;
325}
326
327static int s3c_pcm_set_sysclk(struct snd_soc_dai *cpu_dai,
328 int clk_id, unsigned int freq, int dir)
329{
330 struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(cpu_dai);
331 void __iomem *regs = pcm->regs;
332 u32 clkctl = readl(regs + S3C_PCM_CLKCTL);
333
334 switch (clk_id) {
335 case S3C_PCM_CLKSRC_PCLK:
336 clkctl |= S3C_PCM_CLKCTL_SERCLKSEL_PCLK;
337 break;
338
339 case S3C_PCM_CLKSRC_MUX:
340 clkctl &= ~S3C_PCM_CLKCTL_SERCLKSEL_PCLK;
341
342 if (clk_get_rate(pcm->cclk) != freq)
343 clk_set_rate(pcm->cclk, freq);
344
345 break;
346
347 default:
348 return -EINVAL;
349 }
350
351 writel(clkctl, regs + S3C_PCM_CLKCTL);
352
353 return 0;
354}
355
356static struct snd_soc_dai_ops s3c_pcm_dai_ops = {
357 .set_sysclk = s3c_pcm_set_sysclk,
358 .set_clkdiv = s3c_pcm_set_clkdiv,
359 .trigger = s3c_pcm_trigger,
360 .hw_params = s3c_pcm_hw_params,
361 .set_fmt = s3c_pcm_set_fmt,
362};
363
364#define S3C_PCM_RATES SNDRV_PCM_RATE_8000_96000
365
366#define S3C_PCM_DAI_DECLARE \
367 .symmetric_rates = 1, \
368 .ops = &s3c_pcm_dai_ops, \
369 .playback = { \
370 .channels_min = 2, \
371 .channels_max = 2, \
372 .rates = S3C_PCM_RATES, \
373 .formats = SNDRV_PCM_FMTBIT_S16_LE, \
374 }, \
375 .capture = { \
376 .channels_min = 2, \
377 .channels_max = 2, \
378 .rates = S3C_PCM_RATES, \
379 .formats = SNDRV_PCM_FMTBIT_S16_LE, \
380 }
381
382struct snd_soc_dai_driver s3c_pcm_dai[] = {
383 [0] = {
384 .name = "samsung-pcm.0",
385 S3C_PCM_DAI_DECLARE,
386 },
387 [1] = {
388 .name = "samsung-pcm.1",
389 S3C_PCM_DAI_DECLARE,
390 },
391};
392EXPORT_SYMBOL_GPL(s3c_pcm_dai);
393
394static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev)
395{
396 struct s3c_pcm_info *pcm;
397 struct resource *mem_res, *dmatx_res, *dmarx_res;
398 struct s3c_audio_pdata *pcm_pdata;
399 int ret;
400
401 /* Check for valid device index */
402 if ((pdev->id < 0) || pdev->id >= ARRAY_SIZE(s3c_pcm)) {
403 dev_err(&pdev->dev, "id %d out of range\n", pdev->id);
404 return -EINVAL;
405 }
406
407 pcm_pdata = pdev->dev.platform_data;
408
409 /* Check for availability of necessary resource */
410 dmatx_res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
411 if (!dmatx_res) {
412 dev_err(&pdev->dev, "Unable to get PCM-TX dma resource\n");
413 return -ENXIO;
414 }
415
416 dmarx_res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
417 if (!dmarx_res) {
418 dev_err(&pdev->dev, "Unable to get PCM-RX dma resource\n");
419 return -ENXIO;
420 }
421
422 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
423 if (!mem_res) {
424 dev_err(&pdev->dev, "Unable to get register resource\n");
425 return -ENXIO;
426 }
427
428 if (pcm_pdata && pcm_pdata->cfg_gpio && pcm_pdata->cfg_gpio(pdev)) {
429 dev_err(&pdev->dev, "Unable to configure gpio\n");
430 return -EINVAL;
431 }
432
433 pcm = &s3c_pcm[pdev->id];
434 pcm->dev = &pdev->dev;
435
436 spin_lock_init(&pcm->lock);
437
438 /* Default is 128fs */
439 pcm->sclk_per_fs = 128;
440
441 pcm->cclk = clk_get(&pdev->dev, "audio-bus");
442 if (IS_ERR(pcm->cclk)) {
443 dev_err(&pdev->dev, "failed to get audio-bus\n");
444 ret = PTR_ERR(pcm->cclk);
445 goto err1;
446 }
447 clk_enable(pcm->cclk);
448
449 /* record our pcm structure for later use in the callbacks */
450 dev_set_drvdata(&pdev->dev, pcm);
451
452 if (!request_mem_region(mem_res->start,
453 resource_size(mem_res), "samsung-pcm")) {
454 dev_err(&pdev->dev, "Unable to request register region\n");
455 ret = -EBUSY;
456 goto err2;
457 }
458
459 pcm->regs = ioremap(mem_res->start, 0x100);
460 if (pcm->regs == NULL) {
461 dev_err(&pdev->dev, "cannot ioremap registers\n");
462 ret = -ENXIO;
463 goto err3;
464 }
465
466 pcm->pclk = clk_get(&pdev->dev, "pcm");
467 if (IS_ERR(pcm->pclk)) {
468 dev_err(&pdev->dev, "failed to get pcm_clock\n");
469 ret = -ENOENT;
470 goto err4;
471 }
472 clk_enable(pcm->pclk);
473
474 ret = snd_soc_register_dai(&pdev->dev, &s3c_pcm_dai[pdev->id]);
475 if (ret != 0) {
476 dev_err(&pdev->dev, "failed to get pcm_clock\n");
477 goto err5;
478 }
479
480 s3c_pcm_stereo_in[pdev->id].dma_addr = mem_res->start
481 + S3C_PCM_RXFIFO;
482 s3c_pcm_stereo_out[pdev->id].dma_addr = mem_res->start
483 + S3C_PCM_TXFIFO;
484
485 s3c_pcm_stereo_in[pdev->id].channel = dmarx_res->start;
486 s3c_pcm_stereo_out[pdev->id].channel = dmatx_res->start;
487
488 pcm->dma_capture = &s3c_pcm_stereo_in[pdev->id];
489 pcm->dma_playback = &s3c_pcm_stereo_out[pdev->id];
490
491 return 0;
492
493err5:
494 clk_disable(pcm->pclk);
495 clk_put(pcm->pclk);
496err4:
497 iounmap(pcm->regs);
498err3:
499 release_mem_region(mem_res->start, resource_size(mem_res));
500err2:
501 clk_disable(pcm->cclk);
502 clk_put(pcm->cclk);
503err1:
504 return ret;
505}
506
507static __devexit int s3c_pcm_dev_remove(struct platform_device *pdev)
508{
509 struct s3c_pcm_info *pcm = &s3c_pcm[pdev->id];
510 struct resource *mem_res;
511
512 snd_soc_unregister_dai(&pdev->dev);
513
514 iounmap(pcm->regs);
515
516 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
517 release_mem_region(mem_res->start, resource_size(mem_res));
518
519 clk_disable(pcm->cclk);
520 clk_disable(pcm->pclk);
521 clk_put(pcm->pclk);
522 clk_put(pcm->cclk);
523
524 return 0;
525}
526
527static struct platform_driver s3c_pcm_driver = {
528 .probe = s3c_pcm_dev_probe,
529 .remove = s3c_pcm_dev_remove,
530 .driver = {
531 .name = "samsung-pcm",
532 .owner = THIS_MODULE,
533 },
534};
535
536static int __init s3c_pcm_init(void)
537{
538 return platform_driver_register(&s3c_pcm_driver);
539}
540module_init(s3c_pcm_init);
541
542static void __exit s3c_pcm_exit(void)
543{
544 platform_driver_unregister(&s3c_pcm_driver);
545}
546module_exit(s3c_pcm_exit);
547
548/* Module information */
549MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");
550MODULE_DESCRIPTION("S3C PCM Controller Driver");
551MODULE_LICENSE("GPL");
552MODULE_ALIAS("platform:samsung-pcm");
diff --git a/sound/soc/s3c24xx/s3c-pcm.h b/sound/soc/s3c24xx/s3c-pcm.h
deleted file mode 100644
index f60baa19387d..000000000000
--- a/sound/soc/s3c24xx/s3c-pcm.h
+++ /dev/null
@@ -1,124 +0,0 @@
1/* sound/soc/s3c24xx/s3c-pcm.h
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 as
5 * published by the Free Software Foundation.
6 *
7 */
8
9#ifndef __S3C_PCM_H
10#define __S3C_PCM_H __FILE__
11
12/*Register Offsets */
13#define S3C_PCM_CTL (0x00)
14#define S3C_PCM_CLKCTL (0x04)
15#define S3C_PCM_TXFIFO (0x08)
16#define S3C_PCM_RXFIFO (0x0C)
17#define S3C_PCM_IRQCTL (0x10)
18#define S3C_PCM_IRQSTAT (0x14)
19#define S3C_PCM_FIFOSTAT (0x18)
20#define S3C_PCM_CLRINT (0x20)
21
22/* PCM_CTL Bit-Fields */
23#define S3C_PCM_CTL_TXDIPSTICK_MASK (0x3f)
24#define S3C_PCM_CTL_TXDIPSTICK_SHIFT (13)
25#define S3C_PCM_CTL_RXDIPSTICK_MASK (0x3f)
26#define S3C_PCM_CTL_RXDIPSTICK_SHIFT (7)
27#define S3C_PCM_CTL_TXDMA_EN (0x1<<6)
28#define S3C_PCM_CTL_RXDMA_EN (0x1<<5)
29#define S3C_PCM_CTL_TXMSB_AFTER_FSYNC (0x1<<4)
30#define S3C_PCM_CTL_RXMSB_AFTER_FSYNC (0x1<<3)
31#define S3C_PCM_CTL_TXFIFO_EN (0x1<<2)
32#define S3C_PCM_CTL_RXFIFO_EN (0x1<<1)
33#define S3C_PCM_CTL_ENABLE (0x1<<0)
34
35/* PCM_CLKCTL Bit-Fields */
36#define S3C_PCM_CLKCTL_SERCLK_EN (0x1<<19)
37#define S3C_PCM_CLKCTL_SERCLKSEL_PCLK (0x1<<18)
38#define S3C_PCM_CLKCTL_SCLKDIV_MASK (0x1ff)
39#define S3C_PCM_CLKCTL_SYNCDIV_MASK (0x1ff)
40#define S3C_PCM_CLKCTL_SCLKDIV_SHIFT (9)
41#define S3C_PCM_CLKCTL_SYNCDIV_SHIFT (0)
42
43/* PCM_TXFIFO Bit-Fields */
44#define S3C_PCM_TXFIFO_DVALID (0x1<<16)
45#define S3C_PCM_TXFIFO_DATA_MSK (0xffff<<0)
46
47/* PCM_RXFIFO Bit-Fields */
48#define S3C_PCM_RXFIFO_DVALID (0x1<<16)
49#define S3C_PCM_RXFIFO_DATA_MSK (0xffff<<0)
50
51/* PCM_IRQCTL Bit-Fields */
52#define S3C_PCM_IRQCTL_IRQEN (0x1<<14)
53#define S3C_PCM_IRQCTL_WRDEN (0x1<<12)
54#define S3C_PCM_IRQCTL_TXEMPTYEN (0x1<<11)
55#define S3C_PCM_IRQCTL_TXALMSTEMPTYEN (0x1<<10)
56#define S3C_PCM_IRQCTL_TXFULLEN (0x1<<9)
57#define S3C_PCM_IRQCTL_TXALMSTFULLEN (0x1<<8)
58#define S3C_PCM_IRQCTL_TXSTARVEN (0x1<<7)
59#define S3C_PCM_IRQCTL_TXERROVRFLEN (0x1<<6)
60#define S3C_PCM_IRQCTL_RXEMPTEN (0x1<<5)
61#define S3C_PCM_IRQCTL_RXALMSTEMPTEN (0x1<<4)
62#define S3C_PCM_IRQCTL_RXFULLEN (0x1<<3)
63#define S3C_PCM_IRQCTL_RXALMSTFULLEN (0x1<<2)
64#define S3C_PCM_IRQCTL_RXSTARVEN (0x1<<1)
65#define S3C_PCM_IRQCTL_RXERROVRFLEN (0x1<<0)
66
67/* PCM_IRQSTAT Bit-Fields */
68#define S3C_PCM_IRQSTAT_IRQPND (0x1<<13)
69#define S3C_PCM_IRQSTAT_WRD_XFER (0x1<<12)
70#define S3C_PCM_IRQSTAT_TXEMPTY (0x1<<11)
71#define S3C_PCM_IRQSTAT_TXALMSTEMPTY (0x1<<10)
72#define S3C_PCM_IRQSTAT_TXFULL (0x1<<9)
73#define S3C_PCM_IRQSTAT_TXALMSTFULL (0x1<<8)
74#define S3C_PCM_IRQSTAT_TXSTARV (0x1<<7)
75#define S3C_PCM_IRQSTAT_TXERROVRFL (0x1<<6)
76#define S3C_PCM_IRQSTAT_RXEMPT (0x1<<5)
77#define S3C_PCM_IRQSTAT_RXALMSTEMPT (0x1<<4)
78#define S3C_PCM_IRQSTAT_RXFULL (0x1<<3)
79#define S3C_PCM_IRQSTAT_RXALMSTFULL (0x1<<2)
80#define S3C_PCM_IRQSTAT_RXSTARV (0x1<<1)
81#define S3C_PCM_IRQSTAT_RXERROVRFL (0x1<<0)
82
83/* PCM_FIFOSTAT Bit-Fields */
84#define S3C_PCM_FIFOSTAT_TXCNT_MSK (0x3f<<14)
85#define S3C_PCM_FIFOSTAT_TXFIFOEMPTY (0x1<<13)
86#define S3C_PCM_FIFOSTAT_TXFIFOALMSTEMPTY (0x1<<12)
87#define S3C_PCM_FIFOSTAT_TXFIFOFULL (0x1<<11)
88#define S3C_PCM_FIFOSTAT_TXFIFOALMSTFULL (0x1<<10)
89#define S3C_PCM_FIFOSTAT_RXCNT_MSK (0x3f<<4)
90#define S3C_PCM_FIFOSTAT_RXFIFOEMPTY (0x1<<3)
91#define S3C_PCM_FIFOSTAT_RXFIFOALMSTEMPTY (0x1<<2)
92#define S3C_PCM_FIFOSTAT_RXFIFOFULL (0x1<<1)
93#define S3C_PCM_FIFOSTAT_RXFIFOALMSTFULL (0x1<<0)
94
95#define S3C_PCM_CLKSRC_PCLK 0
96#define S3C_PCM_CLKSRC_MUX 1
97
98#define S3C_PCM_SCLK_PER_FS 0
99
100/**
101 * struct s3c_pcm_info - S3C PCM Controller information
102 * @dev: The parent device passed to use from the probe.
103 * @regs: The pointer to the device register block.
104 * @dma_playback: DMA information for playback channel.
105 * @dma_capture: DMA information for capture channel.
106 */
107struct s3c_pcm_info {
108 spinlock_t lock;
109 struct device *dev;
110 void __iomem *regs;
111
112 unsigned int sclk_per_fs;
113
114 /* Whether to keep PCMSCLK enabled even when idle(no active xfer) */
115 unsigned int idleclk;
116
117 struct clk *pclk;
118 struct clk *cclk;
119
120 struct s3c_dma_params *dma_playback;
121 struct s3c_dma_params *dma_capture;
122};
123
124#endif /* __S3C_PCM_H */
diff --git a/sound/soc/s3c24xx/s3c2412-i2s.c b/sound/soc/s3c24xx/s3c2412-i2s.c
deleted file mode 100644
index 4a861cfa52c5..000000000000
--- a/sound/soc/s3c24xx/s3c2412-i2s.c
+++ /dev/null
@@ -1,212 +0,0 @@
1/* sound/soc/s3c24xx/s3c2412-i2s.c
2 *
3 * ALSA Soc Audio Layer - S3C2412 I2S driver
4 *
5 * Copyright (c) 2006 Wolfson Microelectronics PLC.
6 * Graeme Gregory graeme.gregory@wolfsonmicro.com
7 * linux@wolfsonmicro.com
8 *
9 * Copyright (c) 2007, 2004-2005 Simtec Electronics
10 * http://armlinux.simtec.co.uk/
11 * Ben Dooks <ben@simtec.co.uk>
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version.
17 */
18
19#include <linux/init.h>
20#include <linux/module.h>
21#include <linux/device.h>
22#include <linux/delay.h>
23#include <linux/gpio.h>
24#include <linux/clk.h>
25#include <linux/kernel.h>
26#include <linux/io.h>
27
28#include <sound/core.h>
29#include <sound/pcm.h>
30#include <sound/pcm_params.h>
31#include <sound/initval.h>
32#include <sound/soc.h>
33#include <mach/hardware.h>
34
35#include <mach/regs-gpio.h>
36#include <mach/dma.h>
37
38#include "s3c-dma.h"
39#include "regs-i2s-v2.h"
40#include "s3c2412-i2s.h"
41
42#define S3C2412_I2S_DEBUG 0
43
44static struct s3c2410_dma_client s3c2412_dma_client_out = {
45 .name = "I2S PCM Stereo out"
46};
47
48static struct s3c2410_dma_client s3c2412_dma_client_in = {
49 .name = "I2S PCM Stereo in"
50};
51
52static struct s3c_dma_params s3c2412_i2s_pcm_stereo_out = {
53 .client = &s3c2412_dma_client_out,
54 .channel = DMACH_I2S_OUT,
55 .dma_addr = S3C2410_PA_IIS + S3C2412_IISTXD,
56 .dma_size = 4,
57};
58
59static struct s3c_dma_params s3c2412_i2s_pcm_stereo_in = {
60 .client = &s3c2412_dma_client_in,
61 .channel = DMACH_I2S_IN,
62 .dma_addr = S3C2410_PA_IIS + S3C2412_IISRXD,
63 .dma_size = 4,
64};
65
66static struct s3c_i2sv2_info s3c2412_i2s;
67
68static int s3c2412_i2s_probe(struct snd_soc_dai *dai)
69{
70 int ret;
71
72 pr_debug("Entered %s\n", __func__);
73
74 ret = s3c_i2sv2_probe(dai, &s3c2412_i2s, S3C2410_PA_IIS);
75 if (ret)
76 return ret;
77
78 s3c2412_i2s.dma_capture = &s3c2412_i2s_pcm_stereo_in;
79 s3c2412_i2s.dma_playback = &s3c2412_i2s_pcm_stereo_out;
80
81 s3c2412_i2s.iis_cclk = clk_get(dai->dev, "i2sclk");
82 if (s3c2412_i2s.iis_cclk == NULL) {
83 pr_err("failed to get i2sclk clock\n");
84 iounmap(s3c2412_i2s.regs);
85 return -ENODEV;
86 }
87
88 /* Set MPLL as the source for IIS CLK */
89
90 clk_set_parent(s3c2412_i2s.iis_cclk, clk_get(NULL, "mpll"));
91 clk_enable(s3c2412_i2s.iis_cclk);
92
93 s3c2412_i2s.iis_cclk = s3c2412_i2s.iis_pclk;
94
95 /* Configure the I2S pins in correct mode */
96 s3c2410_gpio_cfgpin(S3C2410_GPE0, S3C2410_GPE0_I2SLRCK);
97 s3c2410_gpio_cfgpin(S3C2410_GPE1, S3C2410_GPE1_I2SSCLK);
98 s3c2410_gpio_cfgpin(S3C2410_GPE2, S3C2410_GPE2_CDCLK);
99 s3c2410_gpio_cfgpin(S3C2410_GPE3, S3C2410_GPE3_I2SSDI);
100 s3c2410_gpio_cfgpin(S3C2410_GPE4, S3C2410_GPE4_I2SSDO);
101
102 return 0;
103}
104
105static int s3c2412_i2s_remove(struct snd_soc_dai *dai)
106{
107 clk_disable(s3c2412_i2s.iis_cclk);
108 clk_put(s3c2412_i2s.iis_cclk);
109 iounmap(s3c2412_i2s.regs);
110
111 return 0;
112}
113
114static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
115 struct snd_pcm_hw_params *params,
116 struct snd_soc_dai *cpu_dai)
117{
118 struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(cpu_dai);
119 struct s3c_dma_params *dma_data;
120 u32 iismod;
121
122 pr_debug("Entered %s\n", __func__);
123
124 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
125 dma_data = i2s->dma_playback;
126 else
127 dma_data = i2s->dma_capture;
128
129 snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
130
131 iismod = readl(i2s->regs + S3C2412_IISMOD);
132 pr_debug("%s: r: IISMOD: %x\n", __func__, iismod);
133
134 switch (params_format(params)) {
135 case SNDRV_PCM_FORMAT_S8:
136 iismod |= S3C2412_IISMOD_8BIT;
137 break;
138 case SNDRV_PCM_FORMAT_S16_LE:
139 iismod &= ~S3C2412_IISMOD_8BIT;
140 break;
141 }
142
143 writel(iismod, i2s->regs + S3C2412_IISMOD);
144 pr_debug("%s: w: IISMOD: %x\n", __func__, iismod);
145
146 return 0;
147}
148
149#define S3C2412_I2S_RATES \
150 (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
151 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
152 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
153
154static struct snd_soc_dai_ops s3c2412_i2s_dai_ops = {
155 .hw_params = s3c2412_i2s_hw_params,
156};
157
158static struct snd_soc_dai_driver s3c2412_i2s_dai = {
159 .probe = s3c2412_i2s_probe,
160 .remove = s3c2412_i2s_remove,
161 .playback = {
162 .channels_min = 2,
163 .channels_max = 2,
164 .rates = S3C2412_I2S_RATES,
165 .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,
166 },
167 .capture = {
168 .channels_min = 2,
169 .channels_max = 2,
170 .rates = S3C2412_I2S_RATES,
171 .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,
172 },
173 .ops = &s3c2412_i2s_dai_ops,
174};
175
176static __devinit int s3c2412_iis_dev_probe(struct platform_device *pdev)
177{
178 return snd_soc_register_dai(&pdev->dev, &s3c2412_i2s_dai);
179}
180
181static __devexit int s3c2412_iis_dev_remove(struct platform_device *pdev)
182{
183 snd_soc_unregister_dai(&pdev->dev);
184 return 0;
185}
186
187static struct platform_driver s3c2412_iis_driver = {
188 .probe = s3c2412_iis_dev_probe,
189 .remove = s3c2412_iis_dev_remove,
190 .driver = {
191 .name = "s3c2412-iis",
192 .owner = THIS_MODULE,
193 },
194};
195
196static int __init s3c2412_i2s_init(void)
197{
198 return platform_driver_register(&s3c2412_iis_driver);
199}
200module_init(s3c2412_i2s_init);
201
202static void __exit s3c2412_i2s_exit(void)
203{
204 platform_driver_unregister(&s3c2412_iis_driver);
205}
206module_exit(s3c2412_i2s_exit);
207
208/* Module information */
209MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
210MODULE_DESCRIPTION("S3C2412 I2S SoC Interface");
211MODULE_LICENSE("GPL");
212MODULE_ALIAS("platform:s3c2412-iis");
diff --git a/sound/soc/s3c24xx/s3c2412-i2s.h b/sound/soc/s3c24xx/s3c2412-i2s.h
deleted file mode 100644
index 01a0471ac65c..000000000000
--- a/sound/soc/s3c24xx/s3c2412-i2s.h
+++ /dev/null
@@ -1,27 +0,0 @@
1/* sound/soc/s3c24xx/s3c2412-i2s.c
2 *
3 * ALSA Soc Audio Layer - S3C2412 I2S driver
4 *
5 * Copyright (c) 2007 Simtec Electronics
6 * http://armlinux.simtec.co.uk/
7 * Ben Dooks <ben@simtec.co.uk>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13*/
14
15#ifndef __SND_SOC_S3C24XX_S3C2412_I2S_H
16#define __SND_SOC_S3C24XX_S3C2412_I2S_H __FILE__
17
18#include "s3c-i2s-v2.h"
19
20#define S3C2412_DIV_BCLK S3C_I2SV2_DIV_BCLK
21#define S3C2412_DIV_RCLK S3C_I2SV2_DIV_RCLK
22#define S3C2412_DIV_PRESCALER S3C_I2SV2_DIV_PRESCALER
23
24#define S3C2412_CLKSRC_PCLK S3C_I2SV2_CLKSRC_PCLK
25#define S3C2412_CLKSRC_I2SCLK S3C_I2SV2_CLKSRC_AUDIOBUS
26
27#endif /* __SND_SOC_S3C24XX_S3C2412_I2S_H */
diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c
deleted file mode 100644
index e060daaa458f..000000000000
--- a/sound/soc/s3c24xx/s3c24xx-i2s.c
+++ /dev/null
@@ -1,519 +0,0 @@
1/*
2 * s3c24xx-i2s.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/init.h>
18#include <linux/module.h>
19#include <linux/device.h>
20#include <linux/delay.h>
21#include <linux/clk.h>
22#include <linux/jiffies.h>
23#include <linux/io.h>
24#include <linux/gpio.h>
25
26#include <sound/core.h>
27#include <sound/pcm.h>
28#include <sound/pcm_params.h>
29#include <sound/initval.h>
30#include <sound/soc.h>
31
32#include <mach/hardware.h>
33#include <mach/regs-gpio.h>
34#include <mach/regs-clock.h>
35
36#include <asm/dma.h>
37#include <mach/dma.h>
38
39#include <plat/regs-iis.h>
40
41#include "s3c-dma.h"
42#include "s3c24xx-i2s.h"
43
44static struct s3c2410_dma_client s3c24xx_dma_client_out = {
45 .name = "I2S PCM Stereo out"
46};
47
48static struct s3c2410_dma_client s3c24xx_dma_client_in = {
49 .name = "I2S PCM Stereo in"
50};
51
52static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_out = {
53 .client = &s3c24xx_dma_client_out,
54 .channel = DMACH_I2S_OUT,
55 .dma_addr = S3C2410_PA_IIS + S3C2410_IISFIFO,
56 .dma_size = 2,
57};
58
59static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_in = {
60 .client = &s3c24xx_dma_client_in,
61 .channel = DMACH_I2S_IN,
62 .dma_addr = S3C2410_PA_IIS + S3C2410_IISFIFO,
63 .dma_size = 2,
64};
65
66struct s3c24xx_i2s_info {
67 void __iomem *regs;
68 struct clk *iis_clk;
69 u32 iiscon;
70 u32 iismod;
71 u32 iisfcon;
72 u32 iispsr;
73};
74static struct s3c24xx_i2s_info s3c24xx_i2s;
75
76static void s3c24xx_snd_txctrl(int on)
77{
78 u32 iisfcon;
79 u32 iiscon;
80 u32 iismod;
81
82 pr_debug("Entered %s\n", __func__);
83
84 iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON);
85 iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON);
86 iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
87
88 pr_debug("r: IISCON: %x IISMOD: %x IISFCON: %x\n", iiscon, iismod, iisfcon);
89
90 if (on) {
91 iisfcon |= S3C2410_IISFCON_TXDMA | S3C2410_IISFCON_TXENABLE;
92 iiscon |= S3C2410_IISCON_TXDMAEN | S3C2410_IISCON_IISEN;
93 iiscon &= ~S3C2410_IISCON_TXIDLE;
94 iismod |= S3C2410_IISMOD_TXMODE;
95
96 writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD);
97 writel(iisfcon, s3c24xx_i2s.regs + S3C2410_IISFCON);
98 writel(iiscon, s3c24xx_i2s.regs + S3C2410_IISCON);
99 } else {
100 /* note, we have to disable the FIFOs otherwise bad things
101 * seem to happen when the DMA stops. According to the
102 * Samsung supplied kernel, this should allow the DMA
103 * engine and FIFOs to reset. If this isn't allowed, the
104 * DMA engine will simply freeze randomly.
105 */
106
107 iisfcon &= ~S3C2410_IISFCON_TXENABLE;
108 iisfcon &= ~S3C2410_IISFCON_TXDMA;
109 iiscon |= S3C2410_IISCON_TXIDLE;
110 iiscon &= ~S3C2410_IISCON_TXDMAEN;
111 iismod &= ~S3C2410_IISMOD_TXMODE;
112
113 writel(iiscon, s3c24xx_i2s.regs + S3C2410_IISCON);
114 writel(iisfcon, s3c24xx_i2s.regs + S3C2410_IISFCON);
115 writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD);
116 }
117
118 pr_debug("w: IISCON: %x IISMOD: %x IISFCON: %x\n", iiscon, iismod, iisfcon);
119}
120
121static void s3c24xx_snd_rxctrl(int on)
122{
123 u32 iisfcon;
124 u32 iiscon;
125 u32 iismod;
126
127 pr_debug("Entered %s\n", __func__);
128
129 iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON);
130 iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON);
131 iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
132
133 pr_debug("r: IISCON: %x IISMOD: %x IISFCON: %x\n", iiscon, iismod, iisfcon);
134
135 if (on) {
136 iisfcon |= S3C2410_IISFCON_RXDMA | S3C2410_IISFCON_RXENABLE;
137 iiscon |= S3C2410_IISCON_RXDMAEN | S3C2410_IISCON_IISEN;
138 iiscon &= ~S3C2410_IISCON_RXIDLE;
139 iismod |= S3C2410_IISMOD_RXMODE;
140
141 writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD);
142 writel(iisfcon, s3c24xx_i2s.regs + S3C2410_IISFCON);
143 writel(iiscon, s3c24xx_i2s.regs + S3C2410_IISCON);
144 } else {
145 /* note, we have to disable the FIFOs otherwise bad things
146 * seem to happen when the DMA stops. According to the
147 * Samsung supplied kernel, this should allow the DMA
148 * engine and FIFOs to reset. If this isn't allowed, the
149 * DMA engine will simply freeze randomly.
150 */
151
152 iisfcon &= ~S3C2410_IISFCON_RXENABLE;
153 iisfcon &= ~S3C2410_IISFCON_RXDMA;
154 iiscon |= S3C2410_IISCON_RXIDLE;
155 iiscon &= ~S3C2410_IISCON_RXDMAEN;
156 iismod &= ~S3C2410_IISMOD_RXMODE;
157
158 writel(iisfcon, s3c24xx_i2s.regs + S3C2410_IISFCON);
159 writel(iiscon, s3c24xx_i2s.regs + S3C2410_IISCON);
160 writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD);
161 }
162
163 pr_debug("w: IISCON: %x IISMOD: %x IISFCON: %x\n", iiscon, iismod, iisfcon);
164}
165
166/*
167 * Wait for the LR signal to allow synchronisation to the L/R clock
168 * from the codec. May only be needed for slave mode.
169 */
170static int s3c24xx_snd_lrsync(void)
171{
172 u32 iiscon;
173 int timeout = 50; /* 5ms */
174
175 pr_debug("Entered %s\n", __func__);
176
177 while (1) {
178 iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON);
179 if (iiscon & S3C2410_IISCON_LRINDEX)
180 break;
181
182 if (!timeout--)
183 return -ETIMEDOUT;
184 udelay(100);
185 }
186
187 return 0;
188}
189
190/*
191 * Check whether CPU is the master or slave
192 */
193static inline int s3c24xx_snd_is_clkmaster(void)
194{
195 pr_debug("Entered %s\n", __func__);
196
197 return (readl(s3c24xx_i2s.regs + S3C2410_IISMOD) & S3C2410_IISMOD_SLAVE) ? 0:1;
198}
199
200/*
201 * Set S3C24xx I2S DAI format
202 */
203static int s3c24xx_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
204 unsigned int fmt)
205{
206 u32 iismod;
207
208 pr_debug("Entered %s\n", __func__);
209
210 iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
211 pr_debug("hw_params r: IISMOD: %x \n", iismod);
212
213 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
214 case SND_SOC_DAIFMT_CBM_CFM:
215 iismod |= S3C2410_IISMOD_SLAVE;
216 break;
217 case SND_SOC_DAIFMT_CBS_CFS:
218 iismod &= ~S3C2410_IISMOD_SLAVE;
219 break;
220 default:
221 return -EINVAL;
222 }
223
224 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
225 case SND_SOC_DAIFMT_LEFT_J:
226 iismod |= S3C2410_IISMOD_MSB;
227 break;
228 case SND_SOC_DAIFMT_I2S:
229 iismod &= ~S3C2410_IISMOD_MSB;
230 break;
231 default:
232 return -EINVAL;
233 }
234
235 writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD);
236 pr_debug("hw_params w: IISMOD: %x \n", iismod);
237 return 0;
238}
239
240static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream,
241 struct snd_pcm_hw_params *params,
242 struct snd_soc_dai *dai)
243{
244 struct snd_soc_pcm_runtime *rtd = substream->private_data;
245 struct s3c_dma_params *dma_data;
246 u32 iismod;
247
248 pr_debug("Entered %s\n", __func__);
249
250 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
251 dma_data = &s3c24xx_i2s_pcm_stereo_out;
252 else
253 dma_data = &s3c24xx_i2s_pcm_stereo_in;
254
255 snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_data);
256
257 /* Working copies of register */
258 iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
259 pr_debug("hw_params r: IISMOD: %x\n", iismod);
260
261 switch (params_format(params)) {
262 case SNDRV_PCM_FORMAT_S8:
263 iismod &= ~S3C2410_IISMOD_16BIT;
264 dma_data->dma_size = 1;
265 break;
266 case SNDRV_PCM_FORMAT_S16_LE:
267 iismod |= S3C2410_IISMOD_16BIT;
268 dma_data->dma_size = 2;
269 break;
270 default:
271 return -EINVAL;
272 }
273
274 writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD);
275 pr_debug("hw_params w: IISMOD: %x\n", iismod);
276 return 0;
277}
278
279static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
280 struct snd_soc_dai *dai)
281{
282 int ret = 0;
283 struct s3c_dma_params *dma_data =
284 snd_soc_dai_get_dma_data(dai, substream);
285
286 pr_debug("Entered %s\n", __func__);
287
288 switch (cmd) {
289 case SNDRV_PCM_TRIGGER_START:
290 case SNDRV_PCM_TRIGGER_RESUME:
291 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
292 if (!s3c24xx_snd_is_clkmaster()) {
293 ret = s3c24xx_snd_lrsync();
294 if (ret)
295 goto exit_err;
296 }
297
298 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
299 s3c24xx_snd_rxctrl(1);
300 else
301 s3c24xx_snd_txctrl(1);
302
303 s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED);
304 break;
305 case SNDRV_PCM_TRIGGER_STOP:
306 case SNDRV_PCM_TRIGGER_SUSPEND:
307 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
308 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
309 s3c24xx_snd_rxctrl(0);
310 else
311 s3c24xx_snd_txctrl(0);
312 break;
313 default:
314 ret = -EINVAL;
315 break;
316 }
317
318exit_err:
319 return ret;
320}
321
322/*
323 * Set S3C24xx Clock source
324 */
325static int s3c24xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
326 int clk_id, unsigned int freq, int dir)
327{
328 u32 iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
329
330 pr_debug("Entered %s\n", __func__);
331
332 iismod &= ~S3C2440_IISMOD_MPLL;
333
334 switch (clk_id) {
335 case S3C24XX_CLKSRC_PCLK:
336 break;
337 case S3C24XX_CLKSRC_MPLL:
338 iismod |= S3C2440_IISMOD_MPLL;
339 break;
340 default:
341 return -EINVAL;
342 }
343
344 writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD);
345 return 0;
346}
347
348/*
349 * Set S3C24xx Clock dividers
350 */
351static int s3c24xx_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai,
352 int div_id, int div)
353{
354 u32 reg;
355
356 pr_debug("Entered %s\n", __func__);
357
358 switch (div_id) {
359 case S3C24XX_DIV_BCLK:
360 reg = readl(s3c24xx_i2s.regs + S3C2410_IISMOD) & ~S3C2410_IISMOD_FS_MASK;
361 writel(reg | div, s3c24xx_i2s.regs + S3C2410_IISMOD);
362 break;
363 case S3C24XX_DIV_MCLK:
364 reg = readl(s3c24xx_i2s.regs + S3C2410_IISMOD) & ~(S3C2410_IISMOD_384FS);
365 writel(reg | div, s3c24xx_i2s.regs + S3C2410_IISMOD);
366 break;
367 case S3C24XX_DIV_PRESCALER:
368 writel(div, s3c24xx_i2s.regs + S3C2410_IISPSR);
369 reg = readl(s3c24xx_i2s.regs + S3C2410_IISCON);
370 writel(reg | S3C2410_IISCON_PSCEN, s3c24xx_i2s.regs + S3C2410_IISCON);
371 break;
372 default:
373 return -EINVAL;
374 }
375
376 return 0;
377}
378
379/*
380 * To avoid duplicating clock code, allow machine driver to
381 * get the clockrate from here.
382 */
383u32 s3c24xx_i2s_get_clockrate(void)
384{
385 return clk_get_rate(s3c24xx_i2s.iis_clk);
386}
387EXPORT_SYMBOL_GPL(s3c24xx_i2s_get_clockrate);
388
389static int s3c24xx_i2s_probe(struct snd_soc_dai *dai)
390{
391 pr_debug("Entered %s\n", __func__);
392
393 s3c24xx_i2s.regs = ioremap(S3C2410_PA_IIS, 0x100);
394 if (s3c24xx_i2s.regs == NULL)
395 return -ENXIO;
396
397 s3c24xx_i2s.iis_clk = clk_get(dai->dev, "iis");
398 if (s3c24xx_i2s.iis_clk == NULL) {
399 pr_err("failed to get iis_clock\n");
400 iounmap(s3c24xx_i2s.regs);
401 return -ENODEV;
402 }
403 clk_enable(s3c24xx_i2s.iis_clk);
404
405 /* Configure the I2S pins in correct mode */
406 s3c2410_gpio_cfgpin(S3C2410_GPE0, S3C2410_GPE0_I2SLRCK);
407 s3c2410_gpio_cfgpin(S3C2410_GPE1, S3C2410_GPE1_I2SSCLK);
408 s3c2410_gpio_cfgpin(S3C2410_GPE2, S3C2410_GPE2_CDCLK);
409 s3c2410_gpio_cfgpin(S3C2410_GPE3, S3C2410_GPE3_I2SSDI);
410 s3c2410_gpio_cfgpin(S3C2410_GPE4, S3C2410_GPE4_I2SSDO);
411
412 writel(S3C2410_IISCON_IISEN, s3c24xx_i2s.regs + S3C2410_IISCON);
413
414 s3c24xx_snd_txctrl(0);
415 s3c24xx_snd_rxctrl(0);
416
417 return 0;
418}
419
420#ifdef CONFIG_PM
421static int s3c24xx_i2s_suspend(struct snd_soc_dai *cpu_dai)
422{
423 pr_debug("Entered %s\n", __func__);
424
425 s3c24xx_i2s.iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON);
426 s3c24xx_i2s.iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
427 s3c24xx_i2s.iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON);
428 s3c24xx_i2s.iispsr = readl(s3c24xx_i2s.regs + S3C2410_IISPSR);
429
430 clk_disable(s3c24xx_i2s.iis_clk);
431
432 return 0;
433}
434
435static int s3c24xx_i2s_resume(struct snd_soc_dai *cpu_dai)
436{
437 pr_debug("Entered %s\n", __func__);
438 clk_enable(s3c24xx_i2s.iis_clk);
439
440 writel(s3c24xx_i2s.iiscon, s3c24xx_i2s.regs + S3C2410_IISCON);
441 writel(s3c24xx_i2s.iismod, s3c24xx_i2s.regs + S3C2410_IISMOD);
442 writel(s3c24xx_i2s.iisfcon, s3c24xx_i2s.regs + S3C2410_IISFCON);
443 writel(s3c24xx_i2s.iispsr, s3c24xx_i2s.regs + S3C2410_IISPSR);
444
445 return 0;
446}
447#else
448#define s3c24xx_i2s_suspend NULL
449#define s3c24xx_i2s_resume NULL
450#endif
451
452
453#define S3C24XX_I2S_RATES \
454 (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
455 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
456 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
457
458static struct snd_soc_dai_ops s3c24xx_i2s_dai_ops = {
459 .trigger = s3c24xx_i2s_trigger,
460 .hw_params = s3c24xx_i2s_hw_params,
461 .set_fmt = s3c24xx_i2s_set_fmt,
462 .set_clkdiv = s3c24xx_i2s_set_clkdiv,
463 .set_sysclk = s3c24xx_i2s_set_sysclk,
464};
465
466static struct snd_soc_dai_driver s3c24xx_i2s_dai = {
467 .probe = s3c24xx_i2s_probe,
468 .suspend = s3c24xx_i2s_suspend,
469 .resume = s3c24xx_i2s_resume,
470 .playback = {
471 .channels_min = 2,
472 .channels_max = 2,
473 .rates = S3C24XX_I2S_RATES,
474 .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,},
475 .capture = {
476 .channels_min = 2,
477 .channels_max = 2,
478 .rates = S3C24XX_I2S_RATES,
479 .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,},
480 .ops = &s3c24xx_i2s_dai_ops,
481};
482
483static __devinit int s3c24xx_iis_dev_probe(struct platform_device *pdev)
484{
485 return snd_soc_register_dai(&pdev->dev, &s3c24xx_i2s_dai);
486}
487
488static __devexit int s3c24xx_iis_dev_remove(struct platform_device *pdev)
489{
490 snd_soc_unregister_dai(&pdev->dev);
491 return 0;
492}
493
494static struct platform_driver s3c24xx_iis_driver = {
495 .probe = s3c24xx_iis_dev_probe,
496 .remove = s3c24xx_iis_dev_remove,
497 .driver = {
498 .name = "s3c24xx-iis",
499 .owner = THIS_MODULE,
500 },
501};
502
503static int __init s3c24xx_i2s_init(void)
504{
505 return platform_driver_register(&s3c24xx_iis_driver);
506}
507module_init(s3c24xx_i2s_init);
508
509static void __exit s3c24xx_i2s_exit(void)
510{
511 platform_driver_unregister(&s3c24xx_iis_driver);
512}
513module_exit(s3c24xx_i2s_exit);
514
515/* Module information */
516MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
517MODULE_DESCRIPTION("s3c24xx I2S SoC Interface");
518MODULE_LICENSE("GPL");
519MODULE_ALIAS("platform:s3c24xx-iis");
diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.h b/sound/soc/s3c24xx/s3c24xx-i2s.h
deleted file mode 100644
index f9ca04edacb7..000000000000
--- a/sound/soc/s3c24xx/s3c24xx-i2s.h
+++ /dev/null
@@ -1,35 +0,0 @@
1/*
2 * s3c24xx-i2s.c -- ALSA Soc Audio Layer
3 *
4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Author: Graeme Gregory
6 * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * Revision history
14 * 10th Nov 2006 Initial version.
15 */
16
17#ifndef S3C24XXI2S_H_
18#define S3C24XXI2S_H_
19
20/* clock sources */
21#define S3C24XX_CLKSRC_PCLK 0
22#define S3C24XX_CLKSRC_MPLL 1
23
24/* Clock dividers */
25#define S3C24XX_DIV_MCLK 0
26#define S3C24XX_DIV_BCLK 1
27#define S3C24XX_DIV_PRESCALER 2
28
29/* prescaler */
30#define S3C24XX_PRESCALE(a,b) \
31 (((a - 1) << S3C2410_IISPSR_INTSHIFT) | ((b - 1) << S3C2410_IISPSR_EXTSHFIT))
32
33u32 s3c24xx_i2s_get_clockrate(void);
34
35#endif /*S3C24XXI2S_H_*/
diff --git a/sound/soc/s3c24xx/s3c24xx_simtec.c b/sound/soc/s3c24xx/s3c24xx_simtec.c
deleted file mode 100644
index c4c111442010..000000000000
--- a/sound/soc/s3c24xx/s3c24xx_simtec.c
+++ /dev/null
@@ -1,395 +0,0 @@
1/* sound/soc/s3c24xx/s3c24xx_simtec.c
2 *
3 * Copyright 2009 Simtec Electronics
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8*/
9
10#include <linux/module.h>
11#include <linux/moduleparam.h>
12#include <linux/platform_device.h>
13#include <linux/gpio.h>
14#include <linux/clk.h>
15#include <linux/i2c.h>
16
17#include <sound/core.h>
18#include <sound/pcm.h>
19#include <sound/soc.h>
20#include <sound/soc-dapm.h>
21
22#include <plat/audio-simtec.h>
23
24#include "s3c-dma.h"
25#include "s3c24xx-i2s.h"
26#include "s3c24xx_simtec.h"
27
28static struct s3c24xx_audio_simtec_pdata *pdata;
29static struct clk *xtal_clk;
30
31static int spk_gain;
32static int spk_unmute;
33
34/**
35 * speaker_gain_get - read the speaker gain setting.
36 * @kcontrol: The control for the speaker gain.
37 * @ucontrol: The value that needs to be updated.
38 *
39 * Read the value for the AMP gain control.
40 */
41static int speaker_gain_get(struct snd_kcontrol *kcontrol,
42 struct snd_ctl_elem_value *ucontrol)
43{
44 ucontrol->value.integer.value[0] = spk_gain;
45 return 0;
46}
47
48/**
49 * speaker_gain_set - set the value of the speaker amp gain
50 * @value: The value to write.
51 */
52static void speaker_gain_set(int value)
53{
54 gpio_set_value_cansleep(pdata->amp_gain[0], value & 1);
55 gpio_set_value_cansleep(pdata->amp_gain[1], value >> 1);
56}
57
58/**
59 * speaker_gain_put - set the speaker gain setting.
60 * @kcontrol: The control for the speaker gain.
61 * @ucontrol: The value that needs to be set.
62 *
63 * Set the value of the speaker gain from the specified
64 * @ucontrol setting.
65 *
66 * Note, if the speaker amp is muted, then we do not set a gain value
67 * as at-least one of the ICs that is fitted will try and power up even
68 * if the main control is set to off.
69 */
70static int speaker_gain_put(struct snd_kcontrol *kcontrol,
71 struct snd_ctl_elem_value *ucontrol)
72{
73 int value = ucontrol->value.integer.value[0];
74
75 spk_gain = value;
76
77 if (!spk_unmute)
78 speaker_gain_set(value);
79
80 return 0;
81}
82
83static const struct snd_kcontrol_new amp_gain_controls[] = {
84 SOC_SINGLE_EXT("Speaker Gain", 0, 0, 3, 0,
85 speaker_gain_get, speaker_gain_put),
86};
87
88/**
89 * spk_unmute_state - set the unmute state of the speaker
90 * @to: zero to unmute, non-zero to ununmute.
91 */
92static void spk_unmute_state(int to)
93{
94 pr_debug("%s: to=%d\n", __func__, to);
95
96 spk_unmute = to;
97 gpio_set_value(pdata->amp_gpio, to);
98
99 /* if we're umuting, also re-set the gain */
100 if (to && pdata->amp_gain[0] > 0)
101 speaker_gain_set(spk_gain);
102}
103
104/**
105 * speaker_unmute_get - read the speaker unmute setting.
106 * @kcontrol: The control for the speaker gain.
107 * @ucontrol: The value that needs to be updated.
108 *
109 * Read the value for the AMP gain control.
110 */
111static int speaker_unmute_get(struct snd_kcontrol *kcontrol,
112 struct snd_ctl_elem_value *ucontrol)
113{
114 ucontrol->value.integer.value[0] = spk_unmute;
115 return 0;
116}
117
118/**
119 * speaker_unmute_put - set the speaker unmute setting.
120 * @kcontrol: The control for the speaker gain.
121 * @ucontrol: The value that needs to be set.
122 *
123 * Set the value of the speaker gain from the specified
124 * @ucontrol setting.
125 */
126static int speaker_unmute_put(struct snd_kcontrol *kcontrol,
127 struct snd_ctl_elem_value *ucontrol)
128{
129 spk_unmute_state(ucontrol->value.integer.value[0]);
130 return 0;
131}
132
133/* This is added as a manual control as the speaker amps create clicks
134 * when their power state is changed, which are far more noticeable than
135 * anything produced by the CODEC itself.
136 */
137static const struct snd_kcontrol_new amp_unmute_controls[] = {
138 SOC_SINGLE_EXT("Speaker Switch", 0, 0, 1, 0,
139 speaker_unmute_get, speaker_unmute_put),
140};
141
142void simtec_audio_init(struct snd_soc_pcm_runtime *rtd)
143{
144 struct snd_soc_codec *codec = rtd->codec;
145
146 if (pdata->amp_gpio > 0) {
147 pr_debug("%s: adding amp routes\n", __func__);
148
149 snd_soc_add_controls(codec, amp_unmute_controls,
150 ARRAY_SIZE(amp_unmute_controls));
151 }
152
153 if (pdata->amp_gain[0] > 0) {
154 pr_debug("%s: adding amp controls\n", __func__);
155 snd_soc_add_controls(codec, amp_gain_controls,
156 ARRAY_SIZE(amp_gain_controls));
157 }
158}
159EXPORT_SYMBOL_GPL(simtec_audio_init);
160
161#define CODEC_CLOCK 12000000
162
163/**
164 * simtec_hw_params - update hardware parameters
165 * @substream: The audio substream instance.
166 * @params: The parameters requested.
167 *
168 * Update the codec data routing and configuration settings
169 * from the supplied data.
170 */
171static int simtec_hw_params(struct snd_pcm_substream *substream,
172 struct snd_pcm_hw_params *params)
173{
174 struct snd_soc_pcm_runtime *rtd = substream->private_data;
175 struct snd_soc_dai *codec_dai = rtd->codec_dai;
176 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
177 int ret;
178
179 /* Set the CODEC as the bus clock master, I2S */
180 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
181 SND_SOC_DAIFMT_NB_NF |
182 SND_SOC_DAIFMT_CBM_CFM);
183 if (ret) {
184 pr_err("%s: failed set cpu dai format\n", __func__);
185 return ret;
186 }
187
188 /* Set the CODEC as the bus clock master */
189 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
190 SND_SOC_DAIFMT_NB_NF |
191 SND_SOC_DAIFMT_CBM_CFM);
192 if (ret) {
193 pr_err("%s: failed set codec dai format\n", __func__);
194 return ret;
195 }
196
197 ret = snd_soc_dai_set_sysclk(codec_dai, 0,
198 CODEC_CLOCK, SND_SOC_CLOCK_IN);
199 if (ret) {
200 pr_err( "%s: failed setting codec sysclk\n", __func__);
201 return ret;
202 }
203
204 if (pdata->use_mpllin) {
205 ret = snd_soc_dai_set_sysclk(cpu_dai, S3C24XX_CLKSRC_MPLL,
206 0, SND_SOC_CLOCK_OUT);
207
208 if (ret) {
209 pr_err("%s: failed to set MPLLin as clksrc\n",
210 __func__);
211 return ret;
212 }
213 }
214
215 if (pdata->output_cdclk) {
216 int cdclk_scale;
217
218 cdclk_scale = clk_get_rate(xtal_clk) / CODEC_CLOCK;
219 cdclk_scale--;
220
221 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
222 cdclk_scale);
223 }
224
225 return 0;
226}
227
228static int simtec_call_startup(struct s3c24xx_audio_simtec_pdata *pd)
229{
230 /* call any board supplied startup code, this currently only
231 * covers the bast/vr1000 which have a CPLD in the way of the
232 * LRCLK */
233 if (pd->startup)
234 pd->startup();
235
236 return 0;
237}
238
239static struct snd_soc_ops simtec_snd_ops = {
240 .hw_params = simtec_hw_params,
241};
242
243/**
244 * attach_gpio_amp - get and configure the necessary gpios
245 * @dev: The device we're probing.
246 * @pd: The platform data supplied by the board.
247 *
248 * If there is a GPIO based amplifier attached to the board, claim
249 * the necessary GPIO lines for it, and set default values.
250 */
251static int attach_gpio_amp(struct device *dev,
252 struct s3c24xx_audio_simtec_pdata *pd)
253{
254 int ret;
255
256 /* attach gpio amp gain (if any) */
257 if (pdata->amp_gain[0] > 0) {
258 ret = gpio_request(pd->amp_gain[0], "gpio-amp-gain0");
259 if (ret) {
260 dev_err(dev, "cannot get amp gpio gain0\n");
261 return ret;
262 }
263
264 ret = gpio_request(pd->amp_gain[1], "gpio-amp-gain1");
265 if (ret) {
266 dev_err(dev, "cannot get amp gpio gain1\n");
267 gpio_free(pdata->amp_gain[0]);
268 return ret;
269 }
270
271 gpio_direction_output(pd->amp_gain[0], 0);
272 gpio_direction_output(pd->amp_gain[1], 0);
273 }
274
275 /* note, currently we assume GPA0 isn't valid amp */
276 if (pdata->amp_gpio > 0) {
277 ret = gpio_request(pd->amp_gpio, "gpio-amp");
278 if (ret) {
279 dev_err(dev, "cannot get amp gpio %d (%d)\n",
280 pd->amp_gpio, ret);
281 goto err_amp;
282 }
283
284 /* set the amp off at startup */
285 spk_unmute_state(0);
286 }
287
288 return 0;
289
290err_amp:
291 if (pd->amp_gain[0] > 0) {
292 gpio_free(pd->amp_gain[0]);
293 gpio_free(pd->amp_gain[1]);
294 }
295
296 return ret;
297}
298
299static void detach_gpio_amp(struct s3c24xx_audio_simtec_pdata *pd)
300{
301 if (pd->amp_gain[0] > 0) {
302 gpio_free(pd->amp_gain[0]);
303 gpio_free(pd->amp_gain[1]);
304 }
305
306 if (pd->amp_gpio > 0)
307 gpio_free(pd->amp_gpio);
308}
309
310#ifdef CONFIG_PM
311int simtec_audio_resume(struct device *dev)
312{
313 simtec_call_startup(pdata);
314 return 0;
315}
316
317const struct dev_pm_ops simtec_audio_pmops = {
318 .resume = simtec_audio_resume,
319};
320EXPORT_SYMBOL_GPL(simtec_audio_pmops);
321#endif
322
323int __devinit simtec_audio_core_probe(struct platform_device *pdev,
324 struct snd_soc_card *card)
325{
326 struct platform_device *snd_dev;
327 int ret;
328
329 card->dai_link->ops = &simtec_snd_ops;
330
331 pdata = pdev->dev.platform_data;
332 if (!pdata) {
333 dev_err(&pdev->dev, "no platform data supplied\n");
334 return -EINVAL;
335 }
336
337 simtec_call_startup(pdata);
338
339 xtal_clk = clk_get(&pdev->dev, "xtal");
340 if (IS_ERR(xtal_clk)) {
341 dev_err(&pdev->dev, "could not get clkout0\n");
342 return -EINVAL;
343 }
344
345 dev_info(&pdev->dev, "xtal rate is %ld\n", clk_get_rate(xtal_clk));
346
347 ret = attach_gpio_amp(&pdev->dev, pdata);
348 if (ret)
349 goto err_clk;
350
351 snd_dev = platform_device_alloc("soc-audio", -1);
352 if (!snd_dev) {
353 dev_err(&pdev->dev, "failed to alloc soc-audio devicec\n");
354 ret = -ENOMEM;
355 goto err_gpio;
356 }
357
358 platform_set_drvdata(snd_dev, card);
359
360 ret = platform_device_add(snd_dev);
361 if (ret) {
362 dev_err(&pdev->dev, "failed to add soc-audio dev\n");
363 goto err_pdev;
364 }
365
366 platform_set_drvdata(pdev, snd_dev);
367 return 0;
368
369err_pdev:
370 platform_device_put(snd_dev);
371
372err_gpio:
373 detach_gpio_amp(pdata);
374
375err_clk:
376 clk_put(xtal_clk);
377 return ret;
378}
379EXPORT_SYMBOL_GPL(simtec_audio_core_probe);
380
381int __devexit simtec_audio_remove(struct platform_device *pdev)
382{
383 struct platform_device *snd_dev = platform_get_drvdata(pdev);
384
385 platform_device_unregister(snd_dev);
386
387 detach_gpio_amp(pdata);
388 clk_put(xtal_clk);
389 return 0;
390}
391EXPORT_SYMBOL_GPL(simtec_audio_remove);
392
393MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
394MODULE_DESCRIPTION("ALSA SoC Simtec Audio common support");
395MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/s3c24xx_simtec.h b/sound/soc/s3c24xx/s3c24xx_simtec.h
deleted file mode 100644
index e63d5ff9c41f..000000000000
--- a/sound/soc/s3c24xx/s3c24xx_simtec.h
+++ /dev/null
@@ -1,22 +0,0 @@
1/* sound/soc/s3c24xx/s3c24xx_simtec.h
2 *
3 * Copyright 2009 Simtec Electronics
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8*/
9
10extern void simtec_audio_init(struct snd_soc_pcm_runtime *rtd);
11
12extern int simtec_audio_core_probe(struct platform_device *pdev,
13 struct snd_soc_card *card);
14
15extern int simtec_audio_remove(struct platform_device *pdev);
16
17#ifdef CONFIG_PM
18extern const struct dev_pm_ops simtec_audio_pmops;
19#define simtec_audio_pm &simtec_audio_pmops
20#else
21#define simtec_audio_pm NULL
22#endif
diff --git a/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c b/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c
deleted file mode 100644
index f88453735ae2..000000000000
--- a/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c
+++ /dev/null
@@ -1,146 +0,0 @@
1/* sound/soc/s3c24xx/s3c24xx_simtec_hermes.c
2 *
3 * Copyright 2009 Simtec Electronics
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8*/
9
10#include <linux/module.h>
11#include <linux/clk.h>
12#include <linux/platform_device.h>
13
14#include <sound/core.h>
15#include <sound/pcm.h>
16#include <sound/soc.h>
17#include <sound/soc-dapm.h>
18
19#include <plat/audio-simtec.h>
20
21#include "s3c-dma.h"
22#include "s3c24xx-i2s.h"
23#include "s3c24xx_simtec.h"
24
25#include "../codecs/tlv320aic3x.h"
26
27static const struct snd_soc_dapm_widget dapm_widgets[] = {
28 SND_SOC_DAPM_LINE("GSM Out", NULL),
29 SND_SOC_DAPM_LINE("GSM In", NULL),
30 SND_SOC_DAPM_LINE("Line In", NULL),
31 SND_SOC_DAPM_LINE("Line Out", NULL),
32 SND_SOC_DAPM_LINE("ZV", NULL),
33 SND_SOC_DAPM_MIC("Mic Jack", NULL),
34 SND_SOC_DAPM_HP("Headphone Jack", NULL),
35};
36
37static const struct snd_soc_dapm_route base_map[] = {
38 /* Headphone connected to HP{L,R}OUT and HP{L,R}COM */
39
40 { "Headphone Jack", NULL, "HPLOUT" },
41 { "Headphone Jack", NULL, "HPLCOM" },
42 { "Headphone Jack", NULL, "HPROUT" },
43 { "Headphone Jack", NULL, "HPRCOM" },
44
45 /* ZV connected to Line1 */
46
47 { "LINE1L", NULL, "ZV" },
48 { "LINE1R", NULL, "ZV" },
49
50 /* Line In connected to Line2 */
51
52 { "LINE2L", NULL, "Line In" },
53 { "LINE2R", NULL, "Line In" },
54
55 /* Microphone connected to MIC3R and MIC_BIAS */
56
57 { "MIC3L", NULL, "Mic Jack" },
58
59 /* GSM connected to MONO_LOUT and MIC3L (in) */
60
61 { "GSM Out", NULL, "MONO_LOUT" },
62 { "MIC3L", NULL, "GSM In" },
63
64 /* Speaker is connected to LINEOUT{LN,LP,RN,RP}, however we are
65 * not using the DAPM to power it up and down as there it makes
66 * a click when powering up. */
67};
68
69/**
70 * simtec_hermes_init - initialise and add controls
71 * @codec; The codec instance to attach to.
72 *
73 * Attach our controls and configure the necessary codec
74 * mappings for our sound card instance.
75*/
76static int simtec_hermes_init(struct snd_soc_pcm_runtime *rtd)
77{
78 struct snd_soc_codec *codec = rtd->codec;
79
80 snd_soc_dapm_new_controls(codec, dapm_widgets,
81 ARRAY_SIZE(dapm_widgets));
82
83 snd_soc_dapm_add_routes(codec, base_map, ARRAY_SIZE(base_map));
84
85 snd_soc_dapm_enable_pin(codec, "Headphone Jack");
86 snd_soc_dapm_enable_pin(codec, "Line In");
87 snd_soc_dapm_enable_pin(codec, "Line Out");
88 snd_soc_dapm_enable_pin(codec, "Mic Jack");
89
90 simtec_audio_init(rtd);
91 snd_soc_dapm_sync(codec);
92
93 return 0;
94}
95
96static struct snd_soc_dai_link simtec_dai_aic33 = {
97 .name = "tlv320aic33",
98 .stream_name = "TLV320AIC33",
99 .codec_name = "tlv320aic3x-codec.0-0x1a",
100 .cpu_dai_name = "s3c24xx-i2s",
101 .codec_dai_name = "tlv320aic3x-hifi",
102 .platform_name = "s3c24xx-pcm-audio",
103 .init = simtec_hermes_init,
104};
105
106/* simtec audio machine driver */
107static struct snd_soc_card snd_soc_machine_simtec_aic33 = {
108 .name = "Simtec-Hermes",
109 .dai_link = &simtec_dai_aic33,
110 .num_links = 1,
111};
112
113static int __devinit simtec_audio_hermes_probe(struct platform_device *pd)
114{
115 dev_info(&pd->dev, "probing....\n");
116 return simtec_audio_core_probe(pd, &snd_soc_machine_simtec_aic33);
117}
118
119static struct platform_driver simtec_audio_hermes_platdrv = {
120 .driver = {
121 .owner = THIS_MODULE,
122 .name = "s3c24xx-simtec-hermes-snd",
123 .pm = simtec_audio_pm,
124 },
125 .probe = simtec_audio_hermes_probe,
126 .remove = __devexit_p(simtec_audio_remove),
127};
128
129MODULE_ALIAS("platform:s3c24xx-simtec-hermes-snd");
130
131static int __init simtec_hermes_modinit(void)
132{
133 return platform_driver_register(&simtec_audio_hermes_platdrv);
134}
135
136static void __exit simtec_hermes_modexit(void)
137{
138 platform_driver_unregister(&simtec_audio_hermes_platdrv);
139}
140
141module_init(simtec_hermes_modinit);
142module_exit(simtec_hermes_modexit);
143
144MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
145MODULE_DESCRIPTION("ALSA SoC Simtec Audio support");
146MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c b/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c
deleted file mode 100644
index c0967593510d..000000000000
--- a/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c
+++ /dev/null
@@ -1,134 +0,0 @@
1/* sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c
2 *
3 * Copyright 2009 Simtec Electronics
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8*/
9
10#include <linux/module.h>
11#include <linux/clk.h>
12#include <linux/platform_device.h>
13
14#include <sound/core.h>
15#include <sound/pcm.h>
16#include <sound/soc.h>
17#include <sound/soc-dapm.h>
18
19#include <plat/audio-simtec.h>
20
21#include "s3c-dma.h"
22#include "s3c24xx-i2s.h"
23#include "s3c24xx_simtec.h"
24
25#include "../codecs/tlv320aic23.h"
26
27/* supported machines:
28 *
29 * Machine Connections AMP
30 * ------- ----------- ---
31 * BAST MIC, HPOUT, LOUT, LIN TPA2001D1 (HPOUTL,R) (gain hardwired)
32 * VR1000 HPOUT, LIN None
33 * VR2000 LIN, LOUT, MIC, HP LM4871 (HPOUTL,R)
34 * DePicture LIN, LOUT, MIC, HP LM4871 (HPOUTL,R)
35 * Anubis LIN, LOUT, MIC, HP TPA2001D1 (HPOUTL,R)
36 */
37
38static const struct snd_soc_dapm_widget dapm_widgets[] = {
39 SND_SOC_DAPM_HP("Headphone Jack", NULL),
40 SND_SOC_DAPM_LINE("Line In", NULL),
41 SND_SOC_DAPM_LINE("Line Out", NULL),
42 SND_SOC_DAPM_MIC("Mic Jack", NULL),
43};
44
45static const struct snd_soc_dapm_route base_map[] = {
46 { "Headphone Jack", NULL, "LHPOUT"},
47 { "Headphone Jack", NULL, "RHPOUT"},
48
49 { "Line Out", NULL, "LOUT" },
50 { "Line Out", NULL, "ROUT" },
51
52 { "LLINEIN", NULL, "Line In"},
53 { "RLINEIN", NULL, "Line In"},
54
55 { "MICIN", NULL, "Mic Jack"},
56};
57
58/**
59 * simtec_tlv320aic23_init - initialise and add controls
60 * @codec; The codec instance to attach to.
61 *
62 * Attach our controls and configure the necessary codec
63 * mappings for our sound card instance.
64*/
65static int simtec_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)
66{
67 struct snd_soc_codec *codec = rtd->codec;
68
69 snd_soc_dapm_new_controls(codec, dapm_widgets,
70 ARRAY_SIZE(dapm_widgets));
71
72 snd_soc_dapm_add_routes(codec, base_map, ARRAY_SIZE(base_map));
73
74 snd_soc_dapm_enable_pin(codec, "Headphone Jack");
75 snd_soc_dapm_enable_pin(codec, "Line In");
76 snd_soc_dapm_enable_pin(codec, "Line Out");
77 snd_soc_dapm_enable_pin(codec, "Mic Jack");
78
79 simtec_audio_init(rtd);
80 snd_soc_dapm_sync(codec);
81
82 return 0;
83}
84
85static struct snd_soc_dai_link simtec_dai_aic23 = {
86 .name = "tlv320aic23",
87 .stream_name = "TLV320AIC23",
88 .codec_name = "tlv320aic3x-codec.0-0x1a",
89 .cpu_dai_name = "s3c24xx-i2s",
90 .codec_dai_name = "tlv320aic3x-hifi",
91 .platform_name = "s3c24xx-pcm-audio",
92 .init = simtec_tlv320aic23_init,
93};
94
95/* simtec audio machine driver */
96static struct snd_soc_card snd_soc_machine_simtec_aic23 = {
97 .name = "Simtec",
98 .dai_link = &simtec_dai_aic23,
99 .num_links = 1,
100};
101
102static int __devinit simtec_audio_tlv320aic23_probe(struct platform_device *pd)
103{
104 return simtec_audio_core_probe(pd, &snd_soc_machine_simtec_aic23);
105}
106
107static struct platform_driver simtec_audio_tlv320aic23_platdrv = {
108 .driver = {
109 .owner = THIS_MODULE,
110 .name = "s3c24xx-simtec-tlv320aic23",
111 .pm = simtec_audio_pm,
112 },
113 .probe = simtec_audio_tlv320aic23_probe,
114 .remove = __devexit_p(simtec_audio_remove),
115};
116
117MODULE_ALIAS("platform:s3c24xx-simtec-tlv320aic23");
118
119static int __init simtec_tlv320aic23_modinit(void)
120{
121 return platform_driver_register(&simtec_audio_tlv320aic23_platdrv);
122}
123
124static void __exit simtec_tlv320aic23_modexit(void)
125{
126 platform_driver_unregister(&simtec_audio_tlv320aic23_platdrv);
127}
128
129module_init(simtec_tlv320aic23_modinit);
130module_exit(simtec_tlv320aic23_modexit);
131
132MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
133MODULE_DESCRIPTION("ALSA SoC Simtec Audio support");
134MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/s3c24xx_uda134x.c b/sound/soc/s3c24xx/s3c24xx_uda134x.c
deleted file mode 100644
index bd48ffbde880..000000000000
--- a/sound/soc/s3c24xx/s3c24xx_uda134x.c
+++ /dev/null
@@ -1,368 +0,0 @@
1/*
2 * Modifications by Christian Pellegrin <chripell@evolware.org>
3 *
4 * s3c24xx_uda134x.c -- S3C24XX_UDA134X ALSA SoC Audio board driver
5 *
6 * Copyright 2007 Dension Audio Systems Ltd.
7 * Author: Zoltan Devai
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/module.h>
15#include <linux/clk.h>
16#include <linux/mutex.h>
17#include <linux/gpio.h>
18#include <sound/pcm.h>
19#include <sound/pcm_params.h>
20#include <sound/soc.h>
21#include <sound/soc-dapm.h>
22#include <sound/s3c24xx_uda134x.h>
23#include <sound/uda134x.h>
24
25#include <plat/regs-iis.h>
26
27#include "s3c-dma.h"
28#include "s3c24xx-i2s.h"
29#include "../codecs/uda134x.h"
30
31
32/* #define ENFORCE_RATES 1 */
33/*
34 Unfortunately the S3C24XX in master mode has a limited capacity of
35 generating the clock for the codec. If you define this only rates
36 that are really available will be enforced. But be careful, most
37 user level application just want the usual sampling frequencies (8,
38 11.025, 22.050, 44.1 kHz) and anyway resampling is a costly
39 operation for embedded systems. So if you aren't very lucky or your
40 hardware engineer wasn't very forward-looking it's better to leave
41 this undefined. If you do so an approximate value for the requested
42 sampling rate in the range -/+ 5% will be chosen. If this in not
43 possible an error will be returned.
44*/
45
46static struct clk *xtal;
47static struct clk *pclk;
48/* this is need because we don't have a place where to keep the
49 * pointers to the clocks in each substream. We get the clocks only
50 * when we are actually using them so we don't block stuff like
51 * frequency change or oscillator power-off */
52static int clk_users;
53static DEFINE_MUTEX(clk_lock);
54
55static unsigned int rates[33 * 2];
56#ifdef ENFORCE_RATES
57static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
58 .count = ARRAY_SIZE(rates),
59 .list = rates,
60 .mask = 0,
61};
62#endif
63
64static struct platform_device *s3c24xx_uda134x_snd_device;
65
66static int s3c24xx_uda134x_startup(struct snd_pcm_substream *substream)
67{
68 int ret = 0;
69#ifdef ENFORCE_RATES
70 struct snd_pcm_runtime *runtime = substream->runtime;
71#endif
72
73 mutex_lock(&clk_lock);
74 pr_debug("%s %d\n", __func__, clk_users);
75 if (clk_users == 0) {
76 xtal = clk_get(&s3c24xx_uda134x_snd_device->dev, "xtal");
77 if (!xtal) {
78 printk(KERN_ERR "%s cannot get xtal\n", __func__);
79 ret = -EBUSY;
80 } else {
81 pclk = clk_get(&s3c24xx_uda134x_snd_device->dev,
82 "pclk");
83 if (!pclk) {
84 printk(KERN_ERR "%s cannot get pclk\n",
85 __func__);
86 clk_put(xtal);
87 ret = -EBUSY;
88 }
89 }
90 if (!ret) {
91 int i, j;
92
93 for (i = 0; i < 2; i++) {
94 int fs = i ? 256 : 384;
95
96 rates[i*33] = clk_get_rate(xtal) / fs;
97 for (j = 1; j < 33; j++)
98 rates[i*33 + j] = clk_get_rate(pclk) /
99 (j * fs);
100 }
101 }
102 }
103 clk_users += 1;
104 mutex_unlock(&clk_lock);
105 if (!ret) {
106#ifdef ENFORCE_RATES
107 ret = snd_pcm_hw_constraint_list(runtime, 0,
108 SNDRV_PCM_HW_PARAM_RATE,
109 &hw_constraints_rates);
110 if (ret < 0)
111 printk(KERN_ERR "%s cannot set constraints\n",
112 __func__);
113#endif
114 }
115 return ret;
116}
117
118static void s3c24xx_uda134x_shutdown(struct snd_pcm_substream *substream)
119{
120 mutex_lock(&clk_lock);
121 pr_debug("%s %d\n", __func__, clk_users);
122 clk_users -= 1;
123 if (clk_users == 0) {
124 clk_put(xtal);
125 xtal = NULL;
126 clk_put(pclk);
127 pclk = NULL;
128 }
129 mutex_unlock(&clk_lock);
130}
131
132static int s3c24xx_uda134x_hw_params(struct snd_pcm_substream *substream,
133 struct snd_pcm_hw_params *params)
134{
135 struct snd_soc_pcm_runtime *rtd = substream->private_data;
136 struct snd_soc_dai *codec_dai = rtd->codec_dai;
137 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
138 unsigned int clk = 0;
139 int ret = 0;
140 int clk_source, fs_mode;
141 unsigned long rate = params_rate(params);
142 long err, cerr;
143 unsigned int div;
144 int i, bi;
145
146 err = 999999;
147 bi = 0;
148 for (i = 0; i < 2*33; i++) {
149 cerr = rates[i] - rate;
150 if (cerr < 0)
151 cerr = -cerr;
152 if (cerr < err) {
153 err = cerr;
154 bi = i;
155 }
156 }
157 if (bi / 33 == 1)
158 fs_mode = S3C2410_IISMOD_256FS;
159 else
160 fs_mode = S3C2410_IISMOD_384FS;
161 if (bi % 33 == 0) {
162 clk_source = S3C24XX_CLKSRC_MPLL;
163 div = 1;
164 } else {
165 clk_source = S3C24XX_CLKSRC_PCLK;
166 div = bi % 33;
167 }
168 pr_debug("%s desired rate %lu, %d\n", __func__, rate, bi);
169
170 clk = (fs_mode == S3C2410_IISMOD_384FS ? 384 : 256) * rate;
171 pr_debug("%s will use: %s %s %d sysclk %d err %ld\n", __func__,
172 fs_mode == S3C2410_IISMOD_384FS ? "384FS" : "256FS",
173 clk_source == S3C24XX_CLKSRC_MPLL ? "MPLLin" : "PCLK",
174 div, clk, err);
175
176 if ((err * 100 / rate) > 5) {
177 printk(KERN_ERR "S3C24XX_UDA134X: effective frequency "
178 "too different from desired (%ld%%)\n",
179 err * 100 / rate);
180 return -EINVAL;
181 }
182
183 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
184 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
185 if (ret < 0)
186 return ret;
187
188 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
189 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
190 if (ret < 0)
191 return ret;
192
193 ret = snd_soc_dai_set_sysclk(cpu_dai, clk_source , clk,
194 SND_SOC_CLOCK_IN);
195 if (ret < 0)
196 return ret;
197
198 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK, fs_mode);
199 if (ret < 0)
200 return ret;
201
202 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_BCLK,
203 S3C2410_IISMOD_32FS);
204 if (ret < 0)
205 return ret;
206
207 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
208 S3C24XX_PRESCALE(div, div));
209 if (ret < 0)
210 return ret;
211
212 /* set the codec system clock for DAC and ADC */
213 ret = snd_soc_dai_set_sysclk(codec_dai, 0, clk,
214 SND_SOC_CLOCK_OUT);
215 if (ret < 0)
216 return ret;
217
218 return 0;
219}
220
221static struct snd_soc_ops s3c24xx_uda134x_ops = {
222 .startup = s3c24xx_uda134x_startup,
223 .shutdown = s3c24xx_uda134x_shutdown,
224 .hw_params = s3c24xx_uda134x_hw_params,
225};
226
227static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = {
228 .name = "UDA134X",
229 .stream_name = "UDA134X",
230 .codec_name = "uda134x-hifi",
231 .codec_dai_name = "uda134x-hifi",
232 .cpu_dai_name = "s3c24xx-i2s",
233 .ops = &s3c24xx_uda134x_ops,
234 .platform_name = "s3c24xx-pcm-audio",
235};
236
237static struct snd_soc_card snd_soc_s3c24xx_uda134x = {
238 .name = "S3C24XX_UDA134X",
239 .dai_link = &s3c24xx_uda134x_dai_link,
240 .num_links = 1,
241};
242
243static struct s3c24xx_uda134x_platform_data *s3c24xx_uda134x_l3_pins;
244
245static void setdat(int v)
246{
247 gpio_set_value(s3c24xx_uda134x_l3_pins->l3_data, v > 0);
248}
249
250static void setclk(int v)
251{
252 gpio_set_value(s3c24xx_uda134x_l3_pins->l3_clk, v > 0);
253}
254
255static void setmode(int v)
256{
257 gpio_set_value(s3c24xx_uda134x_l3_pins->l3_mode, v > 0);
258}
259
260/* FIXME - This must be codec platform data but in which board file ?? */
261static struct uda134x_platform_data s3c24xx_uda134x = {
262 .l3 = {
263 .setdat = setdat,
264 .setclk = setclk,
265 .setmode = setmode,
266 .data_hold = 1,
267 .data_setup = 1,
268 .clock_high = 1,
269 .mode_hold = 1,
270 .mode = 1,
271 .mode_setup = 1,
272 },
273};
274
275static int s3c24xx_uda134x_setup_pin(int pin, char *fun)
276{
277 if (gpio_request(pin, "s3c24xx_uda134x") < 0) {
278 printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: "
279 "l3 %s pin already in use", fun);
280 return -EBUSY;
281 }
282 gpio_direction_output(pin, 0);
283 return 0;
284}
285
286static int s3c24xx_uda134x_probe(struct platform_device *pdev)
287{
288 int ret;
289
290 printk(KERN_INFO "S3C24XX_UDA134X SoC Audio driver\n");
291
292 s3c24xx_uda134x_l3_pins = pdev->dev.platform_data;
293 if (s3c24xx_uda134x_l3_pins == NULL) {
294 printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: "
295 "unable to find platform data\n");
296 return -ENODEV;
297 }
298 s3c24xx_uda134x.power = s3c24xx_uda134x_l3_pins->power;
299 s3c24xx_uda134x.model = s3c24xx_uda134x_l3_pins->model;
300
301 if (s3c24xx_uda134x_setup_pin(s3c24xx_uda134x_l3_pins->l3_data,
302 "data") < 0)
303 return -EBUSY;
304 if (s3c24xx_uda134x_setup_pin(s3c24xx_uda134x_l3_pins->l3_clk,
305 "clk") < 0) {
306 gpio_free(s3c24xx_uda134x_l3_pins->l3_data);
307 return -EBUSY;
308 }
309 if (s3c24xx_uda134x_setup_pin(s3c24xx_uda134x_l3_pins->l3_mode,
310 "mode") < 0) {
311 gpio_free(s3c24xx_uda134x_l3_pins->l3_data);
312 gpio_free(s3c24xx_uda134x_l3_pins->l3_clk);
313 return -EBUSY;
314 }
315
316 s3c24xx_uda134x_snd_device = platform_device_alloc("soc-audio", -1);
317 if (!s3c24xx_uda134x_snd_device) {
318 printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: "
319 "Unable to register\n");
320 return -ENOMEM;
321 }
322
323 platform_set_drvdata(s3c24xx_uda134x_snd_device,
324 &snd_soc_s3c24xx_uda134x);
325 ret = platform_device_add(s3c24xx_uda134x_snd_device);
326 if (ret) {
327 printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: Unable to add\n");
328 platform_device_put(s3c24xx_uda134x_snd_device);
329 }
330
331 return ret;
332}
333
334static int s3c24xx_uda134x_remove(struct platform_device *pdev)
335{
336 platform_device_unregister(s3c24xx_uda134x_snd_device);
337 gpio_free(s3c24xx_uda134x_l3_pins->l3_data);
338 gpio_free(s3c24xx_uda134x_l3_pins->l3_clk);
339 gpio_free(s3c24xx_uda134x_l3_pins->l3_mode);
340 return 0;
341}
342
343static struct platform_driver s3c24xx_uda134x_driver = {
344 .probe = s3c24xx_uda134x_probe,
345 .remove = s3c24xx_uda134x_remove,
346 .driver = {
347 .name = "s3c24xx_uda134x",
348 .owner = THIS_MODULE,
349 },
350};
351
352static int __init s3c24xx_uda134x_init(void)
353{
354 return platform_driver_register(&s3c24xx_uda134x_driver);
355}
356
357static void __exit s3c24xx_uda134x_exit(void)
358{
359 platform_driver_unregister(&s3c24xx_uda134x_driver);
360}
361
362
363module_init(s3c24xx_uda134x_init);
364module_exit(s3c24xx_uda134x_exit);
365
366MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>");
367MODULE_DESCRIPTION("S3C24XX_UDA134X ALSA SoC audio driver");
368MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s-v4.c b/sound/soc/s3c24xx/s3c64xx-i2s-v4.c
deleted file mode 100644
index a9628472ebfe..000000000000
--- a/sound/soc/s3c24xx/s3c64xx-i2s-v4.c
+++ /dev/null
@@ -1,230 +0,0 @@
1/* sound/soc/s3c24xx/s3c64xx-i2s-v4.c
2 *
3 * ALSA SoC Audio Layer - S3C64XX I2Sv4 driver
4 * Copyright (c) 2010 Samsung Electronics Co. Ltd
5 * Author: Jaswinder Singh <jassi.brar@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/clk.h>
13#include <linux/gpio.h>
14#include <linux/io.h>
15
16#include <sound/soc.h>
17#include <sound/pcm_params.h>
18
19#include <plat/audio.h>
20
21#include <mach/map.h>
22#include <mach/dma.h>
23
24#include "s3c-dma.h"
25#include "regs-i2s-v2.h"
26#include "s3c64xx-i2s.h"
27
28static struct s3c2410_dma_client s3c64xx_dma_client_out = {
29 .name = "I2Sv4 PCM Stereo out"
30};
31
32static struct s3c2410_dma_client s3c64xx_dma_client_in = {
33 .name = "I2Sv4 PCM Stereo in"
34};
35
36static struct s3c_dma_params s3c64xx_i2sv4_pcm_stereo_out;
37static struct s3c_dma_params s3c64xx_i2sv4_pcm_stereo_in;
38static struct s3c_i2sv2_info s3c64xx_i2sv4;
39
40static int s3c64xx_i2sv4_probe(struct snd_soc_dai *dai)
41{
42 struct s3c_i2sv2_info *i2s = &s3c64xx_i2sv4;
43 int ret = 0;
44
45 snd_soc_dai_set_drvdata(dai, i2s);
46
47 ret = s3c_i2sv2_probe(dai, i2s, i2s->base);
48
49 return ret;
50}
51
52static int s3c_i2sv4_hw_params(struct snd_pcm_substream *substream,
53 struct snd_pcm_hw_params *params,
54 struct snd_soc_dai *cpu_dai)
55{
56 struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(cpu_dai);
57 struct s3c_dma_params *dma_data;
58 u32 iismod;
59
60 dev_dbg(cpu_dai->dev, "Entered %s\n", __func__);
61
62 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
63 dma_data = i2s->dma_playback;
64 else
65 dma_data = i2s->dma_capture;
66
67 snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
68
69 iismod = readl(i2s->regs + S3C2412_IISMOD);
70 dev_dbg(cpu_dai->dev, "%s: r: IISMOD: %x\n", __func__, iismod);
71
72 iismod &= ~S3C64XX_IISMOD_BLC_MASK;
73 switch (params_format(params)) {
74 case SNDRV_PCM_FORMAT_S8:
75 iismod |= S3C64XX_IISMOD_BLC_8BIT;
76 break;
77 case SNDRV_PCM_FORMAT_S16_LE:
78 break;
79 case SNDRV_PCM_FORMAT_S24_LE:
80 iismod |= S3C64XX_IISMOD_BLC_24BIT;
81 break;
82 }
83
84 writel(iismod, i2s->regs + S3C2412_IISMOD);
85 dev_dbg(cpu_dai->dev, "%s: w: IISMOD: %x\n", __func__, iismod);
86
87 return 0;
88}
89
90static struct snd_soc_dai_ops s3c64xx_i2sv4_dai_ops = {
91 .hw_params = s3c_i2sv4_hw_params,
92};
93
94static struct snd_soc_dai_driver s3c64xx_i2s_v4_dai = {
95 .symmetric_rates = 1,
96 .playback = {
97 .channels_min = 2,
98 .channels_max = 2,
99 .rates = S3C64XX_I2S_RATES,
100 .formats = S3C64XX_I2S_FMTS,
101 },
102 .capture = {
103 .channels_min = 2,
104 .channels_max = 2,
105 .rates = S3C64XX_I2S_RATES,
106 .formats = S3C64XX_I2S_FMTS,
107 },
108 .probe = s3c64xx_i2sv4_probe,
109 .ops = &s3c64xx_i2sv4_dai_ops,
110};
111
112static __devinit int s3c64xx_i2sv4_dev_probe(struct platform_device *pdev)
113{
114 struct s3c_audio_pdata *i2s_pdata;
115 struct s3c_i2sv2_info *i2s;
116 struct resource *res;
117 int ret;
118
119 i2s = &s3c64xx_i2sv4;
120
121 i2s->feature |= S3C_FEATURE_CDCLKCON;
122
123 i2s->dma_capture = &s3c64xx_i2sv4_pcm_stereo_in;
124 i2s->dma_playback = &s3c64xx_i2sv4_pcm_stereo_out;
125
126 res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
127 if (!res) {
128 dev_err(&pdev->dev, "Unable to get I2S-TX dma resource\n");
129 return -ENXIO;
130 }
131 i2s->dma_playback->channel = res->start;
132
133 res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
134 if (!res) {
135 dev_err(&pdev->dev, "Unable to get I2S-RX dma resource\n");
136 return -ENXIO;
137 }
138 i2s->dma_capture->channel = res->start;
139
140 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
141 if (!res) {
142 dev_err(&pdev->dev, "Unable to get I2S SFR address\n");
143 return -ENXIO;
144 }
145
146 if (!request_mem_region(res->start, resource_size(res),
147 "s3c64xx-i2s-v4")) {
148 dev_err(&pdev->dev, "Unable to request SFR region\n");
149 return -EBUSY;
150 }
151 i2s->dma_capture->dma_addr = res->start + S3C2412_IISRXD;
152 i2s->dma_playback->dma_addr = res->start + S3C2412_IISTXD;
153
154 i2s->dma_capture->client = &s3c64xx_dma_client_in;
155 i2s->dma_capture->dma_size = 4;
156 i2s->dma_playback->client = &s3c64xx_dma_client_out;
157 i2s->dma_playback->dma_size = 4;
158
159 i2s->base = res->start;
160
161 i2s_pdata = pdev->dev.platform_data;
162 if (i2s_pdata && i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) {
163 dev_err(&pdev->dev, "Unable to configure gpio\n");
164 return -EINVAL;
165 }
166
167 i2s->iis_cclk = clk_get(&pdev->dev, "audio-bus");
168 if (IS_ERR(i2s->iis_cclk)) {
169 dev_err(&pdev->dev, "failed to get audio-bus\n");
170 ret = PTR_ERR(i2s->iis_cclk);
171 goto err;
172 }
173
174 clk_enable(i2s->iis_cclk);
175
176 ret = s3c_i2sv2_register_dai(&pdev->dev, pdev->id, &s3c64xx_i2s_v4_dai);
177 if (ret != 0)
178 goto err_i2sv2;
179
180 return 0;
181
182err_i2sv2:
183 clk_put(i2s->iis_cclk);
184err:
185 return ret;
186}
187
188static __devexit int s3c64xx_i2sv4_dev_remove(struct platform_device *pdev)
189{
190 struct s3c_i2sv2_info *i2s = &s3c64xx_i2sv4;
191 struct resource *res;
192
193 snd_soc_unregister_dai(&pdev->dev);
194 clk_put(i2s->iis_cclk);
195
196 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
197 if (res)
198 release_mem_region(res->start, resource_size(res));
199 else
200 dev_warn(&pdev->dev, "Unable to get I2S SFR address\n");
201
202 return 0;
203}
204
205static struct platform_driver s3c64xx_i2sv4_driver = {
206 .probe = s3c64xx_i2sv4_dev_probe,
207 .remove = s3c64xx_i2sv4_dev_remove,
208 .driver = {
209 .name = "s3c64xx-iis-v4",
210 .owner = THIS_MODULE,
211 },
212};
213
214static int __init s3c64xx_i2sv4_init(void)
215{
216 return platform_driver_register(&s3c64xx_i2sv4_driver);
217}
218module_init(s3c64xx_i2sv4_init);
219
220static void __exit s3c64xx_i2sv4_exit(void)
221{
222 platform_driver_unregister(&s3c64xx_i2sv4_driver);
223}
224module_exit(s3c64xx_i2sv4_exit);
225
226/* Module information */
227MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");
228MODULE_DESCRIPTION("S3C64XX I2Sv4 SoC Interface");
229MODULE_LICENSE("GPL");
230MODULE_ALIAS("platform:s3c64xx-iis-v4");
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.c b/sound/soc/s3c24xx/s3c64xx-i2s.c
deleted file mode 100644
index ae7acb6c4f1d..000000000000
--- a/sound/soc/s3c24xx/s3c64xx-i2s.c
+++ /dev/null
@@ -1,242 +0,0 @@
1/* sound/soc/s3c24xx/s3c64xx-i2s.c
2 *
3 * ALSA SoC Audio Layer - S3C64XX I2S driver
4 *
5 * Copyright 2008 Openmoko, Inc.
6 * Copyright 2008 Simtec Electronics
7 * Ben Dooks <ben@simtec.co.uk>
8 * http://armlinux.simtec.co.uk/
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/module.h>
16#include <linux/clk.h>
17#include <linux/gpio.h>
18#include <linux/io.h>
19#include <linux/slab.h>
20
21#include <sound/soc.h>
22
23#include <plat/audio.h>
24
25#include <mach/map.h>
26#include <mach/dma.h>
27
28#include "s3c-dma.h"
29#include "regs-i2s-v2.h"
30#include "s3c64xx-i2s.h"
31
32/* The value should be set to maximum of the total number
33 * of I2Sv3 controllers that any supported SoC has.
34 */
35#define MAX_I2SV3 2
36
37static struct s3c2410_dma_client s3c64xx_dma_client_out = {
38 .name = "I2S PCM Stereo out"
39};
40
41static struct s3c2410_dma_client s3c64xx_dma_client_in = {
42 .name = "I2S PCM Stereo in"
43};
44
45static struct s3c_dma_params s3c64xx_i2s_pcm_stereo_out[MAX_I2SV3];
46static struct s3c_dma_params s3c64xx_i2s_pcm_stereo_in[MAX_I2SV3];
47static struct s3c_i2sv2_info s3c64xx_i2s[MAX_I2SV3];
48
49struct clk *s3c64xx_i2s_get_clock(struct snd_soc_dai *dai)
50{
51 struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(dai);
52 u32 iismod = readl(i2s->regs + S3C2412_IISMOD);
53
54 if (iismod & S3C2412_IISMOD_IMS_SYSMUX)
55 return i2s->iis_cclk;
56 else
57 return i2s->iis_pclk;
58}
59EXPORT_SYMBOL_GPL(s3c64xx_i2s_get_clock);
60
61static int s3c64xx_i2s_probe(struct snd_soc_dai *dai)
62{
63 struct s3c_i2sv2_info *i2s;
64 int ret;
65
66 if (dai->id >= MAX_I2SV3) {
67 dev_err(dai->dev, "id %d out of range\n", dai->id);
68 return -EINVAL;
69 }
70
71 i2s = &s3c64xx_i2s[dai->id];
72 snd_soc_dai_set_drvdata(dai, i2s);
73
74 i2s->iis_cclk = clk_get(dai->dev, "audio-bus");
75 if (IS_ERR(i2s->iis_cclk)) {
76 dev_err(dai->dev, "failed to get audio-bus\n");
77 ret = PTR_ERR(i2s->iis_cclk);
78 goto err;
79 }
80
81 clk_enable(i2s->iis_cclk);
82
83 ret = s3c_i2sv2_probe(dai, i2s, i2s->base);
84 if (ret)
85 goto err_clk;
86
87 return 0;
88
89err_clk:
90 clk_disable(i2s->iis_cclk);
91 clk_put(i2s->iis_cclk);
92err:
93 kfree(i2s);
94 return ret;
95}
96
97static int s3c64xx_i2s_remove(struct snd_soc_dai *dai)
98{
99 struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(dai);
100
101 clk_disable(i2s->iis_cclk);
102 clk_put(i2s->iis_cclk);
103 kfree(i2s);
104 return 0;
105}
106
107static struct snd_soc_dai_ops s3c64xx_i2s_dai_ops;
108
109static struct snd_soc_dai_driver s3c64xx_i2s_dai[MAX_I2SV3] = {
110{
111 .name = "s3c64xx-i2s-0",
112 .probe = s3c64xx_i2s_probe,
113 .remove = s3c64xx_i2s_remove,
114 .playback = {
115 .channels_min = 2,
116 .channels_max = 2,
117 .rates = S3C64XX_I2S_RATES,
118 .formats = S3C64XX_I2S_FMTS,},
119 .capture = {
120 .channels_min = 2,
121 .channels_max = 2,
122 .rates = S3C64XX_I2S_RATES,
123 .formats = S3C64XX_I2S_FMTS,},
124 .ops = &s3c64xx_i2s_dai_ops,
125 .symmetric_rates = 1,
126}, {
127 .name = "s3c64xx-i2s-1",
128 .probe = s3c64xx_i2s_probe,
129 .remove = s3c64xx_i2s_remove,
130 .playback = {
131 .channels_min = 2,
132 .channels_max = 2,
133 .rates = S3C64XX_I2S_RATES,
134 .formats = S3C64XX_I2S_FMTS,},
135 .capture = {
136 .channels_min = 2,
137 .channels_max = 2,
138 .rates = S3C64XX_I2S_RATES,
139 .formats = S3C64XX_I2S_FMTS,},
140 .ops = &s3c64xx_i2s_dai_ops,
141 .symmetric_rates = 1,
142},};
143
144static __devinit int s3c64xx_iis_dev_probe(struct platform_device *pdev)
145{
146 struct s3c_audio_pdata *i2s_pdata;
147 struct s3c_i2sv2_info *i2s;
148 struct resource *res;
149 int i, ret;
150
151 if (pdev->id >= MAX_I2SV3) {
152 dev_err(&pdev->dev, "id %d out of range\n", pdev->id);
153 return -EINVAL;
154 }
155
156 i2s = &s3c64xx_i2s[pdev->id];
157
158 i2s->dma_capture = &s3c64xx_i2s_pcm_stereo_in[pdev->id];
159 i2s->dma_playback = &s3c64xx_i2s_pcm_stereo_out[pdev->id];
160
161 res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
162 if (!res) {
163 dev_err(&pdev->dev, "Unable to get I2S-TX dma resource\n");
164 return -ENXIO;
165 }
166 i2s->dma_playback->channel = res->start;
167
168 res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
169 if (!res) {
170 dev_err(&pdev->dev, "Unable to get I2S-RX dma resource\n");
171 return -ENXIO;
172 }
173 i2s->dma_capture->channel = res->start;
174
175 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
176 if (!res) {
177 dev_err(&pdev->dev, "Unable to get I2S SFR address\n");
178 return -ENXIO;
179 }
180
181 if (!request_mem_region(res->start, resource_size(res),
182 "s3c64xx-i2s")) {
183 dev_err(&pdev->dev, "Unable to request SFR region\n");
184 return -EBUSY;
185 }
186 i2s->base = res->start;
187
188 i2s_pdata = pdev->dev.platform_data;
189 if (i2s_pdata && i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) {
190 dev_err(&pdev->dev, "Unable to configure gpio\n");
191 return -EINVAL;
192 }
193 i2s->dma_capture->dma_addr = res->start + S3C2412_IISRXD;
194 i2s->dma_playback->dma_addr = res->start + S3C2412_IISTXD;
195
196 i2s->dma_capture->client = &s3c64xx_dma_client_in;
197 i2s->dma_capture->dma_size = 4;
198 i2s->dma_playback->client = &s3c64xx_dma_client_out;
199 i2s->dma_playback->dma_size = 4;
200
201 for (i = 0; i < ARRAY_SIZE(s3c64xx_i2s_dai); i++) {
202 ret = s3c_i2sv2_register_dai(&pdev->dev, i,
203 &s3c64xx_i2s_dai[i]);
204 if (ret != 0)
205 return ret;
206 }
207
208 return 0;
209}
210
211static __devexit int s3c64xx_iis_dev_remove(struct platform_device *pdev)
212{
213 snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(s3c64xx_i2s_dai));
214 return 0;
215}
216
217static struct platform_driver s3c64xx_iis_driver = {
218 .probe = s3c64xx_iis_dev_probe,
219 .remove = s3c64xx_iis_dev_remove,
220 .driver = {
221 .name = "s3c64xx-iis",
222 .owner = THIS_MODULE,
223 },
224};
225
226static int __init s3c64xx_i2s_init(void)
227{
228 return platform_driver_register(&s3c64xx_iis_driver);
229}
230module_init(s3c64xx_i2s_init);
231
232static void __exit s3c64xx_i2s_exit(void)
233{
234 platform_driver_unregister(&s3c64xx_iis_driver);
235}
236module_exit(s3c64xx_i2s_exit);
237
238/* Module information */
239MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
240MODULE_DESCRIPTION("S3C64XX I2S SoC Interface");
241MODULE_LICENSE("GPL");
242MODULE_ALIAS("platform:s3c64xx-iis");
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.h b/sound/soc/s3c24xx/s3c64xx-i2s.h
deleted file mode 100644
index de4075d26f0c..000000000000
--- a/sound/soc/s3c24xx/s3c64xx-i2s.h
+++ /dev/null
@@ -1,41 +0,0 @@
1/* sound/soc/s3c24xx/s3c64xx-i2s.h
2 *
3 * ALSA SoC Audio Layer - S3C64XX I2S driver
4 *
5 * Copyright 2008 Openmoko, Inc.
6 * Copyright 2008 Simtec Electronics
7 * Ben Dooks <ben@simtec.co.uk>
8 * http://armlinux.simtec.co.uk/
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#ifndef __SND_SOC_S3C24XX_S3C64XX_I2S_H
16#define __SND_SOC_S3C24XX_S3C64XX_I2S_H __FILE__
17
18struct clk;
19
20#include "s3c-i2s-v2.h"
21
22#define S3C64XX_DIV_BCLK S3C_I2SV2_DIV_BCLK
23#define S3C64XX_DIV_RCLK S3C_I2SV2_DIV_RCLK
24#define S3C64XX_DIV_PRESCALER S3C_I2SV2_DIV_PRESCALER
25
26#define S3C64XX_CLKSRC_PCLK S3C_I2SV2_CLKSRC_PCLK
27#define S3C64XX_CLKSRC_MUX S3C_I2SV2_CLKSRC_AUDIOBUS
28#define S3C64XX_CLKSRC_CDCLK S3C_I2SV2_CLKSRC_CDCLK
29
30#define S3C64XX_I2S_RATES \
31 (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
32 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
33 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
34
35#define S3C64XX_I2S_FMTS \
36 (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
37 SNDRV_PCM_FMTBIT_S24_LE)
38
39struct clk *s3c64xx_i2s_get_clock(struct snd_soc_dai *dai);
40
41#endif /* __SND_SOC_S3C24XX_S3C64XX_I2S_H */
diff --git a/sound/soc/s3c24xx/smartq_wm8987.c b/sound/soc/s3c24xx/smartq_wm8987.c
deleted file mode 100644
index dd20ca7f4681..000000000000
--- a/sound/soc/s3c24xx/smartq_wm8987.c
+++ /dev/null
@@ -1,290 +0,0 @@
1/* sound/soc/s3c24xx/smartq_wm8987.c
2 *
3 * Copyright 2010 Maurus Cuelenaere <mcuelenaere@gmail.com>
4 *
5 * Based on smdk6410_wm8987.c
6 * Copyright 2007 Wolfson Microelectronics PLC. - linux@wolfsonmicro.com
7 * Graeme Gregory - graeme.gregory@wolfsonmicro.com
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 */
15
16#include <linux/module.h>
17#include <linux/platform_device.h>
18#include <linux/gpio.h>
19
20#include <sound/pcm.h>
21#include <sound/pcm_params.h>
22#include <sound/soc-dapm.h>
23#include <sound/jack.h>
24
25#include <asm/mach-types.h>
26
27#include "s3c-dma.h"
28#include "s3c64xx-i2s.h"
29
30#include "../codecs/wm8750.h"
31
32/*
33 * WM8987 is register compatible with WM8750, so using that as base driver.
34 */
35
36static struct snd_soc_card snd_soc_smartq;
37
38static int smartq_hifi_hw_params(struct snd_pcm_substream *substream,
39 struct snd_pcm_hw_params *params)
40{
41 struct snd_soc_pcm_runtime *rtd = substream->private_data;
42 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
43 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
44 struct s3c_i2sv2_rate_calc div;
45 unsigned int clk = 0;
46 int ret;
47
48 s3c_i2sv2_iis_calc_rate(&div, NULL, params_rate(params),
49 s3c_i2sv2_get_clock(cpu_dai));
50
51 switch (params_rate(params)) {
52 case 8000:
53 case 16000:
54 case 32000:
55 case 48000:
56 case 96000:
57 clk = 12288000;
58 break;
59 case 11025:
60 case 22050:
61 case 44100:
62 case 88200:
63 clk = 11289600;
64 break;
65 }
66
67 /* set codec DAI configuration */
68 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
69 SND_SOC_DAIFMT_NB_NF |
70 SND_SOC_DAIFMT_CBS_CFS);
71 if (ret < 0)
72 return ret;
73
74 /* set cpu DAI configuration */
75 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
76 SND_SOC_DAIFMT_NB_NF |
77 SND_SOC_DAIFMT_CBS_CFS);
78 if (ret < 0)
79 return ret;
80
81 /* set the codec system clock for DAC and ADC */
82 ret = snd_soc_dai_set_sysclk(codec_dai, WM8750_SYSCLK, clk,
83 SND_SOC_CLOCK_IN);
84 if (ret < 0)
85 return ret;
86
87 /* set MCLK division for sample rate */
88 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C_I2SV2_DIV_RCLK, div.fs_div);
89 if (ret < 0)
90 return ret;
91
92 /* set prescaler division for sample rate */
93 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C_I2SV2_DIV_PRESCALER,
94 div.clk_div - 1);
95 if (ret < 0)
96 return ret;
97
98 return 0;
99}
100
101/*
102 * SmartQ WM8987 HiFi DAI operations.
103 */
104static struct snd_soc_ops smartq_hifi_ops = {
105 .hw_params = smartq_hifi_hw_params,
106};
107
108static struct snd_soc_jack smartq_jack;
109
110static struct snd_soc_jack_pin smartq_jack_pins[] = {
111 /* Disable speaker when headphone is plugged in */
112 {
113 .pin = "Internal Speaker",
114 .mask = SND_JACK_HEADPHONE,
115 },
116};
117
118static struct snd_soc_jack_gpio smartq_jack_gpios[] = {
119 {
120 .gpio = S3C64XX_GPL(12),
121 .name = "headphone detect",
122 .report = SND_JACK_HEADPHONE,
123 .debounce_time = 200,
124 },
125};
126
127static const struct snd_kcontrol_new wm8987_smartq_controls[] = {
128 SOC_DAPM_PIN_SWITCH("Internal Speaker"),
129 SOC_DAPM_PIN_SWITCH("Headphone Jack"),
130 SOC_DAPM_PIN_SWITCH("Internal Mic"),
131};
132
133static int smartq_speaker_event(struct snd_soc_dapm_widget *w,
134 struct snd_kcontrol *k,
135 int event)
136{
137 gpio_set_value(S3C64XX_GPK(12), SND_SOC_DAPM_EVENT_OFF(event));
138
139 return 0;
140}
141
142static const struct snd_soc_dapm_widget wm8987_dapm_widgets[] = {
143 SND_SOC_DAPM_SPK("Internal Speaker", smartq_speaker_event),
144 SND_SOC_DAPM_HP("Headphone Jack", NULL),
145 SND_SOC_DAPM_MIC("Internal Mic", NULL),
146};
147
148static const struct snd_soc_dapm_route audio_map[] = {
149 {"Headphone Jack", NULL, "LOUT2"},
150 {"Headphone Jack", NULL, "ROUT2"},
151
152 {"Internal Speaker", NULL, "LOUT2"},
153 {"Internal Speaker", NULL, "ROUT2"},
154
155 {"Mic Bias", NULL, "Internal Mic"},
156 {"LINPUT2", NULL, "Mic Bias"},
157};
158
159static int smartq_wm8987_init(struct snd_soc_codec *codec)
160{
161 int err = 0;
162
163 /* Add SmartQ specific widgets */
164 snd_soc_dapm_new_controls(codec, wm8987_dapm_widgets,
165 ARRAY_SIZE(wm8987_dapm_widgets));
166
167 /* add SmartQ specific controls */
168 err = snd_soc_add_controls(codec, wm8987_smartq_controls,
169 ARRAY_SIZE(wm8987_smartq_controls));
170
171 if (err < 0)
172 return err;
173
174 /* setup SmartQ specific audio path */
175 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
176
177 /* set endpoints to not connected */
178 snd_soc_dapm_nc_pin(codec, "LINPUT1");
179 snd_soc_dapm_nc_pin(codec, "RINPUT1");
180 snd_soc_dapm_nc_pin(codec, "OUT3");
181 snd_soc_dapm_nc_pin(codec, "ROUT1");
182
183 /* set endpoints to default off mode */
184 snd_soc_dapm_enable_pin(codec, "Internal Speaker");
185 snd_soc_dapm_enable_pin(codec, "Internal Mic");
186 snd_soc_dapm_disable_pin(codec, "Headphone Jack");
187
188 err = snd_soc_dapm_sync(codec);
189 if (err)
190 return err;
191
192 /* Headphone jack detection */
193 err = snd_soc_jack_new(&snd_soc_smartq, "Headphone Jack",
194 SND_JACK_HEADPHONE, &smartq_jack);
195 if (err)
196 return err;
197
198 err = snd_soc_jack_add_pins(&smartq_jack, ARRAY_SIZE(smartq_jack_pins),
199 smartq_jack_pins);
200 if (err)
201 return err;
202
203 err = snd_soc_jack_add_gpios(&smartq_jack,
204 ARRAY_SIZE(smartq_jack_gpios),
205 smartq_jack_gpios);
206
207 return err;
208}
209
210static struct snd_soc_dai_link smartq_dai[] = {
211 {
212 .name = "wm8987",
213 .stream_name = "SmartQ Hi-Fi",
214 .cpu_dai_name = "s3c64xx-i2s.0",
215 .codec_dai_name = "wm8750-hifi",
216 .platform_name = "s3c24xx-pcm-audio",
217 .codec_name = "wm8750-codec.0-0x1a",
218 .init = smartq_wm8987_init,
219 .ops = &smartq_hifi_ops,
220 },
221};
222
223static struct snd_soc_card snd_soc_smartq = {
224 .name = "SmartQ",
225 .dai_link = smartq_dai,
226 .num_links = ARRAY_SIZE(smartq_dai),
227};
228
229static struct platform_device *smartq_snd_device;
230
231static int __init smartq_init(void)
232{
233 int ret;
234
235 if (!machine_is_smartq7() && !machine_is_smartq5()) {
236 pr_info("Only SmartQ is supported by this ASoC driver\n");
237 return -ENODEV;
238 }
239
240 smartq_snd_device = platform_device_alloc("soc-audio", -1);
241 if (!smartq_snd_device)
242 return -ENOMEM;
243
244 platform_set_drvdata(smartq_snd_device, &snd_soc_smartq);
245
246 ret = platform_device_add(smartq_snd_device);
247 if (ret) {
248 platform_device_put(smartq_snd_device);
249 return ret;
250 }
251
252 /* Initialise GPIOs used by amplifiers */
253 ret = gpio_request(S3C64XX_GPK(12), "amplifiers shutdown");
254 if (ret) {
255 dev_err(&smartq_snd_device->dev, "Failed to register GPK12\n");
256 goto err_unregister_device;
257 }
258
259 /* Disable amplifiers */
260 ret = gpio_direction_output(S3C64XX_GPK(12), 1);
261 if (ret) {
262 dev_err(&smartq_snd_device->dev, "Failed to configure GPK12\n");
263 goto err_free_gpio_amp_shut;
264 }
265
266 return 0;
267
268err_free_gpio_amp_shut:
269 gpio_free(S3C64XX_GPK(12));
270err_unregister_device:
271 platform_device_unregister(smartq_snd_device);
272
273 return ret;
274}
275
276static void __exit smartq_exit(void)
277{
278 snd_soc_jack_free_gpios(&smartq_jack, ARRAY_SIZE(smartq_jack_gpios),
279 smartq_jack_gpios);
280
281 platform_device_unregister(smartq_snd_device);
282}
283
284module_init(smartq_init);
285module_exit(smartq_exit);
286
287/* Module information */
288MODULE_AUTHOR("Maurus Cuelenaere <mcuelenaere@gmail.com>");
289MODULE_DESCRIPTION("ALSA SoC SmartQ WM8987");
290MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/smdk2443_wm9710.c b/sound/soc/s3c24xx/smdk2443_wm9710.c
deleted file mode 100644
index 4613288c2772..000000000000
--- a/sound/soc/s3c24xx/smdk2443_wm9710.c
+++ /dev/null
@@ -1,74 +0,0 @@
1/*
2 * smdk2443_wm9710.c -- SoC audio for smdk2443
3 *
4 * Copyright 2007 Wolfson Microelectronics PLC.
5 * Author: Graeme Gregory
6 * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 */
14
15#include <linux/module.h>
16#include <linux/device.h>
17#include <sound/core.h>
18#include <sound/pcm.h>
19#include <sound/soc.h>
20#include <sound/soc-dapm.h>
21
22#include "s3c-dma.h"
23#include "s3c-ac97.h"
24
25static struct snd_soc_card smdk2443;
26
27static struct snd_soc_dai_link smdk2443_dai[] = {
28{
29 .name = "AC97",
30 .stream_name = "AC97 HiFi",
31 .cpu_dai_name = "s3c-ac97",
32 .codec_dai_name = "ac97-hifi",
33 .codec_name = "ac97-codec",
34 .platform_name = "s3c24xx-pcm-audio",
35},
36};
37
38static struct snd_soc_card smdk2443 = {
39 .name = "SMDK2443",
40 .dai_link = smdk2443_dai,
41 .num_links = ARRAY_SIZE(smdk2443_dai),
42};
43
44static struct platform_device *smdk2443_snd_ac97_device;
45
46static int __init smdk2443_init(void)
47{
48 int ret;
49
50 smdk2443_snd_ac97_device = platform_device_alloc("soc-audio", -1);
51 if (!smdk2443_snd_ac97_device)
52 return -ENOMEM;
53
54 platform_set_drvdata(smdk2443_snd_ac97_device, &smdk2443);
55 ret = platform_device_add(smdk2443_snd_ac97_device);
56
57 if (ret)
58 platform_device_put(smdk2443_snd_ac97_device);
59
60 return ret;
61}
62
63static void __exit smdk2443_exit(void)
64{
65 platform_device_unregister(smdk2443_snd_ac97_device);
66}
67
68module_init(smdk2443_init);
69module_exit(smdk2443_exit);
70
71/* Module information */
72MODULE_AUTHOR("Graeme Gregory, graeme.gregory@wolfsonmicro.com, www.wolfsonmicro.com");
73MODULE_DESCRIPTION("ALSA SoC WM9710 SMDK2443");
74MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/smdk64xx_wm8580.c b/sound/soc/s3c24xx/smdk64xx_wm8580.c
deleted file mode 100644
index 052e499b68d1..000000000000
--- a/sound/soc/s3c24xx/smdk64xx_wm8580.c
+++ /dev/null
@@ -1,272 +0,0 @@
1/*
2 * smdk64xx_wm8580.c
3 *
4 * Copyright (c) 2009 Samsung Electronics Co. Ltd
5 * Author: Jaswinder Singh <jassi.brar@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#include <linux/platform_device.h>
14#include <linux/clk.h>
15#include <sound/core.h>
16#include <sound/pcm.h>
17#include <sound/pcm_params.h>
18#include <sound/soc.h>
19#include <sound/soc-dapm.h>
20
21#include "../codecs/wm8580.h"
22#include "s3c-dma.h"
23#include "s3c64xx-i2s.h"
24
25/*
26 * Default CFG switch settings to use this driver:
27 *
28 * SMDK6410: Set CFG1 1-3 Off, CFG2 1-4 On
29 */
30
31/* SMDK64XX has a 12MHZ crystal attached to WM8580 */
32#define SMDK64XX_WM8580_FREQ 12000000
33
34static int smdk64xx_hw_params(struct snd_pcm_substream *substream,
35 struct snd_pcm_hw_params *params)
36{
37 struct snd_soc_pcm_runtime *rtd = substream->private_data;
38 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
39 struct snd_soc_dai *codec_dai = rtd->codec_dai;
40 unsigned int pll_out;
41 int bfs, rfs, ret;
42
43 switch (params_format(params)) {
44 case SNDRV_PCM_FORMAT_U8:
45 case SNDRV_PCM_FORMAT_S8:
46 bfs = 16;
47 break;
48 case SNDRV_PCM_FORMAT_U16_LE:
49 case SNDRV_PCM_FORMAT_S16_LE:
50 bfs = 32;
51 break;
52 default:
53 return -EINVAL;
54 }
55
56 /* The Fvco for WM8580 PLLs must fall within [90,100]MHz.
57 * This criterion can't be met if we request PLL output
58 * as {8000x256, 64000x256, 11025x256}Hz.
59 * As a wayout, we rather change rfs to a minimum value that
60 * results in (params_rate(params) * rfs), and itself, acceptable
61 * to both - the CODEC and the CPU.
62 */
63 switch (params_rate(params)) {
64 case 16000:
65 case 22050:
66 case 32000:
67 case 44100:
68 case 48000:
69 case 88200:
70 case 96000:
71 rfs = 256;
72 break;
73 case 64000:
74 rfs = 384;
75 break;
76 case 8000:
77 case 11025:
78 rfs = 512;
79 break;
80 default:
81 return -EINVAL;
82 }
83 pll_out = params_rate(params) * rfs;
84
85 /* Set the Codec DAI configuration */
86 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S
87 | SND_SOC_DAIFMT_NB_NF
88 | SND_SOC_DAIFMT_CBM_CFM);
89 if (ret < 0)
90 return ret;
91
92 /* Set the AP DAI configuration */
93 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S
94 | SND_SOC_DAIFMT_NB_NF
95 | SND_SOC_DAIFMT_CBM_CFM);
96 if (ret < 0)
97 return ret;
98
99 ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_CDCLK,
100 0, SND_SOC_CLOCK_IN);
101 if (ret < 0)
102 return ret;
103
104 /* We use PCLK for basic ops in SoC-Slave mode */
105 ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_PCLK,
106 0, SND_SOC_CLOCK_IN);
107 if (ret < 0)
108 return ret;
109
110 /* Set WM8580 to drive MCLK from its PLLA */
111 ret = snd_soc_dai_set_clkdiv(codec_dai, WM8580_MCLK,
112 WM8580_CLKSRC_PLLA);
113 if (ret < 0)
114 return ret;
115
116 ret = snd_soc_dai_set_pll(codec_dai, WM8580_PLLA, 0,
117 SMDK64XX_WM8580_FREQ, pll_out);
118 if (ret < 0)
119 return ret;
120
121 ret = snd_soc_dai_set_sysclk(codec_dai, WM8580_CLKSRC_PLLA,
122 pll_out, SND_SOC_CLOCK_IN);
123 if (ret < 0)
124 return ret;
125
126 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C_I2SV2_DIV_BCLK, bfs);
127 if (ret < 0)
128 return ret;
129
130 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C_I2SV2_DIV_RCLK, rfs);
131 if (ret < 0)
132 return ret;
133
134 return 0;
135}
136
137/*
138 * SMDK64XX WM8580 DAI operations.
139 */
140static struct snd_soc_ops smdk64xx_ops = {
141 .hw_params = smdk64xx_hw_params,
142};
143
144/* SMDK64xx Playback widgets */
145static const struct snd_soc_dapm_widget wm8580_dapm_widgets_pbk[] = {
146 SND_SOC_DAPM_HP("Front", NULL),
147 SND_SOC_DAPM_HP("Center+Sub", NULL),
148 SND_SOC_DAPM_HP("Rear", NULL),
149};
150
151/* SMDK64xx Capture widgets */
152static const struct snd_soc_dapm_widget wm8580_dapm_widgets_cpt[] = {
153 SND_SOC_DAPM_MIC("MicIn", NULL),
154 SND_SOC_DAPM_LINE("LineIn", NULL),
155};
156
157/* SMDK-PAIFTX connections */
158static const struct snd_soc_dapm_route audio_map_tx[] = {
159 /* MicIn feeds AINL */
160 {"AINL", NULL, "MicIn"},
161
162 /* LineIn feeds AINL/R */
163 {"AINL", NULL, "LineIn"},
164 {"AINR", NULL, "LineIn"},
165};
166
167/* SMDK-PAIFRX connections */
168static const struct snd_soc_dapm_route audio_map_rx[] = {
169 /* Front Left/Right are fed VOUT1L/R */
170 {"Front", NULL, "VOUT1L"},
171 {"Front", NULL, "VOUT1R"},
172
173 /* Center/Sub are fed VOUT2L/R */
174 {"Center+Sub", NULL, "VOUT2L"},
175 {"Center+Sub", NULL, "VOUT2R"},
176
177 /* Rear Left/Right are fed VOUT3L/R */
178 {"Rear", NULL, "VOUT3L"},
179 {"Rear", NULL, "VOUT3R"},
180};
181
182static int smdk64xx_wm8580_init_paiftx(struct snd_soc_pcm_runtime *rtd)
183{
184 struct snd_soc_codec *codec = rtd->codec;
185
186 /* Add smdk64xx specific Capture widgets */
187 snd_soc_dapm_new_controls(codec, wm8580_dapm_widgets_cpt,
188 ARRAY_SIZE(wm8580_dapm_widgets_cpt));
189
190 /* Set up PAIFTX audio path */
191 snd_soc_dapm_add_routes(codec, audio_map_tx, ARRAY_SIZE(audio_map_tx));
192
193 /* Enabling the microphone requires the fitting of a 0R
194 * resistor to connect the line from the microphone jack.
195 */
196 snd_soc_dapm_disable_pin(codec, "MicIn");
197
198 /* signal a DAPM event */
199 snd_soc_dapm_sync(codec);
200
201 return 0;
202}
203
204static int smdk64xx_wm8580_init_paifrx(struct snd_soc_pcm_runtime *rtd)
205{
206 struct snd_soc_codec *codec = rtd->codec;
207
208 /* Add smdk64xx specific Playback widgets */
209 snd_soc_dapm_new_controls(codec, wm8580_dapm_widgets_pbk,
210 ARRAY_SIZE(wm8580_dapm_widgets_pbk));
211
212 /* Set up PAIFRX audio path */
213 snd_soc_dapm_add_routes(codec, audio_map_rx, ARRAY_SIZE(audio_map_rx));
214
215 /* signal a DAPM event */
216 snd_soc_dapm_sync(codec);
217
218 return 0;
219}
220
221static struct snd_soc_dai_link smdk64xx_dai[] = {
222{ /* Primary Playback i/f */
223 .name = "WM8580 PAIF RX",
224 .stream_name = "Playback",
225 .cpu_dai_name = "s3c64xx-iis-v4",
226 .codec_dai_name = "wm8580-hifi-playback",
227 .platform_name = "s3c24xx-pcm-audio",
228 .codec_name = "wm8580-codec.0-001b",
229 .init = smdk64xx_wm8580_init_paifrx,
230 .ops = &smdk64xx_ops,
231},
232{ /* Primary Capture i/f */
233 .name = "WM8580 PAIF TX",
234 .stream_name = "Capture",
235 .cpu_dai_name = "s3c64xx-iis-v4",
236 .codec_dai_name = "wm8580-hifi-capture",
237 .platform_name = "s3c24xx-pcm-audio",
238 .codec_name = "wm8580-codec.0-001b",
239 .init = smdk64xx_wm8580_init_paiftx,
240 .ops = &smdk64xx_ops,
241},
242};
243
244static struct snd_soc_card smdk64xx = {
245 .name = "SMDK64xx 5.1",
246 .dai_link = smdk64xx_dai,
247 .num_links = ARRAY_SIZE(smdk64xx_dai),
248};
249
250static struct platform_device *smdk64xx_snd_device;
251
252static int __init smdk64xx_audio_init(void)
253{
254 int ret;
255
256 smdk64xx_snd_device = platform_device_alloc("soc-audio", -1);
257 if (!smdk64xx_snd_device)
258 return -ENOMEM;
259
260 platform_set_drvdata(smdk64xx_snd_device, &smdk64xx);
261 ret = platform_device_add(smdk64xx_snd_device);
262
263 if (ret)
264 platform_device_put(smdk64xx_snd_device);
265
266 return ret;
267}
268module_init(smdk64xx_audio_init);
269
270MODULE_AUTHOR("Jaswinder Singh, jassi.brar@samsung.com");
271MODULE_DESCRIPTION("ALSA SoC SMDK64XX WM8580");
272MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/smdk_spdif.c b/sound/soc/s3c24xx/smdk_spdif.c
deleted file mode 100644
index c8bd90488a87..000000000000
--- a/sound/soc/s3c24xx/smdk_spdif.c
+++ /dev/null
@@ -1,223 +0,0 @@
1/*
2 * smdk_spdif.c -- S/PDIF audio for SMDK
3 *
4 * Copyright 2010 Samsung Electronics Co. Ltd.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
10 *
11 */
12
13#include <linux/module.h>
14#include <linux/device.h>
15#include <linux/clk.h>
16
17#include <plat/devs.h>
18
19#include <sound/soc.h>
20
21#include "s3c-dma.h"
22#include "spdif.h"
23
24/* Audio clock settings are belonged to board specific part. Every
25 * board can set audio source clock setting which is matched with H/W
26 * like this function-'set_audio_clock_heirachy'.
27 */
28static int set_audio_clock_heirachy(struct platform_device *pdev)
29{
30 struct clk *fout_epll, *mout_epll, *sclk_audio0, *sclk_spdif;
31 int ret;
32
33 fout_epll = clk_get(NULL, "fout_epll");
34 if (IS_ERR(fout_epll)) {
35 printk(KERN_WARNING "%s: Cannot find fout_epll.\n",
36 __func__);
37 return -EINVAL;
38 }
39
40 mout_epll = clk_get(NULL, "mout_epll");
41 if (IS_ERR(mout_epll)) {
42 printk(KERN_WARNING "%s: Cannot find mout_epll.\n",
43 __func__);
44 ret = -EINVAL;
45 goto out1;
46 }
47
48 sclk_audio0 = clk_get(&pdev->dev, "sclk_audio");
49 if (IS_ERR(sclk_audio0)) {
50 printk(KERN_WARNING "%s: Cannot find sclk_audio.\n",
51 __func__);
52 ret = -EINVAL;
53 goto out2;
54 }
55
56 sclk_spdif = clk_get(NULL, "sclk_spdif");
57 if (IS_ERR(sclk_spdif)) {
58 printk(KERN_WARNING "%s: Cannot find sclk_spdif.\n",
59 __func__);
60 ret = -EINVAL;
61 goto out3;
62 }
63
64 /* Set audio clock heirachy for S/PDIF */
65 clk_set_parent(mout_epll, fout_epll);
66 clk_set_parent(sclk_audio0, mout_epll);
67 clk_set_parent(sclk_spdif, sclk_audio0);
68
69 clk_put(sclk_spdif);
70out3:
71 clk_put(sclk_audio0);
72out2:
73 clk_put(mout_epll);
74out1:
75 clk_put(fout_epll);
76
77 return ret;
78}
79
80/* We should haved to set clock directly on this part because of clock
81 * scheme of Samsudng SoCs did not support to set rates from abstrct
82 * clock of it's heirachy.
83 */
84static int set_audio_clock_rate(unsigned long epll_rate,
85 unsigned long audio_rate)
86{
87 struct clk *fout_epll, *sclk_spdif;
88
89 fout_epll = clk_get(NULL, "fout_epll");
90 if (IS_ERR(fout_epll)) {
91 printk(KERN_ERR "%s: failed to get fout_epll\n", __func__);
92 return -ENOENT;
93 }
94
95 clk_set_rate(fout_epll, epll_rate);
96 clk_put(fout_epll);
97
98 sclk_spdif = clk_get(NULL, "sclk_spdif");
99 if (IS_ERR(sclk_spdif)) {
100 printk(KERN_ERR "%s: failed to get sclk_spdif\n", __func__);
101 return -ENOENT;
102 }
103
104 clk_set_rate(sclk_spdif, audio_rate);
105 clk_put(sclk_spdif);
106
107 return 0;
108}
109
110static int smdk_hw_params(struct snd_pcm_substream *substream,
111 struct snd_pcm_hw_params *params)
112{
113 struct snd_soc_pcm_runtime *rtd = substream->private_data;
114 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
115 unsigned long pll_out, rclk_rate;
116 int ret, ratio;
117
118 switch (params_rate(params)) {
119 case 44100:
120 pll_out = 45158400;
121 break;
122 case 32000:
123 case 48000:
124 case 96000:
125 pll_out = 49152000;
126 break;
127 default:
128 return -EINVAL;
129 }
130
131 /* Setting ratio to 512fs helps to use S/PDIF with HDMI without
132 * modify S/PDIF ASoC machine driver.
133 */
134 ratio = 512;
135 rclk_rate = params_rate(params) * ratio;
136
137 /* Set audio source clock rates */
138 ret = set_audio_clock_rate(pll_out, rclk_rate);
139 if (ret < 0)
140 return ret;
141
142 /* Set S/PDIF uses internal source clock */
143 ret = snd_soc_dai_set_sysclk(cpu_dai, SND_SOC_SPDIF_INT_MCLK,
144 rclk_rate, SND_SOC_CLOCK_IN);
145 if (ret < 0)
146 return ret;
147
148 return ret;
149}
150
151static struct snd_soc_ops smdk_spdif_ops = {
152 .hw_params = smdk_hw_params,
153};
154
155static struct snd_soc_card smdk;
156
157static struct snd_soc_dai_link smdk_dai = {
158 .name = "S/PDIF",
159 .stream_name = "S/PDIF PCM Playback",
160 .platform_name = "s3c24xx-pcm-audio",
161 .cpu_dai_name = "samsung-spdif",
162 .codec_dai_name = "dit-hifi",
163 .codec_name = "spdif-dit",
164 .ops = &smdk_spdif_ops,
165};
166
167static struct snd_soc_card smdk = {
168 .name = "SMDK-S/PDIF",
169 .dai_link = &smdk_dai,
170 .num_links = 1,
171};
172
173static struct platform_device *smdk_snd_spdif_dit_device;
174static struct platform_device *smdk_snd_spdif_device;
175
176static int __init smdk_init(void)
177{
178 int ret;
179
180 smdk_snd_spdif_dit_device = platform_device_alloc("spdif-dit", -1);
181 if (!smdk_snd_spdif_dit_device)
182 return -ENOMEM;
183
184 ret = platform_device_add(smdk_snd_spdif_dit_device);
185 if (ret)
186 goto err2;
187
188 smdk_snd_spdif_device = platform_device_alloc("soc-audio", -1);
189 if (!smdk_snd_spdif_device) {
190 ret = -ENOMEM;
191 goto err2;
192 }
193
194 platform_set_drvdata(smdk_snd_spdif_device, &smdk);
195
196 ret = platform_device_add(smdk_snd_spdif_device);
197 if (ret)
198 goto err1;
199
200 /* Set audio clock heirachy manually */
201 ret = set_audio_clock_heirachy(smdk_snd_spdif_device);
202 if (ret)
203 goto err1;
204
205 return 0;
206err1:
207 platform_device_put(smdk_snd_spdif_device);
208err2:
209 platform_device_put(smdk_snd_spdif_dit_device);
210 return ret;
211}
212
213static void __exit smdk_exit(void)
214{
215 platform_device_unregister(smdk_snd_spdif_device);
216}
217
218module_init(smdk_init);
219module_exit(smdk_exit);
220
221MODULE_AUTHOR("Seungwhan Youn, <sw.youn@samsung.com>");
222MODULE_DESCRIPTION("ALSA SoC SMDK+S/PDIF");
223MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/smdk_wm9713.c b/sound/soc/s3c24xx/smdk_wm9713.c
deleted file mode 100644
index 33ba8fdbcf07..000000000000
--- a/sound/soc/s3c24xx/smdk_wm9713.c
+++ /dev/null
@@ -1,107 +0,0 @@
1/*
2 * smdk_wm9713.c -- SoC audio for SMDK
3 *
4 * Copyright 2010 Samsung Electronics Co. Ltd.
5 * Author: Jaswinder Singh Brar <jassi.brar@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) any later version.
11 *
12 */
13
14#include <linux/module.h>
15#include <linux/device.h>
16#include <sound/soc.h>
17
18#include "s3c-dma.h"
19#include "s3c-ac97.h"
20
21static struct snd_soc_card smdk;
22
23/*
24 * Default CFG switch settings to use this driver:
25 *
26 * SMDK6410: Set CFG1 1-3 On, CFG2 1-4 Off
27 * SMDKC100: Set CFG6 1-3 On, CFG7 1 On
28 * SMDKC110: Set CFGB10 1-2 Off, CFGB12 1-3 On
29 * SMDKV210: Set CFGB10 1-2 Off, CFGB12 1-3 On
30 */
31
32/*
33 Playback (HeadPhone):-
34 $ amixer sset 'Headphone' unmute
35 $ amixer sset 'Right Headphone Out Mux' 'Headphone'
36 $ amixer sset 'Left Headphone Out Mux' 'Headphone'
37 $ amixer sset 'Right HP Mixer PCM' unmute
38 $ amixer sset 'Left HP Mixer PCM' unmute
39
40 Capture (LineIn):-
41 $ amixer sset 'Right Capture Source' 'Line'
42 $ amixer sset 'Left Capture Source' 'Line'
43*/
44
45static struct snd_soc_dai_link smdk_dai = {
46 .name = "AC97",
47 .stream_name = "AC97 PCM",
48 .platform_name = "s3c24xx-pcm-audio",
49 .cpu_dai_name = "s3c-ac97",
50 .codec_dai_name = "wm9713-hifi",
51 .codec_name = "wm9713-codec",
52};
53
54static struct snd_soc_card smdk = {
55 .name = "SMDK WM9713",
56 .dai_link = &smdk_dai,
57 .num_links = 1,
58};
59
60static struct platform_device *smdk_snd_wm9713_device;
61static struct platform_device *smdk_snd_ac97_device;
62
63static int __init smdk_init(void)
64{
65 int ret;
66
67 smdk_snd_wm9713_device = platform_device_alloc("wm9713-codec", -1);
68 if (!smdk_snd_wm9713_device)
69 return -ENOMEM;
70
71 ret = platform_device_add(smdk_snd_wm9713_device);
72 if (ret)
73 goto err;
74
75 smdk_snd_ac97_device = platform_device_alloc("soc-audio", -1);
76 if (!smdk_snd_ac97_device) {
77 ret = -ENOMEM;
78 goto err;
79 }
80
81 platform_set_drvdata(smdk_snd_ac97_device, &smdk);
82
83 ret = platform_device_add(smdk_snd_ac97_device);
84 if (ret) {
85 platform_device_put(smdk_snd_ac97_device);
86 goto err;
87 }
88
89 return 0;
90err:
91 platform_device_put(smdk_snd_wm9713_device);
92 return ret;
93}
94
95static void __exit smdk_exit(void)
96{
97 platform_device_unregister(smdk_snd_ac97_device);
98 platform_device_unregister(smdk_snd_wm9713_device);
99}
100
101module_init(smdk_init);
102module_exit(smdk_exit);
103
104/* Module information */
105MODULE_AUTHOR("Jaswinder Singh Brar, jassi.brar@samsung.com");
106MODULE_DESCRIPTION("ALSA SoC SMDK+WM9713");
107MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/spdif.c b/sound/soc/s3c24xx/spdif.c
deleted file mode 100644
index ce554e9cabcc..000000000000
--- a/sound/soc/s3c24xx/spdif.c
+++ /dev/null
@@ -1,501 +0,0 @@
1/* sound/soc/s3c24xx/spdif.c
2 *
3 * ALSA SoC Audio Layer - Samsung S/PDIF Controller driver
4 *
5 * Copyright (c) 2010 Samsung Electronics Co. Ltd
6 * http://www.samsung.com/
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/clk.h>
14#include <linux/io.h>
15
16#include <sound/pcm.h>
17#include <sound/pcm_params.h>
18#include <sound/soc.h>
19
20#include <plat/audio.h>
21#include <mach/dma.h>
22
23#include "s3c-dma.h"
24#include "spdif.h"
25
26/* Registers */
27#define CLKCON 0x00
28#define CON 0x04
29#define BSTAS 0x08
30#define CSTAS 0x0C
31#define DATA_OUTBUF 0x10
32#define DCNT 0x14
33#define BSTAS_S 0x18
34#define DCNT_S 0x1C
35
36#define CLKCTL_MASK 0x7
37#define CLKCTL_MCLK_EXT (0x1 << 2)
38#define CLKCTL_PWR_ON (0x1 << 0)
39
40#define CON_MASK 0x3ffffff
41#define CON_FIFO_TH_SHIFT 19
42#define CON_FIFO_TH_MASK (0x7 << 19)
43#define CON_USERDATA_23RDBIT (0x1 << 12)
44
45#define CON_SW_RESET (0x1 << 5)
46
47#define CON_MCLKDIV_MASK (0x3 << 3)
48#define CON_MCLKDIV_256FS (0x0 << 3)
49#define CON_MCLKDIV_384FS (0x1 << 3)
50#define CON_MCLKDIV_512FS (0x2 << 3)
51
52#define CON_PCM_MASK (0x3 << 1)
53#define CON_PCM_16BIT (0x0 << 1)
54#define CON_PCM_20BIT (0x1 << 1)
55#define CON_PCM_24BIT (0x2 << 1)
56
57#define CON_PCM_DATA (0x1 << 0)
58
59#define CSTAS_MASK 0x3fffffff
60#define CSTAS_SAMP_FREQ_MASK (0xF << 24)
61#define CSTAS_SAMP_FREQ_44 (0x0 << 24)
62#define CSTAS_SAMP_FREQ_48 (0x2 << 24)
63#define CSTAS_SAMP_FREQ_32 (0x3 << 24)
64#define CSTAS_SAMP_FREQ_96 (0xA << 24)
65
66#define CSTAS_CATEGORY_MASK (0xFF << 8)
67#define CSTAS_CATEGORY_CODE_CDP (0x01 << 8)
68
69#define CSTAS_NO_COPYRIGHT (0x1 << 2)
70
71/**
72 * struct samsung_spdif_info - Samsung S/PDIF Controller information
73 * @lock: Spin lock for S/PDIF.
74 * @dev: The parent device passed to use from the probe.
75 * @regs: The pointer to the device register block.
76 * @clk_rate: Current clock rate for calcurate ratio.
77 * @pclk: The peri-clock pointer for spdif master operation.
78 * @sclk: The source clock pointer for making sync signals.
79 * @save_clkcon: Backup clkcon reg. in suspend.
80 * @save_con: Backup con reg. in suspend.
81 * @save_cstas: Backup cstas reg. in suspend.
82 * @dma_playback: DMA information for playback channel.
83 */
84struct samsung_spdif_info {
85 spinlock_t lock;
86 struct device *dev;
87 void __iomem *regs;
88 unsigned long clk_rate;
89 struct clk *pclk;
90 struct clk *sclk;
91 u32 saved_clkcon;
92 u32 saved_con;
93 u32 saved_cstas;
94 struct s3c_dma_params *dma_playback;
95};
96
97static struct s3c2410_dma_client spdif_dma_client_out = {
98 .name = "S/PDIF Stereo out",
99};
100
101static struct s3c_dma_params spdif_stereo_out;
102static struct samsung_spdif_info spdif_info;
103
104static inline struct samsung_spdif_info *to_info(struct snd_soc_dai *cpu_dai)
105{
106 return snd_soc_dai_get_drvdata(cpu_dai);
107}
108
109static void spdif_snd_txctrl(struct samsung_spdif_info *spdif, int on)
110{
111 void __iomem *regs = spdif->regs;
112 u32 clkcon;
113
114 dev_dbg(spdif->dev, "Entered %s\n", __func__);
115
116 clkcon = readl(regs + CLKCON) & CLKCTL_MASK;
117 if (on)
118 writel(clkcon | CLKCTL_PWR_ON, regs + CLKCON);
119 else
120 writel(clkcon & ~CLKCTL_PWR_ON, regs + CLKCON);
121}
122
123static int spdif_set_sysclk(struct snd_soc_dai *cpu_dai,
124 int clk_id, unsigned int freq, int dir)
125{
126 struct samsung_spdif_info *spdif = to_info(cpu_dai);
127 u32 clkcon;
128
129 dev_dbg(spdif->dev, "Entered %s\n", __func__);
130
131 clkcon = readl(spdif->regs + CLKCON);
132
133 if (clk_id == SND_SOC_SPDIF_INT_MCLK)
134 clkcon &= ~CLKCTL_MCLK_EXT;
135 else
136 clkcon |= CLKCTL_MCLK_EXT;
137
138 writel(clkcon, spdif->regs + CLKCON);
139
140 spdif->clk_rate = freq;
141
142 return 0;
143}
144
145static int spdif_trigger(struct snd_pcm_substream *substream, int cmd,
146 struct snd_soc_dai *dai)
147{
148 struct snd_soc_pcm_runtime *rtd = substream->private_data;
149 struct samsung_spdif_info *spdif = to_info(rtd->cpu_dai);
150 unsigned long flags;
151
152 dev_dbg(spdif->dev, "Entered %s\n", __func__);
153
154 switch (cmd) {
155 case SNDRV_PCM_TRIGGER_START:
156 case SNDRV_PCM_TRIGGER_RESUME:
157 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
158 spin_lock_irqsave(&spdif->lock, flags);
159 spdif_snd_txctrl(spdif, 1);
160 spin_unlock_irqrestore(&spdif->lock, flags);
161 break;
162 case SNDRV_PCM_TRIGGER_STOP:
163 case SNDRV_PCM_TRIGGER_SUSPEND:
164 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
165 spin_lock_irqsave(&spdif->lock, flags);
166 spdif_snd_txctrl(spdif, 0);
167 spin_unlock_irqrestore(&spdif->lock, flags);
168 break;
169 default:
170 return -EINVAL;
171 }
172
173 return 0;
174}
175
176static int spdif_sysclk_ratios[] = {
177 512, 384, 256,
178};
179
180static int spdif_hw_params(struct snd_pcm_substream *substream,
181 struct snd_pcm_hw_params *params,
182 struct snd_soc_dai *socdai)
183{
184 struct snd_soc_pcm_runtime *rtd = substream->private_data;
185 struct samsung_spdif_info *spdif = to_info(rtd->cpu_dai);
186 void __iomem *regs = spdif->regs;
187 struct s3c_dma_params *dma_data;
188 u32 con, clkcon, cstas;
189 unsigned long flags;
190 int i, ratio;
191
192 dev_dbg(spdif->dev, "Entered %s\n", __func__);
193
194 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
195 dma_data = spdif->dma_playback;
196 else {
197 dev_err(spdif->dev, "Capture is not supported\n");
198 return -EINVAL;
199 }
200
201 snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_data);
202
203 spin_lock_irqsave(&spdif->lock, flags);
204
205 con = readl(regs + CON) & CON_MASK;
206 cstas = readl(regs + CSTAS) & CSTAS_MASK;
207 clkcon = readl(regs + CLKCON) & CLKCTL_MASK;
208
209 con &= ~CON_FIFO_TH_MASK;
210 con |= (0x7 << CON_FIFO_TH_SHIFT);
211 con |= CON_USERDATA_23RDBIT;
212 con |= CON_PCM_DATA;
213
214 con &= ~CON_PCM_MASK;
215 switch (params_format(params)) {
216 case SNDRV_PCM_FORMAT_S16_LE:
217 con |= CON_PCM_16BIT;
218 break;
219 default:
220 dev_err(spdif->dev, "Unsupported data size.\n");
221 goto err;
222 }
223
224 ratio = spdif->clk_rate / params_rate(params);
225 for (i = 0; i < ARRAY_SIZE(spdif_sysclk_ratios); i++)
226 if (ratio == spdif_sysclk_ratios[i])
227 break;
228 if (i == ARRAY_SIZE(spdif_sysclk_ratios)) {
229 dev_err(spdif->dev, "Invalid clock ratio %ld/%d\n",
230 spdif->clk_rate, params_rate(params));
231 goto err;
232 }
233
234 con &= ~CON_MCLKDIV_MASK;
235 switch (ratio) {
236 case 256:
237 con |= CON_MCLKDIV_256FS;
238 break;
239 case 384:
240 con |= CON_MCLKDIV_384FS;
241 break;
242 case 512:
243 con |= CON_MCLKDIV_512FS;
244 break;
245 }
246
247 cstas &= ~CSTAS_SAMP_FREQ_MASK;
248 switch (params_rate(params)) {
249 case 44100:
250 cstas |= CSTAS_SAMP_FREQ_44;
251 break;
252 case 48000:
253 cstas |= CSTAS_SAMP_FREQ_48;
254 break;
255 case 32000:
256 cstas |= CSTAS_SAMP_FREQ_32;
257 break;
258 case 96000:
259 cstas |= CSTAS_SAMP_FREQ_96;
260 break;
261 default:
262 dev_err(spdif->dev, "Invalid sampling rate %d\n",
263 params_rate(params));
264 goto err;
265 }
266
267 cstas &= ~CSTAS_CATEGORY_MASK;
268 cstas |= CSTAS_CATEGORY_CODE_CDP;
269 cstas |= CSTAS_NO_COPYRIGHT;
270
271 writel(con, regs + CON);
272 writel(cstas, regs + CSTAS);
273 writel(clkcon, regs + CLKCON);
274
275 spin_unlock_irqrestore(&spdif->lock, flags);
276
277 return 0;
278err:
279 spin_unlock_irqrestore(&spdif->lock, flags);
280 return -EINVAL;
281}
282
283static void spdif_shutdown(struct snd_pcm_substream *substream,
284 struct snd_soc_dai *dai)
285{
286 struct snd_soc_pcm_runtime *rtd = substream->private_data;
287 struct samsung_spdif_info *spdif = to_info(rtd->cpu_dai);
288 void __iomem *regs = spdif->regs;
289 u32 con, clkcon;
290
291 dev_dbg(spdif->dev, "Entered %s\n", __func__);
292
293 con = readl(regs + CON) & CON_MASK;
294 clkcon = readl(regs + CLKCON) & CLKCTL_MASK;
295
296 writel(con | CON_SW_RESET, regs + CON);
297 cpu_relax();
298
299 writel(clkcon & ~CLKCTL_PWR_ON, regs + CLKCON);
300}
301
302#ifdef CONFIG_PM
303static int spdif_suspend(struct snd_soc_dai *cpu_dai)
304{
305 struct samsung_spdif_info *spdif = to_info(cpu_dai);
306 u32 con = spdif->saved_con;
307
308 dev_dbg(spdif->dev, "Entered %s\n", __func__);
309
310 spdif->saved_clkcon = readl(spdif->regs + CLKCON) & CLKCTL_MASK;
311 spdif->saved_con = readl(spdif->regs + CON) & CON_MASK;
312 spdif->saved_cstas = readl(spdif->regs + CSTAS) & CSTAS_MASK;
313
314 writel(con | CON_SW_RESET, spdif->regs + CON);
315 cpu_relax();
316
317 return 0;
318}
319
320static int spdif_resume(struct snd_soc_dai *cpu_dai)
321{
322 struct samsung_spdif_info *spdif = to_info(cpu_dai);
323
324 dev_dbg(spdif->dev, "Entered %s\n", __func__);
325
326 writel(spdif->saved_clkcon, spdif->regs + CLKCON);
327 writel(spdif->saved_con, spdif->regs + CON);
328 writel(spdif->saved_cstas, spdif->regs + CSTAS);
329
330 return 0;
331}
332#else
333#define spdif_suspend NULL
334#define spdif_resume NULL
335#endif
336
337static struct snd_soc_dai_ops spdif_dai_ops = {
338 .set_sysclk = spdif_set_sysclk,
339 .trigger = spdif_trigger,
340 .hw_params = spdif_hw_params,
341 .shutdown = spdif_shutdown,
342};
343
344struct snd_soc_dai_driver samsung_spdif_dai = {
345 .name = "samsung-spdif",
346 .playback = {
347 .stream_name = "S/PDIF Playback",
348 .channels_min = 2,
349 .channels_max = 2,
350 .rates = (SNDRV_PCM_RATE_32000 |
351 SNDRV_PCM_RATE_44100 |
352 SNDRV_PCM_RATE_48000 |
353 SNDRV_PCM_RATE_96000),
354 .formats = SNDRV_PCM_FMTBIT_S16_LE, },
355 .ops = &spdif_dai_ops,
356 .suspend = spdif_suspend,
357 .resume = spdif_resume,
358};
359
360static __devinit int spdif_probe(struct platform_device *pdev)
361{
362 struct s3c_audio_pdata *spdif_pdata;
363 struct resource *mem_res, *dma_res;
364 struct samsung_spdif_info *spdif;
365 int ret;
366
367 spdif_pdata = pdev->dev.platform_data;
368
369 dev_dbg(&pdev->dev, "Entered %s\n", __func__);
370
371 dma_res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
372 if (!dma_res) {
373 dev_err(&pdev->dev, "Unable to get dma resource.\n");
374 return -ENXIO;
375 }
376
377 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
378 if (!mem_res) {
379 dev_err(&pdev->dev, "Unable to get register resource.\n");
380 return -ENXIO;
381 }
382
383 if (spdif_pdata && spdif_pdata->cfg_gpio
384 && spdif_pdata->cfg_gpio(pdev)) {
385 dev_err(&pdev->dev, "Unable to configure GPIO pins\n");
386 return -EINVAL;
387 }
388
389 spdif = &spdif_info;
390 spdif->dev = &pdev->dev;
391
392 spin_lock_init(&spdif->lock);
393
394 spdif->pclk = clk_get(&pdev->dev, "spdif");
395 if (IS_ERR(spdif->pclk)) {
396 dev_err(&pdev->dev, "failed to get peri-clock\n");
397 ret = -ENOENT;
398 goto err0;
399 }
400 clk_enable(spdif->pclk);
401
402 spdif->sclk = clk_get(&pdev->dev, "sclk_spdif");
403 if (IS_ERR(spdif->sclk)) {
404 dev_err(&pdev->dev, "failed to get internal source clock\n");
405 ret = -ENOENT;
406 goto err1;
407 }
408 clk_enable(spdif->sclk);
409
410 /* Request S/PDIF Register's memory region */
411 if (!request_mem_region(mem_res->start,
412 resource_size(mem_res), "samsung-spdif")) {
413 dev_err(&pdev->dev, "Unable to request register region\n");
414 ret = -EBUSY;
415 goto err2;
416 }
417
418 spdif->regs = ioremap(mem_res->start, 0x100);
419 if (spdif->regs == NULL) {
420 dev_err(&pdev->dev, "Cannot ioremap registers\n");
421 ret = -ENXIO;
422 goto err3;
423 }
424
425 dev_set_drvdata(&pdev->dev, spdif);
426
427 ret = snd_soc_register_dai(&pdev->dev, &samsung_spdif_dai);
428 if (ret != 0) {
429 dev_err(&pdev->dev, "fail to register dai\n");
430 goto err4;
431 }
432
433 spdif_stereo_out.dma_size = 2;
434 spdif_stereo_out.client = &spdif_dma_client_out;
435 spdif_stereo_out.dma_addr = mem_res->start + DATA_OUTBUF;
436 spdif_stereo_out.channel = dma_res->start;
437
438 spdif->dma_playback = &spdif_stereo_out;
439
440 return 0;
441
442err4:
443 iounmap(spdif->regs);
444err3:
445 release_mem_region(mem_res->start, resource_size(mem_res));
446err2:
447 clk_disable(spdif->sclk);
448 clk_put(spdif->sclk);
449err1:
450 clk_disable(spdif->pclk);
451 clk_put(spdif->pclk);
452err0:
453 return ret;
454}
455
456static __devexit int spdif_remove(struct platform_device *pdev)
457{
458 struct samsung_spdif_info *spdif = &spdif_info;
459 struct resource *mem_res;
460
461 snd_soc_unregister_dai(&pdev->dev);
462
463 iounmap(spdif->regs);
464
465 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
466 if (mem_res)
467 release_mem_region(mem_res->start, resource_size(mem_res));
468
469 clk_disable(spdif->sclk);
470 clk_put(spdif->sclk);
471 clk_disable(spdif->pclk);
472 clk_put(spdif->pclk);
473
474 return 0;
475}
476
477static struct platform_driver samsung_spdif_driver = {
478 .probe = spdif_probe,
479 .remove = spdif_remove,
480 .driver = {
481 .name = "samsung-spdif",
482 .owner = THIS_MODULE,
483 },
484};
485
486static int __init spdif_init(void)
487{
488 return platform_driver_register(&samsung_spdif_driver);
489}
490module_init(spdif_init);
491
492static void __exit spdif_exit(void)
493{
494 platform_driver_unregister(&samsung_spdif_driver);
495}
496module_exit(spdif_exit);
497
498MODULE_AUTHOR("Seungwhan Youn, <sw.youn@samsung.com>");
499MODULE_DESCRIPTION("Samsung S/PDIF Controller Driver");
500MODULE_LICENSE("GPL");
501MODULE_ALIAS("platform:samsung-spdif");
diff --git a/sound/soc/s3c24xx/spdif.h b/sound/soc/s3c24xx/spdif.h
deleted file mode 100644
index 3ed55592710f..000000000000
--- a/sound/soc/s3c24xx/spdif.h
+++ /dev/null
@@ -1,19 +0,0 @@
1/* sound/soc/s3c24xx/spdif.h
2 *
3 * ALSA SoC Audio Layer - Samsung S/PDIF Controller driver
4 *
5 * Copyright (c) 2010 Samsung Electronics Co. Ltd
6 * http://www.samsung.com/
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef __SND_SOC_SAMSUNG_SPDIF_H
14#define __SND_SOC_SAMSUNG_SPDIF_H __FILE__
15
16#define SND_SOC_SPDIF_INT_MCLK 0
17#define SND_SOC_SPDIF_EXT_MCLK 1
18
19#endif /* __SND_SOC_SAMSUNG_SPDIF_H */