aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8711.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/wm8711.c')
-rw-r--r--sound/soc/codecs/wm8711.c202
1 files changed, 55 insertions, 147 deletions
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c
index e2dba07f0260..f8d9c60e7fad 100644
--- a/sound/soc/codecs/wm8711.c
+++ b/sound/soc/codecs/wm8711.c
@@ -31,11 +31,9 @@
31 31
32#include "wm8711.h" 32#include "wm8711.h"
33 33
34static struct snd_soc_codec *wm8711_codec;
35
36/* codec private data */ 34/* codec private data */
37struct wm8711_priv { 35struct wm8711_priv {
38 struct snd_soc_codec codec; 36 enum snd_soc_control_type bus_type;
39 u16 reg_cache[WM8711_CACHEREGNUM]; 37 u16 reg_cache[WM8711_CACHEREGNUM];
40 unsigned int sysclk; 38 unsigned int sysclk;
41}; 39};
@@ -163,7 +161,7 @@ static int wm8711_hw_params(struct snd_pcm_substream *substream,
163 struct snd_soc_dai *dai) 161 struct snd_soc_dai *dai)
164{ 162{
165 struct snd_soc_codec *codec = dai->codec; 163 struct snd_soc_codec *codec = dai->codec;
166 struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); 164 struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec);
167 u16 iface = snd_soc_read(codec, WM8711_IFACE) & 0xfffc; 165 u16 iface = snd_soc_read(codec, WM8711_IFACE) & 0xfffc;
168 int i = get_coeff(wm8711->sysclk, params_rate(params)); 166 int i = get_coeff(wm8711->sysclk, params_rate(params));
169 u16 srate = (coeff_div[i].sr << 2) | 167 u16 srate = (coeff_div[i].sr << 2) |
@@ -227,7 +225,7 @@ static int wm8711_set_dai_sysclk(struct snd_soc_dai *codec_dai,
227 int clk_id, unsigned int freq, int dir) 225 int clk_id, unsigned int freq, int dir)
228{ 226{
229 struct snd_soc_codec *codec = codec_dai->codec; 227 struct snd_soc_codec *codec = codec_dai->codec;
230 struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); 228 struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec);
231 229
232 switch (freq) { 230 switch (freq) {
233 case 11289600: 231 case 11289600:
@@ -338,8 +336,8 @@ static struct snd_soc_dai_ops wm8711_ops = {
338 .set_fmt = wm8711_set_dai_fmt, 336 .set_fmt = wm8711_set_dai_fmt,
339}; 337};
340 338
341struct snd_soc_dai wm8711_dai = { 339static struct snd_soc_dai_driver wm8711_dai = {
342 .name = "WM8711", 340 .name = "wm8711-hifi",
343 .playback = { 341 .playback = {
344 .stream_name = "Playback", 342 .stream_name = "Playback",
345 .channels_min = 1, 343 .channels_min = 1,
@@ -349,22 +347,16 @@ struct snd_soc_dai wm8711_dai = {
349 }, 347 },
350 .ops = &wm8711_ops, 348 .ops = &wm8711_ops,
351}; 349};
352EXPORT_SYMBOL_GPL(wm8711_dai);
353 350
354static int wm8711_suspend(struct platform_device *pdev, pm_message_t state) 351static int wm8711_suspend(struct snd_soc_codec *codec, pm_message_t state)
355{ 352{
356 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
357 struct snd_soc_codec *codec = socdev->card->codec;
358
359 snd_soc_write(codec, WM8711_ACTIVE, 0x0); 353 snd_soc_write(codec, WM8711_ACTIVE, 0x0);
360 wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF); 354 wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF);
361 return 0; 355 return 0;
362} 356}
363 357
364static int wm8711_resume(struct platform_device *pdev) 358static int wm8711_resume(struct snd_soc_codec *codec)
365{ 359{
366 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
367 struct snd_soc_codec *codec = socdev->card->codec;
368 int i; 360 int i;
369 u8 data[2]; 361 u8 data[2];
370 u16 *cache = codec->reg_cache; 362 u16 *cache = codec->reg_cache;
@@ -380,99 +372,23 @@ static int wm8711_resume(struct platform_device *pdev)
380 return 0; 372 return 0;
381} 373}
382 374
383static int wm8711_probe(struct platform_device *pdev) 375static int wm8711_probe(struct snd_soc_codec *codec)
384{ 376{
385 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 377 struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec);
386 struct snd_soc_codec *codec; 378 int ret, reg;
387 int ret = 0;
388
389 if (wm8711_codec == NULL) {
390 dev_err(&pdev->dev, "Codec device not registered\n");
391 return -ENODEV;
392 }
393
394 socdev->card->codec = wm8711_codec;
395 codec = wm8711_codec;
396
397 /* register pcms */
398 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
399 if (ret < 0) {
400 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
401 goto pcm_err;
402 }
403
404 snd_soc_add_controls(codec, wm8711_snd_controls,
405 ARRAY_SIZE(wm8711_snd_controls));
406 wm8711_add_widgets(codec);
407
408 return ret;
409
410pcm_err:
411 return ret;
412}
413
414/* power down chip */
415static int wm8711_remove(struct platform_device *pdev)
416{
417 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
418
419 snd_soc_free_pcms(socdev);
420 snd_soc_dapm_free(socdev);
421
422 return 0;
423}
424
425struct snd_soc_codec_device soc_codec_dev_wm8711 = {
426 .probe = wm8711_probe,
427 .remove = wm8711_remove,
428 .suspend = wm8711_suspend,
429 .resume = wm8711_resume,
430};
431EXPORT_SYMBOL_GPL(soc_codec_dev_wm8711);
432
433static int wm8711_register(struct wm8711_priv *wm8711,
434 enum snd_soc_control_type control)
435{
436 int ret;
437 struct snd_soc_codec *codec = &wm8711->codec;
438 u16 reg;
439
440 if (wm8711_codec) {
441 dev_err(codec->dev, "Another WM8711 is registered\n");
442 ret = -EINVAL;
443 goto err;
444 }
445
446 mutex_init(&codec->mutex);
447 INIT_LIST_HEAD(&codec->dapm_widgets);
448 INIT_LIST_HEAD(&codec->dapm_paths);
449
450 snd_soc_codec_set_drvdata(codec, wm8711);
451 codec->name = "WM8711";
452 codec->owner = THIS_MODULE;
453 codec->bias_level = SND_SOC_BIAS_OFF;
454 codec->set_bias_level = wm8711_set_bias_level;
455 codec->dai = &wm8711_dai;
456 codec->num_dai = 1;
457 codec->reg_cache_size = WM8711_CACHEREGNUM;
458 codec->reg_cache = &wm8711->reg_cache;
459
460 memcpy(codec->reg_cache, wm8711_reg, sizeof(wm8711_reg));
461 379
462 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); 380 ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8711->bus_type);
463 if (ret < 0) { 381 if (ret < 0) {
464 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); 382 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
465 goto err; 383 return ret;
466 } 384 }
467 385
468 ret = wm8711_reset(codec); 386 ret = wm8711_reset(codec);
469 if (ret < 0) { 387 if (ret < 0) {
470 dev_err(codec->dev, "Failed to issue reset\n"); 388 dev_err(codec->dev, "Failed to issue reset\n");
471 goto err; 389 return ret;
472 } 390 }
473 391
474 wm8711_dai.dev = codec->dev;
475
476 wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 392 wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
477 393
478 /* Latch the update bits */ 394 /* Latch the update bits */
@@ -481,69 +397,62 @@ static int wm8711_register(struct wm8711_priv *wm8711,
481 reg = snd_soc_read(codec, WM8711_ROUT1V); 397 reg = snd_soc_read(codec, WM8711_ROUT1V);
482 snd_soc_write(codec, WM8711_ROUT1V, reg | 0x0100); 398 snd_soc_write(codec, WM8711_ROUT1V, reg | 0x0100);
483 399
484 wm8711_codec = codec; 400 snd_soc_add_controls(codec, wm8711_snd_controls,
485 401 ARRAY_SIZE(wm8711_snd_controls));
486 ret = snd_soc_register_codec(codec); 402 wm8711_add_widgets(codec);
487 if (ret != 0) {
488 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
489 goto err;
490 }
491
492 ret = snd_soc_register_dai(&wm8711_dai);
493 if (ret != 0) {
494 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
495 goto err_codec;
496 }
497
498 return 0;
499 403
500err_codec:
501 snd_soc_unregister_codec(codec);
502err:
503 kfree(wm8711);
504 return ret; 404 return ret;
405
505} 406}
506 407
507static void wm8711_unregister(struct wm8711_priv *wm8711) 408/* power down chip */
409static int wm8711_remove(struct snd_soc_codec *codec)
508{ 410{
509 wm8711_set_bias_level(&wm8711->codec, SND_SOC_BIAS_OFF); 411 wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF);
510 snd_soc_unregister_dai(&wm8711_dai); 412 return 0;
511 snd_soc_unregister_codec(&wm8711->codec);
512 kfree(wm8711);
513 wm8711_codec = NULL;
514} 413}
515 414
415static struct snd_soc_codec_driver soc_codec_dev_wm8711 = {
416 .probe = wm8711_probe,
417 .remove = wm8711_remove,
418 .suspend = wm8711_suspend,
419 .resume = wm8711_resume,
420 .set_bias_level = wm8711_set_bias_level,
421 .reg_cache_size = sizeof(wm8711_reg),
422 .reg_word_size = sizeof(u16),
423 .reg_cache_default = wm8711_reg,
424};
425
516#if defined(CONFIG_SPI_MASTER) 426#if defined(CONFIG_SPI_MASTER)
517static int __devinit wm8711_spi_probe(struct spi_device *spi) 427static int __devinit wm8711_spi_probe(struct spi_device *spi)
518{ 428{
519 struct snd_soc_codec *codec;
520 struct wm8711_priv *wm8711; 429 struct wm8711_priv *wm8711;
430 int ret;
521 431
522 wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL); 432 wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL);
523 if (wm8711 == NULL) 433 if (wm8711 == NULL)
524 return -ENOMEM; 434 return -ENOMEM;
525 435
526 codec = &wm8711->codec; 436 spi_set_drvdata(spi, wm8711);
527 codec->control_data = spi; 437 wm8711->bus_type = SND_SOC_SPI;
528 codec->dev = &spi->dev;
529 438
530 dev_set_drvdata(&spi->dev, wm8711); 439 ret = snd_soc_register_codec(&spi->dev,
531 440 &soc_codec_dev_wm8711, &wm8711_dai, 1);
532 return wm8711_register(wm8711, SND_SOC_SPI); 441 if (ret < 0)
442 kfree(wm8711);
443 return ret;
533} 444}
534 445
535static int __devexit wm8711_spi_remove(struct spi_device *spi) 446static int __devexit wm8711_spi_remove(struct spi_device *spi)
536{ 447{
537 struct wm8711_priv *wm8711 = dev_get_drvdata(&spi->dev); 448 snd_soc_unregister_codec(&spi->dev);
538 449 kfree(spi_get_drvdata(spi));
539 wm8711_unregister(wm8711);
540
541 return 0; 450 return 0;
542} 451}
543 452
544static struct spi_driver wm8711_spi_driver = { 453static struct spi_driver wm8711_spi_driver = {
545 .driver = { 454 .driver = {
546 .name = "wm8711", 455 .name = "wm8711-codec",
547 .bus = &spi_bus_type, 456 .bus = &spi_bus_type,
548 .owner = THIS_MODULE, 457 .owner = THIS_MODULE,
549 }, 458 },
@@ -553,31 +462,30 @@ static struct spi_driver wm8711_spi_driver = {
553#endif /* CONFIG_SPI_MASTER */ 462#endif /* CONFIG_SPI_MASTER */
554 463
555#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 464#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
556static __devinit int wm8711_i2c_probe(struct i2c_client *i2c, 465static __devinit int wm8711_i2c_probe(struct i2c_client *client,
557 const struct i2c_device_id *id) 466 const struct i2c_device_id *id)
558{ 467{
559 struct wm8711_priv *wm8711; 468 struct wm8711_priv *wm8711;
560 struct snd_soc_codec *codec; 469 int ret;
561 470
562 wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL); 471 wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL);
563 if (wm8711 == NULL) 472 if (wm8711 == NULL)
564 return -ENOMEM; 473 return -ENOMEM;
565 474
566 codec = &wm8711->codec; 475 i2c_set_clientdata(client, wm8711);
567 codec->hw_write = (hw_write_t)i2c_master_send; 476 wm8711->bus_type = SND_SOC_I2C;
568
569 i2c_set_clientdata(i2c, wm8711);
570 codec->control_data = i2c;
571 477
572 codec->dev = &i2c->dev; 478 ret = snd_soc_register_codec(&client->dev,
573 479 &soc_codec_dev_wm8711, &wm8711_dai, 1);
574 return wm8711_register(wm8711, SND_SOC_I2C); 480 if (ret < 0)
481 kfree(wm8711);
482 return ret;
575} 483}
576 484
577static __devexit int wm8711_i2c_remove(struct i2c_client *client) 485static __devexit int wm8711_i2c_remove(struct i2c_client *client)
578{ 486{
579 struct wm8711_priv *wm8711 = i2c_get_clientdata(client); 487 snd_soc_unregister_codec(&client->dev);
580 wm8711_unregister(wm8711); 488 kfree(i2c_get_clientdata(client));
581 return 0; 489 return 0;
582} 490}
583 491
@@ -589,7 +497,7 @@ MODULE_DEVICE_TABLE(i2c, wm8711_i2c_id);
589 497
590static struct i2c_driver wm8711_i2c_driver = { 498static struct i2c_driver wm8711_i2c_driver = {
591 .driver = { 499 .driver = {
592 .name = "WM8711 I2C Codec", 500 .name = "wm8711-codec",
593 .owner = THIS_MODULE, 501 .owner = THIS_MODULE,
594 }, 502 },
595 .probe = wm8711_i2c_probe, 503 .probe = wm8711_i2c_probe,