diff options
Diffstat (limited to 'sound/soc/s3c24xx/s3c64xx-i2s.c')
-rw-r--r-- | sound/soc/s3c24xx/s3c64xx-i2s.c | 157 |
1 files changed, 103 insertions, 54 deletions
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.c b/sound/soc/s3c24xx/s3c64xx-i2s.c index 33c5de7e255f..3c06c401d0fb 100644 --- a/sound/soc/s3c24xx/s3c64xx-i2s.c +++ b/sound/soc/s3c24xx/s3c64xx-i2s.c | |||
@@ -108,48 +108,19 @@ static int s3c64xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, | |||
108 | return 0; | 108 | return 0; |
109 | } | 109 | } |
110 | 110 | ||
111 | 111 | struct clk *s3c64xx_i2s_get_clock(struct snd_soc_dai *dai) | |
112 | unsigned long s3c64xx_i2s_get_clockrate(struct snd_soc_dai *dai) | ||
113 | { | 112 | { |
114 | struct s3c_i2sv2_info *i2s = to_info(dai); | 113 | struct s3c_i2sv2_info *i2s = to_info(dai); |
115 | 114 | ||
116 | return clk_get_rate(i2s->iis_cclk); | 115 | return i2s->iis_cclk; |
117 | } | 116 | } |
118 | EXPORT_SYMBOL_GPL(s3c64xx_i2s_get_clockrate); | 117 | EXPORT_SYMBOL_GPL(s3c64xx_i2s_get_clock); |
119 | 118 | ||
120 | static int s3c64xx_i2s_probe(struct platform_device *pdev, | 119 | static int s3c64xx_i2s_probe(struct platform_device *pdev, |
121 | struct snd_soc_dai *dai) | 120 | struct snd_soc_dai *dai) |
122 | { | 121 | { |
123 | struct device *dev = &pdev->dev; | ||
124 | struct s3c_i2sv2_info *i2s; | ||
125 | int ret; | ||
126 | |||
127 | dev_dbg(dev, "%s: probing dai %d\n", __func__, pdev->id); | ||
128 | |||
129 | if (pdev->id < 0 || pdev->id > ARRAY_SIZE(s3c64xx_i2s)) { | ||
130 | dev_err(dev, "id %d out of range\n", pdev->id); | ||
131 | return -EINVAL; | ||
132 | } | ||
133 | |||
134 | i2s = &s3c64xx_i2s[pdev->id]; | ||
135 | |||
136 | ret = s3c_i2sv2_probe(pdev, dai, i2s, | ||
137 | pdev->id ? S3C64XX_PA_IIS1 : S3C64XX_PA_IIS0); | ||
138 | if (ret) | ||
139 | return ret; | ||
140 | |||
141 | i2s->dma_capture = &s3c64xx_i2s_pcm_stereo_in[pdev->id]; | ||
142 | i2s->dma_playback = &s3c64xx_i2s_pcm_stereo_out[pdev->id]; | ||
143 | |||
144 | i2s->iis_cclk = clk_get(dev, "audio-bus"); | ||
145 | if (IS_ERR(i2s->iis_cclk)) { | ||
146 | dev_err(dev, "failed to get audio-bus"); | ||
147 | iounmap(i2s->regs); | ||
148 | return -ENODEV; | ||
149 | } | ||
150 | |||
151 | /* configure GPIO for i2s port */ | 122 | /* configure GPIO for i2s port */ |
152 | switch (pdev->id) { | 123 | switch (dai->id) { |
153 | case 0: | 124 | case 0: |
154 | s3c_gpio_cfgpin(S3C64XX_GPD(0), S3C64XX_GPD0_I2S0_CLK); | 125 | s3c_gpio_cfgpin(S3C64XX_GPD(0), S3C64XX_GPD0_I2S0_CLK); |
155 | s3c_gpio_cfgpin(S3C64XX_GPD(1), S3C64XX_GPD1_I2S0_CDCLK); | 126 | s3c_gpio_cfgpin(S3C64XX_GPD(1), S3C64XX_GPD1_I2S0_CDCLK); |
@@ -175,41 +146,122 @@ static int s3c64xx_i2s_probe(struct platform_device *pdev, | |||
175 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) | 146 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) |
176 | 147 | ||
177 | #define S3C64XX_I2S_FMTS \ | 148 | #define S3C64XX_I2S_FMTS \ |
178 | (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE) | 149 | (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\ |
150 | SNDRV_PCM_FMTBIT_S24_LE) | ||
179 | 151 | ||
180 | static struct snd_soc_dai_ops s3c64xx_i2s_dai_ops = { | 152 | static struct snd_soc_dai_ops s3c64xx_i2s_dai_ops = { |
181 | .set_sysclk = s3c64xx_i2s_set_sysclk, | 153 | .set_sysclk = s3c64xx_i2s_set_sysclk, |
182 | }; | 154 | }; |
183 | 155 | ||
184 | struct snd_soc_dai s3c64xx_i2s_dai = { | 156 | struct snd_soc_dai s3c64xx_i2s_dai[] = { |
185 | .name = "s3c64xx-i2s", | 157 | { |
186 | .id = 0, | 158 | .name = "s3c64xx-i2s", |
187 | .probe = s3c64xx_i2s_probe, | 159 | .id = 0, |
188 | .playback = { | 160 | .probe = s3c64xx_i2s_probe, |
189 | .channels_min = 2, | 161 | .playback = { |
190 | .channels_max = 2, | 162 | .channels_min = 2, |
191 | .rates = S3C64XX_I2S_RATES, | 163 | .channels_max = 2, |
192 | .formats = S3C64XX_I2S_FMTS, | 164 | .rates = S3C64XX_I2S_RATES, |
165 | .formats = S3C64XX_I2S_FMTS, | ||
166 | }, | ||
167 | .capture = { | ||
168 | .channels_min = 2, | ||
169 | .channels_max = 2, | ||
170 | .rates = S3C64XX_I2S_RATES, | ||
171 | .formats = S3C64XX_I2S_FMTS, | ||
172 | }, | ||
173 | .ops = &s3c64xx_i2s_dai_ops, | ||
174 | .symmetric_rates = 1, | ||
193 | }, | 175 | }, |
194 | .capture = { | 176 | { |
195 | .channels_min = 2, | 177 | .name = "s3c64xx-i2s", |
196 | .channels_max = 2, | 178 | .id = 1, |
197 | .rates = S3C64XX_I2S_RATES, | 179 | .probe = s3c64xx_i2s_probe, |
198 | .formats = S3C64XX_I2S_FMTS, | 180 | .playback = { |
181 | .channels_min = 2, | ||
182 | .channels_max = 2, | ||
183 | .rates = S3C64XX_I2S_RATES, | ||
184 | .formats = S3C64XX_I2S_FMTS, | ||
185 | }, | ||
186 | .capture = { | ||
187 | .channels_min = 2, | ||
188 | .channels_max = 2, | ||
189 | .rates = S3C64XX_I2S_RATES, | ||
190 | .formats = S3C64XX_I2S_FMTS, | ||
191 | }, | ||
192 | .ops = &s3c64xx_i2s_dai_ops, | ||
193 | .symmetric_rates = 1, | ||
199 | }, | 194 | }, |
200 | .ops = &s3c64xx_i2s_dai_ops, | ||
201 | }; | 195 | }; |
202 | EXPORT_SYMBOL_GPL(s3c64xx_i2s_dai); | 196 | EXPORT_SYMBOL_GPL(s3c64xx_i2s_dai); |
203 | 197 | ||
198 | static __devinit int s3c64xx_iis_dev_probe(struct platform_device *pdev) | ||
199 | { | ||
200 | struct s3c_i2sv2_info *i2s; | ||
201 | struct snd_soc_dai *dai; | ||
202 | int ret; | ||
203 | |||
204 | if (pdev->id >= ARRAY_SIZE(s3c64xx_i2s)) { | ||
205 | dev_err(&pdev->dev, "id %d out of range\n", pdev->id); | ||
206 | return -EINVAL; | ||
207 | } | ||
208 | |||
209 | i2s = &s3c64xx_i2s[pdev->id]; | ||
210 | dai = &s3c64xx_i2s_dai[pdev->id]; | ||
211 | dai->dev = &pdev->dev; | ||
212 | |||
213 | i2s->dma_capture = &s3c64xx_i2s_pcm_stereo_in[pdev->id]; | ||
214 | i2s->dma_playback = &s3c64xx_i2s_pcm_stereo_out[pdev->id]; | ||
215 | |||
216 | i2s->iis_cclk = clk_get(&pdev->dev, "audio-bus"); | ||
217 | if (IS_ERR(i2s->iis_cclk)) { | ||
218 | dev_err(&pdev->dev, "failed to get audio-bus\n"); | ||
219 | ret = PTR_ERR(i2s->iis_cclk); | ||
220 | goto err; | ||
221 | } | ||
222 | |||
223 | ret = s3c_i2sv2_probe(pdev, dai, i2s, 0); | ||
224 | if (ret) | ||
225 | goto err_clk; | ||
226 | |||
227 | ret = s3c_i2sv2_register_dai(dai); | ||
228 | if (ret != 0) | ||
229 | goto err_i2sv2; | ||
230 | |||
231 | return 0; | ||
232 | |||
233 | err_i2sv2: | ||
234 | /* Not implemented for I2Sv2 core yet */ | ||
235 | err_clk: | ||
236 | clk_put(i2s->iis_cclk); | ||
237 | err: | ||
238 | return ret; | ||
239 | } | ||
240 | |||
241 | static __devexit int s3c64xx_iis_dev_remove(struct platform_device *pdev) | ||
242 | { | ||
243 | dev_err(&pdev->dev, "Device removal not yet supported\n"); | ||
244 | return 0; | ||
245 | } | ||
246 | |||
247 | static struct platform_driver s3c64xx_iis_driver = { | ||
248 | .probe = s3c64xx_iis_dev_probe, | ||
249 | .remove = s3c64xx_iis_dev_remove, | ||
250 | .driver = { | ||
251 | .name = "s3c64xx-iis", | ||
252 | .owner = THIS_MODULE, | ||
253 | }, | ||
254 | }; | ||
255 | |||
204 | static int __init s3c64xx_i2s_init(void) | 256 | static int __init s3c64xx_i2s_init(void) |
205 | { | 257 | { |
206 | return s3c_i2sv2_register_dai(&s3c64xx_i2s_dai); | 258 | return platform_driver_register(&s3c64xx_iis_driver); |
207 | } | 259 | } |
208 | module_init(s3c64xx_i2s_init); | 260 | module_init(s3c64xx_i2s_init); |
209 | 261 | ||
210 | static void __exit s3c64xx_i2s_exit(void) | 262 | static void __exit s3c64xx_i2s_exit(void) |
211 | { | 263 | { |
212 | snd_soc_unregister_dai(&s3c64xx_i2s_dai); | 264 | platform_driver_unregister(&s3c64xx_iis_driver); |
213 | } | 265 | } |
214 | module_exit(s3c64xx_i2s_exit); | 266 | module_exit(s3c64xx_i2s_exit); |
215 | 267 | ||
@@ -217,6 +269,3 @@ module_exit(s3c64xx_i2s_exit); | |||
217 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); | 269 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); |
218 | MODULE_DESCRIPTION("S3C64XX I2S SoC Interface"); | 270 | MODULE_DESCRIPTION("S3C64XX I2S SoC Interface"); |
219 | MODULE_LICENSE("GPL"); | 271 | MODULE_LICENSE("GPL"); |
220 | |||
221 | |||
222 | |||