diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-08-07 06:43:58 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-08-07 06:43:58 -0400 |
commit | 06cddefc1f25b847dafe392f3d5781482b3395b5 (patch) | |
tree | 97f4df2e4ae6a1e8194ca67ede1b552802ba2334 /sound/soc/codecs/wm8731.c | |
parent | b9b5cc26d0b3a9b361cc56c3a3b0d6f819b9195f (diff) | |
parent | 27ded041f03026e8c6be9efc626e11ddfb4620c1 (diff) |
Merge branch 'reg-cache' into for-2.6.32
Diffstat (limited to 'sound/soc/codecs/wm8731.c')
-rw-r--r-- | sound/soc/codecs/wm8731.c | 141 |
1 files changed, 33 insertions, 108 deletions
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 156002852078..2b980ccb6032 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c | |||
@@ -51,60 +51,12 @@ static int wm8731_spi_write(struct spi_device *spi, const char *data, int len); | |||
51 | * There is no point in caching the reset register | 51 | * There is no point in caching the reset register |
52 | */ | 52 | */ |
53 | static const u16 wm8731_reg[WM8731_CACHEREGNUM] = { | 53 | static const u16 wm8731_reg[WM8731_CACHEREGNUM] = { |
54 | 0x0097, 0x0097, 0x0079, 0x0079, | 54 | 0x0097, 0x0097, 0x0079, 0x0079, |
55 | 0x000a, 0x0008, 0x009f, 0x000a, | 55 | 0x000a, 0x0008, 0x009f, 0x000a, |
56 | 0x0000, 0x0000 | 56 | 0x0000, 0x0000 |
57 | }; | 57 | }; |
58 | 58 | ||
59 | /* | 59 | #define wm8731_reset(c) snd_soc_write(c, WM8731_RESET, 0) |
60 | * read wm8731 register cache | ||
61 | */ | ||
62 | static inline unsigned int wm8731_read_reg_cache(struct snd_soc_codec *codec, | ||
63 | unsigned int reg) | ||
64 | { | ||
65 | u16 *cache = codec->reg_cache; | ||
66 | if (reg == WM8731_RESET) | ||
67 | return 0; | ||
68 | if (reg >= WM8731_CACHEREGNUM) | ||
69 | return -1; | ||
70 | return cache[reg]; | ||
71 | } | ||
72 | |||
73 | /* | ||
74 | * write wm8731 register cache | ||
75 | */ | ||
76 | static inline void wm8731_write_reg_cache(struct snd_soc_codec *codec, | ||
77 | u16 reg, unsigned int value) | ||
78 | { | ||
79 | u16 *cache = codec->reg_cache; | ||
80 | if (reg >= WM8731_CACHEREGNUM) | ||
81 | return; | ||
82 | cache[reg] = value; | ||
83 | } | ||
84 | |||
85 | /* | ||
86 | * write to the WM8731 register space | ||
87 | */ | ||
88 | static int wm8731_write(struct snd_soc_codec *codec, unsigned int reg, | ||
89 | unsigned int value) | ||
90 | { | ||
91 | u8 data[2]; | ||
92 | |||
93 | /* data is | ||
94 | * D15..D9 WM8731 register offset | ||
95 | * D8...D0 register data | ||
96 | */ | ||
97 | data[0] = (reg << 1) | ((value >> 8) & 0x0001); | ||
98 | data[1] = value & 0x00ff; | ||
99 | |||
100 | wm8731_write_reg_cache(codec, reg, value); | ||
101 | if (codec->hw_write(codec->control_data, data, 2) == 2) | ||
102 | return 0; | ||
103 | else | ||
104 | return -EIO; | ||
105 | } | ||
106 | |||
107 | #define wm8731_reset(c) wm8731_write(c, WM8731_RESET, 0) | ||
108 | 60 | ||
109 | static const char *wm8731_input_select[] = {"Line In", "Mic"}; | 61 | static const char *wm8731_input_select[] = {"Line In", "Mic"}; |
110 | static const char *wm8731_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"}; | 62 | static const char *wm8731_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"}; |
@@ -267,12 +219,12 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream, | |||
267 | struct snd_soc_device *socdev = rtd->socdev; | 219 | struct snd_soc_device *socdev = rtd->socdev; |
268 | struct snd_soc_codec *codec = socdev->card->codec; | 220 | struct snd_soc_codec *codec = socdev->card->codec; |
269 | struct wm8731_priv *wm8731 = codec->private_data; | 221 | struct wm8731_priv *wm8731 = codec->private_data; |
270 | u16 iface = wm8731_read_reg_cache(codec, WM8731_IFACE) & 0xfff3; | 222 | u16 iface = snd_soc_read(codec, WM8731_IFACE) & 0xfff3; |
271 | int i = get_coeff(wm8731->sysclk, params_rate(params)); | 223 | int i = get_coeff(wm8731->sysclk, params_rate(params)); |
272 | u16 srate = (coeff_div[i].sr << 2) | | 224 | u16 srate = (coeff_div[i].sr << 2) | |
273 | (coeff_div[i].bosr << 1) | coeff_div[i].usb; | 225 | (coeff_div[i].bosr << 1) | coeff_div[i].usb; |
274 | 226 | ||
275 | wm8731_write(codec, WM8731_SRATE, srate); | 227 | snd_soc_write(codec, WM8731_SRATE, srate); |
276 | 228 | ||
277 | /* bit size */ | 229 | /* bit size */ |
278 | switch (params_format(params)) { | 230 | switch (params_format(params)) { |
@@ -286,7 +238,7 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream, | |||
286 | break; | 238 | break; |
287 | } | 239 | } |
288 | 240 | ||
289 | wm8731_write(codec, WM8731_IFACE, iface); | 241 | snd_soc_write(codec, WM8731_IFACE, iface); |
290 | return 0; | 242 | return 0; |
291 | } | 243 | } |
292 | 244 | ||
@@ -298,7 +250,7 @@ static int wm8731_pcm_prepare(struct snd_pcm_substream *substream, | |||
298 | struct snd_soc_codec *codec = socdev->card->codec; | 250 | struct snd_soc_codec *codec = socdev->card->codec; |
299 | 251 | ||
300 | /* set active */ | 252 | /* set active */ |
301 | wm8731_write(codec, WM8731_ACTIVE, 0x0001); | 253 | snd_soc_write(codec, WM8731_ACTIVE, 0x0001); |
302 | 254 | ||
303 | return 0; | 255 | return 0; |
304 | } | 256 | } |
@@ -313,19 +265,19 @@ static void wm8731_shutdown(struct snd_pcm_substream *substream, | |||
313 | /* deactivate */ | 265 | /* deactivate */ |
314 | if (!codec->active) { | 266 | if (!codec->active) { |
315 | udelay(50); | 267 | udelay(50); |
316 | wm8731_write(codec, WM8731_ACTIVE, 0x0); | 268 | snd_soc_write(codec, WM8731_ACTIVE, 0x0); |
317 | } | 269 | } |
318 | } | 270 | } |
319 | 271 | ||
320 | static int wm8731_mute(struct snd_soc_dai *dai, int mute) | 272 | static int wm8731_mute(struct snd_soc_dai *dai, int mute) |
321 | { | 273 | { |
322 | struct snd_soc_codec *codec = dai->codec; | 274 | struct snd_soc_codec *codec = dai->codec; |
323 | u16 mute_reg = wm8731_read_reg_cache(codec, WM8731_APDIGI) & 0xfff7; | 275 | u16 mute_reg = snd_soc_read(codec, WM8731_APDIGI) & 0xfff7; |
324 | 276 | ||
325 | if (mute) | 277 | if (mute) |
326 | wm8731_write(codec, WM8731_APDIGI, mute_reg | 0x8); | 278 | snd_soc_write(codec, WM8731_APDIGI, mute_reg | 0x8); |
327 | else | 279 | else |
328 | wm8731_write(codec, WM8731_APDIGI, mute_reg); | 280 | snd_soc_write(codec, WM8731_APDIGI, mute_reg); |
329 | return 0; | 281 | return 0; |
330 | } | 282 | } |
331 | 283 | ||
@@ -403,7 +355,7 @@ static int wm8731_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
403 | } | 355 | } |
404 | 356 | ||
405 | /* set iface */ | 357 | /* set iface */ |
406 | wm8731_write(codec, WM8731_IFACE, iface); | 358 | snd_soc_write(codec, WM8731_IFACE, iface); |
407 | return 0; | 359 | return 0; |
408 | } | 360 | } |
409 | 361 | ||
@@ -419,12 +371,12 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec, | |||
419 | break; | 371 | break; |
420 | case SND_SOC_BIAS_STANDBY: | 372 | case SND_SOC_BIAS_STANDBY: |
421 | /* Clear PWROFF, gate CLKOUT, everything else as-is */ | 373 | /* Clear PWROFF, gate CLKOUT, everything else as-is */ |
422 | reg = wm8731_read_reg_cache(codec, WM8731_PWR) & 0xff7f; | 374 | reg = snd_soc_read(codec, WM8731_PWR) & 0xff7f; |
423 | wm8731_write(codec, WM8731_PWR, reg | 0x0040); | 375 | snd_soc_write(codec, WM8731_PWR, reg | 0x0040); |
424 | break; | 376 | break; |
425 | case SND_SOC_BIAS_OFF: | 377 | case SND_SOC_BIAS_OFF: |
426 | wm8731_write(codec, WM8731_ACTIVE, 0x0); | 378 | snd_soc_write(codec, WM8731_ACTIVE, 0x0); |
427 | wm8731_write(codec, WM8731_PWR, 0xffff); | 379 | snd_soc_write(codec, WM8731_PWR, 0xffff); |
428 | break; | 380 | break; |
429 | } | 381 | } |
430 | codec->bias_level = level; | 382 | codec->bias_level = level; |
@@ -474,7 +426,7 @@ static int wm8731_suspend(struct platform_device *pdev, pm_message_t state) | |||
474 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 426 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
475 | struct snd_soc_codec *codec = socdev->card->codec; | 427 | struct snd_soc_codec *codec = socdev->card->codec; |
476 | 428 | ||
477 | wm8731_write(codec, WM8731_ACTIVE, 0x0); | 429 | snd_soc_write(codec, WM8731_ACTIVE, 0x0); |
478 | wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); | 430 | wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); |
479 | return 0; | 431 | return 0; |
480 | } | 432 | } |
@@ -560,11 +512,11 @@ struct snd_soc_codec_device soc_codec_dev_wm8731 = { | |||
560 | }; | 512 | }; |
561 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731); | 513 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731); |
562 | 514 | ||
563 | static int wm8731_register(struct wm8731_priv *wm8731) | 515 | static int wm8731_register(struct wm8731_priv *wm8731, |
516 | enum snd_soc_control_type control) | ||
564 | { | 517 | { |
565 | int ret; | 518 | int ret; |
566 | struct snd_soc_codec *codec = &wm8731->codec; | 519 | struct snd_soc_codec *codec = &wm8731->codec; |
567 | u16 reg; | ||
568 | 520 | ||
569 | if (wm8731_codec) { | 521 | if (wm8731_codec) { |
570 | dev_err(codec->dev, "Another WM8731 is registered\n"); | 522 | dev_err(codec->dev, "Another WM8731 is registered\n"); |
@@ -579,8 +531,6 @@ static int wm8731_register(struct wm8731_priv *wm8731) | |||
579 | codec->private_data = wm8731; | 531 | codec->private_data = wm8731; |
580 | codec->name = "WM8731"; | 532 | codec->name = "WM8731"; |
581 | codec->owner = THIS_MODULE; | 533 | codec->owner = THIS_MODULE; |
582 | codec->read = wm8731_read_reg_cache; | ||
583 | codec->write = wm8731_write; | ||
584 | codec->bias_level = SND_SOC_BIAS_OFF; | 534 | codec->bias_level = SND_SOC_BIAS_OFF; |
585 | codec->set_bias_level = wm8731_set_bias_level; | 535 | codec->set_bias_level = wm8731_set_bias_level; |
586 | codec->dai = &wm8731_dai; | 536 | codec->dai = &wm8731_dai; |
@@ -590,6 +540,12 @@ static int wm8731_register(struct wm8731_priv *wm8731) | |||
590 | 540 | ||
591 | memcpy(codec->reg_cache, wm8731_reg, sizeof(wm8731_reg)); | 541 | memcpy(codec->reg_cache, wm8731_reg, sizeof(wm8731_reg)); |
592 | 542 | ||
543 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); | ||
544 | if (ret < 0) { | ||
545 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
546 | goto err; | ||
547 | } | ||
548 | |||
593 | ret = wm8731_reset(codec); | 549 | ret = wm8731_reset(codec); |
594 | if (ret < 0) { | 550 | if (ret < 0) { |
595 | dev_err(codec->dev, "Failed to issue reset: %d\n", ret); | 551 | dev_err(codec->dev, "Failed to issue reset: %d\n", ret); |
@@ -601,18 +557,13 @@ static int wm8731_register(struct wm8731_priv *wm8731) | |||
601 | wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 557 | wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
602 | 558 | ||
603 | /* Latch the update bits */ | 559 | /* Latch the update bits */ |
604 | reg = wm8731_read_reg_cache(codec, WM8731_LOUT1V); | 560 | snd_soc_update_bits(codec, WM8731_LOUT1V, 0x100, 0); |
605 | wm8731_write(codec, WM8731_LOUT1V, reg & ~0x0100); | 561 | snd_soc_update_bits(codec, WM8731_ROUT1V, 0x100, 0); |
606 | reg = wm8731_read_reg_cache(codec, WM8731_ROUT1V); | 562 | snd_soc_update_bits(codec, WM8731_LINVOL, 0x100, 0); |
607 | wm8731_write(codec, WM8731_ROUT1V, reg & ~0x0100); | 563 | snd_soc_update_bits(codec, WM8731_RINVOL, 0x100, 0); |
608 | reg = wm8731_read_reg_cache(codec, WM8731_LINVOL); | ||
609 | wm8731_write(codec, WM8731_LINVOL, reg & ~0x0100); | ||
610 | reg = wm8731_read_reg_cache(codec, WM8731_RINVOL); | ||
611 | wm8731_write(codec, WM8731_RINVOL, reg & ~0x0100); | ||
612 | 564 | ||
613 | /* Disable bypass path by default */ | 565 | /* Disable bypass path by default */ |
614 | reg = wm8731_read_reg_cache(codec, WM8731_APANA); | 566 | snd_soc_update_bits(codec, WM8731_APANA, 0x4, 0); |
615 | wm8731_write(codec, WM8731_APANA, reg & ~0x4); | ||
616 | 567 | ||
617 | wm8731_codec = codec; | 568 | wm8731_codec = codec; |
618 | 569 | ||
@@ -648,30 +599,6 @@ static void wm8731_unregister(struct wm8731_priv *wm8731) | |||
648 | } | 599 | } |
649 | 600 | ||
650 | #if defined(CONFIG_SPI_MASTER) | 601 | #if defined(CONFIG_SPI_MASTER) |
651 | static int wm8731_spi_write(struct spi_device *spi, const char *data, int len) | ||
652 | { | ||
653 | struct spi_transfer t; | ||
654 | struct spi_message m; | ||
655 | u8 msg[2]; | ||
656 | |||
657 | if (len <= 0) | ||
658 | return 0; | ||
659 | |||
660 | msg[0] = data[0]; | ||
661 | msg[1] = data[1]; | ||
662 | |||
663 | spi_message_init(&m); | ||
664 | memset(&t, 0, (sizeof t)); | ||
665 | |||
666 | t.tx_buf = &msg[0]; | ||
667 | t.len = len; | ||
668 | |||
669 | spi_message_add_tail(&t, &m); | ||
670 | spi_sync(spi, &m); | ||
671 | |||
672 | return len; | ||
673 | } | ||
674 | |||
675 | static int __devinit wm8731_spi_probe(struct spi_device *spi) | 602 | static int __devinit wm8731_spi_probe(struct spi_device *spi) |
676 | { | 603 | { |
677 | struct snd_soc_codec *codec; | 604 | struct snd_soc_codec *codec; |
@@ -683,12 +610,11 @@ static int __devinit wm8731_spi_probe(struct spi_device *spi) | |||
683 | 610 | ||
684 | codec = &wm8731->codec; | 611 | codec = &wm8731->codec; |
685 | codec->control_data = spi; | 612 | codec->control_data = spi; |
686 | codec->hw_write = (hw_write_t)wm8731_spi_write; | ||
687 | codec->dev = &spi->dev; | 613 | codec->dev = &spi->dev; |
688 | 614 | ||
689 | dev_set_drvdata(&spi->dev, wm8731); | 615 | dev_set_drvdata(&spi->dev, wm8731); |
690 | 616 | ||
691 | return wm8731_register(wm8731); | 617 | return wm8731_register(wm8731, SND_SOC_SPI); |
692 | } | 618 | } |
693 | 619 | ||
694 | static int __devexit wm8731_spi_remove(struct spi_device *spi) | 620 | static int __devexit wm8731_spi_remove(struct spi_device *spi) |
@@ -740,14 +666,13 @@ static __devinit int wm8731_i2c_probe(struct i2c_client *i2c, | |||
740 | return -ENOMEM; | 666 | return -ENOMEM; |
741 | 667 | ||
742 | codec = &wm8731->codec; | 668 | codec = &wm8731->codec; |
743 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
744 | 669 | ||
745 | i2c_set_clientdata(i2c, wm8731); | 670 | i2c_set_clientdata(i2c, wm8731); |
746 | codec->control_data = i2c; | 671 | codec->control_data = i2c; |
747 | 672 | ||
748 | codec->dev = &i2c->dev; | 673 | codec->dev = &i2c->dev; |
749 | 674 | ||
750 | return wm8731_register(wm8731); | 675 | return wm8731_register(wm8731, SND_SOC_I2C); |
751 | } | 676 | } |
752 | 677 | ||
753 | static __devexit int wm8731_i2c_remove(struct i2c_client *client) | 678 | static __devexit int wm8731_i2c_remove(struct i2c_client *client) |