diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2011-11-21 07:10:03 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-01-24 06:43:18 -0500 |
commit | 05d448e2c9bc587216549d690332c72a74271abd (patch) | |
tree | 7e49fe8e6faa604f823ba6a2099f27a48a58f158 /sound/soc/codecs/wm8731.c | |
parent | 5091f5b797564930371c218dbc57cc4d99732c1e (diff) |
ASoC: Convert WM8731 to direct regmap API usage
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/codecs/wm8731.c')
-rw-r--r-- | sound/soc/codecs/wm8731.c | 109 |
1 files changed, 86 insertions, 23 deletions
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 8821af70e660..a32caa72bd7d 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.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/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/regmap.h> | ||
22 | #include <linux/regulator/consumer.h> | 23 | #include <linux/regulator/consumer.h> |
23 | #include <linux/spi/spi.h> | 24 | #include <linux/spi/spi.h> |
24 | #include <linux/of_device.h> | 25 | #include <linux/of_device.h> |
@@ -41,7 +42,7 @@ static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = { | |||
41 | 42 | ||
42 | /* codec private data */ | 43 | /* codec private data */ |
43 | struct wm8731_priv { | 44 | struct wm8731_priv { |
44 | enum snd_soc_control_type control_type; | 45 | struct regmap *regmap; |
45 | struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES]; | 46 | struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES]; |
46 | unsigned int sysclk; | 47 | unsigned int sysclk; |
47 | int sysclk_type; | 48 | int sysclk_type; |
@@ -52,16 +53,30 @@ struct wm8731_priv { | |||
52 | 53 | ||
53 | /* | 54 | /* |
54 | * wm8731 register cache | 55 | * wm8731 register cache |
55 | * We can't read the WM8731 register space when we are | ||
56 | * using 2 wire for device control, so we cache them instead. | ||
57 | * There is no point in caching the reset register | ||
58 | */ | 56 | */ |
59 | static const u16 wm8731_reg[WM8731_CACHEREGNUM] = { | 57 | static const struct reg_default wm8731_reg_defaults[] = { |
60 | 0x0097, 0x0097, 0x0079, 0x0079, | 58 | { 0, 0x0097 }, |
61 | 0x000a, 0x0008, 0x009f, 0x000a, | 59 | { 1, 0x0097 }, |
62 | 0x0000, 0x0000 | 60 | { 2, 0x0079 }, |
61 | { 3, 0x0079 }, | ||
62 | { 4, 0x000a }, | ||
63 | { 5, 0x0008 }, | ||
64 | { 6, 0x009f }, | ||
65 | { 7, 0x000a }, | ||
66 | { 8, 0x0000 }, | ||
67 | { 9, 0x0000 }, | ||
63 | }; | 68 | }; |
64 | 69 | ||
70 | static bool wm8731_volatile(struct device *dev, unsigned int reg) | ||
71 | { | ||
72 | return reg == WM8731_RESET; | ||
73 | } | ||
74 | |||
75 | static bool wm8731_writeable(struct device *dev, unsigned int reg) | ||
76 | { | ||
77 | return reg <= WM8731_RESET; | ||
78 | } | ||
79 | |||
65 | #define wm8731_reset(c) snd_soc_write(c, WM8731_RESET, 0) | 80 | #define wm8731_reset(c) snd_soc_write(c, WM8731_RESET, 0) |
66 | 81 | ||
67 | static const char *wm8731_input_select[] = {"Line In", "Mic"}; | 82 | static const char *wm8731_input_select[] = {"Line In", "Mic"}; |
@@ -441,7 +456,7 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec, | |||
441 | if (ret != 0) | 456 | if (ret != 0) |
442 | return ret; | 457 | return ret; |
443 | 458 | ||
444 | snd_soc_cache_sync(codec); | 459 | regcache_sync(wm8731->regmap); |
445 | } | 460 | } |
446 | 461 | ||
447 | /* Clear PWROFF, gate CLKOUT, everything else as-is */ | 462 | /* Clear PWROFF, gate CLKOUT, everything else as-is */ |
@@ -452,7 +467,7 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec, | |||
452 | snd_soc_write(codec, WM8731_PWR, 0xffff); | 467 | snd_soc_write(codec, WM8731_PWR, 0xffff); |
453 | regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), | 468 | regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), |
454 | wm8731->supplies); | 469 | wm8731->supplies); |
455 | codec->cache_sync = 1; | 470 | regcache_mark_dirty(wm8731->regmap); |
456 | break; | 471 | break; |
457 | } | 472 | } |
458 | codec->dapm.bias_level = level; | 473 | codec->dapm.bias_level = level; |
@@ -513,7 +528,8 @@ static int wm8731_probe(struct snd_soc_codec *codec) | |||
513 | struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); | 528 | struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); |
514 | int ret = 0, i; | 529 | int ret = 0, i; |
515 | 530 | ||
516 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8731->control_type); | 531 | codec->control_data = wm8731->regmap; |
532 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); | ||
517 | if (ret < 0) { | 533 | if (ret < 0) { |
518 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 534 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
519 | return ret; | 535 | return ret; |
@@ -585,9 +601,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8731 = { | |||
585 | .suspend = wm8731_suspend, | 601 | .suspend = wm8731_suspend, |
586 | .resume = wm8731_resume, | 602 | .resume = wm8731_resume, |
587 | .set_bias_level = wm8731_set_bias_level, | 603 | .set_bias_level = wm8731_set_bias_level, |
588 | .reg_cache_size = ARRAY_SIZE(wm8731_reg), | ||
589 | .reg_word_size = sizeof(u16), | ||
590 | .reg_cache_default = wm8731_reg, | ||
591 | .dapm_widgets = wm8731_dapm_widgets, | 604 | .dapm_widgets = wm8731_dapm_widgets, |
592 | .num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets), | 605 | .num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets), |
593 | .dapm_routes = wm8731_intercon, | 606 | .dapm_routes = wm8731_intercon, |
@@ -603,6 +616,19 @@ static const struct of_device_id wm8731_of_match[] = { | |||
603 | 616 | ||
604 | MODULE_DEVICE_TABLE(of, wm8731_of_match); | 617 | MODULE_DEVICE_TABLE(of, wm8731_of_match); |
605 | 618 | ||
619 | static const struct regmap_config wm8731_regmap = { | ||
620 | .reg_bits = 7, | ||
621 | .val_bits = 9, | ||
622 | |||
623 | .max_register = WM8731_RESET, | ||
624 | .volatile_reg = wm8731_volatile, | ||
625 | .writeable_reg = wm8731_writeable, | ||
626 | |||
627 | .cache_type = REGCACHE_RBTREE, | ||
628 | .reg_defaults = wm8731_reg_defaults, | ||
629 | .num_reg_defaults = ARRAY_SIZE(wm8731_reg_defaults), | ||
630 | }; | ||
631 | |||
606 | #if defined(CONFIG_SPI_MASTER) | 632 | #if defined(CONFIG_SPI_MASTER) |
607 | static int __devinit wm8731_spi_probe(struct spi_device *spi) | 633 | static int __devinit wm8731_spi_probe(struct spi_device *spi) |
608 | { | 634 | { |
@@ -613,20 +639,39 @@ static int __devinit wm8731_spi_probe(struct spi_device *spi) | |||
613 | if (wm8731 == NULL) | 639 | if (wm8731 == NULL) |
614 | return -ENOMEM; | 640 | return -ENOMEM; |
615 | 641 | ||
616 | wm8731->control_type = SND_SOC_SPI; | 642 | wm8731->regmap = regmap_init_spi(spi, &wm8731_regmap); |
643 | if (IS_ERR(wm8731->regmap)) { | ||
644 | ret = PTR_ERR(wm8731->regmap); | ||
645 | dev_err(&spi->dev, "Failed to allocate register map: %d\n", | ||
646 | ret); | ||
647 | goto err; | ||
648 | } | ||
649 | |||
617 | spi_set_drvdata(spi, wm8731); | 650 | spi_set_drvdata(spi, wm8731); |
618 | 651 | ||
619 | ret = snd_soc_register_codec(&spi->dev, | 652 | ret = snd_soc_register_codec(&spi->dev, |
620 | &soc_codec_dev_wm8731, &wm8731_dai, 1); | 653 | &soc_codec_dev_wm8731, &wm8731_dai, 1); |
621 | if (ret < 0) | 654 | if (ret != 0) { |
622 | kfree(wm8731); | 655 | dev_err(&spi->dev, "Failed to register CODEC: %d\n", ret); |
656 | goto err_regmap; | ||
657 | } | ||
658 | |||
659 | return 0; | ||
660 | |||
661 | err_regmap: | ||
662 | regmap_exit(wm8731->regmap); | ||
663 | err: | ||
664 | kfree(wm8731); | ||
623 | return ret; | 665 | return ret; |
624 | } | 666 | } |
625 | 667 | ||
626 | static int __devexit wm8731_spi_remove(struct spi_device *spi) | 668 | static int __devexit wm8731_spi_remove(struct spi_device *spi) |
627 | { | 669 | { |
670 | struct wm8731_priv *wm8731 = spi_get_drvdata(spi); | ||
671 | |||
628 | snd_soc_unregister_codec(&spi->dev); | 672 | snd_soc_unregister_codec(&spi->dev); |
629 | kfree(spi_get_drvdata(spi)); | 673 | regmap_exit(wm8731->regmap); |
674 | kfree(wm8731); | ||
630 | return 0; | 675 | return 0; |
631 | } | 676 | } |
632 | 677 | ||
@@ -652,20 +697,38 @@ static __devinit int wm8731_i2c_probe(struct i2c_client *i2c, | |||
652 | if (wm8731 == NULL) | 697 | if (wm8731 == NULL) |
653 | return -ENOMEM; | 698 | return -ENOMEM; |
654 | 699 | ||
700 | wm8731->regmap = regmap_init_i2c(i2c, &wm8731_regmap); | ||
701 | if (IS_ERR(wm8731->regmap)) { | ||
702 | ret = PTR_ERR(wm8731->regmap); | ||
703 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", | ||
704 | ret); | ||
705 | goto err; | ||
706 | } | ||
707 | |||
655 | i2c_set_clientdata(i2c, wm8731); | 708 | i2c_set_clientdata(i2c, wm8731); |
656 | wm8731->control_type = SND_SOC_I2C; | ||
657 | 709 | ||
658 | ret = snd_soc_register_codec(&i2c->dev, | 710 | ret = snd_soc_register_codec(&i2c->dev, |
659 | &soc_codec_dev_wm8731, &wm8731_dai, 1); | 711 | &soc_codec_dev_wm8731, &wm8731_dai, 1); |
660 | if (ret < 0) | 712 | if (ret != 0) { |
661 | kfree(wm8731); | 713 | dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret); |
714 | goto err_regmap; | ||
715 | } | ||
716 | |||
717 | return 0; | ||
718 | |||
719 | err_regmap: | ||
720 | regmap_exit(wm8731->regmap); | ||
721 | err: | ||
722 | kfree(wm8731); | ||
662 | return ret; | 723 | return ret; |
663 | } | 724 | } |
664 | 725 | ||
665 | static __devexit int wm8731_i2c_remove(struct i2c_client *client) | 726 | static __devexit int wm8731_i2c_remove(struct i2c_client *client) |
666 | { | 727 | { |
728 | struct wm8731_priv *wm8731 = i2c_get_clientdata(client); | ||
667 | snd_soc_unregister_codec(&client->dev); | 729 | snd_soc_unregister_codec(&client->dev); |
668 | kfree(i2c_get_clientdata(client)); | 730 | regmap_exit(wm8731->regmap); |
731 | kfree(wm8731); | ||
669 | return 0; | 732 | return 0; |
670 | } | 733 | } |
671 | 734 | ||