diff options
Diffstat (limited to 'sound/soc/codecs/wm8960.c')
-rw-r--r-- | sound/soc/codecs/wm8960.c | 233 |
1 files changed, 103 insertions, 130 deletions
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index e224d8add170..f59703be61c8 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c | |||
@@ -69,61 +69,7 @@ struct wm8960_priv { | |||
69 | struct snd_soc_codec codec; | 69 | struct snd_soc_codec codec; |
70 | }; | 70 | }; |
71 | 71 | ||
72 | /* | 72 | #define wm8960_reset(c) snd_soc_write(c, WM8960_RESET, 0) |
73 | * read wm8960 register cache | ||
74 | */ | ||
75 | static inline unsigned int wm8960_read_reg_cache(struct snd_soc_codec *codec, | ||
76 | unsigned int reg) | ||
77 | { | ||
78 | u16 *cache = codec->reg_cache; | ||
79 | if (reg == WM8960_RESET) | ||
80 | return 0; | ||
81 | if (reg >= WM8960_CACHEREGNUM) | ||
82 | return -1; | ||
83 | return cache[reg]; | ||
84 | } | ||
85 | |||
86 | /* | ||
87 | * write wm8960 register cache | ||
88 | */ | ||
89 | static inline void wm8960_write_reg_cache(struct snd_soc_codec *codec, | ||
90 | u16 reg, unsigned int value) | ||
91 | { | ||
92 | u16 *cache = codec->reg_cache; | ||
93 | if (reg >= WM8960_CACHEREGNUM) | ||
94 | return; | ||
95 | cache[reg] = value; | ||
96 | } | ||
97 | |||
98 | static inline unsigned int wm8960_read(struct snd_soc_codec *codec, | ||
99 | unsigned int reg) | ||
100 | { | ||
101 | return wm8960_read_reg_cache(codec, reg); | ||
102 | } | ||
103 | |||
104 | /* | ||
105 | * write to the WM8960 register space | ||
106 | */ | ||
107 | static int wm8960_write(struct snd_soc_codec *codec, unsigned int reg, | ||
108 | unsigned int value) | ||
109 | { | ||
110 | u8 data[2]; | ||
111 | |||
112 | /* data is | ||
113 | * D15..D9 WM8960 register offset | ||
114 | * D8...D0 register data | ||
115 | */ | ||
116 | data[0] = (reg << 1) | ((value >> 8) & 0x0001); | ||
117 | data[1] = value & 0x00ff; | ||
118 | |||
119 | wm8960_write_reg_cache(codec, reg, value); | ||
120 | if (codec->hw_write(codec->control_data, data, 2) == 2) | ||
121 | return 0; | ||
122 | else | ||
123 | return -EIO; | ||
124 | } | ||
125 | |||
126 | #define wm8960_reset(c) wm8960_write(c, WM8960_RESET, 0) | ||
127 | 73 | ||
128 | /* enumerated controls */ | 74 | /* enumerated controls */ |
129 | static const char *wm8960_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"}; | 75 | static const char *wm8960_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"}; |
@@ -420,7 +366,7 @@ static int wm8960_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
420 | } | 366 | } |
421 | 367 | ||
422 | /* set iface */ | 368 | /* set iface */ |
423 | wm8960_write(codec, WM8960_IFACE1, iface); | 369 | snd_soc_write(codec, WM8960_IFACE1, iface); |
424 | return 0; | 370 | return 0; |
425 | } | 371 | } |
426 | 372 | ||
@@ -431,7 +377,7 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream, | |||
431 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 377 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
432 | struct snd_soc_device *socdev = rtd->socdev; | 378 | struct snd_soc_device *socdev = rtd->socdev; |
433 | struct snd_soc_codec *codec = socdev->card->codec; | 379 | struct snd_soc_codec *codec = socdev->card->codec; |
434 | u16 iface = wm8960_read(codec, WM8960_IFACE1) & 0xfff3; | 380 | u16 iface = snd_soc_read(codec, WM8960_IFACE1) & 0xfff3; |
435 | 381 | ||
436 | /* bit size */ | 382 | /* bit size */ |
437 | switch (params_format(params)) { | 383 | switch (params_format(params)) { |
@@ -446,19 +392,19 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream, | |||
446 | } | 392 | } |
447 | 393 | ||
448 | /* set iface */ | 394 | /* set iface */ |
449 | wm8960_write(codec, WM8960_IFACE1, iface); | 395 | snd_soc_write(codec, WM8960_IFACE1, iface); |
450 | return 0; | 396 | return 0; |
451 | } | 397 | } |
452 | 398 | ||
453 | static int wm8960_mute(struct snd_soc_dai *dai, int mute) | 399 | static int wm8960_mute(struct snd_soc_dai *dai, int mute) |
454 | { | 400 | { |
455 | struct snd_soc_codec *codec = dai->codec; | 401 | struct snd_soc_codec *codec = dai->codec; |
456 | u16 mute_reg = wm8960_read(codec, WM8960_DACCTL1) & 0xfff7; | 402 | u16 mute_reg = snd_soc_read(codec, WM8960_DACCTL1) & 0xfff7; |
457 | 403 | ||
458 | if (mute) | 404 | if (mute) |
459 | wm8960_write(codec, WM8960_DACCTL1, mute_reg | 0x8); | 405 | snd_soc_write(codec, WM8960_DACCTL1, mute_reg | 0x8); |
460 | else | 406 | else |
461 | wm8960_write(codec, WM8960_DACCTL1, mute_reg); | 407 | snd_soc_write(codec, WM8960_DACCTL1, mute_reg); |
462 | return 0; | 408 | return 0; |
463 | } | 409 | } |
464 | 410 | ||
@@ -474,16 +420,16 @@ static int wm8960_set_bias_level(struct snd_soc_codec *codec, | |||
474 | 420 | ||
475 | case SND_SOC_BIAS_PREPARE: | 421 | case SND_SOC_BIAS_PREPARE: |
476 | /* Set VMID to 2x50k */ | 422 | /* Set VMID to 2x50k */ |
477 | reg = wm8960_read(codec, WM8960_POWER1); | 423 | reg = snd_soc_read(codec, WM8960_POWER1); |
478 | reg &= ~0x180; | 424 | reg &= ~0x180; |
479 | reg |= 0x80; | 425 | reg |= 0x80; |
480 | wm8960_write(codec, WM8960_POWER1, reg); | 426 | snd_soc_write(codec, WM8960_POWER1, reg); |
481 | break; | 427 | break; |
482 | 428 | ||
483 | case SND_SOC_BIAS_STANDBY: | 429 | case SND_SOC_BIAS_STANDBY: |
484 | if (codec->bias_level == SND_SOC_BIAS_OFF) { | 430 | if (codec->bias_level == SND_SOC_BIAS_OFF) { |
485 | /* Enable anti-pop features */ | 431 | /* Enable anti-pop features */ |
486 | wm8960_write(codec, WM8960_APOP1, | 432 | snd_soc_write(codec, WM8960_APOP1, |
487 | WM8960_POBCTRL | WM8960_SOFT_ST | | 433 | WM8960_POBCTRL | WM8960_SOFT_ST | |
488 | WM8960_BUFDCOPEN | WM8960_BUFIOEN); | 434 | WM8960_BUFDCOPEN | WM8960_BUFIOEN); |
489 | 435 | ||
@@ -491,43 +437,43 @@ static int wm8960_set_bias_level(struct snd_soc_codec *codec, | |||
491 | reg = WM8960_DISOP; | 437 | reg = WM8960_DISOP; |
492 | if (pdata) | 438 | if (pdata) |
493 | reg |= pdata->dres << 4; | 439 | reg |= pdata->dres << 4; |
494 | wm8960_write(codec, WM8960_APOP2, reg); | 440 | snd_soc_write(codec, WM8960_APOP2, reg); |
495 | 441 | ||
496 | msleep(400); | 442 | msleep(400); |
497 | 443 | ||
498 | wm8960_write(codec, WM8960_APOP2, 0); | 444 | snd_soc_write(codec, WM8960_APOP2, 0); |
499 | 445 | ||
500 | /* Enable & ramp VMID at 2x50k */ | 446 | /* Enable & ramp VMID at 2x50k */ |
501 | reg = wm8960_read(codec, WM8960_POWER1); | 447 | reg = snd_soc_read(codec, WM8960_POWER1); |
502 | reg |= 0x80; | 448 | reg |= 0x80; |
503 | wm8960_write(codec, WM8960_POWER1, reg); | 449 | snd_soc_write(codec, WM8960_POWER1, reg); |
504 | msleep(100); | 450 | msleep(100); |
505 | 451 | ||
506 | /* Enable VREF */ | 452 | /* Enable VREF */ |
507 | wm8960_write(codec, WM8960_POWER1, reg | WM8960_VREF); | 453 | snd_soc_write(codec, WM8960_POWER1, reg | WM8960_VREF); |
508 | 454 | ||
509 | /* Disable anti-pop features */ | 455 | /* Disable anti-pop features */ |
510 | wm8960_write(codec, WM8960_APOP1, WM8960_BUFIOEN); | 456 | snd_soc_write(codec, WM8960_APOP1, WM8960_BUFIOEN); |
511 | } | 457 | } |
512 | 458 | ||
513 | /* Set VMID to 2x250k */ | 459 | /* Set VMID to 2x250k */ |
514 | reg = wm8960_read(codec, WM8960_POWER1); | 460 | reg = snd_soc_read(codec, WM8960_POWER1); |
515 | reg &= ~0x180; | 461 | reg &= ~0x180; |
516 | reg |= 0x100; | 462 | reg |= 0x100; |
517 | wm8960_write(codec, WM8960_POWER1, reg); | 463 | snd_soc_write(codec, WM8960_POWER1, reg); |
518 | break; | 464 | break; |
519 | 465 | ||
520 | case SND_SOC_BIAS_OFF: | 466 | case SND_SOC_BIAS_OFF: |
521 | /* Enable anti-pop features */ | 467 | /* Enable anti-pop features */ |
522 | wm8960_write(codec, WM8960_APOP1, | 468 | snd_soc_write(codec, WM8960_APOP1, |
523 | WM8960_POBCTRL | WM8960_SOFT_ST | | 469 | WM8960_POBCTRL | WM8960_SOFT_ST | |
524 | WM8960_BUFDCOPEN | WM8960_BUFIOEN); | 470 | WM8960_BUFDCOPEN | WM8960_BUFIOEN); |
525 | 471 | ||
526 | /* Disable VMID and VREF, let them discharge */ | 472 | /* Disable VMID and VREF, let them discharge */ |
527 | wm8960_write(codec, WM8960_POWER1, 0); | 473 | snd_soc_write(codec, WM8960_POWER1, 0); |
528 | msleep(600); | 474 | msleep(600); |
529 | 475 | ||
530 | wm8960_write(codec, WM8960_APOP1, 0); | 476 | snd_soc_write(codec, WM8960_APOP1, 0); |
531 | break; | 477 | break; |
532 | } | 478 | } |
533 | 479 | ||
@@ -610,33 +556,33 @@ static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai, | |||
610 | 556 | ||
611 | /* Disable the PLL: even if we are changing the frequency the | 557 | /* Disable the PLL: even if we are changing the frequency the |
612 | * PLL needs to be disabled while we do so. */ | 558 | * PLL needs to be disabled while we do so. */ |
613 | wm8960_write(codec, WM8960_CLOCK1, | 559 | snd_soc_write(codec, WM8960_CLOCK1, |
614 | wm8960_read(codec, WM8960_CLOCK1) & ~1); | 560 | snd_soc_read(codec, WM8960_CLOCK1) & ~1); |
615 | wm8960_write(codec, WM8960_POWER2, | 561 | snd_soc_write(codec, WM8960_POWER2, |
616 | wm8960_read(codec, WM8960_POWER2) & ~1); | 562 | snd_soc_read(codec, WM8960_POWER2) & ~1); |
617 | 563 | ||
618 | if (!freq_in || !freq_out) | 564 | if (!freq_in || !freq_out) |
619 | return 0; | 565 | return 0; |
620 | 566 | ||
621 | reg = wm8960_read(codec, WM8960_PLL1) & ~0x3f; | 567 | reg = snd_soc_read(codec, WM8960_PLL1) & ~0x3f; |
622 | reg |= pll_div.pre_div << 4; | 568 | reg |= pll_div.pre_div << 4; |
623 | reg |= pll_div.n; | 569 | reg |= pll_div.n; |
624 | 570 | ||
625 | if (pll_div.k) { | 571 | if (pll_div.k) { |
626 | reg |= 0x20; | 572 | reg |= 0x20; |
627 | 573 | ||
628 | wm8960_write(codec, WM8960_PLL2, (pll_div.k >> 18) & 0x3f); | 574 | snd_soc_write(codec, WM8960_PLL2, (pll_div.k >> 18) & 0x3f); |
629 | wm8960_write(codec, WM8960_PLL3, (pll_div.k >> 9) & 0x1ff); | 575 | snd_soc_write(codec, WM8960_PLL3, (pll_div.k >> 9) & 0x1ff); |
630 | wm8960_write(codec, WM8960_PLL4, pll_div.k & 0x1ff); | 576 | snd_soc_write(codec, WM8960_PLL4, pll_div.k & 0x1ff); |
631 | } | 577 | } |
632 | wm8960_write(codec, WM8960_PLL1, reg); | 578 | snd_soc_write(codec, WM8960_PLL1, reg); |
633 | 579 | ||
634 | /* Turn it on */ | 580 | /* Turn it on */ |
635 | wm8960_write(codec, WM8960_POWER2, | 581 | snd_soc_write(codec, WM8960_POWER2, |
636 | wm8960_read(codec, WM8960_POWER2) | 1); | 582 | snd_soc_read(codec, WM8960_POWER2) | 1); |
637 | msleep(250); | 583 | msleep(250); |
638 | wm8960_write(codec, WM8960_CLOCK1, | 584 | snd_soc_write(codec, WM8960_CLOCK1, |
639 | wm8960_read(codec, WM8960_CLOCK1) | 1); | 585 | snd_soc_read(codec, WM8960_CLOCK1) | 1); |
640 | 586 | ||
641 | return 0; | 587 | return 0; |
642 | } | 588 | } |
@@ -649,28 +595,28 @@ static int wm8960_set_dai_clkdiv(struct snd_soc_dai *codec_dai, | |||
649 | 595 | ||
650 | switch (div_id) { | 596 | switch (div_id) { |
651 | case WM8960_SYSCLKSEL: | 597 | case WM8960_SYSCLKSEL: |
652 | reg = wm8960_read(codec, WM8960_CLOCK1) & 0x1fe; | 598 | reg = snd_soc_read(codec, WM8960_CLOCK1) & 0x1fe; |
653 | wm8960_write(codec, WM8960_CLOCK1, reg | div); | 599 | snd_soc_write(codec, WM8960_CLOCK1, reg | div); |
654 | break; | 600 | break; |
655 | case WM8960_SYSCLKDIV: | 601 | case WM8960_SYSCLKDIV: |
656 | reg = wm8960_read(codec, WM8960_CLOCK1) & 0x1f9; | 602 | reg = snd_soc_read(codec, WM8960_CLOCK1) & 0x1f9; |
657 | wm8960_write(codec, WM8960_CLOCK1, reg | div); | 603 | snd_soc_write(codec, WM8960_CLOCK1, reg | div); |
658 | break; | 604 | break; |
659 | case WM8960_DACDIV: | 605 | case WM8960_DACDIV: |
660 | reg = wm8960_read(codec, WM8960_CLOCK1) & 0x1c7; | 606 | reg = snd_soc_read(codec, WM8960_CLOCK1) & 0x1c7; |
661 | wm8960_write(codec, WM8960_CLOCK1, reg | div); | 607 | snd_soc_write(codec, WM8960_CLOCK1, reg | div); |
662 | break; | 608 | break; |
663 | case WM8960_OPCLKDIV: | 609 | case WM8960_OPCLKDIV: |
664 | reg = wm8960_read(codec, WM8960_PLL1) & 0x03f; | 610 | reg = snd_soc_read(codec, WM8960_PLL1) & 0x03f; |
665 | wm8960_write(codec, WM8960_PLL1, reg | div); | 611 | snd_soc_write(codec, WM8960_PLL1, reg | div); |
666 | break; | 612 | break; |
667 | case WM8960_DCLKDIV: | 613 | case WM8960_DCLKDIV: |
668 | reg = wm8960_read(codec, WM8960_CLOCK2) & 0x03f; | 614 | reg = snd_soc_read(codec, WM8960_CLOCK2) & 0x03f; |
669 | wm8960_write(codec, WM8960_CLOCK2, reg | div); | 615 | snd_soc_write(codec, WM8960_CLOCK2, reg | div); |
670 | break; | 616 | break; |
671 | case WM8960_TOCLKSEL: | 617 | case WM8960_TOCLKSEL: |
672 | reg = wm8960_read(codec, WM8960_ADDCTL1) & 0x1fd; | 618 | reg = snd_soc_read(codec, WM8960_ADDCTL1) & 0x1fd; |
673 | wm8960_write(codec, WM8960_ADDCTL1, reg | div); | 619 | snd_soc_write(codec, WM8960_ADDCTL1, reg | div); |
674 | break; | 620 | break; |
675 | default: | 621 | default: |
676 | return -EINVAL; | 622 | return -EINVAL; |
@@ -801,7 +747,8 @@ struct snd_soc_codec_device soc_codec_dev_wm8960 = { | |||
801 | }; | 747 | }; |
802 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8960); | 748 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8960); |
803 | 749 | ||
804 | static int wm8960_register(struct wm8960_priv *wm8960) | 750 | static int wm8960_register(struct wm8960_priv *wm8960, |
751 | enum snd_soc_control_type control) | ||
805 | { | 752 | { |
806 | struct wm8960_data *pdata = wm8960->codec.dev->platform_data; | 753 | struct wm8960_data *pdata = wm8960->codec.dev->platform_data; |
807 | struct snd_soc_codec *codec = &wm8960->codec; | 754 | struct snd_soc_codec *codec = &wm8960->codec; |
@@ -810,7 +757,8 @@ static int wm8960_register(struct wm8960_priv *wm8960) | |||
810 | 757 | ||
811 | if (wm8960_codec) { | 758 | if (wm8960_codec) { |
812 | dev_err(codec->dev, "Another WM8960 is registered\n"); | 759 | dev_err(codec->dev, "Another WM8960 is registered\n"); |
813 | return -EINVAL; | 760 | ret = -EINVAL; |
761 | goto err; | ||
814 | } | 762 | } |
815 | 763 | ||
816 | if (!pdata) { | 764 | if (!pdata) { |
@@ -829,8 +777,6 @@ static int wm8960_register(struct wm8960_priv *wm8960) | |||
829 | codec->private_data = wm8960; | 777 | codec->private_data = wm8960; |
830 | codec->name = "WM8960"; | 778 | codec->name = "WM8960"; |
831 | codec->owner = THIS_MODULE; | 779 | codec->owner = THIS_MODULE; |
832 | codec->read = wm8960_read_reg_cache; | ||
833 | codec->write = wm8960_write; | ||
834 | codec->bias_level = SND_SOC_BIAS_OFF; | 780 | codec->bias_level = SND_SOC_BIAS_OFF; |
835 | codec->set_bias_level = wm8960_set_bias_level; | 781 | codec->set_bias_level = wm8960_set_bias_level; |
836 | codec->dai = &wm8960_dai; | 782 | codec->dai = &wm8960_dai; |
@@ -840,10 +786,16 @@ static int wm8960_register(struct wm8960_priv *wm8960) | |||
840 | 786 | ||
841 | memcpy(codec->reg_cache, wm8960_reg, sizeof(wm8960_reg)); | 787 | memcpy(codec->reg_cache, wm8960_reg, sizeof(wm8960_reg)); |
842 | 788 | ||
789 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); | ||
790 | if (ret < 0) { | ||
791 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
792 | goto err; | ||
793 | } | ||
794 | |||
843 | ret = wm8960_reset(codec); | 795 | ret = wm8960_reset(codec); |
844 | if (ret < 0) { | 796 | if (ret < 0) { |
845 | dev_err(codec->dev, "Failed to issue reset\n"); | 797 | dev_err(codec->dev, "Failed to issue reset\n"); |
846 | return ret; | 798 | goto err; |
847 | } | 799 | } |
848 | 800 | ||
849 | wm8960_dai.dev = codec->dev; | 801 | wm8960_dai.dev = codec->dev; |
@@ -851,43 +803,48 @@ static int wm8960_register(struct wm8960_priv *wm8960) | |||
851 | wm8960_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 803 | wm8960_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
852 | 804 | ||
853 | /* Latch the update bits */ | 805 | /* Latch the update bits */ |
854 | reg = wm8960_read(codec, WM8960_LINVOL); | 806 | reg = snd_soc_read(codec, WM8960_LINVOL); |
855 | wm8960_write(codec, WM8960_LINVOL, reg | 0x100); | 807 | snd_soc_write(codec, WM8960_LINVOL, reg | 0x100); |
856 | reg = wm8960_read(codec, WM8960_RINVOL); | 808 | reg = snd_soc_read(codec, WM8960_RINVOL); |
857 | wm8960_write(codec, WM8960_RINVOL, reg | 0x100); | 809 | snd_soc_write(codec, WM8960_RINVOL, reg | 0x100); |
858 | reg = wm8960_read(codec, WM8960_LADC); | 810 | reg = snd_soc_read(codec, WM8960_LADC); |
859 | wm8960_write(codec, WM8960_LADC, reg | 0x100); | 811 | snd_soc_write(codec, WM8960_LADC, reg | 0x100); |
860 | reg = wm8960_read(codec, WM8960_RADC); | 812 | reg = snd_soc_read(codec, WM8960_RADC); |
861 | wm8960_write(codec, WM8960_RADC, reg | 0x100); | 813 | snd_soc_write(codec, WM8960_RADC, reg | 0x100); |
862 | reg = wm8960_read(codec, WM8960_LDAC); | 814 | reg = snd_soc_read(codec, WM8960_LDAC); |
863 | wm8960_write(codec, WM8960_LDAC, reg | 0x100); | 815 | snd_soc_write(codec, WM8960_LDAC, reg | 0x100); |
864 | reg = wm8960_read(codec, WM8960_RDAC); | 816 | reg = snd_soc_read(codec, WM8960_RDAC); |
865 | wm8960_write(codec, WM8960_RDAC, reg | 0x100); | 817 | snd_soc_write(codec, WM8960_RDAC, reg | 0x100); |
866 | reg = wm8960_read(codec, WM8960_LOUT1); | 818 | reg = snd_soc_read(codec, WM8960_LOUT1); |
867 | wm8960_write(codec, WM8960_LOUT1, reg | 0x100); | 819 | snd_soc_write(codec, WM8960_LOUT1, reg | 0x100); |
868 | reg = wm8960_read(codec, WM8960_ROUT1); | 820 | reg = snd_soc_read(codec, WM8960_ROUT1); |
869 | wm8960_write(codec, WM8960_ROUT1, reg | 0x100); | 821 | snd_soc_write(codec, WM8960_ROUT1, reg | 0x100); |
870 | reg = wm8960_read(codec, WM8960_LOUT2); | 822 | reg = snd_soc_read(codec, WM8960_LOUT2); |
871 | wm8960_write(codec, WM8960_LOUT2, reg | 0x100); | 823 | snd_soc_write(codec, WM8960_LOUT2, reg | 0x100); |
872 | reg = wm8960_read(codec, WM8960_ROUT2); | 824 | reg = snd_soc_read(codec, WM8960_ROUT2); |
873 | wm8960_write(codec, WM8960_ROUT2, reg | 0x100); | 825 | snd_soc_write(codec, WM8960_ROUT2, reg | 0x100); |
874 | 826 | ||
875 | wm8960_codec = codec; | 827 | wm8960_codec = codec; |
876 | 828 | ||
877 | ret = snd_soc_register_codec(codec); | 829 | ret = snd_soc_register_codec(codec); |
878 | if (ret != 0) { | 830 | if (ret != 0) { |
879 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | 831 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); |
880 | return ret; | 832 | goto err; |
881 | } | 833 | } |
882 | 834 | ||
883 | ret = snd_soc_register_dai(&wm8960_dai); | 835 | ret = snd_soc_register_dai(&wm8960_dai); |
884 | if (ret != 0) { | 836 | if (ret != 0) { |
885 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | 837 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); |
886 | snd_soc_unregister_codec(codec); | 838 | goto err_codec; |
887 | return ret; | ||
888 | } | 839 | } |
889 | 840 | ||
890 | return 0; | 841 | return 0; |
842 | |||
843 | err_codec: | ||
844 | snd_soc_unregister_codec(codec); | ||
845 | err: | ||
846 | kfree(wm8960); | ||
847 | return ret; | ||
891 | } | 848 | } |
892 | 849 | ||
893 | static void wm8960_unregister(struct wm8960_priv *wm8960) | 850 | static void wm8960_unregister(struct wm8960_priv *wm8960) |
@@ -910,14 +867,13 @@ static __devinit int wm8960_i2c_probe(struct i2c_client *i2c, | |||
910 | return -ENOMEM; | 867 | return -ENOMEM; |
911 | 868 | ||
912 | codec = &wm8960->codec; | 869 | codec = &wm8960->codec; |
913 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
914 | 870 | ||
915 | i2c_set_clientdata(i2c, wm8960); | 871 | i2c_set_clientdata(i2c, wm8960); |
916 | codec->control_data = i2c; | 872 | codec->control_data = i2c; |
917 | 873 | ||
918 | codec->dev = &i2c->dev; | 874 | codec->dev = &i2c->dev; |
919 | 875 | ||
920 | return wm8960_register(wm8960); | 876 | return wm8960_register(wm8960, SND_SOC_I2C); |
921 | } | 877 | } |
922 | 878 | ||
923 | static __devexit int wm8960_i2c_remove(struct i2c_client *client) | 879 | static __devexit int wm8960_i2c_remove(struct i2c_client *client) |
@@ -927,6 +883,21 @@ static __devexit int wm8960_i2c_remove(struct i2c_client *client) | |||
927 | return 0; | 883 | return 0; |
928 | } | 884 | } |
929 | 885 | ||
886 | #ifdef CONFIG_PM | ||
887 | static int wm8960_i2c_suspend(struct i2c_client *client, pm_message_t msg) | ||
888 | { | ||
889 | return snd_soc_suspend_device(&client->dev); | ||
890 | } | ||
891 | |||
892 | static int wm8960_i2c_resume(struct i2c_client *client) | ||
893 | { | ||
894 | return snd_soc_resume_device(&client->dev); | ||
895 | } | ||
896 | #else | ||
897 | #define wm8960_i2c_suspend NULL | ||
898 | #define wm8960_i2c_resume NULL | ||
899 | #endif | ||
900 | |||
930 | static const struct i2c_device_id wm8960_i2c_id[] = { | 901 | static const struct i2c_device_id wm8960_i2c_id[] = { |
931 | { "wm8960", 0 }, | 902 | { "wm8960", 0 }, |
932 | { } | 903 | { } |
@@ -940,6 +911,8 @@ static struct i2c_driver wm8960_i2c_driver = { | |||
940 | }, | 911 | }, |
941 | .probe = wm8960_i2c_probe, | 912 | .probe = wm8960_i2c_probe, |
942 | .remove = __devexit_p(wm8960_i2c_remove), | 913 | .remove = __devexit_p(wm8960_i2c_remove), |
914 | .suspend = wm8960_i2c_suspend, | ||
915 | .resume = wm8960_i2c_resume, | ||
943 | .id_table = wm8960_i2c_id, | 916 | .id_table = wm8960_i2c_id, |
944 | }; | 917 | }; |
945 | 918 | ||