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