aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8580.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/wm8580.c')
-rw-r--r--sound/soc/codecs/wm8580.c340
1 files changed, 161 insertions, 179 deletions
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c
index 72deeabef4fe..4bbc0a79f01e 100644
--- a/sound/soc/codecs/wm8580.c
+++ b/sound/soc/codecs/wm8580.c
@@ -31,7 +31,6 @@
31#include <sound/pcm.h> 31#include <sound/pcm.h>
32#include <sound/pcm_params.h> 32#include <sound/pcm_params.h>
33#include <sound/soc.h> 33#include <sound/soc.h>
34#include <sound/soc-dapm.h>
35#include <sound/tlv.h> 34#include <sound/tlv.h>
36#include <sound/initval.h> 35#include <sound/initval.h>
37#include <asm/div64.h> 36#include <asm/div64.h>
@@ -94,6 +93,8 @@
94 93
95#define WM8580_MAX_REGISTER 0x35 94#define WM8580_MAX_REGISTER 0x35
96 95
96#define WM8580_DACOSR 0x40
97
97/* PLLB4 (register 7h) */ 98/* PLLB4 (register 7h) */
98#define WM8580_PLLB4_MCLKOUTSRC_MASK 0x60 99#define WM8580_PLLB4_MCLKOUTSRC_MASK 0x60
99#define WM8580_PLLB4_MCLKOUTSRC_PLLA 0x20 100#define WM8580_PLLB4_MCLKOUTSRC_PLLA 0x20
@@ -112,19 +113,7 @@
112 113
113/* AIF control 1 (registers 9h-bh) */ 114/* AIF control 1 (registers 9h-bh) */
114#define WM8580_AIF_RATE_MASK 0x7 115#define WM8580_AIF_RATE_MASK 0x7
115#define WM8580_AIF_RATE_128 0x0
116#define WM8580_AIF_RATE_192 0x1
117#define WM8580_AIF_RATE_256 0x2
118#define WM8580_AIF_RATE_384 0x3
119#define WM8580_AIF_RATE_512 0x4
120#define WM8580_AIF_RATE_768 0x5
121#define WM8580_AIF_RATE_1152 0x6
122
123#define WM8580_AIF_BCLKSEL_MASK 0x18 116#define WM8580_AIF_BCLKSEL_MASK 0x18
124#define WM8580_AIF_BCLKSEL_64 0x00
125#define WM8580_AIF_BCLKSEL_128 0x08
126#define WM8580_AIF_BCLKSEL_256 0x10
127#define WM8580_AIF_BCLKSEL_SYSCLK 0x18
128 117
129#define WM8580_AIF_MS 0x20 118#define WM8580_AIF_MS 0x20
130 119
@@ -171,7 +160,7 @@
171static const u16 wm8580_reg[] = { 160static const u16 wm8580_reg[] = {
172 0x0121, 0x017e, 0x007d, 0x0014, /*R3*/ 161 0x0121, 0x017e, 0x007d, 0x0014, /*R3*/
173 0x0121, 0x017e, 0x007d, 0x0194, /*R7*/ 162 0x0121, 0x017e, 0x007d, 0x0194, /*R7*/
174 0x001c, 0x0002, 0x0002, 0x00c2, /*R11*/ 163 0x0010, 0x0002, 0x0002, 0x00c2, /*R11*/
175 0x0182, 0x0082, 0x000a, 0x0024, /*R15*/ 164 0x0182, 0x0082, 0x000a, 0x0024, /*R15*/
176 0x0009, 0x0000, 0x00ff, 0x0000, /*R19*/ 165 0x0009, 0x0000, 0x00ff, 0x0000, /*R19*/
177 0x00ff, 0x00ff, 0x00ff, 0x00ff, /*R23*/ 166 0x00ff, 0x00ff, 0x00ff, 0x00ff, /*R23*/
@@ -199,11 +188,11 @@ static const char *wm8580_supply_names[WM8580_NUM_SUPPLIES] = {
199 188
200/* codec private data */ 189/* codec private data */
201struct wm8580_priv { 190struct wm8580_priv {
202 struct snd_soc_codec codec; 191 enum snd_soc_control_type control_type;
203 struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES]; 192 struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES];
204 u16 reg_cache[WM8580_MAX_REGISTER + 1];
205 struct pll_state a; 193 struct pll_state a;
206 struct pll_state b; 194 struct pll_state b;
195 int sysclk[2];
207}; 196};
208 197
209static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1); 198static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
@@ -273,8 +262,8 @@ SOC_SINGLE("DAC1 Switch", WM8580_DAC_CONTROL5, 0, 1, 1),
273SOC_SINGLE("DAC2 Switch", WM8580_DAC_CONTROL5, 1, 1, 1), 262SOC_SINGLE("DAC2 Switch", WM8580_DAC_CONTROL5, 1, 1, 1),
274SOC_SINGLE("DAC3 Switch", WM8580_DAC_CONTROL5, 2, 1, 1), 263SOC_SINGLE("DAC3 Switch", WM8580_DAC_CONTROL5, 2, 1, 1),
275 264
276SOC_DOUBLE("ADC Mute Switch", WM8580_ADC_CONTROL1, 0, 1, 1, 0), 265SOC_DOUBLE("Capture Switch", WM8580_ADC_CONTROL1, 0, 1, 1, 1),
277SOC_SINGLE("ADC High-Pass Filter Switch", WM8580_ADC_CONTROL1, 4, 1, 0), 266SOC_SINGLE("Capture High-Pass Filter Switch", WM8580_ADC_CONTROL1, 4, 1, 0),
278}; 267};
279 268
280static const struct snd_soc_dapm_widget wm8580_dapm_widgets[] = { 269static const struct snd_soc_dapm_widget wm8580_dapm_widgets[] = {
@@ -311,10 +300,11 @@ static const struct snd_soc_dapm_route audio_map[] = {
311 300
312static int wm8580_add_widgets(struct snd_soc_codec *codec) 301static int wm8580_add_widgets(struct snd_soc_codec *codec)
313{ 302{
314 snd_soc_dapm_new_controls(codec, wm8580_dapm_widgets, 303 struct snd_soc_dapm_context *dapm = &codec->dapm;
315 ARRAY_SIZE(wm8580_dapm_widgets));
316 304
317 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 305 snd_soc_dapm_new_controls(dapm, wm8580_dapm_widgets,
306 ARRAY_SIZE(wm8580_dapm_widgets));
307 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
318 308
319 return 0; 309 return 0;
320} 310}
@@ -476,6 +466,10 @@ static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
476 return 0; 466 return 0;
477} 467}
478 468
469static const int wm8580_sysclk_ratios[] = {
470 128, 192, 256, 384, 512, 768, 1152,
471};
472
479/* 473/*
480 * Set PCM DAI bit size and sample rate. 474 * Set PCM DAI bit size and sample rate.
481 */ 475 */
@@ -484,29 +478,68 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream,
484 struct snd_soc_dai *dai) 478 struct snd_soc_dai *dai)
485{ 479{
486 struct snd_soc_pcm_runtime *rtd = substream->private_data; 480 struct snd_soc_pcm_runtime *rtd = substream->private_data;
487 struct snd_soc_device *socdev = rtd->socdev; 481 struct snd_soc_codec *codec = rtd->codec;
488 struct snd_soc_codec *codec = socdev->card->codec; 482 struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec);
489 u16 paifb = snd_soc_read(codec, WM8580_PAIF3 + dai->id); 483 u16 paifa = 0;
484 u16 paifb = 0;
485 int i, ratio, osr;
490 486
491 paifb &= ~WM8580_AIF_LENGTH_MASK;
492 /* bit size */ 487 /* bit size */
493 switch (params_format(params)) { 488 switch (params_format(params)) {
494 case SNDRV_PCM_FORMAT_S16_LE: 489 case SNDRV_PCM_FORMAT_S16_LE:
490 paifa |= 0x8;
495 break; 491 break;
496 case SNDRV_PCM_FORMAT_S20_3LE: 492 case SNDRV_PCM_FORMAT_S20_3LE:
493 paifa |= 0x0;
497 paifb |= WM8580_AIF_LENGTH_20; 494 paifb |= WM8580_AIF_LENGTH_20;
498 break; 495 break;
499 case SNDRV_PCM_FORMAT_S24_LE: 496 case SNDRV_PCM_FORMAT_S24_LE:
497 paifa |= 0x0;
500 paifb |= WM8580_AIF_LENGTH_24; 498 paifb |= WM8580_AIF_LENGTH_24;
501 break; 499 break;
502 case SNDRV_PCM_FORMAT_S32_LE: 500 case SNDRV_PCM_FORMAT_S32_LE:
503 paifb |= WM8580_AIF_LENGTH_24; 501 paifa |= 0x0;
502 paifb |= WM8580_AIF_LENGTH_32;
504 break; 503 break;
505 default: 504 default:
506 return -EINVAL; 505 return -EINVAL;
507 } 506 }
508 507
509 snd_soc_write(codec, WM8580_PAIF3 + dai->id, paifb); 508 /* Look up the SYSCLK ratio; accept only exact matches */
509 ratio = wm8580->sysclk[dai->driver->id] / params_rate(params);
510 for (i = 0; i < ARRAY_SIZE(wm8580_sysclk_ratios); i++)
511 if (ratio == wm8580_sysclk_ratios[i])
512 break;
513 if (i == ARRAY_SIZE(wm8580_sysclk_ratios)) {
514 dev_err(codec->dev, "Invalid clock ratio %d/%d\n",
515 wm8580->sysclk[dai->driver->id], params_rate(params));
516 return -EINVAL;
517 }
518 paifa |= i;
519 dev_dbg(codec->dev, "Running at %dfs with %dHz clock\n",
520 wm8580_sysclk_ratios[i], wm8580->sysclk[dai->driver->id]);
521
522 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
523 switch (ratio) {
524 case 128:
525 case 192:
526 osr = WM8580_DACOSR;
527 dev_dbg(codec->dev, "Selecting 64x OSR\n");
528 break;
529 default:
530 osr = 0;
531 dev_dbg(codec->dev, "Selecting 128x OSR\n");
532 break;
533 }
534
535 snd_soc_update_bits(codec, WM8580_PAIF3, WM8580_DACOSR, osr);
536 }
537
538 snd_soc_update_bits(codec, WM8580_PAIF1 + dai->driver->id,
539 WM8580_AIF_RATE_MASK | WM8580_AIF_BCLKSEL_MASK,
540 paifa);
541 snd_soc_update_bits(codec, WM8580_PAIF3 + dai->driver->id,
542 WM8580_AIF_LENGTH_MASK, paifb);
510 return 0; 543 return 0;
511} 544}
512 545
@@ -518,8 +551,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai,
518 unsigned int aifb; 551 unsigned int aifb;
519 int can_invert_lrclk; 552 int can_invert_lrclk;
520 553
521 aifa = snd_soc_read(codec, WM8580_PAIF1 + codec_dai->id); 554 aifa = snd_soc_read(codec, WM8580_PAIF1 + codec_dai->driver->id);
522 aifb = snd_soc_read(codec, WM8580_PAIF3 + codec_dai->id); 555 aifb = snd_soc_read(codec, WM8580_PAIF3 + codec_dai->driver->id);
523 556
524 aifb &= ~(WM8580_AIF_FMT_MASK | WM8580_AIF_LRP | WM8580_AIF_BCP); 557 aifb &= ~(WM8580_AIF_FMT_MASK | WM8580_AIF_LRP | WM8580_AIF_BCP);
525 558
@@ -585,8 +618,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai,
585 return -EINVAL; 618 return -EINVAL;
586 } 619 }
587 620
588 snd_soc_write(codec, WM8580_PAIF1 + codec_dai->id, aifa); 621 snd_soc_write(codec, WM8580_PAIF1 + codec_dai->driver->id, aifa);
589 snd_soc_write(codec, WM8580_PAIF3 + codec_dai->id, aifb); 622 snd_soc_write(codec, WM8580_PAIF3 + codec_dai->driver->id, aifb);
590 623
591 return 0; 624 return 0;
592} 625}
@@ -624,28 +657,6 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
624 snd_soc_write(codec, WM8580_PLLB4, reg); 657 snd_soc_write(codec, WM8580_PLLB4, reg);
625 break; 658 break;
626 659
627 case WM8580_DAC_CLKSEL:
628 reg = snd_soc_read(codec, WM8580_CLKSEL);
629 reg &= ~WM8580_CLKSEL_DAC_CLKSEL_MASK;
630
631 switch (div) {
632 case WM8580_CLKSRC_MCLK:
633 break;
634
635 case WM8580_CLKSRC_PLLA:
636 reg |= WM8580_CLKSEL_DAC_CLKSEL_PLLA;
637 break;
638
639 case WM8580_CLKSRC_PLLB:
640 reg |= WM8580_CLKSEL_DAC_CLKSEL_PLLB;
641 break;
642
643 default:
644 return -EINVAL;
645 }
646 snd_soc_write(codec, WM8580_CLKSEL, reg);
647 break;
648
649 case WM8580_CLKOUTSRC: 660 case WM8580_CLKOUTSRC:
650 reg = snd_soc_read(codec, WM8580_PLLB4); 661 reg = snd_soc_read(codec, WM8580_PLLB4);
651 reg &= ~WM8580_PLLB4_CLKOUTSRC_MASK; 662 reg &= ~WM8580_PLLB4_CLKOUTSRC_MASK;
@@ -679,6 +690,55 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
679 return 0; 690 return 0;
680} 691}
681 692
693static int wm8580_set_sysclk(struct snd_soc_dai *dai, int clk_id,
694 unsigned int freq, int dir)
695{
696 struct snd_soc_codec *codec = dai->codec;
697 struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec);
698 int sel, sel_mask, sel_shift;
699
700 switch (dai->driver->id) {
701 case WM8580_DAI_PAIFRX:
702 sel_mask = 0x3;
703 sel_shift = 0;
704 break;
705
706 case WM8580_DAI_PAIFTX:
707 sel_mask = 0xc;
708 sel_shift = 2;
709 break;
710
711 default:
712 BUG_ON("Unknown DAI driver ID\n");
713 return -EINVAL;
714 }
715
716 switch (clk_id) {
717 case WM8580_CLKSRC_ADCMCLK:
718 if (dai->driver->id != WM8580_DAI_PAIFTX)
719 return -EINVAL;
720 sel = 0 << sel_shift;
721 break;
722 case WM8580_CLKSRC_PLLA:
723 sel = 1 << sel_shift;
724 break;
725 case WM8580_CLKSRC_PLLB:
726 sel = 2 << sel_shift;
727 break;
728 case WM8580_CLKSRC_MCLK:
729 sel = 3 << sel_shift;
730 break;
731 default:
732 dev_err(codec->dev, "Unknown clock %d\n", clk_id);
733 return -EINVAL;
734 }
735
736 /* We really should validate PLL settings but not yet */
737 wm8580->sysclk[dai->driver->id] = freq;
738
739 return snd_soc_update_bits(codec, WM8580_CLKSEL, sel_mask, sel);
740}
741
682static int wm8580_digital_mute(struct snd_soc_dai *codec_dai, int mute) 742static int wm8580_digital_mute(struct snd_soc_dai *codec_dai, int mute)
683{ 743{
684 struct snd_soc_codec *codec = codec_dai->codec; 744 struct snd_soc_codec *codec = codec_dai->codec;
@@ -706,13 +766,13 @@ static int wm8580_set_bias_level(struct snd_soc_codec *codec,
706 break; 766 break;
707 767
708 case SND_SOC_BIAS_STANDBY: 768 case SND_SOC_BIAS_STANDBY:
709 if (codec->bias_level == SND_SOC_BIAS_OFF) { 769 if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
710 /* Power up and get individual control of the DACs */ 770 /* Power up and get individual control of the DACs */
711 reg = snd_soc_read(codec, WM8580_PWRDN1); 771 reg = snd_soc_read(codec, WM8580_PWRDN1);
712 reg &= ~(WM8580_PWRDN1_PWDN | WM8580_PWRDN1_ALLDACPD); 772 reg &= ~(WM8580_PWRDN1_PWDN | WM8580_PWRDN1_ALLDACPD);
713 snd_soc_write(codec, WM8580_PWRDN1, reg); 773 snd_soc_write(codec, WM8580_PWRDN1, reg);
714 774
715 /* Make VMID high impedence */ 775 /* Make VMID high impedance */
716 reg = snd_soc_read(codec, WM8580_ADC_CONTROL1); 776 reg = snd_soc_read(codec, WM8580_ADC_CONTROL1);
717 reg &= ~0x100; 777 reg &= ~0x100;
718 snd_soc_write(codec, WM8580_ADC_CONTROL1, reg); 778 snd_soc_write(codec, WM8580_ADC_CONTROL1, reg);
@@ -724,7 +784,7 @@ static int wm8580_set_bias_level(struct snd_soc_codec *codec,
724 snd_soc_write(codec, WM8580_PWRDN1, reg | WM8580_PWRDN1_PWDN); 784 snd_soc_write(codec, WM8580_PWRDN1, reg | WM8580_PWRDN1_PWDN);
725 break; 785 break;
726 } 786 }
727 codec->bias_level = level; 787 codec->dapm.bias_level = level;
728 return 0; 788 return 0;
729} 789}
730 790
@@ -732,6 +792,7 @@ static int wm8580_set_bias_level(struct snd_soc_codec *codec,
732 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) 792 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
733 793
734static struct snd_soc_dai_ops wm8580_dai_ops_playback = { 794static struct snd_soc_dai_ops wm8580_dai_ops_playback = {
795 .set_sysclk = wm8580_set_sysclk,
735 .hw_params = wm8580_paif_hw_params, 796 .hw_params = wm8580_paif_hw_params,
736 .set_fmt = wm8580_set_paif_dai_fmt, 797 .set_fmt = wm8580_set_paif_dai_fmt,
737 .set_clkdiv = wm8580_set_dai_clkdiv, 798 .set_clkdiv = wm8580_set_dai_clkdiv,
@@ -740,16 +801,17 @@ static struct snd_soc_dai_ops wm8580_dai_ops_playback = {
740}; 801};
741 802
742static struct snd_soc_dai_ops wm8580_dai_ops_capture = { 803static struct snd_soc_dai_ops wm8580_dai_ops_capture = {
804 .set_sysclk = wm8580_set_sysclk,
743 .hw_params = wm8580_paif_hw_params, 805 .hw_params = wm8580_paif_hw_params,
744 .set_fmt = wm8580_set_paif_dai_fmt, 806 .set_fmt = wm8580_set_paif_dai_fmt,
745 .set_clkdiv = wm8580_set_dai_clkdiv, 807 .set_clkdiv = wm8580_set_dai_clkdiv,
746 .set_pll = wm8580_set_dai_pll, 808 .set_pll = wm8580_set_dai_pll,
747}; 809};
748 810
749struct snd_soc_dai wm8580_dai[] = { 811static struct snd_soc_dai_driver wm8580_dai[] = {
750 { 812 {
751 .name = "WM8580 PAIFRX", 813 .name = "wm8580-hifi-playback",
752 .id = 0, 814 .id = WM8580_DAI_PAIFRX,
753 .playback = { 815 .playback = {
754 .stream_name = "Playback", 816 .stream_name = "Playback",
755 .channels_min = 1, 817 .channels_min = 1,
@@ -760,8 +822,8 @@ struct snd_soc_dai wm8580_dai[] = {
760 .ops = &wm8580_dai_ops_playback, 822 .ops = &wm8580_dai_ops_playback,
761 }, 823 },
762 { 824 {
763 .name = "WM8580 PAIFTX", 825 .name = "wm8580-hifi-capture",
764 .id = 1, 826 .id = WM8580_DAI_PAIFTX,
765 .capture = { 827 .capture = {
766 .stream_name = "Capture", 828 .stream_name = "Capture",
767 .channels_min = 2, 829 .channels_min = 2,
@@ -772,90 +834,16 @@ struct snd_soc_dai wm8580_dai[] = {
772 .ops = &wm8580_dai_ops_capture, 834 .ops = &wm8580_dai_ops_capture,
773 }, 835 },
774}; 836};
775EXPORT_SYMBOL_GPL(wm8580_dai);
776
777static struct snd_soc_codec *wm8580_codec;
778
779static int wm8580_probe(struct platform_device *pdev)
780{
781 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
782 struct snd_soc_codec *codec;
783 int ret = 0;
784
785 if (wm8580_codec == NULL) {
786 dev_err(&pdev->dev, "Codec device not registered\n");
787 return -ENODEV;
788 }
789
790 socdev->card->codec = wm8580_codec;
791 codec = wm8580_codec;
792
793 /* register pcms */
794 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
795 if (ret < 0) {
796 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
797 goto pcm_err;
798 }
799
800 snd_soc_add_controls(codec, wm8580_snd_controls,
801 ARRAY_SIZE(wm8580_snd_controls));
802 wm8580_add_widgets(codec);
803
804 return ret;
805
806pcm_err:
807 return ret;
808}
809
810/* power down chip */
811static int wm8580_remove(struct platform_device *pdev)
812{
813 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
814
815 snd_soc_free_pcms(socdev);
816 snd_soc_dapm_free(socdev);
817
818 return 0;
819}
820
821struct snd_soc_codec_device soc_codec_dev_wm8580 = {
822 .probe = wm8580_probe,
823 .remove = wm8580_remove,
824};
825EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580);
826 837
827static int wm8580_register(struct wm8580_priv *wm8580, 838static int wm8580_probe(struct snd_soc_codec *codec)
828 enum snd_soc_control_type control)
829{ 839{
830 int ret, i; 840 struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec);
831 struct snd_soc_codec *codec = &wm8580->codec; 841 int ret = 0,i;
832
833 if (wm8580_codec) {
834 dev_err(codec->dev, "Another WM8580 is registered\n");
835 ret = -EINVAL;
836 goto err;
837 }
838
839 mutex_init(&codec->mutex);
840 INIT_LIST_HEAD(&codec->dapm_widgets);
841 INIT_LIST_HEAD(&codec->dapm_paths);
842
843 snd_soc_codec_set_drvdata(codec, wm8580);
844 codec->name = "WM8580";
845 codec->owner = THIS_MODULE;
846 codec->bias_level = SND_SOC_BIAS_OFF;
847 codec->set_bias_level = wm8580_set_bias_level;
848 codec->dai = wm8580_dai;
849 codec->num_dai = ARRAY_SIZE(wm8580_dai);
850 codec->reg_cache_size = ARRAY_SIZE(wm8580->reg_cache);
851 codec->reg_cache = &wm8580->reg_cache;
852
853 memcpy(codec->reg_cache, wm8580_reg, sizeof(wm8580_reg));
854 842
855 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); 843 ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8580->control_type);
856 if (ret < 0) { 844 if (ret < 0) {
857 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); 845 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
858 goto err; 846 return ret;
859 } 847 }
860 848
861 for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++) 849 for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++)
@@ -865,7 +853,7 @@ static int wm8580_register(struct wm8580_priv *wm8580,
865 wm8580->supplies); 853 wm8580->supplies);
866 if (ret != 0) { 854 if (ret != 0) {
867 dev_err(codec->dev, "Failed to request supplies: %d\n", ret); 855 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
868 goto err; 856 return ret;
869 } 857 }
870 858
871 ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies), 859 ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies),
@@ -882,74 +870,68 @@ static int wm8580_register(struct wm8580_priv *wm8580,
882 goto err_regulator_enable; 870 goto err_regulator_enable;
883 } 871 }
884 872
885 for (i = 0; i < ARRAY_SIZE(wm8580_dai); i++)
886 wm8580_dai[i].dev = codec->dev;
887
888 wm8580_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 873 wm8580_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
889 874
890 wm8580_codec = codec; 875 snd_soc_add_controls(codec, wm8580_snd_controls,
891 876 ARRAY_SIZE(wm8580_snd_controls));
892 ret = snd_soc_register_codec(codec); 877 wm8580_add_widgets(codec);
893 if (ret != 0) {
894 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
895 goto err_regulator_enable;
896 }
897
898 ret = snd_soc_register_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai));
899 if (ret != 0) {
900 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
901 goto err_codec;
902 }
903 878
904 return 0; 879 return 0;
905 880
906err_codec:
907 snd_soc_unregister_codec(codec);
908err_regulator_enable: 881err_regulator_enable:
909 regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); 882 regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
910err_regulator_get: 883err_regulator_get:
911 regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); 884 regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
912err:
913 kfree(wm8580);
914 return ret; 885 return ret;
915} 886}
916 887
917static void wm8580_unregister(struct wm8580_priv *wm8580) 888/* power down chip */
889static int wm8580_remove(struct snd_soc_codec *codec)
918{ 890{
919 wm8580_set_bias_level(&wm8580->codec, SND_SOC_BIAS_OFF); 891 struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec);
920 snd_soc_unregister_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); 892
921 snd_soc_unregister_codec(&wm8580->codec); 893 wm8580_set_bias_level(codec, SND_SOC_BIAS_OFF);
894
922 regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); 895 regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
923 regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); 896 regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
924 kfree(wm8580); 897
925 wm8580_codec = NULL; 898 return 0;
926} 899}
927 900
901static struct snd_soc_codec_driver soc_codec_dev_wm8580 = {
902 .probe = wm8580_probe,
903 .remove = wm8580_remove,
904 .set_bias_level = wm8580_set_bias_level,
905 .reg_cache_size = ARRAY_SIZE(wm8580_reg),
906 .reg_word_size = sizeof(u16),
907 .reg_cache_default = wm8580_reg,
908};
909
928#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 910#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
929static int wm8580_i2c_probe(struct i2c_client *i2c, 911static int wm8580_i2c_probe(struct i2c_client *i2c,
930 const struct i2c_device_id *id) 912 const struct i2c_device_id *id)
931{ 913{
932 struct wm8580_priv *wm8580; 914 struct wm8580_priv *wm8580;
933 struct snd_soc_codec *codec; 915 int ret;
934 916
935 wm8580 = kzalloc(sizeof(struct wm8580_priv), GFP_KERNEL); 917 wm8580 = kzalloc(sizeof(struct wm8580_priv), GFP_KERNEL);
936 if (wm8580 == NULL) 918 if (wm8580 == NULL)
937 return -ENOMEM; 919 return -ENOMEM;
938 920
939 codec = &wm8580->codec;
940
941 i2c_set_clientdata(i2c, wm8580); 921 i2c_set_clientdata(i2c, wm8580);
942 codec->control_data = i2c; 922 wm8580->control_type = SND_SOC_I2C;
943 923
944 codec->dev = &i2c->dev; 924 ret = snd_soc_register_codec(&i2c->dev,
945 925 &soc_codec_dev_wm8580, wm8580_dai, ARRAY_SIZE(wm8580_dai));
946 return wm8580_register(wm8580, SND_SOC_I2C); 926 if (ret < 0)
927 kfree(wm8580);
928 return ret;
947} 929}
948 930
949static int wm8580_i2c_remove(struct i2c_client *client) 931static int wm8580_i2c_remove(struct i2c_client *client)
950{ 932{
951 struct wm8580_priv *wm8580 = i2c_get_clientdata(client); 933 snd_soc_unregister_codec(&client->dev);
952 wm8580_unregister(wm8580); 934 kfree(i2c_get_clientdata(client));
953 return 0; 935 return 0;
954} 936}
955 937
@@ -961,7 +943,7 @@ MODULE_DEVICE_TABLE(i2c, wm8580_i2c_id);
961 943
962static struct i2c_driver wm8580_i2c_driver = { 944static struct i2c_driver wm8580_i2c_driver = {
963 .driver = { 945 .driver = {
964 .name = "wm8580", 946 .name = "wm8580-codec",
965 .owner = THIS_MODULE, 947 .owner = THIS_MODULE,
966 }, 948 },
967 .probe = wm8580_i2c_probe, 949 .probe = wm8580_i2c_probe,
@@ -972,7 +954,7 @@ static struct i2c_driver wm8580_i2c_driver = {
972 954
973static int __init wm8580_modinit(void) 955static int __init wm8580_modinit(void)
974{ 956{
975 int ret; 957 int ret = 0;
976 958
977#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 959#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
978 ret = i2c_add_driver(&wm8580_i2c_driver); 960 ret = i2c_add_driver(&wm8580_i2c_driver);
@@ -981,7 +963,7 @@ static int __init wm8580_modinit(void)
981 } 963 }
982#endif 964#endif
983 965
984 return 0; 966 return ret;
985} 967}
986module_init(wm8580_modinit); 968module_init(wm8580_modinit);
987 969