diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-08-18 16:12:30 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-08-18 16:12:30 -0400 |
commit | d97d2e35b903b11dc6f7f8fcbe9a82fd8929e234 (patch) | |
tree | 149941c91afa80ad8ec6fa34353dc11960060420 /sound/soc/codecs/wm8711.c | |
parent | f72222c74bd642182cc892c99df65cb105c61193 (diff) |
ASoC: Factor out WM8711 cache I/O
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/codecs/wm8711.c')
-rw-r--r-- | sound/soc/codecs/wm8711.c | 114 |
1 files changed, 38 insertions, 76 deletions
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index 812283e27603..c7b1af89297b 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c | |||
@@ -48,55 +48,7 @@ static const u16 wm8711_reg[WM8711_CACHEREGNUM] = { | |||
48 | 0x009f, 0x000a, 0x0000, 0x0000 | 48 | 0x009f, 0x000a, 0x0000, 0x0000 |
49 | }; | 49 | }; |
50 | 50 | ||
51 | /* | 51 | #define wm8711_reset(c) snd_soc_write(c, WM8711_RESET, 0) |
52 | * read wm8711 register cache | ||
53 | */ | ||
54 | static inline unsigned int wm8711_read_reg_cache(struct snd_soc_codec *codec, | ||
55 | unsigned int reg) | ||
56 | { | ||
57 | u16 *cache = codec->reg_cache; | ||
58 | if (reg == WM8711_RESET) | ||
59 | return 0; | ||
60 | if (reg >= WM8711_CACHEREGNUM) | ||
61 | return -1; | ||
62 | return cache[reg]; | ||
63 | } | ||
64 | |||
65 | /* | ||
66 | * write wm8711 register cache | ||
67 | */ | ||
68 | static inline void wm8711_write_reg_cache(struct snd_soc_codec *codec, | ||
69 | u16 reg, unsigned int value) | ||
70 | { | ||
71 | u16 *cache = codec->reg_cache; | ||
72 | if (reg >= WM8711_CACHEREGNUM) | ||
73 | return; | ||
74 | cache[reg] = value; | ||
75 | } | ||
76 | |||
77 | /* | ||
78 | * write to the WM8711 register space | ||
79 | */ | ||
80 | static int wm8711_write(struct snd_soc_codec *codec, unsigned int reg, | ||
81 | unsigned int value) | ||
82 | { | ||
83 | u8 data[2]; | ||
84 | |||
85 | /* data is | ||
86 | * D15..D9 WM8753 register offset | ||
87 | * D8...D0 register data | ||
88 | */ | ||
89 | data[0] = (reg << 1) | ((value >> 8) & 0x0001); | ||
90 | data[1] = value & 0x00ff; | ||
91 | |||
92 | wm8711_write_reg_cache(codec, reg, value); | ||
93 | if (codec->hw_write(codec->control_data, data, 2) == 2) | ||
94 | return 0; | ||
95 | else | ||
96 | return -EIO; | ||
97 | } | ||
98 | |||
99 | #define wm8711_reset(c) wm8711_write(c, WM8711_RESET, 0) | ||
100 | 52 | ||
101 | static const struct snd_kcontrol_new wm8711_snd_controls[] = { | 53 | static const struct snd_kcontrol_new wm8711_snd_controls[] = { |
102 | 54 | ||
@@ -224,12 +176,12 @@ static int wm8711_hw_params(struct snd_pcm_substream *substream, | |||
224 | { | 176 | { |
225 | struct snd_soc_codec *codec = dai->codec; | 177 | struct snd_soc_codec *codec = dai->codec; |
226 | struct wm8711_priv *wm8711 = codec->private_data; | 178 | struct wm8711_priv *wm8711 = codec->private_data; |
227 | u16 iface = wm8711_read_reg_cache(codec, WM8711_IFACE) & 0xfffc; | 179 | u16 iface = snd_soc_read(codec, WM8711_IFACE) & 0xfffc; |
228 | int i = get_coeff(wm8711->sysclk, params_rate(params)); | 180 | int i = get_coeff(wm8711->sysclk, params_rate(params)); |
229 | u16 srate = (coeff_div[i].sr << 2) | | 181 | u16 srate = (coeff_div[i].sr << 2) | |
230 | (coeff_div[i].bosr << 1) | coeff_div[i].usb; | 182 | (coeff_div[i].bosr << 1) | coeff_div[i].usb; |
231 | 183 | ||
232 | wm8711_write(codec, WM8711_SRATE, srate); | 184 | snd_soc_write(codec, WM8711_SRATE, srate); |
233 | 185 | ||
234 | /* bit size */ | 186 | /* bit size */ |
235 | switch (params_format(params)) { | 187 | switch (params_format(params)) { |
@@ -243,7 +195,7 @@ static int wm8711_hw_params(struct snd_pcm_substream *substream, | |||
243 | break; | 195 | break; |
244 | } | 196 | } |
245 | 197 | ||
246 | wm8711_write(codec, WM8711_IFACE, iface); | 198 | snd_soc_write(codec, WM8711_IFACE, iface); |
247 | return 0; | 199 | return 0; |
248 | } | 200 | } |
249 | 201 | ||
@@ -253,7 +205,7 @@ static int wm8711_pcm_prepare(struct snd_pcm_substream *substream, | |||
253 | struct snd_soc_codec *codec = dai->codec; | 205 | struct snd_soc_codec *codec = dai->codec; |
254 | 206 | ||
255 | /* set active */ | 207 | /* set active */ |
256 | wm8711_write(codec, WM8711_ACTIVE, 0x0001); | 208 | snd_soc_write(codec, WM8711_ACTIVE, 0x0001); |
257 | 209 | ||
258 | return 0; | 210 | return 0; |
259 | } | 211 | } |
@@ -266,19 +218,19 @@ static void wm8711_shutdown(struct snd_pcm_substream *substream, | |||
266 | /* deactivate */ | 218 | /* deactivate */ |
267 | if (!codec->active) { | 219 | if (!codec->active) { |
268 | udelay(50); | 220 | udelay(50); |
269 | wm8711_write(codec, WM8711_ACTIVE, 0x0); | 221 | snd_soc_write(codec, WM8711_ACTIVE, 0x0); |
270 | } | 222 | } |
271 | } | 223 | } |
272 | 224 | ||
273 | static int wm8711_mute(struct snd_soc_dai *dai, int mute) | 225 | static int wm8711_mute(struct snd_soc_dai *dai, int mute) |
274 | { | 226 | { |
275 | struct snd_soc_codec *codec = dai->codec; | 227 | struct snd_soc_codec *codec = dai->codec; |
276 | u16 mute_reg = wm8711_read_reg_cache(codec, WM8711_APDIGI) & 0xfff7; | 228 | u16 mute_reg = snd_soc_read(codec, WM8711_APDIGI) & 0xfff7; |
277 | 229 | ||
278 | if (mute) | 230 | if (mute) |
279 | wm8711_write(codec, WM8711_APDIGI, mute_reg | 0x8); | 231 | snd_soc_write(codec, WM8711_APDIGI, mute_reg | 0x8); |
280 | else | 232 | else |
281 | wm8711_write(codec, WM8711_APDIGI, mute_reg); | 233 | snd_soc_write(codec, WM8711_APDIGI, mute_reg); |
282 | 234 | ||
283 | return 0; | 235 | return 0; |
284 | } | 236 | } |
@@ -356,7 +308,7 @@ static int wm8711_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
356 | } | 308 | } |
357 | 309 | ||
358 | /* set iface */ | 310 | /* set iface */ |
359 | wm8711_write(codec, WM8711_IFACE, iface); | 311 | snd_soc_write(codec, WM8711_IFACE, iface); |
360 | return 0; | 312 | return 0; |
361 | } | 313 | } |
362 | 314 | ||
@@ -364,20 +316,20 @@ static int wm8711_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
364 | static int wm8711_set_bias_level(struct snd_soc_codec *codec, | 316 | static int wm8711_set_bias_level(struct snd_soc_codec *codec, |
365 | enum snd_soc_bias_level level) | 317 | enum snd_soc_bias_level level) |
366 | { | 318 | { |
367 | u16 reg = wm8711_read_reg_cache(codec, WM8711_PWR) & 0xff7f; | 319 | u16 reg = snd_soc_read(codec, WM8711_PWR) & 0xff7f; |
368 | 320 | ||
369 | switch (level) { | 321 | switch (level) { |
370 | case SND_SOC_BIAS_ON: | 322 | case SND_SOC_BIAS_ON: |
371 | wm8711_write(codec, WM8711_PWR, reg); | 323 | snd_soc_write(codec, WM8711_PWR, reg); |
372 | break; | 324 | break; |
373 | case SND_SOC_BIAS_PREPARE: | 325 | case SND_SOC_BIAS_PREPARE: |
374 | break; | 326 | break; |
375 | case SND_SOC_BIAS_STANDBY: | 327 | case SND_SOC_BIAS_STANDBY: |
376 | wm8711_write(codec, WM8711_PWR, reg | 0x0040); | 328 | snd_soc_write(codec, WM8711_PWR, reg | 0x0040); |
377 | break; | 329 | break; |
378 | case SND_SOC_BIAS_OFF: | 330 | case SND_SOC_BIAS_OFF: |
379 | wm8711_write(codec, WM8711_ACTIVE, 0x0); | 331 | snd_soc_write(codec, WM8711_ACTIVE, 0x0); |
380 | wm8711_write(codec, WM8711_PWR, 0xffff); | 332 | snd_soc_write(codec, WM8711_PWR, 0xffff); |
381 | break; | 333 | break; |
382 | } | 334 | } |
383 | codec->bias_level = level; | 335 | codec->bias_level = level; |
@@ -419,7 +371,7 @@ static int wm8711_suspend(struct platform_device *pdev, pm_message_t state) | |||
419 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 371 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
420 | struct snd_soc_codec *codec = socdev->card->codec; | 372 | struct snd_soc_codec *codec = socdev->card->codec; |
421 | 373 | ||
422 | wm8711_write(codec, WM8711_ACTIVE, 0x0); | 374 | snd_soc_write(codec, WM8711_ACTIVE, 0x0); |
423 | wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF); | 375 | wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF); |
424 | return 0; | 376 | return 0; |
425 | } | 377 | } |
@@ -501,7 +453,8 @@ struct snd_soc_codec_device soc_codec_dev_wm8711 = { | |||
501 | }; | 453 | }; |
502 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8711); | 454 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8711); |
503 | 455 | ||
504 | static int wm8711_register(struct wm8711_priv *wm8711) | 456 | static int wm8711_register(struct wm8711_priv *wm8711, |
457 | enum snd_soc_control_type control) | ||
505 | { | 458 | { |
506 | int ret; | 459 | int ret; |
507 | struct snd_soc_codec *codec = &wm8711->codec; | 460 | struct snd_soc_codec *codec = &wm8711->codec; |
@@ -519,8 +472,6 @@ static int wm8711_register(struct wm8711_priv *wm8711) | |||
519 | codec->private_data = wm8711; | 472 | codec->private_data = wm8711; |
520 | codec->name = "WM8711"; | 473 | codec->name = "WM8711"; |
521 | codec->owner = THIS_MODULE; | 474 | codec->owner = THIS_MODULE; |
522 | codec->read = wm8711_read_reg_cache; | ||
523 | codec->write = wm8711_write; | ||
524 | codec->bias_level = SND_SOC_BIAS_OFF; | 475 | codec->bias_level = SND_SOC_BIAS_OFF; |
525 | codec->set_bias_level = wm8711_set_bias_level; | 476 | codec->set_bias_level = wm8711_set_bias_level; |
526 | codec->dai = &wm8711_dai; | 477 | codec->dai = &wm8711_dai; |
@@ -530,10 +481,16 @@ static int wm8711_register(struct wm8711_priv *wm8711) | |||
530 | 481 | ||
531 | memcpy(codec->reg_cache, wm8711_reg, sizeof(wm8711_reg)); | 482 | memcpy(codec->reg_cache, wm8711_reg, sizeof(wm8711_reg)); |
532 | 483 | ||
484 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); | ||
485 | if (ret < 0) { | ||
486 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
487 | goto err; | ||
488 | } | ||
489 | |||
533 | ret = wm8711_reset(codec); | 490 | ret = wm8711_reset(codec); |
534 | if (ret < 0) { | 491 | if (ret < 0) { |
535 | dev_err(codec->dev, "Failed to issue reset\n"); | 492 | dev_err(codec->dev, "Failed to issue reset\n"); |
536 | return ret; | 493 | goto err; |
537 | } | 494 | } |
538 | 495 | ||
539 | wm8711_dai.dev = codec->dev; | 496 | wm8711_dai.dev = codec->dev; |
@@ -541,27 +498,32 @@ static int wm8711_register(struct wm8711_priv *wm8711) | |||
541 | wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 498 | wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
542 | 499 | ||
543 | /* Latch the update bits */ | 500 | /* Latch the update bits */ |
544 | reg = wm8711_read_reg_cache(codec, WM8711_LOUT1V); | 501 | reg = snd_soc_read(codec, WM8711_LOUT1V); |
545 | wm8711_write(codec, WM8711_LOUT1V, reg | 0x0100); | 502 | snd_soc_write(codec, WM8711_LOUT1V, reg | 0x0100); |
546 | reg = wm8711_read_reg_cache(codec, WM8711_ROUT1V); | 503 | reg = snd_soc_read(codec, WM8711_ROUT1V); |
547 | wm8711_write(codec, WM8711_ROUT1V, reg | 0x0100); | 504 | snd_soc_write(codec, WM8711_ROUT1V, reg | 0x0100); |
548 | 505 | ||
549 | wm8711_codec = codec; | 506 | wm8711_codec = codec; |
550 | 507 | ||
551 | ret = snd_soc_register_codec(codec); | 508 | ret = snd_soc_register_codec(codec); |
552 | if (ret != 0) { | 509 | if (ret != 0) { |
553 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | 510 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); |
554 | return ret; | 511 | goto err; |
555 | } | 512 | } |
556 | 513 | ||
557 | ret = snd_soc_register_dai(&wm8711_dai); | 514 | ret = snd_soc_register_dai(&wm8711_dai); |
558 | if (ret != 0) { | 515 | if (ret != 0) { |
559 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | 516 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); |
560 | snd_soc_unregister_codec(codec); | 517 | goto err_codec; |
561 | return ret; | ||
562 | } | 518 | } |
563 | 519 | ||
564 | return 0; | 520 | return 0; |
521 | |||
522 | err_codec: | ||
523 | snd_soc_unregister_codec(codec); | ||
524 | err: | ||
525 | kfree(wm8711); | ||
526 | return ret; | ||
565 | } | 527 | } |
566 | 528 | ||
567 | static void wm8711_unregister(struct wm8711_priv *wm8711) | 529 | static void wm8711_unregister(struct wm8711_priv *wm8711) |
@@ -592,7 +554,7 @@ static __devinit int wm8711_i2c_probe(struct i2c_client *i2c, | |||
592 | 554 | ||
593 | codec->dev = &i2c->dev; | 555 | codec->dev = &i2c->dev; |
594 | 556 | ||
595 | return wm8711_register(wm8711); | 557 | return wm8711_register(wm8711, SND_SOC_I2C); |
596 | } | 558 | } |
597 | 559 | ||
598 | static __devexit int wm8711_i2c_remove(struct i2c_client *client) | 560 | static __devexit int wm8711_i2c_remove(struct i2c_client *client) |