aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/ad1836.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/ad1836.c')
-rw-r--r--sound/soc/codecs/ad1836.c191
1 files changed, 55 insertions, 136 deletions
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c
index a01006c8c606..d272534c8f84 100644
--- a/sound/soc/codecs/ad1836.c
+++ b/sound/soc/codecs/ad1836.c
@@ -33,15 +33,10 @@
33 33
34/* codec private data */ 34/* codec private data */
35struct ad1836_priv { 35struct ad1836_priv {
36 struct snd_soc_codec codec; 36 enum snd_soc_control_type control_type;
37 u16 reg_cache[AD1836_NUM_REGS]; 37 void *control_data;
38}; 38};
39 39
40static struct snd_soc_codec *ad1836_codec;
41struct snd_soc_codec_device soc_codec_dev_ad1836;
42static int ad1836_register(struct ad1836_priv *ad1836);
43static void ad1836_unregister(struct ad1836_priv *ad1836);
44
45/* 40/*
46 * AD1836 volume/mute/de-emphasis etc. controls 41 * AD1836 volume/mute/de-emphasis etc. controls
47 */ 42 */
@@ -146,8 +141,7 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream,
146 int word_len = 0; 141 int word_len = 0;
147 142
148 struct snd_soc_pcm_runtime *rtd = substream->private_data; 143 struct snd_soc_pcm_runtime *rtd = substream->private_data;
149 struct snd_soc_device *socdev = rtd->socdev; 144 struct snd_soc_codec *codec = rtd->codec;
150 struct snd_soc_codec *codec = socdev->card->codec;
151 145
152 /* bit size */ 146 /* bit size */
153 switch (params_format(params)) { 147 switch (params_format(params)) {
@@ -173,12 +167,9 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream,
173} 167}
174 168
175#ifdef CONFIG_PM 169#ifdef CONFIG_PM
176static int ad1836_soc_suspend(struct platform_device *pdev, 170static int ad1836_soc_suspend(struct snd_soc_codec *codec,
177 pm_message_t state) 171 pm_message_t state)
178{ 172{
179 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
180 struct snd_soc_codec *codec = socdev->card->codec;
181
182 /* reset clock control mode */ 173 /* reset clock control mode */
183 u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); 174 u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2);
184 adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK; 175 adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK;
@@ -186,11 +177,8 @@ static int ad1836_soc_suspend(struct platform_device *pdev,
186 return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2); 177 return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2);
187} 178}
188 179
189static int ad1836_soc_resume(struct platform_device *pdev) 180static int ad1836_soc_resume(struct snd_soc_codec *codec)
190{ 181{
191 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
192 struct snd_soc_codec *codec = socdev->card->codec;
193
194 /* restore clock control mode */ 182 /* restore clock control mode */
195 u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); 183 u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2);
196 adc_ctrl2 |= AD1836_ADC_AUX; 184 adc_ctrl2 |= AD1836_ADC_AUX;
@@ -202,49 +190,14 @@ static int ad1836_soc_resume(struct platform_device *pdev)
202#define ad1836_soc_resume NULL 190#define ad1836_soc_resume NULL
203#endif 191#endif
204 192
205static int __devinit ad1836_spi_probe(struct spi_device *spi)
206{
207 struct snd_soc_codec *codec;
208 struct ad1836_priv *ad1836;
209
210 ad1836 = kzalloc(sizeof(struct ad1836_priv), GFP_KERNEL);
211 if (ad1836 == NULL)
212 return -ENOMEM;
213
214 codec = &ad1836->codec;
215 codec->control_data = spi;
216 codec->dev = &spi->dev;
217
218 dev_set_drvdata(&spi->dev, ad1836);
219
220 return ad1836_register(ad1836);
221}
222
223static int __devexit ad1836_spi_remove(struct spi_device *spi)
224{
225 struct ad1836_priv *ad1836 = dev_get_drvdata(&spi->dev);
226
227 ad1836_unregister(ad1836);
228 return 0;
229}
230
231static struct spi_driver ad1836_spi_driver = {
232 .driver = {
233 .name = "ad1836",
234 .owner = THIS_MODULE,
235 },
236 .probe = ad1836_spi_probe,
237 .remove = __devexit_p(ad1836_spi_remove),
238};
239
240static struct snd_soc_dai_ops ad1836_dai_ops = { 193static struct snd_soc_dai_ops ad1836_dai_ops = {
241 .hw_params = ad1836_hw_params, 194 .hw_params = ad1836_hw_params,
242 .set_fmt = ad1836_set_dai_fmt, 195 .set_fmt = ad1836_set_dai_fmt,
243}; 196};
244 197
245/* codec DAI instance */ 198/* codec DAI instance */
246struct snd_soc_dai ad1836_dai = { 199static struct snd_soc_dai_driver ad1836_dai = {
247 .name = "AD1836", 200 .name = "ad1836-hifi",
248 .playback = { 201 .playback = {
249 .stream_name = "Playback", 202 .stream_name = "Playback",
250 .channels_min = 2, 203 .channels_min = 2,
@@ -263,35 +216,13 @@ struct snd_soc_dai ad1836_dai = {
263 }, 216 },
264 .ops = &ad1836_dai_ops, 217 .ops = &ad1836_dai_ops,
265}; 218};
266EXPORT_SYMBOL_GPL(ad1836_dai);
267 219
268static int ad1836_register(struct ad1836_priv *ad1836) 220static int ad1836_probe(struct snd_soc_codec *codec)
269{ 221{
270 int ret; 222 struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec);
271 struct snd_soc_codec *codec = &ad1836->codec; 223 int ret = 0;
272
273 if (ad1836_codec) {
274 dev_err(codec->dev, "Another ad1836 is registered\n");
275 kfree(ad1836);
276 return -EINVAL;
277 }
278
279 mutex_init(&codec->mutex);
280 INIT_LIST_HEAD(&codec->dapm_widgets);
281 INIT_LIST_HEAD(&codec->dapm_paths);
282 snd_soc_codec_set_drvdata(codec, ad1836);
283 codec->reg_cache = ad1836->reg_cache;
284 codec->reg_cache_size = AD1836_NUM_REGS;
285 codec->name = "AD1836";
286 codec->owner = THIS_MODULE;
287 codec->dai = &ad1836_dai;
288 codec->num_dai = 1;
289 INIT_LIST_HEAD(&codec->dapm_widgets);
290 INIT_LIST_HEAD(&codec->dapm_paths);
291
292 ad1836_dai.dev = codec->dev;
293 ad1836_codec = codec;
294 224
225 codec->control_data = ad1836->control_data;
295 ret = snd_soc_codec_set_cache_io(codec, 4, 12, SND_SOC_SPI); 226 ret = snd_soc_codec_set_cache_io(codec, 4, 12, SND_SOC_SPI);
296 if (ret < 0) { 227 if (ret < 0) {
297 dev_err(codec->dev, "failed to set cache I/O: %d\n", 228 dev_err(codec->dev, "failed to set cache I/O: %d\n",
@@ -319,81 +250,69 @@ static int ad1836_register(struct ad1836_priv *ad1836)
319 snd_soc_write(codec, AD1836_DAC_L3_VOL, 0x3FF); 250 snd_soc_write(codec, AD1836_DAC_L3_VOL, 0x3FF);
320 snd_soc_write(codec, AD1836_DAC_R3_VOL, 0x3FF); 251 snd_soc_write(codec, AD1836_DAC_R3_VOL, 0x3FF);
321 252
322 ret = snd_soc_register_codec(codec);
323 if (ret != 0) {
324 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
325 kfree(ad1836);
326 return ret;
327 }
328
329 ret = snd_soc_register_dai(&ad1836_dai);
330 if (ret != 0) {
331 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
332 snd_soc_unregister_codec(codec);
333 kfree(ad1836);
334 return ret;
335 }
336
337 return 0;
338}
339
340static void ad1836_unregister(struct ad1836_priv *ad1836)
341{
342 snd_soc_unregister_dai(&ad1836_dai);
343 snd_soc_unregister_codec(&ad1836->codec);
344 kfree(ad1836);
345 ad1836_codec = NULL;
346}
347
348static int ad1836_probe(struct platform_device *pdev)
349{
350 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
351 struct snd_soc_codec *codec;
352 int ret = 0;
353
354 if (ad1836_codec == NULL) {
355 dev_err(&pdev->dev, "Codec device not registered\n");
356 return -ENODEV;
357 }
358
359 socdev->card->codec = ad1836_codec;
360 codec = ad1836_codec;
361
362 /* register pcms */
363 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
364 if (ret < 0) {
365 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
366 goto pcm_err;
367 }
368
369 snd_soc_add_controls(codec, ad1836_snd_controls, 253 snd_soc_add_controls(codec, ad1836_snd_controls,
370 ARRAY_SIZE(ad1836_snd_controls)); 254 ARRAY_SIZE(ad1836_snd_controls));
371 snd_soc_dapm_new_controls(codec, ad1836_dapm_widgets, 255 snd_soc_dapm_new_controls(codec, ad1836_dapm_widgets,
372 ARRAY_SIZE(ad1836_dapm_widgets)); 256 ARRAY_SIZE(ad1836_dapm_widgets));
373 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); 257 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
374 258
375pcm_err:
376 return ret; 259 return ret;
377} 260}
378 261
379/* power down chip */ 262/* power down chip */
380static int ad1836_remove(struct platform_device *pdev) 263static int ad1836_remove(struct snd_soc_codec *codec)
381{ 264{
382 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 265 /* reset clock control mode */
383 266 u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2);
384 snd_soc_free_pcms(socdev); 267 adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK;
385 snd_soc_dapm_free(socdev);
386 268
387 return 0; 269 return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2);
388} 270}
389 271
390struct snd_soc_codec_device soc_codec_dev_ad1836 = { 272static struct snd_soc_codec_driver soc_codec_dev_ad1836 = {
391 .probe = ad1836_probe, 273 .probe = ad1836_probe,
392 .remove = ad1836_remove, 274 .remove = ad1836_remove,
393 .suspend = ad1836_soc_suspend, 275 .suspend = ad1836_soc_suspend,
394 .resume = ad1836_soc_resume, 276 .resume = ad1836_soc_resume,
277 .reg_cache_size = AD1836_NUM_REGS,
278 .reg_word_size = sizeof(u16),
279};
280
281static int __devinit ad1836_spi_probe(struct spi_device *spi)
282{
283 struct ad1836_priv *ad1836;
284 int ret;
285
286 ad1836 = kzalloc(sizeof(struct ad1836_priv), GFP_KERNEL);
287 if (ad1836 == NULL)
288 return -ENOMEM;
289
290 spi_set_drvdata(spi, ad1836);
291 ad1836->control_data = spi;
292 ad1836->control_type = SND_SOC_SPI;
293
294 ret = snd_soc_register_codec(&spi->dev,
295 &soc_codec_dev_ad1836, &ad1836_dai, 1);
296 if (ret < 0)
297 kfree(ad1836);
298 return ret;
299}
300
301static int __devexit ad1836_spi_remove(struct spi_device *spi)
302{
303 snd_soc_unregister_codec(&spi->dev);
304 kfree(spi_get_drvdata(spi));
305 return 0;
306}
307
308static struct spi_driver ad1836_spi_driver = {
309 .driver = {
310 .name = "ad1836-codec",
311 .owner = THIS_MODULE,
312 },
313 .probe = ad1836_spi_probe,
314 .remove = __devexit_p(ad1836_spi_remove),
395}; 315};
396EXPORT_SYMBOL_GPL(soc_codec_dev_ad1836);
397 316
398static int __init ad1836_init(void) 317static int __init ad1836_init(void)
399{ 318{