aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm9081.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2011-10-18 14:49:03 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-11-08 09:14:02 -0500
commit7cfa467b74bb252cc3b74a1a1995c54fe43f90d5 (patch)
treef85adbfcf8105382ef513a79ac9a11b05725a741 /sound/soc/codecs/wm9081.c
parentbd132ec585c498ee27d7eedf8569703606743928 (diff)
ASoC: Convert WM9081 to direct regmap API usage
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/codecs/wm9081.c')
-rw-r--r--sound/soc/codecs/wm9081.c278
1 files changed, 180 insertions, 98 deletions
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c
index 7563a91c9ed3..a8fc0659e4ac 100644
--- a/sound/soc/codecs/wm9081.c
+++ b/sound/soc/codecs/wm9081.c
@@ -19,6 +19,7 @@
19#include <linux/pm.h> 19#include <linux/pm.h>
20#include <linux/i2c.h> 20#include <linux/i2c.h>
21#include <linux/platform_device.h> 21#include <linux/platform_device.h>
22#include <linux/regmap.h>
22#include <linux/slab.h> 23#include <linux/slab.h>
23#include <sound/core.h> 24#include <sound/core.h>
24#include <sound/pcm.h> 25#include <sound/pcm.h>
@@ -30,69 +31,61 @@
30#include <sound/wm9081.h> 31#include <sound/wm9081.h>
31#include "wm9081.h" 32#include "wm9081.h"
32 33
33static u16 wm9081_reg_defaults[] = { 34static struct reg_default wm9081_reg[] = {
34 0x0000, /* R0 - Software Reset */ 35 { 0, 0x9081 }, /* R0 - Software Reset */
35 0x0000, /* R1 */ 36 { 2, 0x00B9 }, /* R2 - Analogue Lineout */
36 0x00B9, /* R2 - Analogue Lineout */ 37 { 3, 0x00B9 }, /* R3 - Analogue Speaker PGA */
37 0x00B9, /* R3 - Analogue Speaker PGA */ 38 { 4, 0x0001 }, /* R4 - VMID Control */
38 0x0001, /* R4 - VMID Control */ 39 { 5, 0x0068 }, /* R5 - Bias Control 1 */
39 0x0068, /* R5 - Bias Control 1 */ 40 { 7, 0x0000 }, /* R7 - Analogue Mixer */
40 0x0000, /* R6 */ 41 { 8, 0x0000 }, /* R8 - Anti Pop Control */
41 0x0000, /* R7 - Analogue Mixer */ 42 { 9, 0x01DB }, /* R9 - Analogue Speaker 1 */
42 0x0000, /* R8 - Anti Pop Control */ 43 { 10, 0x0018 }, /* R10 - Analogue Speaker 2 */
43 0x01DB, /* R9 - Analogue Speaker 1 */ 44 { 11, 0x0180 }, /* R11 - Power Management */
44 0x0018, /* R10 - Analogue Speaker 2 */ 45 { 12, 0x0000 }, /* R12 - Clock Control 1 */
45 0x0180, /* R11 - Power Management */ 46 { 13, 0x0038 }, /* R13 - Clock Control 2 */
46 0x0000, /* R12 - Clock Control 1 */ 47 { 14, 0x4000 }, /* R14 - Clock Control 3 */
47 0x0038, /* R13 - Clock Control 2 */ 48 { 16, 0x0000 }, /* R16 - FLL Control 1 */
48 0x4000, /* R14 - Clock Control 3 */ 49 { 17, 0x0200 }, /* R17 - FLL Control 2 */
49 0x0000, /* R15 */ 50 { 18, 0x0000 }, /* R18 - FLL Control 3 */
50 0x0000, /* R16 - FLL Control 1 */ 51 { 19, 0x0204 }, /* R19 - FLL Control 4 */
51 0x0200, /* R17 - FLL Control 2 */ 52 { 20, 0x0000 }, /* R20 - FLL Control 5 */
52 0x0000, /* R18 - FLL Control 3 */ 53 { 22, 0x0000 }, /* R22 - Audio Interface 1 */
53 0x0204, /* R19 - FLL Control 4 */ 54 { 23, 0x0002 }, /* R23 - Audio Interface 2 */
54 0x0000, /* R20 - FLL Control 5 */ 55 { 24, 0x0008 }, /* R24 - Audio Interface 3 */
55 0x0000, /* R21 */ 56 { 25, 0x0022 }, /* R25 - Audio Interface 4 */
56 0x0000, /* R22 - Audio Interface 1 */ 57 { 27, 0x0006 }, /* R27 - Interrupt Status Mask */
57 0x0002, /* R23 - Audio Interface 2 */ 58 { 28, 0x0000 }, /* R28 - Interrupt Polarity */
58 0x0008, /* R24 - Audio Interface 3 */ 59 { 29, 0x0000 }, /* R29 - Interrupt Control */
59 0x0022, /* R25 - Audio Interface 4 */ 60 { 30, 0x00C0 }, /* R30 - DAC Digital 1 */
60 0x0000, /* R26 - Interrupt Status */ 61 { 31, 0x0008 }, /* R31 - DAC Digital 2 */
61 0x0006, /* R27 - Interrupt Status Mask */ 62 { 32, 0x09AF }, /* R32 - DRC 1 */
62 0x0000, /* R28 - Interrupt Polarity */ 63 { 33, 0x4201 }, /* R33 - DRC 2 */
63 0x0000, /* R29 - Interrupt Control */ 64 { 34, 0x0000 }, /* R34 - DRC 3 */
64 0x00C0, /* R30 - DAC Digital 1 */ 65 { 35, 0x0000 }, /* R35 - DRC 4 */
65 0x0008, /* R31 - DAC Digital 2 */ 66 { 38, 0x0000 }, /* R38 - Write Sequencer 1 */
66 0x09AF, /* R32 - DRC 1 */ 67 { 39, 0x0000 }, /* R39 - Write Sequencer 2 */
67 0x4201, /* R33 - DRC 2 */ 68 { 40, 0x0002 }, /* R40 - MW Slave 1 */
68 0x0000, /* R34 - DRC 3 */ 69 { 42, 0x0000 }, /* R42 - EQ 1 */
69 0x0000, /* R35 - DRC 4 */ 70 { 43, 0x0000 }, /* R43 - EQ 2 */
70 0x0000, /* R36 */ 71 { 44, 0x0FCA }, /* R44 - EQ 3 */
71 0x0000, /* R37 */ 72 { 45, 0x0400 }, /* R45 - EQ 4 */
72 0x0000, /* R38 - Write Sequencer 1 */ 73 { 46, 0x00B8 }, /* R46 - EQ 5 */
73 0x0000, /* R39 - Write Sequencer 2 */ 74 { 47, 0x1EB5 }, /* R47 - EQ 6 */
74 0x0002, /* R40 - MW Slave 1 */ 75 { 48, 0xF145 }, /* R48 - EQ 7 */
75 0x0000, /* R41 */ 76 { 49, 0x0B75 }, /* R49 - EQ 8 */
76 0x0000, /* R42 - EQ 1 */ 77 { 50, 0x01C5 }, /* R50 - EQ 9 */
77 0x0000, /* R43 - EQ 2 */ 78 { 51, 0x169E }, /* R51 - EQ 10 */
78 0x0FCA, /* R44 - EQ 3 */ 79 { 52, 0xF829 }, /* R52 - EQ 11 */
79 0x0400, /* R45 - EQ 4 */ 80 { 53, 0x07AD }, /* R53 - EQ 12 */
80 0x00B8, /* R46 - EQ 5 */ 81 { 54, 0x1103 }, /* R54 - EQ 13 */
81 0x1EB5, /* R47 - EQ 6 */ 82 { 55, 0x1C58 }, /* R55 - EQ 14 */
82 0xF145, /* R48 - EQ 7 */ 83 { 56, 0xF373 }, /* R56 - EQ 15 */
83 0x0B75, /* R49 - EQ 8 */ 84 { 57, 0x0A54 }, /* R57 - EQ 16 */
84 0x01C5, /* R50 - EQ 9 */ 85 { 58, 0x0558 }, /* R58 - EQ 17 */
85 0x169E, /* R51 - EQ 10 */ 86 { 59, 0x0564 }, /* R59 - EQ 18 */
86 0xF829, /* R52 - EQ 11 */ 87 { 60, 0x0559 }, /* R60 - EQ 19 */
87 0x07AD, /* R53 - EQ 12 */ 88 { 61, 0x4000 }, /* R61 - EQ 20 */
88 0x1103, /* R54 - EQ 13 */
89 0x1C58, /* R55 - EQ 14 */
90 0xF373, /* R56 - EQ 15 */
91 0x0A54, /* R57 - EQ 16 */
92 0x0558, /* R58 - EQ 17 */
93 0x0564, /* R59 - EQ 18 */
94 0x0559, /* R60 - EQ 19 */
95 0x4000, /* R61 - EQ 20 */
96}; 89};
97 90
98static struct { 91static struct {
@@ -156,7 +149,7 @@ static struct {
156}; 149};
157 150
158struct wm9081_priv { 151struct wm9081_priv {
159 enum snd_soc_control_type control_type; 152 struct regmap *regmap;
160 int sysclk_source; 153 int sysclk_source;
161 int mclk_rate; 154 int mclk_rate;
162 int sysclk_rate; 155 int sysclk_rate;
@@ -169,20 +162,84 @@ struct wm9081_priv {
169 struct wm9081_pdata pdata; 162 struct wm9081_pdata pdata;
170}; 163};
171 164
172static int wm9081_volatile_register(struct snd_soc_codec *codec, unsigned int reg) 165static bool wm9081_volatile_register(struct device *dev, unsigned int reg)
173{ 166{
174 switch (reg) { 167 switch (reg) {
175 case WM9081_SOFTWARE_RESET: 168 case WM9081_SOFTWARE_RESET:
176 case WM9081_INTERRUPT_STATUS: 169 case WM9081_INTERRUPT_STATUS:
177 return 1; 170 return true;
178 default: 171 default:
179 return 0; 172 return false;
180 } 173 }
181} 174}
182 175
183static int wm9081_reset(struct snd_soc_codec *codec) 176static bool wm9081_readable_register(struct device *dev, unsigned int reg)
184{ 177{
185 return snd_soc_write(codec, WM9081_SOFTWARE_RESET, 0); 178 switch (reg) {
179 case WM9081_SOFTWARE_RESET:
180 case WM9081_ANALOGUE_LINEOUT:
181 case WM9081_ANALOGUE_SPEAKER_PGA:
182 case WM9081_VMID_CONTROL:
183 case WM9081_BIAS_CONTROL_1:
184 case WM9081_ANALOGUE_MIXER:
185 case WM9081_ANTI_POP_CONTROL:
186 case WM9081_ANALOGUE_SPEAKER_1:
187 case WM9081_ANALOGUE_SPEAKER_2:
188 case WM9081_POWER_MANAGEMENT:
189 case WM9081_CLOCK_CONTROL_1:
190 case WM9081_CLOCK_CONTROL_2:
191 case WM9081_CLOCK_CONTROL_3:
192 case WM9081_FLL_CONTROL_1:
193 case WM9081_FLL_CONTROL_2:
194 case WM9081_FLL_CONTROL_3:
195 case WM9081_FLL_CONTROL_4:
196 case WM9081_FLL_CONTROL_5:
197 case WM9081_AUDIO_INTERFACE_1:
198 case WM9081_AUDIO_INTERFACE_2:
199 case WM9081_AUDIO_INTERFACE_3:
200 case WM9081_AUDIO_INTERFACE_4:
201 case WM9081_INTERRUPT_STATUS:
202 case WM9081_INTERRUPT_STATUS_MASK:
203 case WM9081_INTERRUPT_POLARITY:
204 case WM9081_INTERRUPT_CONTROL:
205 case WM9081_DAC_DIGITAL_1:
206 case WM9081_DAC_DIGITAL_2:
207 case WM9081_DRC_1:
208 case WM9081_DRC_2:
209 case WM9081_DRC_3:
210 case WM9081_DRC_4:
211 case WM9081_WRITE_SEQUENCER_1:
212 case WM9081_WRITE_SEQUENCER_2:
213 case WM9081_MW_SLAVE_1:
214 case WM9081_EQ_1:
215 case WM9081_EQ_2:
216 case WM9081_EQ_3:
217 case WM9081_EQ_4:
218 case WM9081_EQ_5:
219 case WM9081_EQ_6:
220 case WM9081_EQ_7:
221 case WM9081_EQ_8:
222 case WM9081_EQ_9:
223 case WM9081_EQ_10:
224 case WM9081_EQ_11:
225 case WM9081_EQ_12:
226 case WM9081_EQ_13:
227 case WM9081_EQ_14:
228 case WM9081_EQ_15:
229 case WM9081_EQ_16:
230 case WM9081_EQ_17:
231 case WM9081_EQ_18:
232 case WM9081_EQ_19:
233 case WM9081_EQ_20:
234 return true;
235 default:
236 return false;
237 }
238}
239
240static int wm9081_reset(struct regmap *map)
241{
242 return regmap_write(map, WM9081_SOFTWARE_RESET, 0x9081);
186} 243}
187 244
188static const DECLARE_TLV_DB_SCALE(drc_in_tlv, -4500, 75, 0); 245static const DECLARE_TLV_DB_SCALE(drc_in_tlv, -4500, 75, 0);
@@ -1215,25 +1272,14 @@ static int wm9081_probe(struct snd_soc_codec *codec)
1215 int ret; 1272 int ret;
1216 u16 reg; 1273 u16 reg;
1217 1274
1218 ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm9081->control_type); 1275 codec->control_data = wm9081->regmap;
1276
1277 ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
1219 if (ret != 0) { 1278 if (ret != 0) {
1220 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); 1279 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
1221 return ret; 1280 return ret;
1222 } 1281 }
1223 1282
1224 reg = snd_soc_read(codec, WM9081_SOFTWARE_RESET);
1225 if (reg != 0x9081) {
1226 dev_err(codec->dev, "Device is not a WM9081: ID=0x%x\n", reg);
1227 ret = -EINVAL;
1228 return ret;
1229 }
1230
1231 ret = wm9081_reset(codec);
1232 if (ret < 0) {
1233 dev_err(codec->dev, "Failed to issue reset\n");
1234 return ret;
1235 }
1236
1237 reg = 0; 1283 reg = 0;
1238 if (wm9081->pdata.irq_high) 1284 if (wm9081->pdata.irq_high)
1239 reg |= WM9081_IRQ_POL; 1285 reg |= WM9081_IRQ_POL;
@@ -1277,15 +1323,9 @@ static int wm9081_suspend(struct snd_soc_codec *codec, pm_message_t state)
1277 1323
1278static int wm9081_resume(struct snd_soc_codec *codec) 1324static int wm9081_resume(struct snd_soc_codec *codec)
1279{ 1325{
1280 u16 *reg_cache = codec->reg_cache; 1326 struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec);
1281 int i;
1282
1283 for (i = 0; i < codec->driver->reg_cache_size; i++) {
1284 if (i == WM9081_SOFTWARE_RESET)
1285 continue;
1286 1327
1287 snd_soc_write(codec, i, reg_cache[i]); 1328 regcache_sync(wm9081->regmap);
1288 }
1289 1329
1290 wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1330 wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1291 1331
@@ -1305,11 +1345,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9081 = {
1305 .set_sysclk = wm9081_set_sysclk, 1345 .set_sysclk = wm9081_set_sysclk,
1306 .set_bias_level = wm9081_set_bias_level, 1346 .set_bias_level = wm9081_set_bias_level,
1307 1347
1308 .reg_cache_size = ARRAY_SIZE(wm9081_reg_defaults),
1309 .reg_word_size = sizeof(u16),
1310 .reg_cache_default = wm9081_reg_defaults,
1311 .volatile_register = wm9081_volatile_register,
1312
1313 .controls = wm9081_snd_controls, 1348 .controls = wm9081_snd_controls,
1314 .num_controls = ARRAY_SIZE(wm9081_snd_controls), 1349 .num_controls = ARRAY_SIZE(wm9081_snd_controls),
1315 .dapm_widgets = wm9081_dapm_widgets, 1350 .dapm_widgets = wm9081_dapm_widgets,
@@ -1318,11 +1353,24 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9081 = {
1318 .num_dapm_routes = ARRAY_SIZE(wm9081_audio_paths), 1353 .num_dapm_routes = ARRAY_SIZE(wm9081_audio_paths),
1319}; 1354};
1320 1355
1356static const struct regmap_config wm9081_regmap = {
1357 .reg_bits = 8,
1358 .val_bits = 16,
1359
1360 .max_register = WM9081_MAX_REGISTER,
1361 .reg_defaults = wm9081_reg,
1362 .num_reg_defaults = ARRAY_SIZE(wm9081_reg),
1363 .volatile_reg = wm9081_volatile_register,
1364 .readable_reg = wm9081_readable_register,
1365 .cache_type = REGCACHE_RBTREE,
1366};
1367
1321#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 1368#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1322static __devinit int wm9081_i2c_probe(struct i2c_client *i2c, 1369static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
1323 const struct i2c_device_id *id) 1370 const struct i2c_device_id *id)
1324{ 1371{
1325 struct wm9081_priv *wm9081; 1372 struct wm9081_priv *wm9081;
1373 unsigned int reg;
1326 int ret; 1374 int ret;
1327 1375
1328 wm9081 = kzalloc(sizeof(struct wm9081_priv), GFP_KERNEL); 1376 wm9081 = kzalloc(sizeof(struct wm9081_priv), GFP_KERNEL);
@@ -1330,7 +1378,30 @@ static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
1330 return -ENOMEM; 1378 return -ENOMEM;
1331 1379
1332 i2c_set_clientdata(i2c, wm9081); 1380 i2c_set_clientdata(i2c, wm9081);
1333 wm9081->control_type = SND_SOC_I2C; 1381
1382 wm9081->regmap = regmap_init_i2c(i2c, &wm9081_regmap);
1383 if (IS_ERR(wm9081->regmap)) {
1384 ret = PTR_ERR(wm9081->regmap);
1385 dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret);
1386 goto err;
1387 }
1388
1389 ret = regmap_read(wm9081->regmap, WM9081_SOFTWARE_RESET, &reg);
1390 if (ret != 0) {
1391 dev_err(&i2c->dev, "Failed to read chip ID: %d\n", ret);
1392 goto err_regmap;
1393 }
1394 if (reg != 0x9081) {
1395 dev_err(&i2c->dev, "Device is not a WM9081: ID=0x%x\n", reg);
1396 ret = -EINVAL;
1397 goto err_regmap;
1398 }
1399
1400 ret = wm9081_reset(wm9081->regmap);
1401 if (ret < 0) {
1402 dev_err(&i2c->dev, "Failed to issue reset\n");
1403 goto err_regmap;
1404 }
1334 1405
1335 if (dev_get_platdata(&i2c->dev)) 1406 if (dev_get_platdata(&i2c->dev))
1336 memcpy(&wm9081->pdata, dev_get_platdata(&i2c->dev), 1407 memcpy(&wm9081->pdata, dev_get_platdata(&i2c->dev),
@@ -1339,13 +1410,24 @@ static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
1339 ret = snd_soc_register_codec(&i2c->dev, 1410 ret = snd_soc_register_codec(&i2c->dev,
1340 &soc_codec_dev_wm9081, &wm9081_dai, 1); 1411 &soc_codec_dev_wm9081, &wm9081_dai, 1);
1341 if (ret < 0) 1412 if (ret < 0)
1342 kfree(wm9081); 1413 goto err_regmap;
1414
1415 return 0;
1416
1417err_regmap:
1418 regmap_exit(wm9081->regmap);
1419err:
1420 kfree(wm9081);
1421
1343 return ret; 1422 return ret;
1344} 1423}
1345 1424
1346static __devexit int wm9081_i2c_remove(struct i2c_client *client) 1425static __devexit int wm9081_i2c_remove(struct i2c_client *client)
1347{ 1426{
1427 struct wm9081_priv *wm9081 = i2c_get_clientdata(client);
1428
1348 snd_soc_unregister_codec(&client->dev); 1429 snd_soc_unregister_codec(&client->dev);
1430 regmap_exit(wm9081->regmap);
1349 kfree(i2c_get_clientdata(client)); 1431 kfree(i2c_get_clientdata(client));
1350 return 0; 1432 return 0;
1351} 1433}