aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2011-12-29 06:39:39 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-01-20 08:58:19 -0500
commitee60d0155d653888de75b642182b0300c21ce07a (patch)
tree8a231003a2e02e843902074b32f812d7b1e4cf7e /sound
parentf98692ea6dda68c7eda6d53a3bc850702c3b8fde (diff)
ASoC: Convert wm8978 to direct regmap API usage
Helps push the register cache code down out of ASoC and improves resume times by using the more efficient regmap cache sync code. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/codecs/wm8978.c116
-rw-r--r--sound/soc/codecs/wm8978.h2
2 files changed, 96 insertions, 22 deletions
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c
index 0ab339c034e6..5ff8734d5d2e 100644
--- a/sound/soc/codecs/wm8978.c
+++ b/sound/soc/codecs/wm8978.c
@@ -18,6 +18,7 @@
18#include <linux/delay.h> 18#include <linux/delay.h>
19#include <linux/pm.h> 19#include <linux/pm.h>
20#include <linux/i2c.h> 20#include <linux/i2c.h>
21#include <linux/regmap.h>
21#include <linux/slab.h> 22#include <linux/slab.h>
22#include <sound/core.h> 23#include <sound/core.h>
23#include <sound/pcm.h> 24#include <sound/pcm.h>
@@ -29,27 +30,74 @@
29 30
30#include "wm8978.h" 31#include "wm8978.h"
31 32
32/* wm8978 register cache. Note that register 0 is not included in the cache. */ 33static const struct reg_default wm8978_reg_defaults[] = {
33static const u16 wm8978_reg[WM8978_CACHEREGNUM] = { 34 { 1, 0x0000 },
34 0x0000, 0x0000, 0x0000, 0x0000, /* 0x00...0x03 */ 35 { 2, 0x0000 },
35 0x0050, 0x0000, 0x0140, 0x0000, /* 0x04...0x07 */ 36 { 3, 0x0000 },
36 0x0000, 0x0000, 0x0000, 0x00ff, /* 0x08...0x0b */ 37 { 4, 0x0050 },
37 0x00ff, 0x0000, 0x0100, 0x00ff, /* 0x0c...0x0f */ 38 { 5, 0x0000 },
38 0x00ff, 0x0000, 0x012c, 0x002c, /* 0x10...0x13 */ 39 { 6, 0x0140 },
39 0x002c, 0x002c, 0x002c, 0x0000, /* 0x14...0x17 */ 40 { 7, 0x0000 },
40 0x0032, 0x0000, 0x0000, 0x0000, /* 0x18...0x1b */ 41 { 8, 0x0000 },
41 0x0000, 0x0000, 0x0000, 0x0000, /* 0x1c...0x1f */ 42 { 9, 0x0000 },
42 0x0038, 0x000b, 0x0032, 0x0000, /* 0x20...0x23 */ 43 { 10, 0x0000 },
43 0x0008, 0x000c, 0x0093, 0x00e9, /* 0x24...0x27 */ 44 { 11, 0x00ff },
44 0x0000, 0x0000, 0x0000, 0x0000, /* 0x28...0x2b */ 45 { 12, 0x00ff },
45 0x0033, 0x0010, 0x0010, 0x0100, /* 0x2c...0x2f */ 46 { 13, 0x0000 },
46 0x0100, 0x0002, 0x0001, 0x0001, /* 0x30...0x33 */ 47 { 14, 0x0100 },
47 0x0039, 0x0039, 0x0039, 0x0039, /* 0x34...0x37 */ 48 { 15, 0x00ff },
48 0x0001, 0x0001, /* 0x38...0x3b */ 49 { 16, 0x00ff },
50 { 17, 0x0000 },
51 { 18, 0x012c },
52 { 19, 0x002c },
53 { 20, 0x002c },
54 { 21, 0x002c },
55 { 22, 0x002c },
56 { 23, 0x0000 },
57 { 24, 0x0032 },
58 { 25, 0x0000 },
59 { 26, 0x0000 },
60 { 27, 0x0000 },
61 { 28, 0x0000 },
62 { 29, 0x0000 },
63 { 30, 0x0000 },
64 { 31, 0x0000 },
65 { 32, 0x0038 },
66 { 33, 0x000b },
67 { 34, 0x0032 },
68 { 35, 0x0000 },
69 { 36, 0x0008 },
70 { 37, 0x000c },
71 { 38, 0x0093 },
72 { 39, 0x00e9 },
73 { 40, 0x0000 },
74 { 41, 0x0000 },
75 { 42, 0x0000 },
76 { 43, 0x0000 },
77 { 44, 0x0033 },
78 { 45, 0x0010 },
79 { 46, 0x0010 },
80 { 47, 0x0100 },
81 { 48, 0x0100 },
82 { 49, 0x0002 },
83 { 50, 0x0001 },
84 { 51, 0x0001 },
85 { 52, 0x0039 },
86 { 53, 0x0039 },
87 { 54, 0x0039 },
88 { 55, 0x0039 },
89 { 56, 0x0001 },
90 { 57, 0x0001 },
49}; 91};
50 92
93static bool wm8978_volatile(struct device *dev, unsigned int reg)
94{
95 return reg == WM8978_RESET;
96}
97
51/* codec private data */ 98/* codec private data */
52struct wm8978_priv { 99struct wm8978_priv {
100 struct regmap *regmap;
53 unsigned int f_pllout; 101 unsigned int f_pllout;
54 unsigned int f_mclk; 102 unsigned int f_mclk;
55 unsigned int f_256fs; 103 unsigned int f_256fs;
@@ -881,10 +929,14 @@ static struct snd_soc_dai_driver wm8978_dai = {
881 929
882static int wm8978_suspend(struct snd_soc_codec *codec) 930static int wm8978_suspend(struct snd_soc_codec *codec)
883{ 931{
932 struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec);
933
884 wm8978_set_bias_level(codec, SND_SOC_BIAS_OFF); 934 wm8978_set_bias_level(codec, SND_SOC_BIAS_OFF);
885 /* Also switch PLL off */ 935 /* Also switch PLL off */
886 snd_soc_write(codec, WM8978_POWER_MANAGEMENT_1, 0); 936 snd_soc_write(codec, WM8978_POWER_MANAGEMENT_1, 0);
887 937
938 regcache_mark_dirty(wm8978->regmap);
939
888 return 0; 940 return 0;
889} 941}
890 942
@@ -893,7 +945,7 @@ static int wm8978_resume(struct snd_soc_codec *codec)
893 struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec); 945 struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec);
894 946
895 /* Sync reg_cache with the hardware */ 947 /* Sync reg_cache with the hardware */
896 snd_soc_cache_sync(codec); 948 regcache_sync(wm8978->regmap);
897 949
898 wm8978_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 950 wm8978_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
899 951
@@ -933,7 +985,8 @@ static int wm8978_probe(struct snd_soc_codec *codec)
933 * default hardware setting 985 * default hardware setting
934 */ 986 */
935 wm8978->sysclk = WM8978_PLL; 987 wm8978->sysclk = WM8978_PLL;
936 ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C); 988 codec->control_data = wm8978->regmap;
989 ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
937 if (ret < 0) { 990 if (ret < 0) {
938 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); 991 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
939 return ret; 992 return ret;
@@ -972,9 +1025,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8978 = {
972 .suspend = wm8978_suspend, 1025 .suspend = wm8978_suspend,
973 .resume = wm8978_resume, 1026 .resume = wm8978_resume,
974 .set_bias_level = wm8978_set_bias_level, 1027 .set_bias_level = wm8978_set_bias_level,
975 .reg_cache_size = ARRAY_SIZE(wm8978_reg),
976 .reg_word_size = sizeof(u16),
977 .reg_cache_default = wm8978_reg,
978 1028
979 .controls = wm8978_snd_controls, 1029 .controls = wm8978_snd_controls,
980 .num_controls = ARRAY_SIZE(wm8978_snd_controls), 1030 .num_controls = ARRAY_SIZE(wm8978_snd_controls),
@@ -984,6 +1034,18 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8978 = {
984 .num_dapm_routes = ARRAY_SIZE(wm8978_dapm_routes), 1034 .num_dapm_routes = ARRAY_SIZE(wm8978_dapm_routes),
985}; 1035};
986 1036
1037static const struct regmap_config wm8978_regmap_config = {
1038 .reg_bits = 7,
1039 .val_bits = 9,
1040
1041 .max_register = WM8978_MAX_REGISTER,
1042 .volatile_reg = wm8978_volatile,
1043
1044 .cache_type = REGCACHE_RBTREE,
1045 .reg_defaults = wm8978_reg_defaults,
1046 .num_reg_defaults = ARRAY_SIZE(wm8978_reg_defaults),
1047};
1048
987static __devinit int wm8978_i2c_probe(struct i2c_client *i2c, 1049static __devinit int wm8978_i2c_probe(struct i2c_client *i2c,
988 const struct i2c_device_id *id) 1050 const struct i2c_device_id *id)
989{ 1051{
@@ -995,6 +1057,13 @@ static __devinit int wm8978_i2c_probe(struct i2c_client *i2c,
995 if (wm8978 == NULL) 1057 if (wm8978 == NULL)
996 return -ENOMEM; 1058 return -ENOMEM;
997 1059
1060 wm8978->regmap = regmap_init_i2c(i2c, &wm8978_regmap_config);
1061 if (IS_ERR(wm8978->regmap)) {
1062 ret = PTR_ERR(wm8978->regmap);
1063 dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
1064 return ret;
1065 }
1066
998 i2c_set_clientdata(i2c, wm8978); 1067 i2c_set_clientdata(i2c, wm8978);
999 1068
1000 ret = snd_soc_register_codec(&i2c->dev, 1069 ret = snd_soc_register_codec(&i2c->dev,
@@ -1005,7 +1074,10 @@ static __devinit int wm8978_i2c_probe(struct i2c_client *i2c,
1005 1074
1006static __devexit int wm8978_i2c_remove(struct i2c_client *client) 1075static __devexit int wm8978_i2c_remove(struct i2c_client *client)
1007{ 1076{
1077 struct wm8978_priv *wm8978 = i2c_get_clientdata(client);
1078
1008 snd_soc_unregister_codec(&client->dev); 1079 snd_soc_unregister_codec(&client->dev);
1080 regmap_exit(wm8978->regmap);
1009 1081
1010 return 0; 1082 return 0;
1011} 1083}
diff --git a/sound/soc/codecs/wm8978.h b/sound/soc/codecs/wm8978.h
index c75525b7f154..6ae43495b7cf 100644
--- a/sound/soc/codecs/wm8978.h
+++ b/sound/soc/codecs/wm8978.h
@@ -67,6 +67,8 @@
67#define WM8978_OUT3_MIXER_CONTROL 0x38 67#define WM8978_OUT3_MIXER_CONTROL 0x38
68#define WM8978_OUT4_MIXER_CONTROL 0x39 68#define WM8978_OUT4_MIXER_CONTROL 0x39
69 69
70#define WM8978_MAX_REGISTER 0x39
71
70#define WM8978_CACHEREGNUM 58 72#define WM8978_CACHEREGNUM 58
71 73
72/* Clock divider Id's */ 74/* Clock divider Id's */