aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2011-12-13 08:20:59 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-01-20 08:58:20 -0500
commitec2c0fec11f072222b63eb160da6be01773bfe65 (patch)
tree94e8eae4191599ee1539013fc24618807afb8b7e
parent008f8d4f9955b5f20be06ed99434cc2f8b025e06 (diff)
ASoC: Convert WM9090 to use regmap directly
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r--sound/soc/codecs/wm9090.c242
1 files changed, 128 insertions, 114 deletions
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c
index 41ebe0dce772..4be5551f06a0 100644
--- a/sound/soc/codecs/wm9090.c
+++ b/sound/soc/codecs/wm9090.c
@@ -25,6 +25,7 @@
25#include <linux/device.h> 25#include <linux/device.h>
26#include <linux/i2c.h> 26#include <linux/i2c.h>
27#include <linux/delay.h> 27#include <linux/delay.h>
28#include <linux/regmap.h>
28#include <linux/slab.h> 29#include <linux/slab.h>
29#include <sound/initval.h> 30#include <sound/initval.h>
30#include <sound/soc.h> 31#include <sound/soc.h>
@@ -33,116 +34,51 @@
33 34
34#include "wm9090.h" 35#include "wm9090.h"
35 36
36static const u16 wm9090_reg_defaults[] = { 37static const struct reg_default wm9090_reg_defaults[] = {
37 0x9093, /* R0 - Software Reset */ 38 { 1, 0x0006 }, /* R1 - Power Management (1) */
38 0x0006, /* R1 - Power Management (1) */ 39 { 2, 0x6000 }, /* R2 - Power Management (2) */
39 0x6000, /* R2 - Power Management (2) */ 40 { 3, 0x0000 }, /* R3 - Power Management (3) */
40 0x0000, /* R3 - Power Management (3) */ 41 { 6, 0x01C0 }, /* R6 - Clocking 1 */
41 0x0000, /* R4 */ 42 { 22, 0x0003 }, /* R22 - IN1 Line Control */
42 0x0000, /* R5 */ 43 { 23, 0x0003 }, /* R23 - IN2 Line Control */
43 0x01C0, /* R6 - Clocking 1 */ 44 { 24, 0x0083 }, /* R24 - IN1 Line Input A Volume */
44 0x0000, /* R7 */ 45 { 25, 0x0083 }, /* R25 - IN1 Line Input B Volume */
45 0x0000, /* R8 */ 46 { 26, 0x0083 }, /* R26 - IN2 Line Input A Volume */
46 0x0000, /* R9 */ 47 { 27, 0x0083 }, /* R27 - IN2 Line Input B Volume */
47 0x0000, /* R10 */ 48 { 28, 0x002D }, /* R28 - Left Output Volume */
48 0x0000, /* R11 */ 49 { 29, 0x002D }, /* R29 - Right Output Volume */
49 0x0000, /* R12 */ 50 { 34, 0x0100 }, /* R34 - SPKMIXL Attenuation */
50 0x0000, /* R13 */ 51 { 35, 0x0010 }, /* R36 - SPKOUT Mixers */
51 0x0000, /* R14 */ 52 { 37, 0x0140 }, /* R37 - ClassD3 */
52 0x0000, /* R15 */ 53 { 38, 0x0039 }, /* R38 - Speaker Volume Left */
53 0x0000, /* R16 */ 54 { 45, 0x0000 }, /* R45 - Output Mixer1 */
54 0x0000, /* R17 */ 55 { 46, 0x0000 }, /* R46 - Output Mixer2 */
55 0x0000, /* R18 */ 56 { 47, 0x0100 }, /* R47 - Output Mixer3 */
56 0x0000, /* R19 */ 57 { 48, 0x0100 }, /* R48 - Output Mixer4 */
57 0x0000, /* R20 */ 58 { 54, 0x0000 }, /* R54 - Speaker Mixer */
58 0x0000, /* R21 */ 59 { 57, 0x000D }, /* R57 - AntiPOP2 */
59 0x0003, /* R22 - IN1 Line Control */ 60 { 70, 0x0000 }, /* R70 - Write Sequencer 0 */
60 0x0003, /* R23 - IN2 Line Control */ 61 { 71, 0x0000 }, /* R71 - Write Sequencer 1 */
61 0x0083, /* R24 - IN1 Line Input A Volume */ 62 { 72, 0x0000 }, /* R72 - Write Sequencer 2 */
62 0x0083, /* R25 - IN1 Line Input B Volume */ 63 { 73, 0x0000 }, /* R73 - Write Sequencer 3 */
63 0x0083, /* R26 - IN2 Line Input A Volume */ 64 { 74, 0x0000 }, /* R74 - Write Sequencer 4 */
64 0x0083, /* R27 - IN2 Line Input B Volume */ 65 { 75, 0x0000 }, /* R75 - Write Sequencer 5 */
65 0x002D, /* R28 - Left Output Volume */ 66 { 76, 0x1F25 }, /* R76 - Charge Pump 1 */
66 0x002D, /* R29 - Right Output Volume */ 67 { 85, 0x054A }, /* R85 - DC Servo 1 */
67 0x0000, /* R30 */ 68 { 87, 0x0000 }, /* R87 - DC Servo 3 */
68 0x0000, /* R31 */ 69 { 96, 0x0100 }, /* R96 - Analogue HP 0 */
69 0x0000, /* R32 */ 70 { 98, 0x8640 }, /* R98 - AGC Control 0 */
70 0x0000, /* R33 */ 71 { 99, 0xC000 }, /* R99 - AGC Control 1 */
71 0x0100, /* R34 - SPKMIXL Attenuation */ 72 { 100, 0x0200 }, /* R100 - AGC Control 2 */
72 0x0000, /* R35 */
73 0x0010, /* R36 - SPKOUT Mixers */
74 0x0140, /* R37 - ClassD3 */
75 0x0039, /* R38 - Speaker Volume Left */
76 0x0000, /* R39 */
77 0x0000, /* R40 */
78 0x0000, /* R41 */
79 0x0000, /* R42 */
80 0x0000, /* R43 */
81 0x0000, /* R44 */
82 0x0000, /* R45 - Output Mixer1 */
83 0x0000, /* R46 - Output Mixer2 */
84 0x0100, /* R47 - Output Mixer3 */
85 0x0100, /* R48 - Output Mixer4 */
86 0x0000, /* R49 */
87 0x0000, /* R50 */
88 0x0000, /* R51 */
89 0x0000, /* R52 */
90 0x0000, /* R53 */
91 0x0000, /* R54 - Speaker Mixer */
92 0x0000, /* R55 */
93 0x0000, /* R56 */
94 0x000D, /* R57 - AntiPOP2 */
95 0x0000, /* R58 */
96 0x0000, /* R59 */
97 0x0000, /* R60 */
98 0x0000, /* R61 */
99 0x0000, /* R62 */
100 0x0000, /* R63 */
101 0x0000, /* R64 */
102 0x0000, /* R65 */
103 0x0000, /* R66 */
104 0x0000, /* R67 */
105 0x0000, /* R68 */
106 0x0000, /* R69 */
107 0x0000, /* R70 - Write Sequencer 0 */
108 0x0000, /* R71 - Write Sequencer 1 */
109 0x0000, /* R72 - Write Sequencer 2 */
110 0x0000, /* R73 - Write Sequencer 3 */
111 0x0000, /* R74 - Write Sequencer 4 */
112 0x0000, /* R75 - Write Sequencer 5 */
113 0x1F25, /* R76 - Charge Pump 1 */
114 0x0000, /* R77 */
115 0x0000, /* R78 */
116 0x0000, /* R79 */
117 0x0000, /* R80 */
118 0x0000, /* R81 */
119 0x0000, /* R82 */
120 0x0000, /* R83 */
121 0x0000, /* R84 - DC Servo 0 */
122 0x054A, /* R85 - DC Servo 1 */
123 0x0000, /* R86 */
124 0x0000, /* R87 - DC Servo 3 */
125 0x0000, /* R88 - DC Servo Readback 0 */
126 0x0000, /* R89 - DC Servo Readback 1 */
127 0x0000, /* R90 - DC Servo Readback 2 */
128 0x0000, /* R91 */
129 0x0000, /* R92 */
130 0x0000, /* R93 */
131 0x0000, /* R94 */
132 0x0000, /* R95 */
133 0x0100, /* R96 - Analogue HP 0 */
134 0x0000, /* R97 */
135 0x8640, /* R98 - AGC Control 0 */
136 0xC000, /* R99 - AGC Control 1 */
137 0x0200, /* R100 - AGC Control 2 */
138}; 73};
139 74
140/* This struct is used to save the context */ 75/* This struct is used to save the context */
141struct wm9090_priv { 76struct wm9090_priv {
142 struct wm9090_platform_data pdata; 77 struct wm9090_platform_data pdata;
78 struct regmap *regmap;
143}; 79};
144 80
145static int wm9090_volatile(struct snd_soc_codec *codec, unsigned int reg) 81static bool wm9090_volatile(struct device *dev, unsigned int reg)
146{ 82{
147 switch (reg) { 83 switch (reg) {
148 case WM9090_SOFTWARE_RESET: 84 case WM9090_SOFTWARE_RESET:
@@ -150,10 +86,60 @@ static int wm9090_volatile(struct snd_soc_codec *codec, unsigned int reg)
150 case WM9090_DC_SERVO_READBACK_0: 86 case WM9090_DC_SERVO_READBACK_0:
151 case WM9090_DC_SERVO_READBACK_1: 87 case WM9090_DC_SERVO_READBACK_1:
152 case WM9090_DC_SERVO_READBACK_2: 88 case WM9090_DC_SERVO_READBACK_2:
153 return 1; 89 return true;
154 90
155 default: 91 default:
156 return 0; 92 return false;
93 }
94}
95
96static bool wm9090_readable(struct device *dev, unsigned int reg)
97{
98 switch (reg) {
99 case WM9090_SOFTWARE_RESET:
100 case WM9090_POWER_MANAGEMENT_1:
101 case WM9090_POWER_MANAGEMENT_2:
102 case WM9090_POWER_MANAGEMENT_3:
103 case WM9090_CLOCKING_1:
104 case WM9090_IN1_LINE_CONTROL:
105 case WM9090_IN2_LINE_CONTROL:
106 case WM9090_IN1_LINE_INPUT_A_VOLUME:
107 case WM9090_IN1_LINE_INPUT_B_VOLUME:
108 case WM9090_IN2_LINE_INPUT_A_VOLUME:
109 case WM9090_IN2_LINE_INPUT_B_VOLUME:
110 case WM9090_LEFT_OUTPUT_VOLUME:
111 case WM9090_RIGHT_OUTPUT_VOLUME:
112 case WM9090_SPKMIXL_ATTENUATION:
113 case WM9090_SPKOUT_MIXERS:
114 case WM9090_CLASSD3:
115 case WM9090_SPEAKER_VOLUME_LEFT:
116 case WM9090_OUTPUT_MIXER1:
117 case WM9090_OUTPUT_MIXER2:
118 case WM9090_OUTPUT_MIXER3:
119 case WM9090_OUTPUT_MIXER4:
120 case WM9090_SPEAKER_MIXER:
121 case WM9090_ANTIPOP2:
122 case WM9090_WRITE_SEQUENCER_0:
123 case WM9090_WRITE_SEQUENCER_1:
124 case WM9090_WRITE_SEQUENCER_2:
125 case WM9090_WRITE_SEQUENCER_3:
126 case WM9090_WRITE_SEQUENCER_4:
127 case WM9090_WRITE_SEQUENCER_5:
128 case WM9090_CHARGE_PUMP_1:
129 case WM9090_DC_SERVO_0:
130 case WM9090_DC_SERVO_1:
131 case WM9090_DC_SERVO_3:
132 case WM9090_DC_SERVO_READBACK_0:
133 case WM9090_DC_SERVO_READBACK_1:
134 case WM9090_DC_SERVO_READBACK_2:
135 case WM9090_ANALOGUE_HP_0:
136 case WM9090_AGC_CONTROL_0:
137 case WM9090_AGC_CONTROL_1:
138 case WM9090_AGC_CONTROL_2:
139 return true;
140
141 default:
142 return false;
157 } 143 }
158} 144}
159 145
@@ -492,8 +478,7 @@ static int wm9090_add_controls(struct snd_soc_codec *codec)
492static int wm9090_set_bias_level(struct snd_soc_codec *codec, 478static int wm9090_set_bias_level(struct snd_soc_codec *codec,
493 enum snd_soc_bias_level level) 479 enum snd_soc_bias_level level)
494{ 480{
495 u16 *reg_cache = codec->reg_cache; 481 struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec);
496 int i, ret;
497 482
498 switch (level) { 483 switch (level) {
499 case SND_SOC_BIAS_ON: 484 case SND_SOC_BIAS_ON:
@@ -513,7 +498,7 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec,
513 case SND_SOC_BIAS_STANDBY: 498 case SND_SOC_BIAS_STANDBY:
514 if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { 499 if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
515 /* Restore the register cache */ 500 /* Restore the register cache */
516 snd_soc_cache_sync(codec); 501 regcache_sync(wm9090->regmap);
517 } 502 }
518 503
519 /* We keep VMID off during standby since the combination of 504 /* We keep VMID off during standby since the combination of
@@ -537,9 +522,11 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec,
537 522
538static int wm9090_probe(struct snd_soc_codec *codec) 523static int wm9090_probe(struct snd_soc_codec *codec)
539{ 524{
525 struct wm9090_priv *wm9090 = dev_get_drvdata(codec->dev);
540 int ret; 526 int ret;
541 527
542 ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); 528 codec->control_data = wm9090->regmap;
529 ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
543 if (ret != 0) { 530 if (ret != 0) {
544 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); 531 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
545 return ret; 532 return ret;
@@ -548,7 +535,7 @@ static int wm9090_probe(struct snd_soc_codec *codec)
548 ret = snd_soc_read(codec, WM9090_SOFTWARE_RESET); 535 ret = snd_soc_read(codec, WM9090_SOFTWARE_RESET);
549 if (ret < 0) 536 if (ret < 0)
550 return ret; 537 return ret;
551 if (ret != wm9090_reg_defaults[WM9090_SOFTWARE_RESET]) { 538 if (ret != 0x9093) {
552 dev_err(codec->dev, "Device is not a WM9090, ID=%x\n", ret); 539 dev_err(codec->dev, "Device is not a WM9090, ID=%x\n", ret);
553 return -EINVAL; 540 return -EINVAL;
554 } 541 }
@@ -624,12 +611,22 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9090 = {
624 .suspend = wm9090_suspend, 611 .suspend = wm9090_suspend,
625 .resume = wm9090_resume, 612 .resume = wm9090_resume,
626 .set_bias_level = wm9090_set_bias_level, 613 .set_bias_level = wm9090_set_bias_level,
627 .reg_cache_size = (WM9090_MAX_REGISTER + 1),
628 .reg_word_size = sizeof(u16),
629 .reg_cache_default = wm9090_reg_defaults,
630 .volatile_register = wm9090_volatile,
631}; 614};
632 615
616static const struct regmap_config wm9090_regmap = {
617 .reg_bits = 8,
618 .val_bits = 16,
619
620 .max_register = WM9090_MAX_REGISTER,
621 .volatile_reg = wm9090_volatile,
622 .readable_reg = wm9090_readable,
623
624 .cache_type = REGCACHE_RBTREE,
625 .reg_defaults = wm9090_reg_defaults,
626 .num_reg_defaults = ARRAY_SIZE(wm9090_reg_defaults),
627};
628
629
633static int wm9090_i2c_probe(struct i2c_client *i2c, 630static int wm9090_i2c_probe(struct i2c_client *i2c,
634 const struct i2c_device_id *id) 631 const struct i2c_device_id *id)
635{ 632{
@@ -642,6 +639,13 @@ static int wm9090_i2c_probe(struct i2c_client *i2c,
642 return -ENOMEM; 639 return -ENOMEM;
643 } 640 }
644 641
642 wm9090->regmap = regmap_init_i2c(i2c, &wm9090_regmap);
643 if (IS_ERR(wm9090->regmap)) {
644 ret = PTR_ERR(wm9090->regmap);
645 dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
646 return ret;
647 }
648
645 if (i2c->dev.platform_data) 649 if (i2c->dev.platform_data)
646 memcpy(&wm9090->pdata, i2c->dev.platform_data, 650 memcpy(&wm9090->pdata, i2c->dev.platform_data,
647 sizeof(wm9090->pdata)); 651 sizeof(wm9090->pdata));
@@ -650,6 +654,15 @@ static int wm9090_i2c_probe(struct i2c_client *i2c,
650 654
651 ret = snd_soc_register_codec(&i2c->dev, 655 ret = snd_soc_register_codec(&i2c->dev,
652 &soc_codec_dev_wm9090, NULL, 0); 656 &soc_codec_dev_wm9090, NULL, 0);
657 if (ret != 0) {
658 dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
659 goto err;
660 }
661
662 return 0;
663
664err:
665 regmap_exit(wm9090->regmap);
653 return ret; 666 return ret;
654} 667}
655 668
@@ -658,6 +671,7 @@ static int __devexit wm9090_i2c_remove(struct i2c_client *i2c)
658 struct wm9090_priv *wm9090 = i2c_get_clientdata(i2c); 671 struct wm9090_priv *wm9090 = i2c_get_clientdata(i2c);
659 672
660 snd_soc_unregister_codec(&i2c->dev); 673 snd_soc_unregister_codec(&i2c->dev);
674 regmap_exit(wm9090->regmap);
661 675
662 return 0; 676 return 0;
663} 677}