diff options
-rw-r--r-- | include/sound/soc.h | 19 | ||||
-rw-r--r-- | include/trace/events/asoc.h | 25 | ||||
-rw-r--r-- | sound/soc/soc-cache.c | 152 | ||||
-rw-r--r-- | sound/soc/soc-core.c | 4 |
4 files changed, 12 insertions, 188 deletions
diff --git a/include/sound/soc.h b/include/sound/soc.h index 7ba7130037a0..fadcb351f3e1 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h | |||
@@ -409,13 +409,9 @@ int devm_snd_soc_register_component(struct device *dev, | |||
409 | const struct snd_soc_component_driver *cmpnt_drv, | 409 | const struct snd_soc_component_driver *cmpnt_drv, |
410 | struct snd_soc_dai_driver *dai_drv, int num_dai); | 410 | struct snd_soc_dai_driver *dai_drv, int num_dai); |
411 | void snd_soc_unregister_component(struct device *dev); | 411 | void snd_soc_unregister_component(struct device *dev); |
412 | int snd_soc_cache_sync(struct snd_soc_codec *codec); | ||
413 | int snd_soc_cache_init(struct snd_soc_codec *codec); | 412 | int snd_soc_cache_init(struct snd_soc_codec *codec); |
414 | int snd_soc_cache_exit(struct snd_soc_codec *codec); | 413 | int snd_soc_cache_exit(struct snd_soc_codec *codec); |
415 | int snd_soc_cache_write(struct snd_soc_codec *codec, | 414 | |
416 | unsigned int reg, unsigned int value); | ||
417 | int snd_soc_cache_read(struct snd_soc_codec *codec, | ||
418 | unsigned int reg, unsigned int *value); | ||
419 | int snd_soc_platform_read(struct snd_soc_platform *platform, | 415 | int snd_soc_platform_read(struct snd_soc_platform *platform, |
420 | unsigned int reg); | 416 | unsigned int reg); |
421 | int snd_soc_platform_write(struct snd_soc_platform *platform, | 417 | int snd_soc_platform_write(struct snd_soc_platform *platform, |
@@ -791,13 +787,11 @@ struct snd_soc_codec { | |||
791 | unsigned int ac97_registered:1; /* Codec has been AC97 registered */ | 787 | unsigned int ac97_registered:1; /* Codec has been AC97 registered */ |
792 | unsigned int ac97_created:1; /* Codec has been created by SoC */ | 788 | unsigned int ac97_created:1; /* Codec has been created by SoC */ |
793 | unsigned int cache_init:1; /* codec cache has been initialized */ | 789 | unsigned int cache_init:1; /* codec cache has been initialized */ |
794 | u32 cache_sync; /* Cache needs to be synced to hardware */ | ||
795 | 790 | ||
796 | /* codec IO */ | 791 | /* codec IO */ |
797 | void *control_data; /* codec control (i2c/3wire) data */ | 792 | void *control_data; /* codec control (i2c/3wire) data */ |
798 | hw_write_t hw_write; | 793 | hw_write_t hw_write; |
799 | void *reg_cache; | 794 | void *reg_cache; |
800 | struct mutex cache_rw_mutex; | ||
801 | 795 | ||
802 | /* component */ | 796 | /* component */ |
803 | struct snd_soc_component component; | 797 | struct snd_soc_component component; |
@@ -1264,6 +1258,17 @@ unsigned int snd_soc_read(struct snd_soc_codec *codec, unsigned int reg); | |||
1264 | int snd_soc_write(struct snd_soc_codec *codec, unsigned int reg, | 1258 | int snd_soc_write(struct snd_soc_codec *codec, unsigned int reg, |
1265 | unsigned int val); | 1259 | unsigned int val); |
1266 | 1260 | ||
1261 | /** | ||
1262 | * snd_soc_cache_sync() - Sync the register cache with the hardware | ||
1263 | * @codec: CODEC to sync | ||
1264 | * | ||
1265 | * Note: This function will call regcache_sync() | ||
1266 | */ | ||
1267 | static inline int snd_soc_cache_sync(struct snd_soc_codec *codec) | ||
1268 | { | ||
1269 | return regcache_sync(codec->component.regmap); | ||
1270 | } | ||
1271 | |||
1267 | /* component IO */ | 1272 | /* component IO */ |
1268 | int snd_soc_component_read(struct snd_soc_component *component, | 1273 | int snd_soc_component_read(struct snd_soc_component *component, |
1269 | unsigned int reg, unsigned int *val); | 1274 | unsigned int reg, unsigned int *val); |
diff --git a/include/trace/events/asoc.h b/include/trace/events/asoc.h index b04ee7e5a466..88cf39d96d0f 100644 --- a/include/trace/events/asoc.h +++ b/include/trace/events/asoc.h | |||
@@ -288,31 +288,6 @@ TRACE_EVENT(snd_soc_jack_notify, | |||
288 | TP_printk("jack=%s %x", __get_str(name), (int)__entry->val) | 288 | TP_printk("jack=%s %x", __get_str(name), (int)__entry->val) |
289 | ); | 289 | ); |
290 | 290 | ||
291 | TRACE_EVENT(snd_soc_cache_sync, | ||
292 | |||
293 | TP_PROTO(struct snd_soc_codec *codec, const char *type, | ||
294 | const char *status), | ||
295 | |||
296 | TP_ARGS(codec, type, status), | ||
297 | |||
298 | TP_STRUCT__entry( | ||
299 | __string( name, codec->component.name) | ||
300 | __string( status, status ) | ||
301 | __string( type, type ) | ||
302 | __field( int, id ) | ||
303 | ), | ||
304 | |||
305 | TP_fast_assign( | ||
306 | __assign_str(name, codec->component.name); | ||
307 | __assign_str(status, status); | ||
308 | __assign_str(type, type); | ||
309 | __entry->id = codec->component.id; | ||
310 | ), | ||
311 | |||
312 | TP_printk("codec=%s.%d type=%s status=%s", __get_str(name), | ||
313 | (int)__entry->id, __get_str(type), __get_str(status)) | ||
314 | ); | ||
315 | |||
316 | #endif /* _TRACE_ASOC_H */ | 291 | #endif /* _TRACE_ASOC_H */ |
317 | 292 | ||
318 | /* This part must be outside protection */ | 293 | /* This part must be outside protection */ |
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 6dab81799b9a..07f43356f963 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c | |||
@@ -15,56 +15,6 @@ | |||
15 | #include <linux/export.h> | 15 | #include <linux/export.h> |
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | 17 | ||
18 | #include <trace/events/asoc.h> | ||
19 | |||
20 | static bool snd_soc_set_cache_val(void *base, unsigned int idx, | ||
21 | unsigned int val, unsigned int word_size) | ||
22 | { | ||
23 | switch (word_size) { | ||
24 | case 1: { | ||
25 | u8 *cache = base; | ||
26 | if (cache[idx] == val) | ||
27 | return true; | ||
28 | cache[idx] = val; | ||
29 | break; | ||
30 | } | ||
31 | case 2: { | ||
32 | u16 *cache = base; | ||
33 | if (cache[idx] == val) | ||
34 | return true; | ||
35 | cache[idx] = val; | ||
36 | break; | ||
37 | } | ||
38 | default: | ||
39 | WARN(1, "Invalid word_size %d\n", word_size); | ||
40 | break; | ||
41 | } | ||
42 | return false; | ||
43 | } | ||
44 | |||
45 | static unsigned int snd_soc_get_cache_val(const void *base, unsigned int idx, | ||
46 | unsigned int word_size) | ||
47 | { | ||
48 | if (!base) | ||
49 | return -1; | ||
50 | |||
51 | switch (word_size) { | ||
52 | case 1: { | ||
53 | const u8 *cache = base; | ||
54 | return cache[idx]; | ||
55 | } | ||
56 | case 2: { | ||
57 | const u16 *cache = base; | ||
58 | return cache[idx]; | ||
59 | } | ||
60 | default: | ||
61 | WARN(1, "Invalid word_size %d\n", word_size); | ||
62 | break; | ||
63 | } | ||
64 | /* unreachable */ | ||
65 | return -1; | ||
66 | } | ||
67 | |||
68 | int snd_soc_cache_init(struct snd_soc_codec *codec) | 18 | int snd_soc_cache_init(struct snd_soc_codec *codec) |
69 | { | 19 | { |
70 | const struct snd_soc_codec_driver *codec_drv = codec->driver; | 20 | const struct snd_soc_codec_driver *codec_drv = codec->driver; |
@@ -75,8 +25,6 @@ int snd_soc_cache_init(struct snd_soc_codec *codec) | |||
75 | if (!reg_size) | 25 | if (!reg_size) |
76 | return 0; | 26 | return 0; |
77 | 27 | ||
78 | mutex_init(&codec->cache_rw_mutex); | ||
79 | |||
80 | dev_dbg(codec->dev, "ASoC: Initializing cache for %s codec\n", | 28 | dev_dbg(codec->dev, "ASoC: Initializing cache for %s codec\n", |
81 | codec->component.name); | 29 | codec->component.name); |
82 | 30 | ||
@@ -103,103 +51,3 @@ int snd_soc_cache_exit(struct snd_soc_codec *codec) | |||
103 | codec->reg_cache = NULL; | 51 | codec->reg_cache = NULL; |
104 | return 0; | 52 | return 0; |
105 | } | 53 | } |
106 | |||
107 | /** | ||
108 | * snd_soc_cache_read: Fetch the value of a given register from the cache. | ||
109 | * | ||
110 | * @codec: CODEC to configure. | ||
111 | * @reg: The register index. | ||
112 | * @value: The value to be returned. | ||
113 | */ | ||
114 | int snd_soc_cache_read(struct snd_soc_codec *codec, | ||
115 | unsigned int reg, unsigned int *value) | ||
116 | { | ||
117 | if (!value) | ||
118 | return -EINVAL; | ||
119 | |||
120 | mutex_lock(&codec->cache_rw_mutex); | ||
121 | if (!ZERO_OR_NULL_PTR(codec->reg_cache)) | ||
122 | *value = snd_soc_get_cache_val(codec->reg_cache, reg, | ||
123 | codec->driver->reg_word_size); | ||
124 | mutex_unlock(&codec->cache_rw_mutex); | ||
125 | |||
126 | return 0; | ||
127 | } | ||
128 | EXPORT_SYMBOL_GPL(snd_soc_cache_read); | ||
129 | |||
130 | /** | ||
131 | * snd_soc_cache_write: Set the value of a given register in the cache. | ||
132 | * | ||
133 | * @codec: CODEC to configure. | ||
134 | * @reg: The register index. | ||
135 | * @value: The new register value. | ||
136 | */ | ||
137 | int snd_soc_cache_write(struct snd_soc_codec *codec, | ||
138 | unsigned int reg, unsigned int value) | ||
139 | { | ||
140 | mutex_lock(&codec->cache_rw_mutex); | ||
141 | if (!ZERO_OR_NULL_PTR(codec->reg_cache)) | ||
142 | snd_soc_set_cache_val(codec->reg_cache, reg, value, | ||
143 | codec->driver->reg_word_size); | ||
144 | mutex_unlock(&codec->cache_rw_mutex); | ||
145 | |||
146 | return 0; | ||
147 | } | ||
148 | EXPORT_SYMBOL_GPL(snd_soc_cache_write); | ||
149 | |||
150 | static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec) | ||
151 | { | ||
152 | int i; | ||
153 | int ret; | ||
154 | const struct snd_soc_codec_driver *codec_drv; | ||
155 | unsigned int val; | ||
156 | |||
157 | codec_drv = codec->driver; | ||
158 | for (i = 0; i < codec_drv->reg_cache_size; ++i) { | ||
159 | ret = snd_soc_cache_read(codec, i, &val); | ||
160 | if (ret) | ||
161 | return ret; | ||
162 | if (codec_drv->reg_cache_default) | ||
163 | if (snd_soc_get_cache_val(codec_drv->reg_cache_default, | ||
164 | i, codec_drv->reg_word_size) == val) | ||
165 | continue; | ||
166 | |||
167 | ret = snd_soc_write(codec, i, val); | ||
168 | if (ret) | ||
169 | return ret; | ||
170 | dev_dbg(codec->dev, "ASoC: Synced register %#x, value = %#x\n", | ||
171 | i, val); | ||
172 | } | ||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | /** | ||
177 | * snd_soc_cache_sync: Sync the register cache with the hardware. | ||
178 | * | ||
179 | * @codec: CODEC to configure. | ||
180 | * | ||
181 | * Any registers that should not be synced should be marked as | ||
182 | * volatile. In general drivers can choose not to use the provided | ||
183 | * syncing functionality if they so require. | ||
184 | */ | ||
185 | int snd_soc_cache_sync(struct snd_soc_codec *codec) | ||
186 | { | ||
187 | const char *name = "flat"; | ||
188 | int ret; | ||
189 | |||
190 | if (codec->component.regmap) | ||
191 | return regcache_sync(codec->component.regmap); | ||
192 | |||
193 | if (!codec->cache_sync) | ||
194 | return 0; | ||
195 | |||
196 | dev_dbg(codec->dev, "ASoC: Syncing cache for %s codec\n", | ||
197 | codec->component.name); | ||
198 | trace_snd_soc_cache_sync(codec, name, "start"); | ||
199 | ret = snd_soc_flat_cache_sync(codec); | ||
200 | if (!ret) | ||
201 | codec->cache_sync = 0; | ||
202 | trace_snd_soc_cache_sync(codec, name, "end"); | ||
203 | return ret; | ||
204 | } | ||
205 | EXPORT_SYMBOL_GPL(snd_soc_cache_sync); | ||
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 4c8f8a23a0e9..4e0e32bb9910 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -309,9 +309,6 @@ static void soc_init_codec_debugfs(struct snd_soc_component *component) | |||
309 | { | 309 | { |
310 | struct snd_soc_codec *codec = snd_soc_component_to_codec(component); | 310 | struct snd_soc_codec *codec = snd_soc_component_to_codec(component); |
311 | 311 | ||
312 | debugfs_create_bool("cache_sync", 0444, codec->component.debugfs_root, | ||
313 | &codec->cache_sync); | ||
314 | |||
315 | codec->debugfs_reg = debugfs_create_file("codec_reg", 0644, | 312 | codec->debugfs_reg = debugfs_create_file("codec_reg", 0644, |
316 | codec->component.debugfs_root, | 313 | codec->component.debugfs_root, |
317 | codec, &codec_reg_fops); | 314 | codec, &codec_reg_fops); |
@@ -656,7 +653,6 @@ int snd_soc_suspend(struct device *dev) | |||
656 | if (codec->driver->suspend) | 653 | if (codec->driver->suspend) |
657 | codec->driver->suspend(codec); | 654 | codec->driver->suspend(codec); |
658 | codec->suspended = 1; | 655 | codec->suspended = 1; |
659 | codec->cache_sync = 1; | ||
660 | if (codec->component.regmap) | 656 | if (codec->component.regmap) |
661 | regcache_mark_dirty(codec->component.regmap); | 657 | regcache_mark_dirty(codec->component.regmap); |
662 | /* deactivate pins to sleep state */ | 658 | /* deactivate pins to sleep state */ |