aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/s3c24xx/s3c64xx-i2s-v4.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/s3c24xx/s3c64xx-i2s-v4.c')
-rw-r--r--sound/soc/s3c24xx/s3c64xx-i2s-v4.c123
1 files changed, 66 insertions, 57 deletions
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s-v4.c b/sound/soc/s3c24xx/s3c64xx-i2s-v4.c
index 06db130030a1..7cab4fcf1f12 100644
--- a/sound/soc/s3c24xx/s3c64xx-i2s-v4.c
+++ b/sound/soc/s3c24xx/s3c64xx-i2s-v4.c
@@ -16,9 +16,7 @@
16#include <sound/soc.h> 16#include <sound/soc.h>
17#include <sound/pcm_params.h> 17#include <sound/pcm_params.h>
18 18
19#include <mach/gpio-bank-c.h> 19#include <plat/audio.h>
20#include <mach/gpio-bank-h.h>
21#include <plat/gpio-cfg.h>
22 20
23#include <mach/map.h> 21#include <mach/map.h>
24#include <mach/dma.h> 22#include <mach/dma.h>
@@ -39,34 +37,23 @@ static struct s3c_dma_params s3c64xx_i2sv4_pcm_stereo_out;
39static struct s3c_dma_params s3c64xx_i2sv4_pcm_stereo_in; 37static struct s3c_dma_params s3c64xx_i2sv4_pcm_stereo_in;
40static struct s3c_i2sv2_info s3c64xx_i2sv4; 38static struct s3c_i2sv2_info s3c64xx_i2sv4;
41 39
42struct snd_soc_dai s3c64xx_i2s_v4_dai; 40static int s3c64xx_i2sv4_probe(struct snd_soc_dai *dai)
43EXPORT_SYMBOL_GPL(s3c64xx_i2s_v4_dai);
44
45static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai)
46{ 41{
47 return cpu_dai->private_data; 42 struct s3c_i2sv2_info *i2s = &s3c64xx_i2sv4;
48} 43 int ret = 0;
49 44
50static int s3c64xx_i2sv4_probe(struct platform_device *pdev, 45 snd_soc_dai_set_drvdata(dai, i2s);
51 struct snd_soc_dai *dai)
52{
53 /* configure GPIO for i2s port */
54 s3c_gpio_cfgpin(S3C64XX_GPC(4), S3C64XX_GPC4_I2S_V40_DO0);
55 s3c_gpio_cfgpin(S3C64XX_GPC(5), S3C64XX_GPC5_I2S_V40_DO1);
56 s3c_gpio_cfgpin(S3C64XX_GPC(7), S3C64XX_GPC7_I2S_V40_DO2);
57 s3c_gpio_cfgpin(S3C64XX_GPH(6), S3C64XX_GPH6_I2S_V40_BCLK);
58 s3c_gpio_cfgpin(S3C64XX_GPH(7), S3C64XX_GPH7_I2S_V40_CDCLK);
59 s3c_gpio_cfgpin(S3C64XX_GPH(8), S3C64XX_GPH8_I2S_V40_LRCLK);
60 s3c_gpio_cfgpin(S3C64XX_GPH(9), S3C64XX_GPH9_I2S_V40_DI);
61 46
62 return 0; 47 ret = s3c_i2sv2_probe(dai, i2s, i2s->base);
48
49 return ret;
63} 50}
64 51
65static int s3c_i2sv4_hw_params(struct snd_pcm_substream *substream, 52static int s3c_i2sv4_hw_params(struct snd_pcm_substream *substream,
66 struct snd_pcm_hw_params *params, 53 struct snd_pcm_hw_params *params,
67 struct snd_soc_dai *cpu_dai) 54 struct snd_soc_dai *cpu_dai)
68{ 55{
69 struct s3c_i2sv2_info *i2s = to_info(cpu_dai); 56 struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(cpu_dai);
70 struct s3c_dma_params *dma_data; 57 struct s3c_dma_params *dma_data;
71 u32 iismod; 58 u32 iismod;
72 59
@@ -104,51 +91,79 @@ static struct snd_soc_dai_ops s3c64xx_i2sv4_dai_ops = {
104 .hw_params = s3c_i2sv4_hw_params, 91 .hw_params = s3c_i2sv4_hw_params,
105}; 92};
106 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
107static __devinit int s3c64xx_i2sv4_dev_probe(struct platform_device *pdev) 112static __devinit int s3c64xx_i2sv4_dev_probe(struct platform_device *pdev)
108{ 113{
114 struct s3c_audio_pdata *i2s_pdata;
109 struct s3c_i2sv2_info *i2s; 115 struct s3c_i2sv2_info *i2s;
110 struct snd_soc_dai *dai; 116 struct resource *res;
111 int ret; 117 int ret;
112 118
113 i2s = &s3c64xx_i2sv4; 119 i2s = &s3c64xx_i2sv4;
114 dai = &s3c64xx_i2s_v4_dai;
115
116 if (dai->dev) {
117 dev_dbg(dai->dev, "%s: \
118 I2Sv4 instance already registered!\n", __func__);
119 return -EBUSY;
120 }
121
122 dai->dev = &pdev->dev;
123 dai->name = "s3c64xx-i2s-v4";
124 dai->id = 0;
125 dai->symmetric_rates = 1;
126 dai->playback.channels_min = 2;
127 dai->playback.channels_max = 2;
128 dai->playback.rates = S3C64XX_I2S_RATES;
129 dai->playback.formats = S3C64XX_I2S_FMTS;
130 dai->capture.channels_min = 2;
131 dai->capture.channels_max = 2;
132 dai->capture.rates = S3C64XX_I2S_RATES;
133 dai->capture.formats = S3C64XX_I2S_FMTS;
134 dai->probe = s3c64xx_i2sv4_probe;
135 dai->ops = &s3c64xx_i2sv4_dai_ops;
136 120
137 i2s->feature |= S3C_FEATURE_CDCLKCON; 121 i2s->feature |= S3C_FEATURE_CDCLKCON;
138 122
139 i2s->dma_capture = &s3c64xx_i2sv4_pcm_stereo_in; 123 i2s->dma_capture = &s3c64xx_i2sv4_pcm_stereo_in;
140 i2s->dma_playback = &s3c64xx_i2sv4_pcm_stereo_out; 124 i2s->dma_playback = &s3c64xx_i2sv4_pcm_stereo_out;
141 125
142 i2s->dma_capture->channel = DMACH_HSI_I2SV40_RX; 126 res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
143 i2s->dma_capture->dma_addr = S3C64XX_PA_IISV4 + S3C2412_IISRXD; 127 if (!res) {
144 i2s->dma_playback->channel = DMACH_HSI_I2SV40_TX; 128 dev_err(&pdev->dev, "Unable to get I2S-TX dma resource\n");
145 i2s->dma_playback->dma_addr = S3C64XX_PA_IISV4 + S3C2412_IISTXD; 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;
146 153
147 i2s->dma_capture->client = &s3c64xx_dma_client_in; 154 i2s->dma_capture->client = &s3c64xx_dma_client_in;
148 i2s->dma_capture->dma_size = 4; 155 i2s->dma_capture->dma_size = 4;
149 i2s->dma_playback->client = &s3c64xx_dma_client_out; 156 i2s->dma_playback->client = &s3c64xx_dma_client_out;
150 i2s->dma_playback->dma_size = 4; 157 i2s->dma_playback->dma_size = 4;
151 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
152 i2s->iis_cclk = clk_get(&pdev->dev, "audio-bus"); 167 i2s->iis_cclk = clk_get(&pdev->dev, "audio-bus");
153 if (IS_ERR(i2s->iis_cclk)) { 168 if (IS_ERR(i2s->iis_cclk)) {
154 dev_err(&pdev->dev, "failed to get audio-bus\n"); 169 dev_err(&pdev->dev, "failed to get audio-bus\n");
@@ -158,19 +173,13 @@ static __devinit int s3c64xx_i2sv4_dev_probe(struct platform_device *pdev)
158 173
159 clk_enable(i2s->iis_cclk); 174 clk_enable(i2s->iis_cclk);
160 175
161 ret = s3c_i2sv2_probe(pdev, dai, i2s, 0); 176 ret = s3c_i2sv2_register_dai(&pdev->dev, pdev->id, &s3c64xx_i2s_v4_dai);
162 if (ret)
163 goto err_clk;
164
165 ret = s3c_i2sv2_register_dai(dai);
166 if (ret != 0) 177 if (ret != 0)
167 goto err_i2sv2; 178 goto err_i2sv2;
168 179
169 return 0; 180 return 0;
170 181
171err_i2sv2: 182err_i2sv2:
172 /* Not implemented for I2Sv2 core yet */
173err_clk:
174 clk_put(i2s->iis_cclk); 183 clk_put(i2s->iis_cclk);
175err: 184err:
176 return ret; 185 return ret;
@@ -178,7 +187,7 @@ err:
178 187
179static __devexit int s3c64xx_i2sv4_dev_remove(struct platform_device *pdev) 188static __devexit int s3c64xx_i2sv4_dev_remove(struct platform_device *pdev)
180{ 189{
181 dev_err(&pdev->dev, "Device removal not yet supported\n"); 190 snd_soc_unregister_dai(&pdev->dev);
182 return 0; 191 return 0;
183} 192}
184 193