| OLD | NEW |
| 1 /* | 1 /* |
| 2 * soc-dapm.c -- ALSA SoC Dynamic Audio Power Management | 2 * soc-dapm.c -- ALSA SoC Dynamic Audio Power Management |
| 3 * | 3 * |
| 4 * Copyright 2005 Wolfson Microelectronics PLC. | 4 * Copyright 2005 Wolfson Microelectronics PLC. |
| 5 * Author: Liam Girdwood <lrg@slimlogic.co.uk> | 5 * Author: Liam Girdwood <lrg@slimlogic.co.uk> |
| 6 * | 6 * |
| 7 * This program is free software; you can redistribute it and/or modify it | 7 * This program is free software; you can redistribute it and/or modify it |
| 8 * under the terms of the GNU General Public License as published by the | 8 * under the terms of the GNU General Public License as published by the |
| 9 * Free Software Foundation; either version 2 of the License, or (at your | 9 * Free Software Foundation; either version 2 of the License, or (at your |
| 10 * option) any later version. | 10 * option) any later version. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 35 #include <linux/delay.h> | 35 #include <linux/delay.h> |
| 36 #include <linux/pm.h> | 36 #include <linux/pm.h> |
| 37 #include <linux/bitops.h> | 37 #include <linux/bitops.h> |
| 38 #include <linux/platform_device.h> | 38 #include <linux/platform_device.h> |
| 39 #include <linux/jiffies.h> | 39 #include <linux/jiffies.h> |
| 40 #include <linux/debugfs.h> | 40 #include <linux/debugfs.h> |
| 41 #include <linux/slab.h> | 41 #include <linux/slab.h> |
| 42 #include <sound/core.h> | 42 #include <sound/core.h> |
| 43 #include <sound/pcm.h> | 43 #include <sound/pcm.h> |
| 44 #include <sound/pcm_params.h> | 44 #include <sound/pcm_params.h> |
| 45 #include <sound/soc-dapm.h> | 45 #include <sound/soc.h> |
| 46 #include <sound/initval.h> | 46 #include <sound/initval.h> |
| 47 | 47 |
| 48 #include <trace/events/asoc.h> |
| 49 |
| 48 /* dapm power sequences - make this per codec in the future */ | 50 /* dapm power sequences - make this per codec in the future */ |
| 49 static int dapm_up_seq[] = { | 51 static int dapm_up_seq[] = { |
| 50 [snd_soc_dapm_pre] = 0, | 52 [snd_soc_dapm_pre] = 0, |
| 51 [snd_soc_dapm_supply] = 1, | 53 [snd_soc_dapm_supply] = 1, |
| 52 [snd_soc_dapm_micbias] = 2, | 54 [snd_soc_dapm_micbias] = 2, |
| 53 [snd_soc_dapm_aif_in] = 3, | 55 [snd_soc_dapm_aif_in] = 3, |
| 54 [snd_soc_dapm_aif_out] = 3, | 56 [snd_soc_dapm_aif_out] = 3, |
| 55 [snd_soc_dapm_mic] = 4, | 57 [snd_soc_dapm_mic] = 4, |
| 56 [snd_soc_dapm_mux] = 5, | 58 [snd_soc_dapm_mux] = 5, |
| 59 [snd_soc_dapm_virt_mux] = 5, |
| 57 [snd_soc_dapm_value_mux] = 5, | 60 [snd_soc_dapm_value_mux] = 5, |
| 58 [snd_soc_dapm_dac] = 6, | 61 [snd_soc_dapm_dac] = 6, |
| 59 [snd_soc_dapm_mixer] = 7, | 62 [snd_soc_dapm_mixer] = 7, |
| 60 [snd_soc_dapm_mixer_named_ctl] = 7, | 63 [snd_soc_dapm_mixer_named_ctl] = 7, |
| 61 [snd_soc_dapm_pga] = 8, | 64 [snd_soc_dapm_pga] = 8, |
| 62 [snd_soc_dapm_adc] = 9, | 65 [snd_soc_dapm_adc] = 9, |
| 66 [snd_soc_dapm_out_drv] = 10, |
| 63 [snd_soc_dapm_hp] = 10, | 67 [snd_soc_dapm_hp] = 10, |
| 64 [snd_soc_dapm_spk] = 10, | 68 [snd_soc_dapm_spk] = 10, |
| 65 [snd_soc_dapm_post] = 11, | 69 [snd_soc_dapm_post] = 11, |
| 66 }; | 70 }; |
| 67 | 71 |
| 68 static int dapm_down_seq[] = { | 72 static int dapm_down_seq[] = { |
| 69 [snd_soc_dapm_pre] = 0, | 73 [snd_soc_dapm_pre] = 0, |
| 70 [snd_soc_dapm_adc] = 1, | 74 [snd_soc_dapm_adc] = 1, |
| 71 [snd_soc_dapm_hp] = 2, | 75 [snd_soc_dapm_hp] = 2, |
| 72 [snd_soc_dapm_spk] = 2, | 76 [snd_soc_dapm_spk] = 2, |
| 77 [snd_soc_dapm_out_drv] = 2, |
| 73 [snd_soc_dapm_pga] = 4, | 78 [snd_soc_dapm_pga] = 4, |
| 74 [snd_soc_dapm_mixer_named_ctl] = 5, | 79 [snd_soc_dapm_mixer_named_ctl] = 5, |
| 75 [snd_soc_dapm_mixer] = 5, | 80 [snd_soc_dapm_mixer] = 5, |
| 76 [snd_soc_dapm_dac] = 6, | 81 [snd_soc_dapm_dac] = 6, |
| 77 [snd_soc_dapm_mic] = 7, | 82 [snd_soc_dapm_mic] = 7, |
| 78 [snd_soc_dapm_micbias] = 8, | 83 [snd_soc_dapm_micbias] = 8, |
| 79 [snd_soc_dapm_mux] = 9, | 84 [snd_soc_dapm_mux] = 9, |
| 85 [snd_soc_dapm_virt_mux] = 9, |
| 80 [snd_soc_dapm_value_mux] = 9, | 86 [snd_soc_dapm_value_mux] = 9, |
| 81 [snd_soc_dapm_aif_in] = 10, | 87 [snd_soc_dapm_aif_in] = 10, |
| 82 [snd_soc_dapm_aif_out] = 10, | 88 [snd_soc_dapm_aif_out] = 10, |
| 83 [snd_soc_dapm_supply] = 11, | 89 [snd_soc_dapm_supply] = 11, |
| 84 [snd_soc_dapm_post] = 12, | 90 [snd_soc_dapm_post] = 12, |
| 85 }; | 91 }; |
| 86 | 92 |
| 87 static void pop_wait(u32 pop_time) | 93 static void pop_wait(u32 pop_time) |
| 88 { | 94 { |
| 89 if (pop_time) | 95 if (pop_time) |
| 90 schedule_timeout_uninterruptible(msecs_to_jiffies(pop_time)); | 96 schedule_timeout_uninterruptible(msecs_to_jiffies(pop_time)); |
| 91 } | 97 } |
| 92 | 98 |
| 93 static void pop_dbg(u32 pop_time, const char *fmt, ...) | 99 static void pop_dbg(struct device *dev, u32 pop_time, const char *fmt, ...) |
| 94 { | 100 { |
| 95 va_list args; | 101 va_list args; |
| 102 char *buf; |
| 103 |
| 104 if (!pop_time) |
| 105 return; |
| 106 |
| 107 buf = kmalloc(PAGE_SIZE, GFP_KERNEL); |
| 108 if (buf == NULL) |
| 109 return; |
| 96 | 110 |
| 97 va_start(args, fmt); | 111 va_start(args, fmt); |
| 112 vsnprintf(buf, PAGE_SIZE, fmt, args); |
| 113 dev_info(dev, "%s", buf); |
| 114 va_end(args); |
| 98 | 115 |
| 99 » if (pop_time) { | 116 » kfree(buf); |
| 100 » » vprintk(fmt, args); | |
| 101 » } | |
| 102 | |
| 103 » va_end(args); | |
| 104 } | 117 } |
| 105 | 118 |
| 106 /* create a new dapm widget */ | 119 /* create a new dapm widget */ |
| 107 static inline struct snd_soc_dapm_widget *dapm_cnew_widget( | 120 static inline struct snd_soc_dapm_widget *dapm_cnew_widget( |
| 108 const struct snd_soc_dapm_widget *_widget) | 121 const struct snd_soc_dapm_widget *_widget) |
| 109 { | 122 { |
| 110 return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL); | 123 return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL); |
| 111 } | 124 } |
| 112 | 125 |
| 113 /** | 126 /** |
| 114 * snd_soc_dapm_set_bias_level - set the bias level for the system | 127 * snd_soc_dapm_set_bias_level - set the bias level for the system |
| 115 * @card: audio device | 128 * @card: audio device |
| 116 * @level: level to configure | 129 * @level: level to configure |
| 117 * | 130 * |
| 118 * Configure the bias (power) levels for the SoC audio device. | 131 * Configure the bias (power) levels for the SoC audio device. |
| 119 * | 132 * |
| 120 * Returns 0 for success else error. | 133 * Returns 0 for success else error. |
| 121 */ | 134 */ |
| 122 static int snd_soc_dapm_set_bias_level(struct snd_soc_card *card, | 135 static int snd_soc_dapm_set_bias_level(struct snd_soc_card *card, |
| 123 » » struct snd_soc_codec *codec, enum snd_soc_bias_level level) | 136 » » » » struct snd_soc_dapm_context *dapm, |
| 137 » » » » enum snd_soc_bias_level level) |
| 124 { | 138 { |
| 125 int ret = 0; | 139 int ret = 0; |
| 126 | 140 |
| 127 switch (level) { | 141 switch (level) { |
| 128 case SND_SOC_BIAS_ON: | 142 case SND_SOC_BIAS_ON: |
| 129 » » dev_dbg(codec->dev, "Setting full bias\n"); | 143 » » dev_dbg(dapm->dev, "Setting full bias\n"); |
| 130 break; | 144 break; |
| 131 case SND_SOC_BIAS_PREPARE: | 145 case SND_SOC_BIAS_PREPARE: |
| 132 » » dev_dbg(codec->dev, "Setting bias prepare\n"); | 146 » » dev_dbg(dapm->dev, "Setting bias prepare\n"); |
| 133 break; | 147 break; |
| 134 case SND_SOC_BIAS_STANDBY: | 148 case SND_SOC_BIAS_STANDBY: |
| 135 » » dev_dbg(codec->dev, "Setting standby bias\n"); | 149 » » dev_dbg(dapm->dev, "Setting standby bias\n"); |
| 136 break; | 150 break; |
| 137 case SND_SOC_BIAS_OFF: | 151 case SND_SOC_BIAS_OFF: |
| 138 » » dev_dbg(codec->dev, "Setting bias off\n"); | 152 » » dev_dbg(dapm->dev, "Setting bias off\n"); |
| 139 break; | 153 break; |
| 140 default: | 154 default: |
| 141 » » dev_err(codec->dev, "Setting invalid bias %d\n", level); | 155 » » dev_err(dapm->dev, "Setting invalid bias %d\n", level); |
| 142 return -EINVAL; | 156 return -EINVAL; |
| 143 } | 157 } |
| 144 | 158 |
| 159 trace_snd_soc_bias_level_start(card, level); |
| 160 |
| 145 if (card && card->set_bias_level) | 161 if (card && card->set_bias_level) |
| 146 ret = card->set_bias_level(card, level); | 162 ret = card->set_bias_level(card, level); |
| 147 if (ret == 0) { | 163 if (ret == 0) { |
| 148 » » if (codec->driver->set_bias_level) | 164 » » if (dapm->codec && dapm->codec->driver->set_bias_level) |
| 149 » » » ret = codec->driver->set_bias_level(codec, level); | 165 » » » ret = dapm->codec->driver->set_bias_level(dapm->codec, l
evel); |
| 150 else | 166 else |
| 151 » » » codec->bias_level = level; | 167 » » » dapm->bias_level = level; |
| 152 } | 168 } |
| 169 if (ret == 0) { |
| 170 if (card && card->set_bias_level_post) |
| 171 ret = card->set_bias_level_post(card, level); |
| 172 } |
| 173 |
| 174 trace_snd_soc_bias_level_done(card, level); |
| 153 | 175 |
| 154 return ret; | 176 return ret; |
| 155 } | 177 } |
| 156 | 178 |
| 157 /* set up initial codec paths */ | 179 /* set up initial codec paths */ |
| 158 static void dapm_set_path_status(struct snd_soc_dapm_widget *w, | 180 static void dapm_set_path_status(struct snd_soc_dapm_widget *w, |
| 159 struct snd_soc_dapm_path *p, int i) | 181 struct snd_soc_dapm_path *p, int i) |
| 160 { | 182 { |
| 161 switch (w->id) { | 183 switch (w->id) { |
| 162 case snd_soc_dapm_switch: | 184 case snd_soc_dapm_switch: |
| (...skipping 26 matching lines...) Expand all Loading... |
| 189 val = snd_soc_read(w->codec, e->reg); | 211 val = snd_soc_read(w->codec, e->reg); |
| 190 item = (val >> e->shift_l) & (bitmask - 1); | 212 item = (val >> e->shift_l) & (bitmask - 1); |
| 191 | 213 |
| 192 p->connect = 0; | 214 p->connect = 0; |
| 193 for (i = 0; i < e->max; i++) { | 215 for (i = 0; i < e->max; i++) { |
| 194 if (!(strcmp(p->name, e->texts[i])) && item == i) | 216 if (!(strcmp(p->name, e->texts[i])) && item == i) |
| 195 p->connect = 1; | 217 p->connect = 1; |
| 196 } | 218 } |
| 197 } | 219 } |
| 198 break; | 220 break; |
| 221 case snd_soc_dapm_virt_mux: { |
| 222 struct soc_enum *e = (struct soc_enum *)w->kcontrols[i].private_
value; |
| 223 |
| 224 p->connect = 0; |
| 225 /* since a virtual mux has no backing registers to |
| 226 * decide which path to connect, it will try to match |
| 227 * with the first enumeration. This is to ensure |
| 228 * that the default mux choice (the first) will be |
| 229 * correctly powered up during initialization. |
| 230 */ |
| 231 if (!strcmp(p->name, e->texts[0])) |
| 232 p->connect = 1; |
| 233 } |
| 234 break; |
| 199 case snd_soc_dapm_value_mux: { | 235 case snd_soc_dapm_value_mux: { |
| 200 struct soc_enum *e = (struct soc_enum *) | 236 struct soc_enum *e = (struct soc_enum *) |
| 201 w->kcontrols[i].private_value; | 237 w->kcontrols[i].private_value; |
| 202 int val, item; | 238 int val, item; |
| 203 | 239 |
| 204 val = snd_soc_read(w->codec, e->reg); | 240 val = snd_soc_read(w->codec, e->reg); |
| 205 val = (val >> e->shift_l) & e->mask; | 241 val = (val >> e->shift_l) & e->mask; |
| 206 for (item = 0; item < e->max; item++) { | 242 for (item = 0; item < e->max; item++) { |
| 207 if (val == e->values[item]) | 243 if (val == e->values[item]) |
| 208 break; | 244 break; |
| 209 } | 245 } |
| 210 | 246 |
| 211 p->connect = 0; | 247 p->connect = 0; |
| 212 for (i = 0; i < e->max; i++) { | 248 for (i = 0; i < e->max; i++) { |
| 213 if (!(strcmp(p->name, e->texts[i])) && item == i) | 249 if (!(strcmp(p->name, e->texts[i])) && item == i) |
| 214 p->connect = 1; | 250 p->connect = 1; |
| 215 } | 251 } |
| 216 } | 252 } |
| 217 break; | 253 break; |
| 218 /* does not effect routing - always connected */ | 254 /* does not effect routing - always connected */ |
| 219 case snd_soc_dapm_pga: | 255 case snd_soc_dapm_pga: |
| 256 case snd_soc_dapm_out_drv: |
| 220 case snd_soc_dapm_output: | 257 case snd_soc_dapm_output: |
| 221 case snd_soc_dapm_adc: | 258 case snd_soc_dapm_adc: |
| 222 case snd_soc_dapm_input: | 259 case snd_soc_dapm_input: |
| 223 case snd_soc_dapm_dac: | 260 case snd_soc_dapm_dac: |
| 224 case snd_soc_dapm_micbias: | 261 case snd_soc_dapm_micbias: |
| 225 case snd_soc_dapm_vmid: | 262 case snd_soc_dapm_vmid: |
| 226 case snd_soc_dapm_supply: | 263 case snd_soc_dapm_supply: |
| 227 case snd_soc_dapm_aif_in: | 264 case snd_soc_dapm_aif_in: |
| 228 case snd_soc_dapm_aif_out: | 265 case snd_soc_dapm_aif_out: |
| 229 p->connect = 1; | 266 p->connect = 1; |
| 230 break; | 267 break; |
| 231 /* does effect routing - dynamically connected */ | 268 /* does effect routing - dynamically connected */ |
| 232 case snd_soc_dapm_hp: | 269 case snd_soc_dapm_hp: |
| 233 case snd_soc_dapm_mic: | 270 case snd_soc_dapm_mic: |
| 234 case snd_soc_dapm_spk: | 271 case snd_soc_dapm_spk: |
| 235 case snd_soc_dapm_line: | 272 case snd_soc_dapm_line: |
| 236 case snd_soc_dapm_pre: | 273 case snd_soc_dapm_pre: |
| 237 case snd_soc_dapm_post: | 274 case snd_soc_dapm_post: |
| 238 p->connect = 0; | 275 p->connect = 0; |
| 239 break; | 276 break; |
| 240 } | 277 } |
| 241 } | 278 } |
| 242 | 279 |
| 243 /* connect mux widget to its interconnecting audio paths */ | 280 /* connect mux widget to its interconnecting audio paths */ |
| 244 static int dapm_connect_mux(struct snd_soc_codec *codec, | 281 static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, |
| 245 struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest, | 282 struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest, |
| 246 struct snd_soc_dapm_path *path, const char *control_name, | 283 struct snd_soc_dapm_path *path, const char *control_name, |
| 247 const struct snd_kcontrol_new *kcontrol) | 284 const struct snd_kcontrol_new *kcontrol) |
| 248 { | 285 { |
| 249 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 286 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
| 250 int i; | 287 int i; |
| 251 | 288 |
| 252 for (i = 0; i < e->max; i++) { | 289 for (i = 0; i < e->max; i++) { |
| 253 if (!(strcmp(control_name, e->texts[i]))) { | 290 if (!(strcmp(control_name, e->texts[i]))) { |
| 254 » » » list_add(&path->list, &codec->dapm_paths); | 291 » » » list_add(&path->list, &dapm->card->paths); |
| 255 list_add(&path->list_sink, &dest->sources); | 292 list_add(&path->list_sink, &dest->sources); |
| 256 list_add(&path->list_source, &src->sinks); | 293 list_add(&path->list_source, &src->sinks); |
| 257 path->name = (char*)e->texts[i]; | 294 path->name = (char*)e->texts[i]; |
| 258 dapm_set_path_status(dest, path, 0); | 295 dapm_set_path_status(dest, path, 0); |
| 259 return 0; | 296 return 0; |
| 260 } | 297 } |
| 261 } | 298 } |
| 262 | 299 |
| 263 return -ENODEV; | 300 return -ENODEV; |
| 264 } | 301 } |
| 265 | 302 |
| 266 /* connect mixer widget to its interconnecting audio paths */ | 303 /* connect mixer widget to its interconnecting audio paths */ |
| 267 static int dapm_connect_mixer(struct snd_soc_codec *codec, | 304 static int dapm_connect_mixer(struct snd_soc_dapm_context *dapm, |
| 268 struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest, | 305 struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest, |
| 269 struct snd_soc_dapm_path *path, const char *control_name) | 306 struct snd_soc_dapm_path *path, const char *control_name) |
| 270 { | 307 { |
| 271 int i; | 308 int i; |
| 272 | 309 |
| 273 /* search for mixer kcontrol */ | 310 /* search for mixer kcontrol */ |
| 274 for (i = 0; i < dest->num_kcontrols; i++) { | 311 for (i = 0; i < dest->num_kcontrols; i++) { |
| 275 if (!strcmp(control_name, dest->kcontrols[i].name)) { | 312 if (!strcmp(control_name, dest->kcontrols[i].name)) { |
| 276 » » » list_add(&path->list, &codec->dapm_paths); | 313 » » » list_add(&path->list, &dapm->card->paths); |
| 277 list_add(&path->list_sink, &dest->sources); | 314 list_add(&path->list_sink, &dest->sources); |
| 278 list_add(&path->list_source, &src->sinks); | 315 list_add(&path->list_source, &src->sinks); |
| 279 path->name = dest->kcontrols[i].name; | 316 path->name = dest->kcontrols[i].name; |
| 280 dapm_set_path_status(dest, path, i); | 317 dapm_set_path_status(dest, path, i); |
| 281 return 0; | 318 return 0; |
| 282 } | 319 } |
| 283 } | 320 } |
| 284 return -ENODEV; | 321 return -ENODEV; |
| 285 } | 322 } |
| 286 | 323 |
| 287 /* update dapm codec register bits */ | 324 /* update dapm codec register bits */ |
| 288 static int dapm_update_bits(struct snd_soc_dapm_widget *widget) | 325 static int dapm_update_bits(struct snd_soc_dapm_widget *widget) |
| 289 { | 326 { |
| 290 int change, power; | 327 int change, power; |
| 291 unsigned int old, new; | 328 unsigned int old, new; |
| 292 struct snd_soc_codec *codec = widget->codec; | 329 struct snd_soc_codec *codec = widget->codec; |
| 330 struct snd_soc_dapm_context *dapm = widget->dapm; |
| 331 struct snd_soc_card *card = dapm->card; |
| 293 | 332 |
| 294 /* check for valid widgets */ | 333 /* check for valid widgets */ |
| 295 if (widget->reg < 0 || widget->id == snd_soc_dapm_input || | 334 if (widget->reg < 0 || widget->id == snd_soc_dapm_input || |
| 296 widget->id == snd_soc_dapm_output || | 335 widget->id == snd_soc_dapm_output || |
| 297 widget->id == snd_soc_dapm_hp || | 336 widget->id == snd_soc_dapm_hp || |
| 298 widget->id == snd_soc_dapm_mic || | 337 widget->id == snd_soc_dapm_mic || |
| 299 widget->id == snd_soc_dapm_line || | 338 widget->id == snd_soc_dapm_line || |
| 300 widget->id == snd_soc_dapm_spk) | 339 widget->id == snd_soc_dapm_spk) |
| 301 return 0; | 340 return 0; |
| 302 | 341 |
| 303 power = widget->power; | 342 power = widget->power; |
| 304 if (widget->invert) | 343 if (widget->invert) |
| 305 power = (power ? 0:1); | 344 power = (power ? 0:1); |
| 306 | 345 |
| 307 old = snd_soc_read(codec, widget->reg); | 346 old = snd_soc_read(codec, widget->reg); |
| 308 new = (old & ~(0x1 << widget->shift)) | (power << widget->shift); | 347 new = (old & ~(0x1 << widget->shift)) | (power << widget->shift); |
| 309 | 348 |
| 310 change = old != new; | 349 change = old != new; |
| 311 if (change) { | 350 if (change) { |
| 312 » » pop_dbg(codec->pop_time, "pop test %s : %s in %d ms\n", | 351 » » pop_dbg(dapm->dev, card->pop_time, |
| 352 » » » "pop test %s : %s in %d ms\n", |
| 313 widget->name, widget->power ? "on" : "off", | 353 widget->name, widget->power ? "on" : "off", |
| 314 » » » codec->pop_time); | 354 » » » card->pop_time); |
| 315 » » pop_wait(codec->pop_time); | 355 » » pop_wait(card->pop_time); |
| 316 snd_soc_write(codec, widget->reg, new); | 356 snd_soc_write(codec, widget->reg, new); |
| 317 } | 357 } |
| 318 » pr_debug("reg %x old %x new %x change %d\n", widget->reg, | 358 » dev_dbg(dapm->dev, "reg %x old %x new %x change %d\n", widget->reg, |
| 319 » » old, new, change); | 359 » » old, new, change); |
| 320 return change; | 360 return change; |
| 321 } | 361 } |
| 322 | 362 |
| 323 /* create new dapm mixer control */ | 363 /* create new dapm mixer control */ |
| 324 static int dapm_new_mixer(struct snd_soc_codec *codec, | 364 static int dapm_new_mixer(struct snd_soc_dapm_context *dapm, |
| 325 struct snd_soc_dapm_widget *w) | 365 struct snd_soc_dapm_widget *w) |
| 326 { | 366 { |
| 327 int i, ret = 0; | 367 int i, ret = 0; |
| 328 size_t name_len; | 368 size_t name_len; |
| 329 struct snd_soc_dapm_path *path; | 369 struct snd_soc_dapm_path *path; |
| 370 struct snd_card *card = dapm->codec->card->snd_card; |
| 330 | 371 |
| 331 /* add kcontrol */ | 372 /* add kcontrol */ |
| 332 for (i = 0; i < w->num_kcontrols; i++) { | 373 for (i = 0; i < w->num_kcontrols; i++) { |
| 333 | 374 |
| 334 /* match name */ | 375 /* match name */ |
| 335 list_for_each_entry(path, &w->sources, list_sink) { | 376 list_for_each_entry(path, &w->sources, list_sink) { |
| 336 | 377 |
| 337 /* mixer/mux paths name must match control name */ | 378 /* mixer/mux paths name must match control name */ |
| 338 if (path->name != (char*)w->kcontrols[i].name) | 379 if (path->name != (char*)w->kcontrols[i].name) |
| 339 continue; | 380 continue; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 361 case snd_soc_dapm_mixer_named_ctl: | 402 case snd_soc_dapm_mixer_named_ctl: |
| 362 snprintf(path->long_name, name_len, "%s", | 403 snprintf(path->long_name, name_len, "%s", |
| 363 w->kcontrols[i].name); | 404 w->kcontrols[i].name); |
| 364 break; | 405 break; |
| 365 } | 406 } |
| 366 | 407 |
| 367 path->long_name[name_len - 1] = '\0'; | 408 path->long_name[name_len - 1] = '\0'; |
| 368 | 409 |
| 369 path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w, | 410 path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w, |
| 370 path->long_name); | 411 path->long_name); |
| 371 » » » ret = snd_ctl_add(codec->card->snd_card, path->kcontrol)
; | 412 » » » ret = snd_ctl_add(card, path->kcontrol); |
| 372 if (ret < 0) { | 413 if (ret < 0) { |
| 373 » » » » printk(KERN_ERR "asoc: failed to add dapm kcontr
ol %s: %d\n", | 414 » » » » dev_err(dapm->dev, |
| 374 » » » » path->long_name, | 415 » » » » » "asoc: failed to add dapm kcontrol %s: %
d\n", |
| 375 » » » » ret); | 416 » » » » » path->long_name, ret); |
| 376 kfree(path->long_name); | 417 kfree(path->long_name); |
| 377 path->long_name = NULL; | 418 path->long_name = NULL; |
| 378 return ret; | 419 return ret; |
| 379 } | 420 } |
| 380 } | 421 } |
| 381 } | 422 } |
| 382 return ret; | 423 return ret; |
| 383 } | 424 } |
| 384 | 425 |
| 385 /* create new dapm mux control */ | 426 /* create new dapm mux control */ |
| 386 static int dapm_new_mux(struct snd_soc_codec *codec, | 427 static int dapm_new_mux(struct snd_soc_dapm_context *dapm, |
| 387 struct snd_soc_dapm_widget *w) | 428 struct snd_soc_dapm_widget *w) |
| 388 { | 429 { |
| 389 struct snd_soc_dapm_path *path = NULL; | 430 struct snd_soc_dapm_path *path = NULL; |
| 390 struct snd_kcontrol *kcontrol; | 431 struct snd_kcontrol *kcontrol; |
| 432 struct snd_card *card = dapm->codec->card->snd_card; |
| 391 int ret = 0; | 433 int ret = 0; |
| 392 | 434 |
| 393 if (!w->num_kcontrols) { | 435 if (!w->num_kcontrols) { |
| 394 » » printk(KERN_ERR "asoc: mux %s has no controls\n", w->name); | 436 » » dev_err(dapm->dev, "asoc: mux %s has no controls\n", w->name); |
| 395 return -EINVAL; | 437 return -EINVAL; |
| 396 } | 438 } |
| 397 | 439 |
| 398 kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name); | 440 kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name); |
| 399 » ret = snd_ctl_add(codec->card->snd_card, kcontrol); | 441 » ret = snd_ctl_add(card, kcontrol); |
| 442 |
| 400 if (ret < 0) | 443 if (ret < 0) |
| 401 goto err; | 444 goto err; |
| 402 | 445 |
| 403 list_for_each_entry(path, &w->sources, list_sink) | 446 list_for_each_entry(path, &w->sources, list_sink) |
| 404 path->kcontrol = kcontrol; | 447 path->kcontrol = kcontrol; |
| 405 | 448 |
| 406 return ret; | 449 return ret; |
| 407 | 450 |
| 408 err: | 451 err: |
| 409 » printk(KERN_ERR "asoc: failed to add kcontrol %s\n", w->name); | 452 » dev_err(dapm->dev, "asoc: failed to add kcontrol %s\n", w->name); |
| 410 return ret; | 453 return ret; |
| 411 } | 454 } |
| 412 | 455 |
| 413 /* create new dapm volume control */ | 456 /* create new dapm volume control */ |
| 414 static int dapm_new_pga(struct snd_soc_codec *codec, | 457 static int dapm_new_pga(struct snd_soc_dapm_context *dapm, |
| 415 struct snd_soc_dapm_widget *w) | 458 struct snd_soc_dapm_widget *w) |
| 416 { | 459 { |
| 417 if (w->num_kcontrols) | 460 if (w->num_kcontrols) |
| 418 » » pr_err("asoc: PGA controls not supported: '%s'\n", w->name); | 461 » » dev_err(w->dapm->dev, |
| 462 » » » "asoc: PGA controls not supported: '%s'\n", w->name); |
| 419 | 463 |
| 420 return 0; | 464 return 0; |
| 421 } | 465 } |
| 422 | 466 |
| 423 /* reset 'walked' bit for each dapm path */ | 467 /* reset 'walked' bit for each dapm path */ |
| 424 static inline void dapm_clear_walk(struct snd_soc_codec *codec) | 468 static inline void dapm_clear_walk(struct snd_soc_dapm_context *dapm) |
| 425 { | 469 { |
| 426 struct snd_soc_dapm_path *p; | 470 struct snd_soc_dapm_path *p; |
| 427 | 471 |
| 428 » list_for_each_entry(p, &codec->dapm_paths, list) | 472 » list_for_each_entry(p, &dapm->card->paths, list) |
| 429 p->walked = 0; | 473 p->walked = 0; |
| 430 } | 474 } |
| 431 | 475 |
| 432 /* We implement power down on suspend by checking the power state of | 476 /* We implement power down on suspend by checking the power state of |
| 433 * the ALSA card - when we are suspending the ALSA state for the card | 477 * the ALSA card - when we are suspending the ALSA state for the card |
| 434 * is set to D3. | 478 * is set to D3. |
| 435 */ | 479 */ |
| 436 static int snd_soc_dapm_suspend_check(struct snd_soc_dapm_widget *widget) | 480 static int snd_soc_dapm_suspend_check(struct snd_soc_dapm_widget *widget) |
| 437 { | 481 { |
| 438 » int level = snd_power_get_state(widget->codec->card->snd_card); | 482 » int level = snd_power_get_state(widget->dapm->codec->card->snd_card); |
| 439 | 483 |
| 440 switch (level) { | 484 switch (level) { |
| 441 case SNDRV_CTL_POWER_D3hot: | 485 case SNDRV_CTL_POWER_D3hot: |
| 442 case SNDRV_CTL_POWER_D3cold: | 486 case SNDRV_CTL_POWER_D3cold: |
| 443 if (widget->ignore_suspend) | 487 if (widget->ignore_suspend) |
| 444 » » » pr_debug("%s ignoring suspend\n", widget->name); | 488 » » » dev_dbg(widget->dapm->dev, "%s ignoring suspend\n", |
| 489 » » » » widget->name); |
| 445 return widget->ignore_suspend; | 490 return widget->ignore_suspend; |
| 446 default: | 491 default: |
| 447 return 1; | 492 return 1; |
| 448 } | 493 } |
| 449 } | 494 } |
| 450 | 495 |
| 451 /* | 496 /* |
| 452 * Recursively check for a completed path to an active or physically connected | 497 * Recursively check for a completed path to an active or physically connected |
| 453 * output widget. Returns number of complete paths. | 498 * output widget. Returns number of complete paths. |
| 454 */ | 499 */ |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 565 | 610 |
| 566 /* Standard power change method, used to apply power changes to most | 611 /* Standard power change method, used to apply power changes to most |
| 567 * widgets. | 612 * widgets. |
| 568 */ | 613 */ |
| 569 static int dapm_generic_apply_power(struct snd_soc_dapm_widget *w) | 614 static int dapm_generic_apply_power(struct snd_soc_dapm_widget *w) |
| 570 { | 615 { |
| 571 int ret; | 616 int ret; |
| 572 | 617 |
| 573 /* call any power change event handlers */ | 618 /* call any power change event handlers */ |
| 574 if (w->event) | 619 if (w->event) |
| 575 » » pr_debug("power %s event for %s flags %x\n", | 620 » » dev_dbg(w->dapm->dev, "power %s event for %s flags %x\n", |
| 576 w->power ? "on" : "off", | 621 w->power ? "on" : "off", |
| 577 w->name, w->event_flags); | 622 w->name, w->event_flags); |
| 578 | 623 |
| 579 /* power up pre event */ | 624 /* power up pre event */ |
| 580 if (w->power && w->event && | 625 if (w->power && w->event && |
| 581 (w->event_flags & SND_SOC_DAPM_PRE_PMU)) { | 626 (w->event_flags & SND_SOC_DAPM_PRE_PMU)) { |
| 582 ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU); | 627 ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU); |
| 583 if (ret < 0) | 628 if (ret < 0) |
| 584 return ret; | 629 return ret; |
| 585 } | 630 } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 614 return 0; | 659 return 0; |
| 615 } | 660 } |
| 616 | 661 |
| 617 /* Generic check to see if a widget should be powered. | 662 /* Generic check to see if a widget should be powered. |
| 618 */ | 663 */ |
| 619 static int dapm_generic_check_power(struct snd_soc_dapm_widget *w) | 664 static int dapm_generic_check_power(struct snd_soc_dapm_widget *w) |
| 620 { | 665 { |
| 621 int in, out; | 666 int in, out; |
| 622 | 667 |
| 623 in = is_connected_input_ep(w); | 668 in = is_connected_input_ep(w); |
| 624 » dapm_clear_walk(w->codec); | 669 » dapm_clear_walk(w->dapm); |
| 625 out = is_connected_output_ep(w); | 670 out = is_connected_output_ep(w); |
| 626 » dapm_clear_walk(w->codec); | 671 » dapm_clear_walk(w->dapm); |
| 627 return out != 0 && in != 0; | 672 return out != 0 && in != 0; |
| 628 } | 673 } |
| 629 | 674 |
| 630 /* Check to see if an ADC has power */ | 675 /* Check to see if an ADC has power */ |
| 631 static int dapm_adc_check_power(struct snd_soc_dapm_widget *w) | 676 static int dapm_adc_check_power(struct snd_soc_dapm_widget *w) |
| 632 { | 677 { |
| 633 int in; | 678 int in; |
| 634 | 679 |
| 635 if (w->active) { | 680 if (w->active) { |
| 636 in = is_connected_input_ep(w); | 681 in = is_connected_input_ep(w); |
| 637 » » dapm_clear_walk(w->codec); | 682 » » dapm_clear_walk(w->dapm); |
| 638 return in != 0; | 683 return in != 0; |
| 639 } else { | 684 } else { |
| 640 return dapm_generic_check_power(w); | 685 return dapm_generic_check_power(w); |
| 641 } | 686 } |
| 642 } | 687 } |
| 643 | 688 |
| 644 /* Check to see if a DAC has power */ | 689 /* Check to see if a DAC has power */ |
| 645 static int dapm_dac_check_power(struct snd_soc_dapm_widget *w) | 690 static int dapm_dac_check_power(struct snd_soc_dapm_widget *w) |
| 646 { | 691 { |
| 647 int out; | 692 int out; |
| 648 | 693 |
| 649 if (w->active) { | 694 if (w->active) { |
| 650 out = is_connected_output_ep(w); | 695 out = is_connected_output_ep(w); |
| 651 » » dapm_clear_walk(w->codec); | 696 » » dapm_clear_walk(w->dapm); |
| 652 return out != 0; | 697 return out != 0; |
| 653 } else { | 698 } else { |
| 654 return dapm_generic_check_power(w); | 699 return dapm_generic_check_power(w); |
| 655 } | 700 } |
| 656 } | 701 } |
| 657 | 702 |
| 658 /* Check to see if a power supply is needed */ | 703 /* Check to see if a power supply is needed */ |
| 659 static int dapm_supply_check_power(struct snd_soc_dapm_widget *w) | 704 static int dapm_supply_check_power(struct snd_soc_dapm_widget *w) |
| 660 { | 705 { |
| 661 struct snd_soc_dapm_path *path; | 706 struct snd_soc_dapm_path *path; |
| 662 int power = 0; | 707 int power = 0; |
| 663 | 708 |
| 664 /* Check if one of our outputs is connected */ | 709 /* Check if one of our outputs is connected */ |
| 665 list_for_each_entry(path, &w->sinks, list_source) { | 710 list_for_each_entry(path, &w->sinks, list_source) { |
| 666 if (path->connected && | 711 if (path->connected && |
| 667 !path->connected(path->source, path->sink)) | 712 !path->connected(path->source, path->sink)) |
| 668 continue; | 713 continue; |
| 669 | 714 |
| 670 » » if (path->sink && path->sink->power_check && | 715 » » if (!path->sink) |
| 716 » » » continue; |
| 717 |
| 718 » » if (path->sink->force) { |
| 719 » » » power = 1; |
| 720 » » » break; |
| 721 » » } |
| 722 |
| 723 » » if (path->sink->power_check && |
| 671 path->sink->power_check(path->sink)) { | 724 path->sink->power_check(path->sink)) { |
| 672 power = 1; | 725 power = 1; |
| 673 break; | 726 break; |
| 674 } | 727 } |
| 675 } | 728 } |
| 676 | 729 |
| 677 » dapm_clear_walk(w->codec); | 730 » dapm_clear_walk(w->dapm); |
| 678 | 731 |
| 679 return power; | 732 return power; |
| 680 } | 733 } |
| 681 | 734 |
| 682 static int dapm_seq_compare(struct snd_soc_dapm_widget *a, | 735 static int dapm_seq_compare(struct snd_soc_dapm_widget *a, |
| 683 struct snd_soc_dapm_widget *b, | 736 struct snd_soc_dapm_widget *b, |
| 684 » » » int sort[]) | 737 » » » bool power_up) |
| 685 { | 738 { |
| 739 int *sort; |
| 740 |
| 741 if (power_up) |
| 742 sort = dapm_up_seq; |
| 743 else |
| 744 sort = dapm_down_seq; |
| 745 |
| 686 if (sort[a->id] != sort[b->id]) | 746 if (sort[a->id] != sort[b->id]) |
| 687 return sort[a->id] - sort[b->id]; | 747 return sort[a->id] - sort[b->id]; |
| 748 if (a->subseq != b->subseq) { |
| 749 if (power_up) |
| 750 return a->subseq - b->subseq; |
| 751 else |
| 752 return b->subseq - a->subseq; |
| 753 } |
| 688 if (a->reg != b->reg) | 754 if (a->reg != b->reg) |
| 689 return a->reg - b->reg; | 755 return a->reg - b->reg; |
| 690 » if (a->codec != b->codec) | 756 » if (a->dapm != b->dapm) |
| 691 » » return (unsigned long)a->codec - (unsigned long)b->codec; | 757 » » return (unsigned long)a->dapm - (unsigned long)b->dapm; |
| 692 | 758 |
| 693 return 0; | 759 return 0; |
| 694 } | 760 } |
| 695 | 761 |
| 696 /* Insert a widget in order into a DAPM power sequence. */ | 762 /* Insert a widget in order into a DAPM power sequence. */ |
| 697 static void dapm_seq_insert(struct snd_soc_dapm_widget *new_widget, | 763 static void dapm_seq_insert(struct snd_soc_dapm_widget *new_widget, |
| 698 struct list_head *list, | 764 struct list_head *list, |
| 699 » » » int sort[]) | 765 » » » bool power_up) |
| 700 { | 766 { |
| 701 struct snd_soc_dapm_widget *w; | 767 struct snd_soc_dapm_widget *w; |
| 702 | 768 |
| 703 list_for_each_entry(w, list, power_list) | 769 list_for_each_entry(w, list, power_list) |
| 704 » » if (dapm_seq_compare(new_widget, w, sort) < 0) { | 770 » » if (dapm_seq_compare(new_widget, w, power_up) < 0) { |
| 705 list_add_tail(&new_widget->power_list, &w->power_list); | 771 list_add_tail(&new_widget->power_list, &w->power_list); |
| 706 return; | 772 return; |
| 707 } | 773 } |
| 708 | 774 |
| 709 list_add_tail(&new_widget->power_list, list); | 775 list_add_tail(&new_widget->power_list, list); |
| 710 } | 776 } |
| 711 | 777 |
| 778 static void dapm_seq_check_event(struct snd_soc_dapm_context *dapm, |
| 779 struct snd_soc_dapm_widget *w, int event) |
| 780 { |
| 781 struct snd_soc_card *card = dapm->card; |
| 782 const char *ev_name; |
| 783 int power, ret; |
| 784 |
| 785 switch (event) { |
| 786 case SND_SOC_DAPM_PRE_PMU: |
| 787 ev_name = "PRE_PMU"; |
| 788 power = 1; |
| 789 break; |
| 790 case SND_SOC_DAPM_POST_PMU: |
| 791 ev_name = "POST_PMU"; |
| 792 power = 1; |
| 793 break; |
| 794 case SND_SOC_DAPM_PRE_PMD: |
| 795 ev_name = "PRE_PMD"; |
| 796 power = 0; |
| 797 break; |
| 798 case SND_SOC_DAPM_POST_PMD: |
| 799 ev_name = "POST_PMD"; |
| 800 power = 0; |
| 801 break; |
| 802 default: |
| 803 BUG(); |
| 804 return; |
| 805 } |
| 806 |
| 807 if (w->power != power) |
| 808 return; |
| 809 |
| 810 if (w->event && (w->event_flags & event)) { |
| 811 pop_dbg(dapm->dev, card->pop_time, "pop test : %s %s\n", |
| 812 w->name, ev_name); |
| 813 trace_snd_soc_dapm_widget_event_start(w, event); |
| 814 ret = w->event(w, NULL, event); |
| 815 trace_snd_soc_dapm_widget_event_done(w, event); |
| 816 if (ret < 0) |
| 817 pr_err("%s: %s event failed: %d\n", |
| 818 ev_name, w->name, ret); |
| 819 } |
| 820 } |
| 821 |
| 712 /* Apply the coalesced changes from a DAPM sequence */ | 822 /* Apply the coalesced changes from a DAPM sequence */ |
| 713 static void dapm_seq_run_coalesced(struct snd_soc_codec *codec, | 823 static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm, |
| 714 struct list_head *pending) | 824 struct list_head *pending) |
| 715 { | 825 { |
| 826 struct snd_soc_card *card = dapm->card; |
| 716 struct snd_soc_dapm_widget *w; | 827 struct snd_soc_dapm_widget *w; |
| 717 » int reg, power, ret; | 828 » int reg, power; |
| 718 unsigned int value = 0; | 829 unsigned int value = 0; |
| 719 unsigned int mask = 0; | 830 unsigned int mask = 0; |
| 720 unsigned int cur_mask; | 831 unsigned int cur_mask; |
| 721 | 832 |
| 722 reg = list_first_entry(pending, struct snd_soc_dapm_widget, | 833 reg = list_first_entry(pending, struct snd_soc_dapm_widget, |
| 723 power_list)->reg; | 834 power_list)->reg; |
| 724 | 835 |
| 725 list_for_each_entry(w, pending, power_list) { | 836 list_for_each_entry(w, pending, power_list) { |
| 726 cur_mask = 1 << w->shift; | 837 cur_mask = 1 << w->shift; |
| 727 BUG_ON(reg != w->reg); | 838 BUG_ON(reg != w->reg); |
| 728 | 839 |
| 729 if (w->invert) | 840 if (w->invert) |
| 730 power = !w->power; | 841 power = !w->power; |
| 731 else | 842 else |
| 732 power = w->power; | 843 power = w->power; |
| 733 | 844 |
| 734 mask |= cur_mask; | 845 mask |= cur_mask; |
| 735 if (power) | 846 if (power) |
| 736 value |= cur_mask; | 847 value |= cur_mask; |
| 737 | 848 |
| 738 » » pop_dbg(codec->pop_time, | 849 » » pop_dbg(dapm->dev, card->pop_time, |
| 739 "pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n", | 850 "pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n", |
| 740 w->name, reg, value, mask); | 851 w->name, reg, value, mask); |
| 741 | 852 |
| 742 » » /* power up pre event */ | 853 » » /* Check for events */ |
| 743 » » if (w->power && w->event && | 854 » » dapm_seq_check_event(dapm, w, SND_SOC_DAPM_PRE_PMU); |
| 744 » » (w->event_flags & SND_SOC_DAPM_PRE_PMU)) { | 855 » » dapm_seq_check_event(dapm, w, SND_SOC_DAPM_PRE_PMD); |
| 745 » » » pop_dbg(codec->pop_time, "pop test : %s PRE_PMU\n", | |
| 746 » » » » w->name); | |
| 747 » » » ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU); | |
| 748 » » » if (ret < 0) | |
| 749 » » » » pr_err("%s: pre event failed: %d\n", | |
| 750 » » » » w->name, ret); | |
| 751 » » } | |
| 752 | |
| 753 » » /* power down pre event */ | |
| 754 » » if (!w->power && w->event && | |
| 755 » » (w->event_flags & SND_SOC_DAPM_PRE_PMD)) { | |
| 756 » » » pop_dbg(codec->pop_time, "pop test : %s PRE_PMD\n", | |
| 757 » » » » w->name); | |
| 758 » » » ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMD); | |
| 759 » » » if (ret < 0) | |
| 760 » » » » pr_err("%s: pre event failed: %d\n", | |
| 761 » » » » w->name, ret); | |
| 762 » » } | |
| 763 } | 856 } |
| 764 | 857 |
| 765 if (reg >= 0) { | 858 if (reg >= 0) { |
| 766 » » pop_dbg(codec->pop_time, | 859 » » pop_dbg(dapm->dev, card->pop_time, |
| 767 "pop test : Applying 0x%x/0x%x to %x in %dms\n", | 860 "pop test : Applying 0x%x/0x%x to %x in %dms\n", |
| 768 » » » value, mask, reg, codec->pop_time); | 861 » » » value, mask, reg, card->pop_time); |
| 769 » » pop_wait(codec->pop_time); | 862 » » pop_wait(card->pop_time); |
| 770 » » snd_soc_update_bits(codec, reg, mask, value); | 863 » » snd_soc_update_bits(dapm->codec, reg, mask, value); |
| 771 } | 864 } |
| 772 | 865 |
| 773 list_for_each_entry(w, pending, power_list) { | 866 list_for_each_entry(w, pending, power_list) { |
| 774 » » /* power up post event */ | 867 » » dapm_seq_check_event(dapm, w, SND_SOC_DAPM_POST_PMU); |
| 775 » » if (w->power && w->event && | 868 » » dapm_seq_check_event(dapm, w, SND_SOC_DAPM_POST_PMD); |
| 776 » » (w->event_flags & SND_SOC_DAPM_POST_PMU)) { | |
| 777 » » » pop_dbg(codec->pop_time, "pop test : %s POST_PMU\n", | |
| 778 » » » » w->name); | |
| 779 » » » ret = w->event(w, | |
| 780 » » » » NULL, SND_SOC_DAPM_POST_PMU); | |
| 781 » » » if (ret < 0) | |
| 782 » » » » pr_err("%s: post event failed: %d\n", | |
| 783 » » » » w->name, ret); | |
| 784 » » } | |
| 785 | |
| 786 » » /* power down post event */ | |
| 787 » » if (!w->power && w->event && | |
| 788 » » (w->event_flags & SND_SOC_DAPM_POST_PMD)) { | |
| 789 » » » pop_dbg(codec->pop_time, "pop test : %s POST_PMD\n", | |
| 790 » » » » w->name); | |
| 791 » » » ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMD); | |
| 792 » » » if (ret < 0) | |
| 793 » » » » pr_err("%s: post event failed: %d\n", | |
| 794 » » » » w->name, ret); | |
| 795 » » } | |
| 796 } | 869 } |
| 797 } | 870 } |
| 798 | 871 |
| 799 /* Apply a DAPM power sequence. | 872 /* Apply a DAPM power sequence. |
| 800 * | 873 * |
| 801 * We walk over a pre-sorted list of widgets to apply power to. In | 874 * We walk over a pre-sorted list of widgets to apply power to. In |
| 802 * order to minimise the number of writes to the device required | 875 * order to minimise the number of writes to the device required |
| 803 * multiple widgets will be updated in a single write where possible. | 876 * multiple widgets will be updated in a single write where possible. |
| 804 * Currently anything that requires more than a single write is not | 877 * Currently anything that requires more than a single write is not |
| 805 * handled. | 878 * handled. |
| 806 */ | 879 */ |
| 807 static void dapm_seq_run(struct snd_soc_codec *codec, struct list_head *list, | 880 static void dapm_seq_run(struct snd_soc_dapm_context *dapm, |
| 808 » » » int event, int sort[]) | 881 » » » struct list_head *list, int event, bool power_up) |
| 809 { | 882 { |
| 810 struct snd_soc_dapm_widget *w, *n; | 883 struct snd_soc_dapm_widget *w, *n; |
| 811 LIST_HEAD(pending); | 884 LIST_HEAD(pending); |
| 812 int cur_sort = -1; | 885 int cur_sort = -1; |
| 886 int cur_subseq = -1; |
| 813 int cur_reg = SND_SOC_NOPM; | 887 int cur_reg = SND_SOC_NOPM; |
| 814 » int ret; | 888 » struct snd_soc_dapm_context *cur_dapm = NULL; |
| 889 » int ret, i; |
| 890 » int *sort; |
| 891 |
| 892 » if (power_up) |
| 893 » » sort = dapm_up_seq; |
| 894 » else |
| 895 » » sort = dapm_down_seq; |
| 815 | 896 |
| 816 list_for_each_entry_safe(w, n, list, power_list) { | 897 list_for_each_entry_safe(w, n, list, power_list) { |
| 817 ret = 0; | 898 ret = 0; |
| 818 | 899 |
| 819 /* Do we need to apply any queued changes? */ | 900 /* Do we need to apply any queued changes? */ |
| 820 » » if (sort[w->id] != cur_sort || w->reg != cur_reg) { | 901 » » if (sort[w->id] != cur_sort || w->reg != cur_reg || |
| 902 » » w->dapm != cur_dapm || w->subseq != cur_subseq) { |
| 821 if (!list_empty(&pending)) | 903 if (!list_empty(&pending)) |
| 822 » » » » dapm_seq_run_coalesced(codec, &pending); | 904 » » » » dapm_seq_run_coalesced(cur_dapm, &pending); |
| 905 |
| 906 » » » if (cur_dapm && cur_dapm->seq_notifier) { |
| 907 » » » » for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++) |
| 908 » » » » » if (sort[i] == cur_sort) |
| 909 » » » » » » cur_dapm->seq_notifier(cur_dapm, |
| 910 » » » » » » » » i, |
| 911 » » » » » » » » cur_subse
q); |
| 912 » » » } |
| 823 | 913 |
| 824 INIT_LIST_HEAD(&pending); | 914 INIT_LIST_HEAD(&pending); |
| 825 cur_sort = -1; | 915 cur_sort = -1; |
| 916 cur_subseq = -1; |
| 826 cur_reg = SND_SOC_NOPM; | 917 cur_reg = SND_SOC_NOPM; |
| 918 cur_dapm = NULL; |
| 827 } | 919 } |
| 828 | 920 |
| 829 switch (w->id) { | 921 switch (w->id) { |
| 830 case snd_soc_dapm_pre: | 922 case snd_soc_dapm_pre: |
| 831 if (!w->event) | 923 if (!w->event) |
| 832 list_for_each_entry_safe_continue(w, n, list, | 924 list_for_each_entry_safe_continue(w, n, list, |
| 833 power_list); | 925 power_list); |
| 834 | 926 |
| 835 if (event == SND_SOC_DAPM_STREAM_START) | 927 if (event == SND_SOC_DAPM_STREAM_START) |
| 836 ret = w->event(w, | 928 ret = w->event(w, |
| (...skipping 22 matching lines...) Expand all Loading... |
| 859 case snd_soc_dapm_mic: | 951 case snd_soc_dapm_mic: |
| 860 case snd_soc_dapm_line: | 952 case snd_soc_dapm_line: |
| 861 case snd_soc_dapm_spk: | 953 case snd_soc_dapm_spk: |
| 862 /* No register support currently */ | 954 /* No register support currently */ |
| 863 ret = dapm_generic_apply_power(w); | 955 ret = dapm_generic_apply_power(w); |
| 864 break; | 956 break; |
| 865 | 957 |
| 866 default: | 958 default: |
| 867 /* Queue it up for application */ | 959 /* Queue it up for application */ |
| 868 cur_sort = sort[w->id]; | 960 cur_sort = sort[w->id]; |
| 961 cur_subseq = w->subseq; |
| 869 cur_reg = w->reg; | 962 cur_reg = w->reg; |
| 963 cur_dapm = w->dapm; |
| 870 list_move(&w->power_list, &pending); | 964 list_move(&w->power_list, &pending); |
| 871 break; | 965 break; |
| 872 } | 966 } |
| 873 | 967 |
| 874 if (ret < 0) | 968 if (ret < 0) |
| 875 » » » pr_err("Failed to apply widget power: %d\n", | 969 » » » dev_err(w->dapm->dev, |
| 876 » » » ret); | 970 » » » » "Failed to apply widget power: %d\n", ret); |
| 877 } | 971 } |
| 878 | 972 |
| 879 if (!list_empty(&pending)) | 973 if (!list_empty(&pending)) |
| 880 » » dapm_seq_run_coalesced(codec, &pending); | 974 » » dapm_seq_run_coalesced(dapm, &pending); |
| 975 |
| 976 » if (cur_dapm && cur_dapm->seq_notifier) { |
| 977 » » for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++) |
| 978 » » » if (sort[i] == cur_sort) |
| 979 » » » » cur_dapm->seq_notifier(cur_dapm, |
| 980 » » » » » » i, cur_subseq); |
| 981 » } |
| 881 } | 982 } |
| 882 | 983 |
| 984 static void dapm_widget_update(struct snd_soc_dapm_context *dapm) |
| 985 { |
| 986 struct snd_soc_dapm_update *update = dapm->update; |
| 987 struct snd_soc_dapm_widget *w; |
| 988 int ret; |
| 989 |
| 990 if (!update) |
| 991 return; |
| 992 |
| 993 w = update->widget; |
| 994 |
| 995 if (w->event && |
| 996 (w->event_flags & SND_SOC_DAPM_PRE_REG)) { |
| 997 ret = w->event(w, update->kcontrol, SND_SOC_DAPM_PRE_REG); |
| 998 if (ret != 0) |
| 999 pr_err("%s DAPM pre-event failed: %d\n", |
| 1000 w->name, ret); |
| 1001 } |
| 1002 |
| 1003 ret = snd_soc_update_bits(w->codec, update->reg, update->mask, |
| 1004 update->val); |
| 1005 if (ret < 0) |
| 1006 pr_err("%s DAPM update failed: %d\n", w->name, ret); |
| 1007 |
| 1008 if (w->event && |
| 1009 (w->event_flags & SND_SOC_DAPM_POST_REG)) { |
| 1010 ret = w->event(w, update->kcontrol, SND_SOC_DAPM_POST_REG); |
| 1011 if (ret != 0) |
| 1012 pr_err("%s DAPM post-event failed: %d\n", |
| 1013 w->name, ret); |
| 1014 } |
| 1015 } |
| 1016 |
| 1017 |
| 1018 |
| 883 /* | 1019 /* |
| 884 * Scan each dapm widget for complete audio path. | 1020 * Scan each dapm widget for complete audio path. |
| 885 * A complete path is a route that has valid endpoints i.e.:- | 1021 * A complete path is a route that has valid endpoints i.e.:- |
| 886 * | 1022 * |
| 887 * o DAC to output pin. | 1023 * o DAC to output pin. |
| 888 * o Input Pin to ADC. | 1024 * o Input Pin to ADC. |
| 889 * o Input pin to Output pin (bypass, sidetone) | 1025 * o Input pin to Output pin (bypass, sidetone) |
| 890 * o DAC to ADC (loopback). | 1026 * o DAC to ADC (loopback). |
| 891 */ | 1027 */ |
| 892 static int dapm_power_widgets(struct snd_soc_codec *codec, int event) | 1028 static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) |
| 893 { | 1029 { |
| 894 » struct snd_soc_card *card = codec->card; | 1030 » struct snd_soc_card *card = dapm->codec->card; |
| 895 struct snd_soc_dapm_widget *w; | 1031 struct snd_soc_dapm_widget *w; |
| 1032 struct snd_soc_dapm_context *d; |
| 896 LIST_HEAD(up_list); | 1033 LIST_HEAD(up_list); |
| 897 LIST_HEAD(down_list); | 1034 LIST_HEAD(down_list); |
| 898 int ret = 0; | 1035 int ret = 0; |
| 899 int power; | 1036 int power; |
| 900 » int sys_power = 0; | 1037 |
| 1038 » trace_snd_soc_dapm_start(card); |
| 1039 |
| 1040 » list_for_each_entry(d, &card->dapm_list, list) |
| 1041 » » if (d->n_widgets) |
| 1042 » » » d->dev_power = 0; |
| 901 | 1043 |
| 902 /* Check which widgets we need to power and store them in | 1044 /* Check which widgets we need to power and store them in |
| 903 * lists indicating if they should be powered up or down. | 1045 * lists indicating if they should be powered up or down. |
| 904 */ | 1046 */ |
| 905 » list_for_each_entry(w, &codec->dapm_widgets, list) { | 1047 » list_for_each_entry(w, &card->widgets, list) { |
| 906 switch (w->id) { | 1048 switch (w->id) { |
| 907 case snd_soc_dapm_pre: | 1049 case snd_soc_dapm_pre: |
| 908 » » » dapm_seq_insert(w, &down_list, dapm_down_seq); | 1050 » » » dapm_seq_insert(w, &down_list, false); |
| 909 break; | 1051 break; |
| 910 case snd_soc_dapm_post: | 1052 case snd_soc_dapm_post: |
| 911 » » » dapm_seq_insert(w, &up_list, dapm_up_seq); | 1053 » » » dapm_seq_insert(w, &up_list, true); |
| 912 break; | 1054 break; |
| 913 | 1055 |
| 914 default: | 1056 default: |
| 915 if (!w->power_check) | 1057 if (!w->power_check) |
| 916 continue; | 1058 continue; |
| 917 | 1059 |
| 918 if (!w->force) | 1060 if (!w->force) |
| 919 power = w->power_check(w); | 1061 power = w->power_check(w); |
| 920 else | 1062 else |
| 921 power = 1; | 1063 power = 1; |
| 922 if (power) | 1064 if (power) |
| 923 » » » » sys_power = 1; | 1065 » » » » w->dapm->dev_power = 1; |
| 924 | 1066 |
| 925 if (w->power == power) | 1067 if (w->power == power) |
| 926 continue; | 1068 continue; |
| 927 | 1069 |
| 1070 trace_snd_soc_dapm_widget_power(w, power); |
| 1071 |
| 928 if (power) | 1072 if (power) |
| 929 » » » » dapm_seq_insert(w, &up_list, dapm_up_seq); | 1073 » » » » dapm_seq_insert(w, &up_list, true); |
| 930 else | 1074 else |
| 931 » » » » dapm_seq_insert(w, &down_list, dapm_down_seq); | 1075 » » » » dapm_seq_insert(w, &down_list, false); |
| 932 | 1076 |
| 933 w->power = power; | 1077 w->power = power; |
| 934 break; | 1078 break; |
| 935 } | 1079 } |
| 936 } | 1080 } |
| 937 | 1081 |
| 938 /* If there are no DAPM widgets then try to figure out power from the | 1082 /* If there are no DAPM widgets then try to figure out power from the |
| 939 * event type. | 1083 * event type. |
| 940 */ | 1084 */ |
| 941 » if (list_empty(&codec->dapm_widgets)) { | 1085 » if (!dapm->n_widgets) { |
| 942 switch (event) { | 1086 switch (event) { |
| 943 case SND_SOC_DAPM_STREAM_START: | 1087 case SND_SOC_DAPM_STREAM_START: |
| 944 case SND_SOC_DAPM_STREAM_RESUME: | 1088 case SND_SOC_DAPM_STREAM_RESUME: |
| 945 » » » sys_power = 1; | 1089 » » » dapm->dev_power = 1; |
| 946 break; | 1090 break; |
| 947 case SND_SOC_DAPM_STREAM_STOP: | 1091 case SND_SOC_DAPM_STREAM_STOP: |
| 948 » » » sys_power = !!codec->active; | 1092 » » » dapm->dev_power = !!dapm->codec->active; |
| 949 break; | 1093 break; |
| 950 case SND_SOC_DAPM_STREAM_SUSPEND: | 1094 case SND_SOC_DAPM_STREAM_SUSPEND: |
| 951 » » » sys_power = 0; | 1095 » » » dapm->dev_power = 0; |
| 952 break; | 1096 break; |
| 953 case SND_SOC_DAPM_STREAM_NOP: | 1097 case SND_SOC_DAPM_STREAM_NOP: |
| 954 » » » switch (codec->bias_level) { | 1098 » » » switch (dapm->bias_level) { |
| 955 case SND_SOC_BIAS_STANDBY: | 1099 case SND_SOC_BIAS_STANDBY: |
| 956 case SND_SOC_BIAS_OFF: | 1100 case SND_SOC_BIAS_OFF: |
| 957 » » » » » sys_power = 0; | 1101 » » » » » dapm->dev_power = 0; |
| 958 break; | 1102 break; |
| 959 default: | 1103 default: |
| 960 » » » » » sys_power = 1; | 1104 » » » » » dapm->dev_power = 1; |
| 961 break; | 1105 break; |
| 962 } | 1106 } |
| 963 break; | 1107 break; |
| 964 default: | 1108 default: |
| 965 break; | 1109 break; |
| 966 } | 1110 } |
| 967 } | 1111 } |
| 968 | 1112 |
| 969 » if (sys_power && codec->bias_level == SND_SOC_BIAS_OFF) { | 1113 » list_for_each_entry(d, &dapm->card->dapm_list, list) { |
| 970 » » ret = snd_soc_dapm_set_bias_level(card, codec, | 1114 » » if (d->dev_power && d->bias_level == SND_SOC_BIAS_OFF) { |
| 971 » » » » » » SND_SOC_BIAS_STANDBY); | 1115 » » » ret = snd_soc_dapm_set_bias_level(card, d, |
| 972 » » if (ret != 0) | 1116 » » » » » » » SND_SOC_BIAS_STANDBY); |
| 973 » » » pr_err("Failed to turn on bias: %d\n", ret); | 1117 » » » if (ret != 0) |
| 974 » } | 1118 » » » » dev_err(d->dev, |
| 1119 » » » » » "Failed to turn on bias: %d\n", ret); |
| 1120 » » } |
| 975 | 1121 |
| 976 » /* If we're changing to all on or all off then prepare */ | 1122 » » /* If we're changing to all on or all off then prepare */ |
| 977 » if ((sys_power && codec->bias_level == SND_SOC_BIAS_STANDBY) || | 1123 » » if ((d->dev_power && d->bias_level == SND_SOC_BIAS_STANDBY) || |
| 978 » (!sys_power && codec->bias_level == SND_SOC_BIAS_ON)) { | 1124 » » (!d->dev_power && d->bias_level == SND_SOC_BIAS_ON)) { |
| 979 » » ret = snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_PREP
ARE); | 1125 » » » ret = snd_soc_dapm_set_bias_level(card, d, |
| 980 » » if (ret != 0) | 1126 » » » » » » » SND_SOC_BIAS_PREPARE); |
| 981 » » » pr_err("Failed to prepare bias: %d\n", ret); | 1127 » » » if (ret != 0) |
| 1128 » » » » dev_err(d->dev, |
| 1129 » » » » » "Failed to prepare bias: %d\n", ret); |
| 1130 » » } |
| 982 } | 1131 } |
| 983 | 1132 |
| 984 /* Power down widgets first; try to avoid amplifying pops. */ | 1133 /* Power down widgets first; try to avoid amplifying pops. */ |
| 985 » dapm_seq_run(codec, &down_list, event, dapm_down_seq); | 1134 » dapm_seq_run(dapm, &down_list, event, false); |
| 1135 |
| 1136 » dapm_widget_update(dapm); |
| 986 | 1137 |
| 987 /* Now power up. */ | 1138 /* Now power up. */ |
| 988 » dapm_seq_run(codec, &up_list, event, dapm_up_seq); | 1139 » dapm_seq_run(dapm, &up_list, event, true); |
| 989 | 1140 |
| 990 » /* If we just powered the last thing off drop to standby bias */ | 1141 » list_for_each_entry(d, &dapm->card->dapm_list, list) { |
| 991 » if (codec->bias_level == SND_SOC_BIAS_PREPARE && !sys_power) { | 1142 » » /* If we just powered the last thing off drop to standby bias */ |
| 992 » » ret = snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_STAN
DBY); | 1143 » » if (d->bias_level == SND_SOC_BIAS_PREPARE && !d->dev_power) { |
| 993 » » if (ret != 0) | 1144 » » » ret = snd_soc_dapm_set_bias_level(card, d, |
| 994 » » » pr_err("Failed to apply standby bias: %d\n", ret); | 1145 » » » » » » » SND_SOC_BIAS_STANDBY); |
| 1146 » » » if (ret != 0) |
| 1147 » » » » dev_err(d->dev, |
| 1148 » » » » » "Failed to apply standby bias: %d\n", |
| 1149 » » » » » ret); |
| 1150 » » } |
| 1151 |
| 1152 » » /* If we're in standby and can support bias off then do that */ |
| 1153 » » if (d->bias_level == SND_SOC_BIAS_STANDBY && |
| 1154 » » d->idle_bias_off) { |
| 1155 » » » ret = snd_soc_dapm_set_bias_level(card, d, |
| 1156 » » » » » » » SND_SOC_BIAS_OFF); |
| 1157 » » » if (ret != 0) |
| 1158 » » » » dev_err(d->dev, |
| 1159 » » » » » "Failed to turn off bias: %d\n", ret); |
| 1160 » » } |
| 1161 |
| 1162 » » /* If we just powered up then move to active bias */ |
| 1163 » » if (d->bias_level == SND_SOC_BIAS_PREPARE && d->dev_power) { |
| 1164 » » » ret = snd_soc_dapm_set_bias_level(card, d, |
| 1165 » » » » » » » SND_SOC_BIAS_ON); |
| 1166 » » » if (ret != 0) |
| 1167 » » » » dev_err(d->dev, |
| 1168 » » » » » "Failed to apply active bias: %d\n", |
| 1169 » » » » » ret); |
| 1170 » » } |
| 995 } | 1171 } |
| 996 | 1172 |
| 997 » /* If we're in standby and can support bias off then do that */ | 1173 » pop_dbg(dapm->dev, card->pop_time, |
| 998 » if (codec->bias_level == SND_SOC_BIAS_STANDBY && | 1174 » » "DAPM sequencing finished, waiting %dms\n", card->pop_time); |
| 999 » codec->idle_bias_off) { | 1175 » pop_wait(card->pop_time); |
| 1000 » » ret = snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_OFF)
; | |
| 1001 » » if (ret != 0) | |
| 1002 » » » pr_err("Failed to turn off bias: %d\n", ret); | |
| 1003 » } | |
| 1004 | 1176 |
| 1005 » /* If we just powered up then move to active bias */ | 1177 » trace_snd_soc_dapm_done(card); |
| 1006 » if (codec->bias_level == SND_SOC_BIAS_PREPARE && sys_power) { | |
| 1007 » » ret = snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_ON); | |
| 1008 » » if (ret != 0) | |
| 1009 » » » pr_err("Failed to apply active bias: %d\n", ret); | |
| 1010 » } | |
| 1011 | |
| 1012 » pop_dbg(codec->pop_time, "DAPM sequencing finished, waiting %dms\n", | |
| 1013 » » codec->pop_time); | |
| 1014 » pop_wait(codec->pop_time); | |
| 1015 | 1178 |
| 1016 return 0; | 1179 return 0; |
| 1017 } | 1180 } |
| 1018 | 1181 |
| 1019 #ifdef CONFIG_DEBUG_FS | 1182 #ifdef CONFIG_DEBUG_FS |
| 1020 static int dapm_widget_power_open_file(struct inode *inode, struct file *file) | 1183 static int dapm_widget_power_open_file(struct inode *inode, struct file *file) |
| 1021 { | 1184 { |
| 1022 file->private_data = inode->i_private; | 1185 file->private_data = inode->i_private; |
| 1023 return 0; | 1186 return 0; |
| 1024 } | 1187 } |
| 1025 | 1188 |
| 1026 static ssize_t dapm_widget_power_read_file(struct file *file, | 1189 static ssize_t dapm_widget_power_read_file(struct file *file, |
| 1027 char __user *user_buf, | 1190 char __user *user_buf, |
| 1028 size_t count, loff_t *ppos) | 1191 size_t count, loff_t *ppos) |
| 1029 { | 1192 { |
| 1030 struct snd_soc_dapm_widget *w = file->private_data; | 1193 struct snd_soc_dapm_widget *w = file->private_data; |
| 1031 char *buf; | 1194 char *buf; |
| 1032 int in, out; | 1195 int in, out; |
| 1033 ssize_t ret; | 1196 ssize_t ret; |
| 1034 struct snd_soc_dapm_path *p = NULL; | 1197 struct snd_soc_dapm_path *p = NULL; |
| 1035 | 1198 |
| 1036 buf = kmalloc(PAGE_SIZE, GFP_KERNEL); | 1199 buf = kmalloc(PAGE_SIZE, GFP_KERNEL); |
| 1037 if (!buf) | 1200 if (!buf) |
| 1038 return -ENOMEM; | 1201 return -ENOMEM; |
| 1039 | 1202 |
| 1040 in = is_connected_input_ep(w); | 1203 in = is_connected_input_ep(w); |
| 1041 » dapm_clear_walk(w->codec); | 1204 » dapm_clear_walk(w->dapm); |
| 1042 out = is_connected_output_ep(w); | 1205 out = is_connected_output_ep(w); |
| 1043 » dapm_clear_walk(w->codec); | 1206 » dapm_clear_walk(w->dapm); |
| 1044 | 1207 |
| 1045 ret = snprintf(buf, PAGE_SIZE, "%s: %s in %d out %d", | 1208 ret = snprintf(buf, PAGE_SIZE, "%s: %s in %d out %d", |
| 1046 w->name, w->power ? "On" : "Off", in, out); | 1209 w->name, w->power ? "On" : "Off", in, out); |
| 1047 | 1210 |
| 1048 if (w->reg >= 0) | 1211 if (w->reg >= 0) |
| 1049 ret += snprintf(buf + ret, PAGE_SIZE - ret, | 1212 ret += snprintf(buf + ret, PAGE_SIZE - ret, |
| 1050 " - R%d(0x%x) bit %d", | 1213 " - R%d(0x%x) bit %d", |
| 1051 w->reg, w->reg, w->shift); | 1214 w->reg, w->reg, w->shift); |
| 1052 | 1215 |
| 1053 ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n"); | 1216 ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n"); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1083 kfree(buf); | 1246 kfree(buf); |
| 1084 return ret; | 1247 return ret; |
| 1085 } | 1248 } |
| 1086 | 1249 |
| 1087 static const struct file_operations dapm_widget_power_fops = { | 1250 static const struct file_operations dapm_widget_power_fops = { |
| 1088 .open = dapm_widget_power_open_file, | 1251 .open = dapm_widget_power_open_file, |
| 1089 .read = dapm_widget_power_read_file, | 1252 .read = dapm_widget_power_read_file, |
| 1090 .llseek = default_llseek, | 1253 .llseek = default_llseek, |
| 1091 }; | 1254 }; |
| 1092 | 1255 |
| 1093 void snd_soc_dapm_debugfs_init(struct snd_soc_codec *codec) | 1256 void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm) |
| 1094 { | 1257 { |
| 1095 struct snd_soc_dapm_widget *w; | 1258 struct snd_soc_dapm_widget *w; |
| 1096 struct dentry *d; | 1259 struct dentry *d; |
| 1097 | 1260 |
| 1098 » if (!codec->debugfs_dapm) | 1261 » if (!dapm->debugfs_dapm) |
| 1099 return; | 1262 return; |
| 1100 | 1263 |
| 1101 » list_for_each_entry(w, &codec->dapm_widgets, list) { | 1264 » list_for_each_entry(w, &dapm->card->widgets, list) { |
| 1102 » » if (!w->name) | 1265 » » if (!w->name || w->dapm != dapm) |
| 1103 continue; | 1266 continue; |
| 1104 | 1267 |
| 1105 d = debugfs_create_file(w->name, 0444, | 1268 d = debugfs_create_file(w->name, 0444, |
| 1106 » » » » » codec->debugfs_dapm, w, | 1269 » » » » » dapm->debugfs_dapm, w, |
| 1107 &dapm_widget_power_fops); | 1270 &dapm_widget_power_fops); |
| 1108 if (!d) | 1271 if (!d) |
| 1109 » » » printk(KERN_WARNING | 1272 » » » dev_warn(w->dapm->dev, |
| 1110 » » » "ASoC: Failed to create %s debugfs file\n", | 1273 » » » » "ASoC: Failed to create %s debugfs file\n", |
| 1111 » » » w->name); | 1274 » » » » w->name); |
| 1112 } | 1275 } |
| 1113 } | 1276 } |
| 1114 #else | 1277 #else |
| 1115 void snd_soc_dapm_debugfs_init(struct snd_soc_codec *codec) | 1278 void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm) |
| 1116 { | 1279 { |
| 1117 } | 1280 } |
| 1118 #endif | 1281 #endif |
| 1119 | 1282 |
| 1120 /* test and update the power status of a mux widget */ | 1283 /* test and update the power status of a mux widget */ |
| 1121 static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget, | 1284 static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget, |
| 1122 struct snd_kcontrol *kcontrol, int change, | 1285 struct snd_kcontrol *kcontrol, int change, |
| 1123 int mux, struct soc_enum *e) | 1286 int mux, struct soc_enum *e) |
| 1124 { | 1287 { |
| 1125 struct snd_soc_dapm_path *path; | 1288 struct snd_soc_dapm_path *path; |
| 1126 int found = 0; | 1289 int found = 0; |
| 1127 | 1290 |
| 1128 if (widget->id != snd_soc_dapm_mux && | 1291 if (widget->id != snd_soc_dapm_mux && |
| 1292 widget->id != snd_soc_dapm_virt_mux && |
| 1129 widget->id != snd_soc_dapm_value_mux) | 1293 widget->id != snd_soc_dapm_value_mux) |
| 1130 return -ENODEV; | 1294 return -ENODEV; |
| 1131 | 1295 |
| 1132 if (!change) | 1296 if (!change) |
| 1133 return 0; | 1297 return 0; |
| 1134 | 1298 |
| 1135 /* find dapm widget path assoc with kcontrol */ | 1299 /* find dapm widget path assoc with kcontrol */ |
| 1136 » list_for_each_entry(path, &widget->codec->dapm_paths, list) { | 1300 » list_for_each_entry(path, &widget->dapm->card->paths, list) { |
| 1137 if (path->kcontrol != kcontrol) | 1301 if (path->kcontrol != kcontrol) |
| 1138 continue; | 1302 continue; |
| 1139 | 1303 |
| 1140 if (!path->name || !e->texts[mux]) | 1304 if (!path->name || !e->texts[mux]) |
| 1141 continue; | 1305 continue; |
| 1142 | 1306 |
| 1143 found = 1; | 1307 found = 1; |
| 1144 /* we now need to match the string in the enum to the path */ | 1308 /* we now need to match the string in the enum to the path */ |
| 1145 if (!(strcmp(path->name, e->texts[mux]))) | 1309 if (!(strcmp(path->name, e->texts[mux]))) |
| 1146 path->connect = 1; /* new connection */ | 1310 path->connect = 1; /* new connection */ |
| 1147 else | 1311 else |
| 1148 path->connect = 0; /* old connection must be powered dow
n */ | 1312 path->connect = 0; /* old connection must be powered dow
n */ |
| 1149 } | 1313 } |
| 1150 | 1314 |
| 1151 if (found) | 1315 if (found) |
| 1152 » » dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP); | 1316 » » dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP); |
| 1153 | 1317 |
| 1154 return 0; | 1318 return 0; |
| 1155 } | 1319 } |
| 1156 | 1320 |
| 1157 /* test and update the power status of a mixer or switch widget */ | 1321 /* test and update the power status of a mixer or switch widget */ |
| 1158 static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, | 1322 static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, |
| 1159 struct snd_kcontrol *kcontrol, int connect) | 1323 struct snd_kcontrol *kcontrol, int connect) |
| 1160 { | 1324 { |
| 1161 struct snd_soc_dapm_path *path; | 1325 struct snd_soc_dapm_path *path; |
| 1162 int found = 0; | 1326 int found = 0; |
| 1163 | 1327 |
| 1164 if (widget->id != snd_soc_dapm_mixer && | 1328 if (widget->id != snd_soc_dapm_mixer && |
| 1165 widget->id != snd_soc_dapm_mixer_named_ctl && | 1329 widget->id != snd_soc_dapm_mixer_named_ctl && |
| 1166 widget->id != snd_soc_dapm_switch) | 1330 widget->id != snd_soc_dapm_switch) |
| 1167 return -ENODEV; | 1331 return -ENODEV; |
| 1168 | 1332 |
| 1169 /* find dapm widget path assoc with kcontrol */ | 1333 /* find dapm widget path assoc with kcontrol */ |
| 1170 » list_for_each_entry(path, &widget->codec->dapm_paths, list) { | 1334 » list_for_each_entry(path, &widget->dapm->card->paths, list) { |
| 1171 if (path->kcontrol != kcontrol) | 1335 if (path->kcontrol != kcontrol) |
| 1172 continue; | 1336 continue; |
| 1173 | 1337 |
| 1174 /* found, now check type */ | 1338 /* found, now check type */ |
| 1175 found = 1; | 1339 found = 1; |
| 1176 path->connect = connect; | 1340 path->connect = connect; |
| 1177 break; | 1341 break; |
| 1178 } | 1342 } |
| 1179 | 1343 |
| 1180 if (found) | 1344 if (found) |
| 1181 » » dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP); | 1345 » » dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP); |
| 1182 | 1346 |
| 1183 return 0; | 1347 return 0; |
| 1184 } | 1348 } |
| 1185 | 1349 |
| 1186 /* show dapm widget status in sys fs */ | 1350 /* show dapm widget status in sys fs */ |
| 1187 static ssize_t dapm_widget_show(struct device *dev, | 1351 static ssize_t dapm_widget_show(struct device *dev, |
| 1188 struct device_attribute *attr, char *buf) | 1352 struct device_attribute *attr, char *buf) |
| 1189 { | 1353 { |
| 1190 struct snd_soc_pcm_runtime *rtd = | 1354 struct snd_soc_pcm_runtime *rtd = |
| 1191 container_of(dev, struct snd_soc_pcm_runtime, dev); | 1355 container_of(dev, struct snd_soc_pcm_runtime, dev); |
| 1192 struct snd_soc_codec *codec =rtd->codec; | 1356 struct snd_soc_codec *codec =rtd->codec; |
| 1193 struct snd_soc_dapm_widget *w; | 1357 struct snd_soc_dapm_widget *w; |
| 1194 int count = 0; | 1358 int count = 0; |
| 1195 char *state = "not set"; | 1359 char *state = "not set"; |
| 1196 | 1360 |
| 1197 » list_for_each_entry(w, &codec->dapm_widgets, list) { | 1361 » list_for_each_entry(w, &codec->card->widgets, list) { |
| 1362 » » if (w->dapm != &codec->dapm) |
| 1363 » » » continue; |
| 1198 | 1364 |
| 1199 /* only display widgets that burnm power */ | 1365 /* only display widgets that burnm power */ |
| 1200 switch (w->id) { | 1366 switch (w->id) { |
| 1201 case snd_soc_dapm_hp: | 1367 case snd_soc_dapm_hp: |
| 1202 case snd_soc_dapm_mic: | 1368 case snd_soc_dapm_mic: |
| 1203 case snd_soc_dapm_spk: | 1369 case snd_soc_dapm_spk: |
| 1204 case snd_soc_dapm_line: | 1370 case snd_soc_dapm_line: |
| 1205 case snd_soc_dapm_micbias: | 1371 case snd_soc_dapm_micbias: |
| 1206 case snd_soc_dapm_dac: | 1372 case snd_soc_dapm_dac: |
| 1207 case snd_soc_dapm_adc: | 1373 case snd_soc_dapm_adc: |
| 1208 case snd_soc_dapm_pga: | 1374 case snd_soc_dapm_pga: |
| 1375 case snd_soc_dapm_out_drv: |
| 1209 case snd_soc_dapm_mixer: | 1376 case snd_soc_dapm_mixer: |
| 1210 case snd_soc_dapm_mixer_named_ctl: | 1377 case snd_soc_dapm_mixer_named_ctl: |
| 1211 case snd_soc_dapm_supply: | 1378 case snd_soc_dapm_supply: |
| 1212 if (w->name) | 1379 if (w->name) |
| 1213 count += sprintf(buf + count, "%s: %s\n", | 1380 count += sprintf(buf + count, "%s: %s\n", |
| 1214 w->name, w->power ? "On":"Off"); | 1381 w->name, w->power ? "On":"Off"); |
| 1215 break; | 1382 break; |
| 1216 default: | 1383 default: |
| 1217 break; | 1384 break; |
| 1218 } | 1385 } |
| 1219 } | 1386 } |
| 1220 | 1387 |
| 1221 » switch (codec->bias_level) { | 1388 » switch (codec->dapm.bias_level) { |
| 1222 case SND_SOC_BIAS_ON: | 1389 case SND_SOC_BIAS_ON: |
| 1223 state = "On"; | 1390 state = "On"; |
| 1224 break; | 1391 break; |
| 1225 case SND_SOC_BIAS_PREPARE: | 1392 case SND_SOC_BIAS_PREPARE: |
| 1226 state = "Prepare"; | 1393 state = "Prepare"; |
| 1227 break; | 1394 break; |
| 1228 case SND_SOC_BIAS_STANDBY: | 1395 case SND_SOC_BIAS_STANDBY: |
| 1229 state = "Standby"; | 1396 state = "Standby"; |
| 1230 break; | 1397 break; |
| 1231 case SND_SOC_BIAS_OFF: | 1398 case SND_SOC_BIAS_OFF: |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1243 { | 1410 { |
| 1244 return device_create_file(dev, &dev_attr_dapm_widget); | 1411 return device_create_file(dev, &dev_attr_dapm_widget); |
| 1245 } | 1412 } |
| 1246 | 1413 |
| 1247 static void snd_soc_dapm_sys_remove(struct device *dev) | 1414 static void snd_soc_dapm_sys_remove(struct device *dev) |
| 1248 { | 1415 { |
| 1249 device_remove_file(dev, &dev_attr_dapm_widget); | 1416 device_remove_file(dev, &dev_attr_dapm_widget); |
| 1250 } | 1417 } |
| 1251 | 1418 |
| 1252 /* free all dapm widgets and resources */ | 1419 /* free all dapm widgets and resources */ |
| 1253 static void dapm_free_widgets(struct snd_soc_codec *codec) | 1420 static void dapm_free_widgets(struct snd_soc_dapm_context *dapm) |
| 1254 { | 1421 { |
| 1255 struct snd_soc_dapm_widget *w, *next_w; | 1422 struct snd_soc_dapm_widget *w, *next_w; |
| 1256 struct snd_soc_dapm_path *p, *next_p; | 1423 struct snd_soc_dapm_path *p, *next_p; |
| 1257 | 1424 |
| 1258 » list_for_each_entry_safe(w, next_w, &codec->dapm_widgets, list) { | 1425 » list_for_each_entry_safe(w, next_w, &dapm->card->widgets, list) { |
| 1426 » » if (w->dapm != dapm) |
| 1427 » » » continue; |
| 1259 list_del(&w->list); | 1428 list_del(&w->list); |
| 1429 /* |
| 1430 * remove source and sink paths associated to this widget. |
| 1431 * While removing the path, remove reference to it from both |
| 1432 * source and sink widgets so that path is removed only once. |
| 1433 */ |
| 1434 list_for_each_entry_safe(p, next_p, &w->sources, list_sink) { |
| 1435 list_del(&p->list_sink); |
| 1436 list_del(&p->list_source); |
| 1437 list_del(&p->list); |
| 1438 kfree(p->long_name); |
| 1439 kfree(p); |
| 1440 } |
| 1441 list_for_each_entry_safe(p, next_p, &w->sinks, list_source) { |
| 1442 list_del(&p->list_sink); |
| 1443 list_del(&p->list_source); |
| 1444 list_del(&p->list); |
| 1445 kfree(p->long_name); |
| 1446 kfree(p); |
| 1447 } |
| 1448 kfree(w->name); |
| 1260 kfree(w); | 1449 kfree(w); |
| 1261 } | 1450 } |
| 1262 | |
| 1263 list_for_each_entry_safe(p, next_p, &codec->dapm_paths, list) { | |
| 1264 list_del(&p->list); | |
| 1265 kfree(p->long_name); | |
| 1266 kfree(p); | |
| 1267 } | |
| 1268 } | 1451 } |
| 1269 | 1452 |
| 1270 static int snd_soc_dapm_set_pin(struct snd_soc_codec *codec, | 1453 static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm, |
| 1271 const char *pin, int status) | 1454 const char *pin, int status) |
| 1272 { | 1455 { |
| 1273 struct snd_soc_dapm_widget *w; | 1456 struct snd_soc_dapm_widget *w; |
| 1274 | 1457 |
| 1275 » list_for_each_entry(w, &codec->dapm_widgets, list) { | 1458 » list_for_each_entry(w, &dapm->card->widgets, list) { |
| 1459 » » if (w->dapm != dapm) |
| 1460 » » » continue; |
| 1276 if (!strcmp(w->name, pin)) { | 1461 if (!strcmp(w->name, pin)) { |
| 1277 » » » pr_debug("dapm: %s: pin %s\n", codec->name, pin); | 1462 » » » dev_dbg(w->dapm->dev, "dapm: pin %s = %d\n", |
| 1463 » » » » pin, status); |
| 1278 w->connected = status; | 1464 w->connected = status; |
| 1279 /* Allow disabling of forced pins */ | 1465 /* Allow disabling of forced pins */ |
| 1280 if (status == 0) | 1466 if (status == 0) |
| 1281 w->force = 0; | 1467 w->force = 0; |
| 1282 return 0; | 1468 return 0; |
| 1283 } | 1469 } |
| 1284 } | 1470 } |
| 1285 | 1471 |
| 1286 » pr_err("dapm: %s: configuring unknown pin %s\n", codec->name, pin); | 1472 » dev_err(dapm->dev, "dapm: unknown pin %s\n", pin); |
| 1287 return -EINVAL; | 1473 return -EINVAL; |
| 1288 } | 1474 } |
| 1289 | 1475 |
| 1290 /** | 1476 /** |
| 1291 * snd_soc_dapm_sync - scan and power dapm paths | 1477 * snd_soc_dapm_sync - scan and power dapm paths |
| 1292 * @codec: audio codec | 1478 * @dapm: DAPM context |
| 1293 * | 1479 * |
| 1294 * Walks all dapm audio paths and powers widgets according to their | 1480 * Walks all dapm audio paths and powers widgets according to their |
| 1295 * stream or path usage. | 1481 * stream or path usage. |
| 1296 * | 1482 * |
| 1297 * Returns 0 for success. | 1483 * Returns 0 for success. |
| 1298 */ | 1484 */ |
| 1299 int snd_soc_dapm_sync(struct snd_soc_codec *codec) | 1485 int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm) |
| 1300 { | 1486 { |
| 1301 » return dapm_power_widgets(codec, SND_SOC_DAPM_STREAM_NOP); | 1487 » return dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP); |
| 1302 } | 1488 } |
| 1303 EXPORT_SYMBOL_GPL(snd_soc_dapm_sync); | 1489 EXPORT_SYMBOL_GPL(snd_soc_dapm_sync); |
| 1304 | 1490 |
| 1305 static int snd_soc_dapm_add_route(struct snd_soc_codec *codec, | 1491 static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm, |
| 1306 const struct snd_soc_dapm_route *route) | 1492 const struct snd_soc_dapm_route *route) |
| 1307 { | 1493 { |
| 1308 struct snd_soc_dapm_path *path; | 1494 struct snd_soc_dapm_path *path; |
| 1309 struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w; | 1495 struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w; |
| 1310 » const char *sink = route->sink; | 1496 » struct snd_soc_dapm_widget *wtsource = NULL, *wtsink = NULL; |
| 1497 » const char *sink; |
| 1311 const char *control = route->control; | 1498 const char *control = route->control; |
| 1312 » const char *source = route->source; | 1499 » const char *source; |
| 1500 » char prefixed_sink[80]; |
| 1501 » char prefixed_source[80]; |
| 1313 int ret = 0; | 1502 int ret = 0; |
| 1314 | 1503 |
| 1315 » /* find src and dest widgets */ | 1504 » if (dapm->codec->name_prefix) { |
| 1316 » list_for_each_entry(w, &codec->dapm_widgets, list) { | 1505 » » snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s", |
| 1506 » » » dapm->codec->name_prefix, route->sink); |
| 1507 » » sink = prefixed_sink; |
| 1508 » » snprintf(prefixed_source, sizeof(prefixed_source), "%s %s", |
| 1509 » » » dapm->codec->name_prefix, route->source); |
| 1510 » » source = prefixed_source; |
| 1511 » } else { |
| 1512 » » sink = route->sink; |
| 1513 » » source = route->source; |
| 1514 » } |
| 1317 | 1515 |
| 1516 /* |
| 1517 * find src and dest widgets over all widgets but favor a widget from |
| 1518 * current DAPM context |
| 1519 */ |
| 1520 list_for_each_entry(w, &dapm->card->widgets, list) { |
| 1318 if (!wsink && !(strcmp(w->name, sink))) { | 1521 if (!wsink && !(strcmp(w->name, sink))) { |
| 1319 » » » wsink = w; | 1522 » » » wtsink = w; |
| 1523 » » » if (w->dapm == dapm) |
| 1524 » » » » wsink = w; |
| 1320 continue; | 1525 continue; |
| 1321 } | 1526 } |
| 1322 if (!wsource && !(strcmp(w->name, source))) { | 1527 if (!wsource && !(strcmp(w->name, source))) { |
| 1323 » » » wsource = w; | 1528 » » » wtsource = w; |
| 1529 » » » if (w->dapm == dapm) |
| 1530 » » » » wsource = w; |
| 1324 } | 1531 } |
| 1325 } | 1532 } |
| 1533 /* use widget from another DAPM context if not found from this */ |
| 1534 if (!wsink) |
| 1535 wsink = wtsink; |
| 1536 if (!wsource) |
| 1537 wsource = wtsource; |
| 1326 | 1538 |
| 1327 if (wsource == NULL || wsink == NULL) | 1539 if (wsource == NULL || wsink == NULL) |
| 1328 return -ENODEV; | 1540 return -ENODEV; |
| 1329 | 1541 |
| 1330 path = kzalloc(sizeof(struct snd_soc_dapm_path), GFP_KERNEL); | 1542 path = kzalloc(sizeof(struct snd_soc_dapm_path), GFP_KERNEL); |
| 1331 if (!path) | 1543 if (!path) |
| 1332 return -ENOMEM; | 1544 return -ENOMEM; |
| 1333 | 1545 |
| 1334 path->source = wsource; | 1546 path->source = wsource; |
| 1335 path->sink = wsink; | 1547 path->sink = wsink; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1349 if (wsource->id == snd_soc_dapm_output) { | 1561 if (wsource->id == snd_soc_dapm_output) { |
| 1350 if (wsink->id == snd_soc_dapm_spk || | 1562 if (wsink->id == snd_soc_dapm_spk || |
| 1351 wsink->id == snd_soc_dapm_hp || | 1563 wsink->id == snd_soc_dapm_hp || |
| 1352 wsink->id == snd_soc_dapm_line || | 1564 wsink->id == snd_soc_dapm_line || |
| 1353 wsink->id == snd_soc_dapm_input) | 1565 wsink->id == snd_soc_dapm_input) |
| 1354 wsource->ext = 1; | 1566 wsource->ext = 1; |
| 1355 } | 1567 } |
| 1356 | 1568 |
| 1357 /* connect static paths */ | 1569 /* connect static paths */ |
| 1358 if (control == NULL) { | 1570 if (control == NULL) { |
| 1359 » » list_add(&path->list, &codec->dapm_paths); | 1571 » » list_add(&path->list, &dapm->card->paths); |
| 1360 list_add(&path->list_sink, &wsink->sources); | 1572 list_add(&path->list_sink, &wsink->sources); |
| 1361 list_add(&path->list_source, &wsource->sinks); | 1573 list_add(&path->list_source, &wsource->sinks); |
| 1362 path->connect = 1; | 1574 path->connect = 1; |
| 1363 return 0; | 1575 return 0; |
| 1364 } | 1576 } |
| 1365 | 1577 |
| 1366 /* connect dynamic paths */ | 1578 /* connect dynamic paths */ |
| 1367 switch(wsink->id) { | 1579 switch(wsink->id) { |
| 1368 case snd_soc_dapm_adc: | 1580 case snd_soc_dapm_adc: |
| 1369 case snd_soc_dapm_dac: | 1581 case snd_soc_dapm_dac: |
| 1370 case snd_soc_dapm_pga: | 1582 case snd_soc_dapm_pga: |
| 1583 case snd_soc_dapm_out_drv: |
| 1371 case snd_soc_dapm_input: | 1584 case snd_soc_dapm_input: |
| 1372 case snd_soc_dapm_output: | 1585 case snd_soc_dapm_output: |
| 1373 case snd_soc_dapm_micbias: | 1586 case snd_soc_dapm_micbias: |
| 1374 case snd_soc_dapm_vmid: | 1587 case snd_soc_dapm_vmid: |
| 1375 case snd_soc_dapm_pre: | 1588 case snd_soc_dapm_pre: |
| 1376 case snd_soc_dapm_post: | 1589 case snd_soc_dapm_post: |
| 1377 case snd_soc_dapm_supply: | 1590 case snd_soc_dapm_supply: |
| 1378 case snd_soc_dapm_aif_in: | 1591 case snd_soc_dapm_aif_in: |
| 1379 case snd_soc_dapm_aif_out: | 1592 case snd_soc_dapm_aif_out: |
| 1380 » » list_add(&path->list, &codec->dapm_paths); | 1593 » » list_add(&path->list, &dapm->card->paths); |
| 1381 list_add(&path->list_sink, &wsink->sources); | 1594 list_add(&path->list_sink, &wsink->sources); |
| 1382 list_add(&path->list_source, &wsource->sinks); | 1595 list_add(&path->list_source, &wsource->sinks); |
| 1383 path->connect = 1; | 1596 path->connect = 1; |
| 1384 return 0; | 1597 return 0; |
| 1385 case snd_soc_dapm_mux: | 1598 case snd_soc_dapm_mux: |
| 1599 case snd_soc_dapm_virt_mux: |
| 1386 case snd_soc_dapm_value_mux: | 1600 case snd_soc_dapm_value_mux: |
| 1387 » » ret = dapm_connect_mux(codec, wsource, wsink, path, control, | 1601 » » ret = dapm_connect_mux(dapm, wsource, wsink, path, control, |
| 1388 &wsink->kcontrols[0]); | 1602 &wsink->kcontrols[0]); |
| 1389 if (ret != 0) | 1603 if (ret != 0) |
| 1390 goto err; | 1604 goto err; |
| 1391 break; | 1605 break; |
| 1392 case snd_soc_dapm_switch: | 1606 case snd_soc_dapm_switch: |
| 1393 case snd_soc_dapm_mixer: | 1607 case snd_soc_dapm_mixer: |
| 1394 case snd_soc_dapm_mixer_named_ctl: | 1608 case snd_soc_dapm_mixer_named_ctl: |
| 1395 » » ret = dapm_connect_mixer(codec, wsource, wsink, path, control); | 1609 » » ret = dapm_connect_mixer(dapm, wsource, wsink, path, control); |
| 1396 if (ret != 0) | 1610 if (ret != 0) |
| 1397 goto err; | 1611 goto err; |
| 1398 break; | 1612 break; |
| 1399 case snd_soc_dapm_hp: | 1613 case snd_soc_dapm_hp: |
| 1400 case snd_soc_dapm_mic: | 1614 case snd_soc_dapm_mic: |
| 1401 case snd_soc_dapm_line: | 1615 case snd_soc_dapm_line: |
| 1402 case snd_soc_dapm_spk: | 1616 case snd_soc_dapm_spk: |
| 1403 » » list_add(&path->list, &codec->dapm_paths); | 1617 » » list_add(&path->list, &dapm->card->paths); |
| 1404 list_add(&path->list_sink, &wsink->sources); | 1618 list_add(&path->list_sink, &wsink->sources); |
| 1405 list_add(&path->list_source, &wsource->sinks); | 1619 list_add(&path->list_source, &wsource->sinks); |
| 1406 path->connect = 0; | 1620 path->connect = 0; |
| 1407 return 0; | 1621 return 0; |
| 1408 } | 1622 } |
| 1409 return 0; | 1623 return 0; |
| 1410 | 1624 |
| 1411 err: | 1625 err: |
| 1412 » printk(KERN_WARNING "asoc: no dapm match for %s --> %s --> %s\n", source
, | 1626 » dev_warn(dapm->dev, "asoc: no dapm match for %s --> %s --> %s\n", |
| 1413 » » control, sink); | 1627 » » source, control, sink); |
| 1414 kfree(path); | 1628 kfree(path); |
| 1415 return ret; | 1629 return ret; |
| 1416 } | 1630 } |
| 1417 | 1631 |
| 1418 /** | 1632 /** |
| 1419 * snd_soc_dapm_add_routes - Add routes between DAPM widgets | 1633 * snd_soc_dapm_add_routes - Add routes between DAPM widgets |
| 1420 * @codec: codec | 1634 * @dapm: DAPM context |
| 1421 * @route: audio routes | 1635 * @route: audio routes |
| 1422 * @num: number of routes | 1636 * @num: number of routes |
| 1423 * | 1637 * |
| 1424 * Connects 2 dapm widgets together via a named audio path. The sink is | 1638 * Connects 2 dapm widgets together via a named audio path. The sink is |
| 1425 * the widget receiving the audio signal, whilst the source is the sender | 1639 * the widget receiving the audio signal, whilst the source is the sender |
| 1426 * of the audio signal. | 1640 * of the audio signal. |
| 1427 * | 1641 * |
| 1428 * Returns 0 for success else error. On error all resources can be freed | 1642 * Returns 0 for success else error. On error all resources can be freed |
| 1429 * with a call to snd_soc_card_free(). | 1643 * with a call to snd_soc_card_free(). |
| 1430 */ | 1644 */ |
| 1431 int snd_soc_dapm_add_routes(struct snd_soc_codec *codec, | 1645 int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm, |
| 1432 const struct snd_soc_dapm_route *route, int num) | 1646 const struct snd_soc_dapm_route *route, int num) |
| 1433 { | 1647 { |
| 1434 int i, ret; | 1648 int i, ret; |
| 1435 | 1649 |
| 1436 for (i = 0; i < num; i++) { | 1650 for (i = 0; i < num; i++) { |
| 1437 » » ret = snd_soc_dapm_add_route(codec, route); | 1651 » » ret = snd_soc_dapm_add_route(dapm, route); |
| 1438 if (ret < 0) { | 1652 if (ret < 0) { |
| 1439 » » » printk(KERN_ERR "Failed to add route %s->%s\n", | 1653 » » » dev_err(dapm->dev, "Failed to add route %s->%s\n", |
| 1440 » » » route->source, | 1654 » » » » route->source, route->sink); |
| 1441 » » » route->sink); | |
| 1442 return ret; | 1655 return ret; |
| 1443 } | 1656 } |
| 1444 route++; | 1657 route++; |
| 1445 } | 1658 } |
| 1446 | 1659 |
| 1447 return 0; | 1660 return 0; |
| 1448 } | 1661 } |
| 1449 EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes); | 1662 EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes); |
| 1450 | 1663 |
| 1451 /** | 1664 /** |
| 1452 * snd_soc_dapm_new_widgets - add new dapm widgets | 1665 * snd_soc_dapm_new_widgets - add new dapm widgets |
| 1453 * @codec: audio codec | 1666 * @dapm: DAPM context |
| 1454 * | 1667 * |
| 1455 * Checks the codec for any new dapm widgets and creates them if found. | 1668 * Checks the codec for any new dapm widgets and creates them if found. |
| 1456 * | 1669 * |
| 1457 * Returns 0 for success. | 1670 * Returns 0 for success. |
| 1458 */ | 1671 */ |
| 1459 int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec) | 1672 int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm) |
| 1460 { | 1673 { |
| 1461 struct snd_soc_dapm_widget *w; | 1674 struct snd_soc_dapm_widget *w; |
| 1675 unsigned int val; |
| 1462 | 1676 |
| 1463 » list_for_each_entry(w, &codec->dapm_widgets, list) | 1677 » list_for_each_entry(w, &dapm->card->widgets, list) |
| 1464 { | 1678 { |
| 1465 if (w->new) | 1679 if (w->new) |
| 1466 continue; | 1680 continue; |
| 1467 | 1681 |
| 1468 switch(w->id) { | 1682 switch(w->id) { |
| 1469 case snd_soc_dapm_switch: | 1683 case snd_soc_dapm_switch: |
| 1470 case snd_soc_dapm_mixer: | 1684 case snd_soc_dapm_mixer: |
| 1471 case snd_soc_dapm_mixer_named_ctl: | 1685 case snd_soc_dapm_mixer_named_ctl: |
| 1472 w->power_check = dapm_generic_check_power; | 1686 w->power_check = dapm_generic_check_power; |
| 1473 » » » dapm_new_mixer(codec, w); | 1687 » » » dapm_new_mixer(dapm, w); |
| 1474 break; | 1688 break; |
| 1475 case snd_soc_dapm_mux: | 1689 case snd_soc_dapm_mux: |
| 1690 case snd_soc_dapm_virt_mux: |
| 1476 case snd_soc_dapm_value_mux: | 1691 case snd_soc_dapm_value_mux: |
| 1477 w->power_check = dapm_generic_check_power; | 1692 w->power_check = dapm_generic_check_power; |
| 1478 » » » dapm_new_mux(codec, w); | 1693 » » » dapm_new_mux(dapm, w); |
| 1479 break; | 1694 break; |
| 1480 case snd_soc_dapm_adc: | 1695 case snd_soc_dapm_adc: |
| 1481 case snd_soc_dapm_aif_out: | 1696 case snd_soc_dapm_aif_out: |
| 1482 w->power_check = dapm_adc_check_power; | 1697 w->power_check = dapm_adc_check_power; |
| 1483 break; | 1698 break; |
| 1484 case snd_soc_dapm_dac: | 1699 case snd_soc_dapm_dac: |
| 1485 case snd_soc_dapm_aif_in: | 1700 case snd_soc_dapm_aif_in: |
| 1486 w->power_check = dapm_dac_check_power; | 1701 w->power_check = dapm_dac_check_power; |
| 1487 break; | 1702 break; |
| 1488 case snd_soc_dapm_pga: | 1703 case snd_soc_dapm_pga: |
| 1704 case snd_soc_dapm_out_drv: |
| 1489 w->power_check = dapm_generic_check_power; | 1705 w->power_check = dapm_generic_check_power; |
| 1490 » » » dapm_new_pga(codec, w); | 1706 » » » dapm_new_pga(dapm, w); |
| 1491 break; | 1707 break; |
| 1492 case snd_soc_dapm_input: | 1708 case snd_soc_dapm_input: |
| 1493 case snd_soc_dapm_output: | 1709 case snd_soc_dapm_output: |
| 1494 case snd_soc_dapm_micbias: | 1710 case snd_soc_dapm_micbias: |
| 1495 case snd_soc_dapm_spk: | 1711 case snd_soc_dapm_spk: |
| 1496 case snd_soc_dapm_hp: | 1712 case snd_soc_dapm_hp: |
| 1497 case snd_soc_dapm_mic: | 1713 case snd_soc_dapm_mic: |
| 1498 case snd_soc_dapm_line: | 1714 case snd_soc_dapm_line: |
| 1499 w->power_check = dapm_generic_check_power; | 1715 w->power_check = dapm_generic_check_power; |
| 1500 break; | 1716 break; |
| 1501 case snd_soc_dapm_supply: | 1717 case snd_soc_dapm_supply: |
| 1502 w->power_check = dapm_supply_check_power; | 1718 w->power_check = dapm_supply_check_power; |
| 1503 case snd_soc_dapm_vmid: | 1719 case snd_soc_dapm_vmid: |
| 1504 case snd_soc_dapm_pre: | 1720 case snd_soc_dapm_pre: |
| 1505 case snd_soc_dapm_post: | 1721 case snd_soc_dapm_post: |
| 1506 break; | 1722 break; |
| 1507 } | 1723 } |
| 1724 |
| 1725 /* Read the initial power state from the device */ |
| 1726 if (w->reg >= 0) { |
| 1727 val = snd_soc_read(w->codec, w->reg); |
| 1728 val &= 1 << w->shift; |
| 1729 if (w->invert) |
| 1730 val = !val; |
| 1731 |
| 1732 if (val) |
| 1733 w->power = 1; |
| 1734 } |
| 1735 |
| 1508 w->new = 1; | 1736 w->new = 1; |
| 1509 } | 1737 } |
| 1510 | 1738 |
| 1511 » dapm_power_widgets(codec, SND_SOC_DAPM_STREAM_NOP); | 1739 » dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP); |
| 1512 return 0; | 1740 return 0; |
| 1513 } | 1741 } |
| 1514 EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets); | 1742 EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets); |
| 1515 | 1743 |
| 1516 /** | 1744 /** |
| 1517 * snd_soc_dapm_get_volsw - dapm mixer get callback | 1745 * snd_soc_dapm_get_volsw - dapm mixer get callback |
| 1518 * @kcontrol: mixer control | 1746 * @kcontrol: mixer control |
| 1519 * @ucontrol: control element information | 1747 * @ucontrol: control element information |
| 1520 * | 1748 * |
| 1521 * Callback to get the value of a dapm mixer control. | 1749 * Callback to get the value of a dapm mixer control. |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1562 * Returns 0 for success. | 1790 * Returns 0 for success. |
| 1563 */ | 1791 */ |
| 1564 int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | 1792 int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, |
| 1565 struct snd_ctl_elem_value *ucontrol) | 1793 struct snd_ctl_elem_value *ucontrol) |
| 1566 { | 1794 { |
| 1567 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); | 1795 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); |
| 1568 struct soc_mixer_control *mc = | 1796 struct soc_mixer_control *mc = |
| 1569 (struct soc_mixer_control *)kcontrol->private_value; | 1797 (struct soc_mixer_control *)kcontrol->private_value; |
| 1570 unsigned int reg = mc->reg; | 1798 unsigned int reg = mc->reg; |
| 1571 unsigned int shift = mc->shift; | 1799 unsigned int shift = mc->shift; |
| 1572 unsigned int rshift = mc->rshift; | |
| 1573 int max = mc->max; | 1800 int max = mc->max; |
| 1574 unsigned int mask = (1 << fls(max)) - 1; | 1801 unsigned int mask = (1 << fls(max)) - 1; |
| 1575 unsigned int invert = mc->invert; | 1802 unsigned int invert = mc->invert; |
| 1576 » unsigned int val, val2, val_mask; | 1803 » unsigned int val; |
| 1577 » int connect; | 1804 » int connect, change; |
| 1578 » int ret; | 1805 » struct snd_soc_dapm_update update; |
| 1579 | 1806 |
| 1580 val = (ucontrol->value.integer.value[0] & mask); | 1807 val = (ucontrol->value.integer.value[0] & mask); |
| 1581 | 1808 |
| 1582 if (invert) | 1809 if (invert) |
| 1583 val = max - val; | 1810 val = max - val; |
| 1584 » val_mask = mask << shift; | 1811 » mask = mask << shift; |
| 1585 val = val << shift; | 1812 val = val << shift; |
| 1586 if (shift != rshift) { | |
| 1587 val2 = (ucontrol->value.integer.value[1] & mask); | |
| 1588 if (invert) | |
| 1589 val2 = max - val2; | |
| 1590 val_mask |= mask << rshift; | |
| 1591 val |= val2 << rshift; | |
| 1592 } | |
| 1593 | 1813 |
| 1594 mutex_lock(&widget->codec->mutex); | 1814 mutex_lock(&widget->codec->mutex); |
| 1595 widget->value = val; | 1815 widget->value = val; |
| 1596 | 1816 |
| 1597 » if (snd_soc_test_bits(widget->codec, reg, val_mask, val)) { | 1817 » change = snd_soc_test_bits(widget->codec, reg, mask, val); |
| 1818 » if (change) { |
| 1598 if (val) | 1819 if (val) |
| 1599 /* new connection */ | 1820 /* new connection */ |
| 1600 connect = invert ? 0:1; | 1821 connect = invert ? 0:1; |
| 1601 else | 1822 else |
| 1602 /* old connection must be powered down */ | 1823 /* old connection must be powered down */ |
| 1603 connect = invert ? 1:0; | 1824 connect = invert ? 1:0; |
| 1604 | 1825 |
| 1826 update.kcontrol = kcontrol; |
| 1827 update.widget = widget; |
| 1828 update.reg = reg; |
| 1829 update.mask = mask; |
| 1830 update.val = val; |
| 1831 widget->dapm->update = &update; |
| 1832 |
| 1605 dapm_mixer_update_power(widget, kcontrol, connect); | 1833 dapm_mixer_update_power(widget, kcontrol, connect); |
| 1834 |
| 1835 widget->dapm->update = NULL; |
| 1606 } | 1836 } |
| 1607 | 1837 |
| 1608 if (widget->event) { | |
| 1609 if (widget->event_flags & SND_SOC_DAPM_PRE_REG) { | |
| 1610 ret = widget->event(widget, kcontrol, | |
| 1611 SND_SOC_DAPM_PRE_REG); | |
| 1612 if (ret < 0) { | |
| 1613 ret = 1; | |
| 1614 goto out; | |
| 1615 } | |
| 1616 } | |
| 1617 ret = snd_soc_update_bits(widget->codec, reg, val_mask, val); | |
| 1618 if (widget->event_flags & SND_SOC_DAPM_POST_REG) | |
| 1619 ret = widget->event(widget, kcontrol, | |
| 1620 SND_SOC_DAPM_POST_REG); | |
| 1621 } else | |
| 1622 ret = snd_soc_update_bits(widget->codec, reg, val_mask, val); | |
| 1623 | |
| 1624 out: | |
| 1625 mutex_unlock(&widget->codec->mutex); | 1838 mutex_unlock(&widget->codec->mutex); |
| 1626 » return ret; | 1839 » return 0; |
| 1627 } | 1840 } |
| 1628 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw); | 1841 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw); |
| 1629 | 1842 |
| 1630 /** | 1843 /** |
| 1631 * snd_soc_dapm_get_enum_double - dapm enumerated double mixer get callback | 1844 * snd_soc_dapm_get_enum_double - dapm enumerated double mixer get callback |
| 1632 * @kcontrol: mixer control | 1845 * @kcontrol: mixer control |
| 1633 * @ucontrol: control element information | 1846 * @ucontrol: control element information |
| 1634 * | 1847 * |
| 1635 * Callback to get the value of a dapm enumerated double mixer control. | 1848 * Callback to get the value of a dapm enumerated double mixer control. |
| 1636 * | 1849 * |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1664 * | 1877 * |
| 1665 * Returns 0 for success. | 1878 * Returns 0 for success. |
| 1666 */ | 1879 */ |
| 1667 int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, | 1880 int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, |
| 1668 struct snd_ctl_elem_value *ucontrol) | 1881 struct snd_ctl_elem_value *ucontrol) |
| 1669 { | 1882 { |
| 1670 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); | 1883 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); |
| 1671 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 1884 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
| 1672 unsigned int val, mux, change; | 1885 unsigned int val, mux, change; |
| 1673 unsigned int mask, bitmask; | 1886 unsigned int mask, bitmask; |
| 1674 » int ret = 0; | 1887 » struct snd_soc_dapm_update update; |
| 1675 | 1888 |
| 1676 for (bitmask = 1; bitmask < e->max; bitmask <<= 1) | 1889 for (bitmask = 1; bitmask < e->max; bitmask <<= 1) |
| 1677 ; | 1890 ; |
| 1678 if (ucontrol->value.enumerated.item[0] > e->max - 1) | 1891 if (ucontrol->value.enumerated.item[0] > e->max - 1) |
| 1679 return -EINVAL; | 1892 return -EINVAL; |
| 1680 mux = ucontrol->value.enumerated.item[0]; | 1893 mux = ucontrol->value.enumerated.item[0]; |
| 1681 val = mux << e->shift_l; | 1894 val = mux << e->shift_l; |
| 1682 mask = (bitmask - 1) << e->shift_l; | 1895 mask = (bitmask - 1) << e->shift_l; |
| 1683 if (e->shift_l != e->shift_r) { | 1896 if (e->shift_l != e->shift_r) { |
| 1684 if (ucontrol->value.enumerated.item[1] > e->max - 1) | 1897 if (ucontrol->value.enumerated.item[1] > e->max - 1) |
| 1685 return -EINVAL; | 1898 return -EINVAL; |
| 1686 val |= ucontrol->value.enumerated.item[1] << e->shift_r; | 1899 val |= ucontrol->value.enumerated.item[1] << e->shift_r; |
| 1687 mask |= (bitmask - 1) << e->shift_r; | 1900 mask |= (bitmask - 1) << e->shift_r; |
| 1688 } | 1901 } |
| 1689 | 1902 |
| 1690 mutex_lock(&widget->codec->mutex); | 1903 mutex_lock(&widget->codec->mutex); |
| 1691 widget->value = val; | 1904 widget->value = val; |
| 1692 change = snd_soc_test_bits(widget->codec, e->reg, mask, val); | 1905 change = snd_soc_test_bits(widget->codec, e->reg, mask, val); |
| 1906 |
| 1907 update.kcontrol = kcontrol; |
| 1908 update.widget = widget; |
| 1909 update.reg = e->reg; |
| 1910 update.mask = mask; |
| 1911 update.val = val; |
| 1912 widget->dapm->update = &update; |
| 1913 |
| 1693 dapm_mux_update_power(widget, kcontrol, change, mux, e); | 1914 dapm_mux_update_power(widget, kcontrol, change, mux, e); |
| 1694 | 1915 |
| 1695 » if (widget->event_flags & SND_SOC_DAPM_PRE_REG) { | 1916 » widget->dapm->update = NULL; |
| 1696 » » ret = widget->event(widget, | |
| 1697 » » » » kcontrol, SND_SOC_DAPM_PRE_REG); | |
| 1698 » » if (ret < 0) | |
| 1699 » » » goto out; | |
| 1700 » } | |
| 1701 | 1917 |
| 1702 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val); | |
| 1703 | |
| 1704 if (widget->event_flags & SND_SOC_DAPM_POST_REG) | |
| 1705 ret = widget->event(widget, | |
| 1706 kcontrol, SND_SOC_DAPM_POST_REG); | |
| 1707 | |
| 1708 out: | |
| 1709 mutex_unlock(&widget->codec->mutex); | 1918 mutex_unlock(&widget->codec->mutex); |
| 1710 » return ret; | 1919 » return change; |
| 1711 } | 1920 } |
| 1712 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); | 1921 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); |
| 1713 | 1922 |
| 1714 /** | 1923 /** |
| 1715 * snd_soc_dapm_get_enum_virt - Get virtual DAPM mux | 1924 * snd_soc_dapm_get_enum_virt - Get virtual DAPM mux |
| 1716 * @kcontrol: mixer control | 1925 * @kcontrol: mixer control |
| 1717 * @ucontrol: control element information | 1926 * @ucontrol: control element information |
| 1718 * | 1927 * |
| 1719 * Returns 0 for success. | 1928 * Returns 0 for success. |
| 1720 */ | 1929 */ |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1812 * | 2021 * |
| 1813 * Returns 0 for success. | 2022 * Returns 0 for success. |
| 1814 */ | 2023 */ |
| 1815 int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, | 2024 int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, |
| 1816 struct snd_ctl_elem_value *ucontrol) | 2025 struct snd_ctl_elem_value *ucontrol) |
| 1817 { | 2026 { |
| 1818 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); | 2027 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); |
| 1819 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 2028 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
| 1820 unsigned int val, mux, change; | 2029 unsigned int val, mux, change; |
| 1821 unsigned int mask; | 2030 unsigned int mask; |
| 1822 » int ret = 0; | 2031 » struct snd_soc_dapm_update update; |
| 1823 | 2032 |
| 1824 if (ucontrol->value.enumerated.item[0] > e->max - 1) | 2033 if (ucontrol->value.enumerated.item[0] > e->max - 1) |
| 1825 return -EINVAL; | 2034 return -EINVAL; |
| 1826 mux = ucontrol->value.enumerated.item[0]; | 2035 mux = ucontrol->value.enumerated.item[0]; |
| 1827 val = e->values[ucontrol->value.enumerated.item[0]] << e->shift_l; | 2036 val = e->values[ucontrol->value.enumerated.item[0]] << e->shift_l; |
| 1828 mask = e->mask << e->shift_l; | 2037 mask = e->mask << e->shift_l; |
| 1829 if (e->shift_l != e->shift_r) { | 2038 if (e->shift_l != e->shift_r) { |
| 1830 if (ucontrol->value.enumerated.item[1] > e->max - 1) | 2039 if (ucontrol->value.enumerated.item[1] > e->max - 1) |
| 1831 return -EINVAL; | 2040 return -EINVAL; |
| 1832 val |= e->values[ucontrol->value.enumerated.item[1]] << e->shift
_r; | 2041 val |= e->values[ucontrol->value.enumerated.item[1]] << e->shift
_r; |
| 1833 mask |= e->mask << e->shift_r; | 2042 mask |= e->mask << e->shift_r; |
| 1834 } | 2043 } |
| 1835 | 2044 |
| 1836 mutex_lock(&widget->codec->mutex); | 2045 mutex_lock(&widget->codec->mutex); |
| 1837 widget->value = val; | 2046 widget->value = val; |
| 1838 change = snd_soc_test_bits(widget->codec, e->reg, mask, val); | 2047 change = snd_soc_test_bits(widget->codec, e->reg, mask, val); |
| 2048 |
| 2049 update.kcontrol = kcontrol; |
| 2050 update.widget = widget; |
| 2051 update.reg = e->reg; |
| 2052 update.mask = mask; |
| 2053 update.val = val; |
| 2054 widget->dapm->update = &update; |
| 2055 |
| 1839 dapm_mux_update_power(widget, kcontrol, change, mux, e); | 2056 dapm_mux_update_power(widget, kcontrol, change, mux, e); |
| 1840 | 2057 |
| 1841 » if (widget->event_flags & SND_SOC_DAPM_PRE_REG) { | 2058 » widget->dapm->update = NULL; |
| 1842 » » ret = widget->event(widget, | |
| 1843 » » » » kcontrol, SND_SOC_DAPM_PRE_REG); | |
| 1844 » » if (ret < 0) | |
| 1845 » » » goto out; | |
| 1846 » } | |
| 1847 | 2059 |
| 1848 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val); | |
| 1849 | |
| 1850 if (widget->event_flags & SND_SOC_DAPM_POST_REG) | |
| 1851 ret = widget->event(widget, | |
| 1852 kcontrol, SND_SOC_DAPM_POST_REG); | |
| 1853 | |
| 1854 out: | |
| 1855 mutex_unlock(&widget->codec->mutex); | 2060 mutex_unlock(&widget->codec->mutex); |
| 1856 » return ret; | 2061 » return change; |
| 1857 } | 2062 } |
| 1858 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double); | 2063 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double); |
| 1859 | 2064 |
| 1860 /** | 2065 /** |
| 1861 * snd_soc_dapm_info_pin_switch - Info for a pin switch | 2066 * snd_soc_dapm_info_pin_switch - Info for a pin switch |
| 1862 * | 2067 * |
| 1863 * @kcontrol: mixer control | 2068 * @kcontrol: mixer control |
| 1864 * @uinfo: control element information | 2069 * @uinfo: control element information |
| 1865 * | 2070 * |
| 1866 * Callback to provide information about a pin switch control. | 2071 * Callback to provide information about a pin switch control. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1885 */ | 2090 */ |
| 1886 int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol, | 2091 int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol, |
| 1887 struct snd_ctl_elem_value *ucontrol) | 2092 struct snd_ctl_elem_value *ucontrol) |
| 1888 { | 2093 { |
| 1889 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 2094 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
| 1890 const char *pin = (const char *)kcontrol->private_value; | 2095 const char *pin = (const char *)kcontrol->private_value; |
| 1891 | 2096 |
| 1892 mutex_lock(&codec->mutex); | 2097 mutex_lock(&codec->mutex); |
| 1893 | 2098 |
| 1894 ucontrol->value.integer.value[0] = | 2099 ucontrol->value.integer.value[0] = |
| 1895 » » snd_soc_dapm_get_pin_status(codec, pin); | 2100 » » snd_soc_dapm_get_pin_status(&codec->dapm, pin); |
| 1896 | 2101 |
| 1897 mutex_unlock(&codec->mutex); | 2102 mutex_unlock(&codec->mutex); |
| 1898 | 2103 |
| 1899 return 0; | 2104 return 0; |
| 1900 } | 2105 } |
| 1901 EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_switch); | 2106 EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_switch); |
| 1902 | 2107 |
| 1903 /** | 2108 /** |
| 1904 * snd_soc_dapm_put_pin_switch - Set information for a pin switch | 2109 * snd_soc_dapm_put_pin_switch - Set information for a pin switch |
| 1905 * | 2110 * |
| 1906 * @kcontrol: mixer control | 2111 * @kcontrol: mixer control |
| 1907 * @ucontrol: Value | 2112 * @ucontrol: Value |
| 1908 */ | 2113 */ |
| 1909 int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol, | 2114 int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol, |
| 1910 struct snd_ctl_elem_value *ucontrol) | 2115 struct snd_ctl_elem_value *ucontrol) |
| 1911 { | 2116 { |
| 1912 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 2117 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
| 1913 const char *pin = (const char *)kcontrol->private_value; | 2118 const char *pin = (const char *)kcontrol->private_value; |
| 1914 | 2119 |
| 1915 mutex_lock(&codec->mutex); | 2120 mutex_lock(&codec->mutex); |
| 1916 | 2121 |
| 1917 if (ucontrol->value.integer.value[0]) | 2122 if (ucontrol->value.integer.value[0]) |
| 1918 » » snd_soc_dapm_enable_pin(codec, pin); | 2123 » » snd_soc_dapm_enable_pin(&codec->dapm, pin); |
| 1919 else | 2124 else |
| 1920 » » snd_soc_dapm_disable_pin(codec, pin); | 2125 » » snd_soc_dapm_disable_pin(&codec->dapm, pin); |
| 1921 | 2126 |
| 1922 » snd_soc_dapm_sync(codec); | 2127 » snd_soc_dapm_sync(&codec->dapm); |
| 1923 | 2128 |
| 1924 mutex_unlock(&codec->mutex); | 2129 mutex_unlock(&codec->mutex); |
| 1925 | 2130 |
| 1926 return 0; | 2131 return 0; |
| 1927 } | 2132 } |
| 1928 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch); | 2133 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch); |
| 1929 | 2134 |
| 1930 /** | 2135 /** |
| 1931 * snd_soc_dapm_new_control - create new dapm control | 2136 * snd_soc_dapm_new_control - create new dapm control |
| 1932 * @codec: audio codec | 2137 * @dapm: DAPM context |
| 1933 * @widget: widget template | 2138 * @widget: widget template |
| 1934 * | 2139 * |
| 1935 * Creates a new dapm control based upon the template. | 2140 * Creates a new dapm control based upon the template. |
| 1936 * | 2141 * |
| 1937 * Returns 0 for success else error. | 2142 * Returns 0 for success else error. |
| 1938 */ | 2143 */ |
| 1939 int snd_soc_dapm_new_control(struct snd_soc_codec *codec, | 2144 int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, |
| 1940 const struct snd_soc_dapm_widget *widget) | 2145 const struct snd_soc_dapm_widget *widget) |
| 1941 { | 2146 { |
| 1942 struct snd_soc_dapm_widget *w; | 2147 struct snd_soc_dapm_widget *w; |
| 2148 size_t name_len; |
| 1943 | 2149 |
| 1944 if ((w = dapm_cnew_widget(widget)) == NULL) | 2150 if ((w = dapm_cnew_widget(widget)) == NULL) |
| 1945 return -ENOMEM; | 2151 return -ENOMEM; |
| 1946 | 2152 |
| 1947 » w->codec = codec; | 2153 » name_len = strlen(widget->name) + 1; |
| 2154 » if (dapm->codec->name_prefix) |
| 2155 » » name_len += 1 + strlen(dapm->codec->name_prefix); |
| 2156 » w->name = kmalloc(name_len, GFP_KERNEL); |
| 2157 » if (w->name == NULL) { |
| 2158 » » kfree(w); |
| 2159 » » return -ENOMEM; |
| 2160 » } |
| 2161 » if (dapm->codec->name_prefix) |
| 2162 » » snprintf(w->name, name_len, "%s %s", |
| 2163 » » » dapm->codec->name_prefix, widget->name); |
| 2164 » else |
| 2165 » » snprintf(w->name, name_len, "%s", widget->name); |
| 2166 |
| 2167 » dapm->n_widgets++; |
| 2168 » w->dapm = dapm; |
| 2169 » w->codec = dapm->codec; |
| 1948 INIT_LIST_HEAD(&w->sources); | 2170 INIT_LIST_HEAD(&w->sources); |
| 1949 INIT_LIST_HEAD(&w->sinks); | 2171 INIT_LIST_HEAD(&w->sinks); |
| 1950 INIT_LIST_HEAD(&w->list); | 2172 INIT_LIST_HEAD(&w->list); |
| 1951 » list_add(&w->list, &codec->dapm_widgets); | 2173 » list_add(&w->list, &dapm->card->widgets); |
| 1952 | 2174 |
| 1953 /* machine layer set ups unconnected pins and insertions */ | 2175 /* machine layer set ups unconnected pins and insertions */ |
| 1954 w->connected = 1; | 2176 w->connected = 1; |
| 1955 return 0; | 2177 return 0; |
| 1956 } | 2178 } |
| 1957 EXPORT_SYMBOL_GPL(snd_soc_dapm_new_control); | 2179 EXPORT_SYMBOL_GPL(snd_soc_dapm_new_control); |
| 1958 | 2180 |
| 1959 /** | 2181 /** |
| 1960 * snd_soc_dapm_new_controls - create new dapm controls | 2182 * snd_soc_dapm_new_controls - create new dapm controls |
| 1961 * @codec: audio codec | 2183 * @dapm: DAPM context |
| 1962 * @widget: widget array | 2184 * @widget: widget array |
| 1963 * @num: number of widgets | 2185 * @num: number of widgets |
| 1964 * | 2186 * |
| 1965 * Creates new DAPM controls based upon the templates. | 2187 * Creates new DAPM controls based upon the templates. |
| 1966 * | 2188 * |
| 1967 * Returns 0 for success else error. | 2189 * Returns 0 for success else error. |
| 1968 */ | 2190 */ |
| 1969 int snd_soc_dapm_new_controls(struct snd_soc_codec *codec, | 2191 int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm, |
| 1970 const struct snd_soc_dapm_widget *widget, | 2192 const struct snd_soc_dapm_widget *widget, |
| 1971 int num) | 2193 int num) |
| 1972 { | 2194 { |
| 1973 int i, ret; | 2195 int i, ret; |
| 1974 | 2196 |
| 1975 for (i = 0; i < num; i++) { | 2197 for (i = 0; i < num; i++) { |
| 1976 » » ret = snd_soc_dapm_new_control(codec, widget); | 2198 » » ret = snd_soc_dapm_new_control(dapm, widget); |
| 1977 if (ret < 0) { | 2199 if (ret < 0) { |
| 1978 » » » printk(KERN_ERR | 2200 » » » dev_err(dapm->dev, |
| 1979 » » » "ASoC: Failed to create DAPM control %s: %d\n", | 2201 » » » » "ASoC: Failed to create DAPM control %s: %d\n", |
| 1980 » » » widget->name, ret); | 2202 » » » » widget->name, ret); |
| 1981 return ret; | 2203 return ret; |
| 1982 } | 2204 } |
| 1983 widget++; | 2205 widget++; |
| 1984 } | 2206 } |
| 1985 return 0; | 2207 return 0; |
| 1986 } | 2208 } |
| 1987 EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls); | 2209 EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls); |
| 1988 | 2210 |
| 1989 | 2211 static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm, |
| 1990 /** | |
| 1991 * snd_soc_dapm_stream_event - send a stream event to the dapm core | |
| 1992 * @codec: audio codec | |
| 1993 * @stream: stream name | |
| 1994 * @event: stream event | |
| 1995 * | |
| 1996 * Sends a stream event to the dapm core. The core then makes any | |
| 1997 * necessary widget power changes. | |
| 1998 * | |
| 1999 * Returns 0 for success else error. | |
| 2000 */ | |
| 2001 int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, | |
| 2002 const char *stream, int event) | 2212 const char *stream, int event) |
| 2003 { | 2213 { |
| 2004 struct snd_soc_codec *codec = rtd->codec; | |
| 2005 struct snd_soc_dapm_widget *w; | 2214 struct snd_soc_dapm_widget *w; |
| 2006 | 2215 |
| 2007 » if (stream == NULL) | 2216 » list_for_each_entry(w, &dapm->card->widgets, list) |
| 2008 » » return 0; | |
| 2009 | |
| 2010 » mutex_lock(&codec->mutex); | |
| 2011 » list_for_each_entry(w, &codec->dapm_widgets, list) | |
| 2012 { | 2217 { |
| 2013 » » if (!w->sname) | 2218 » » if (!w->sname || w->dapm != dapm) |
| 2014 continue; | 2219 continue; |
| 2015 » » pr_debug("widget %s\n %s stream %s event %d\n", | 2220 » » dev_dbg(w->dapm->dev, "widget %s\n %s stream %s event %d\n", |
| 2016 » » » w->name, w->sname, stream, event); | 2221 » » » w->name, w->sname, stream, event); |
| 2017 if (strstr(w->sname, stream)) { | 2222 if (strstr(w->sname, stream)) { |
| 2018 switch(event) { | 2223 switch(event) { |
| 2019 case SND_SOC_DAPM_STREAM_START: | 2224 case SND_SOC_DAPM_STREAM_START: |
| 2020 w->active = 1; | 2225 w->active = 1; |
| 2021 break; | 2226 break; |
| 2022 case SND_SOC_DAPM_STREAM_STOP: | 2227 case SND_SOC_DAPM_STREAM_STOP: |
| 2023 w->active = 0; | 2228 w->active = 0; |
| 2024 break; | 2229 break; |
| 2025 case SND_SOC_DAPM_STREAM_SUSPEND: | 2230 case SND_SOC_DAPM_STREAM_SUSPEND: |
| 2026 case SND_SOC_DAPM_STREAM_RESUME: | 2231 case SND_SOC_DAPM_STREAM_RESUME: |
| 2027 case SND_SOC_DAPM_STREAM_PAUSE_PUSH: | 2232 case SND_SOC_DAPM_STREAM_PAUSE_PUSH: |
| 2028 case SND_SOC_DAPM_STREAM_PAUSE_RELEASE: | 2233 case SND_SOC_DAPM_STREAM_PAUSE_RELEASE: |
| 2029 break; | 2234 break; |
| 2030 } | 2235 } |
| 2031 } | 2236 } |
| 2032 } | 2237 } |
| 2033 | 2238 |
| 2034 » dapm_power_widgets(codec, event); | 2239 » dapm_power_widgets(dapm, event); |
| 2240 } |
| 2241 |
| 2242 /** |
| 2243 * snd_soc_dapm_stream_event - send a stream event to the dapm core |
| 2244 * @rtd: PCM runtime data |
| 2245 * @stream: stream name |
| 2246 * @event: stream event |
| 2247 * |
| 2248 * Sends a stream event to the dapm core. The core then makes any |
| 2249 * necessary widget power changes. |
| 2250 * |
| 2251 * Returns 0 for success else error. |
| 2252 */ |
| 2253 int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, |
| 2254 » const char *stream, int event) |
| 2255 { |
| 2256 » struct snd_soc_codec *codec = rtd->codec; |
| 2257 |
| 2258 » if (stream == NULL) |
| 2259 » » return 0; |
| 2260 |
| 2261 » mutex_lock(&codec->mutex); |
| 2262 » soc_dapm_stream_event(&codec->dapm, stream, event); |
| 2035 mutex_unlock(&codec->mutex); | 2263 mutex_unlock(&codec->mutex); |
| 2036 return 0; | 2264 return 0; |
| 2037 } | 2265 } |
| 2038 EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event); | 2266 EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event); |
| 2039 | 2267 |
| 2040 /** | 2268 /** |
| 2041 * snd_soc_dapm_enable_pin - enable pin. | 2269 * snd_soc_dapm_enable_pin - enable pin. |
| 2042 * @codec: SoC codec | 2270 * @dapm: DAPM context |
| 2043 * @pin: pin name | 2271 * @pin: pin name |
| 2044 * | 2272 * |
| 2045 * Enables input/output pin and its parents or children widgets iff there is | 2273 * Enables input/output pin and its parents or children widgets iff there is |
| 2046 * a valid audio route and active audio stream. | 2274 * a valid audio route and active audio stream. |
| 2047 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to | 2275 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to |
| 2048 * do any widget power switching. | 2276 * do any widget power switching. |
| 2049 */ | 2277 */ |
| 2050 int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, const char *pin) | 2278 int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin) |
| 2051 { | 2279 { |
| 2052 » return snd_soc_dapm_set_pin(codec, pin, 1); | 2280 » return snd_soc_dapm_set_pin(dapm, pin, 1); |
| 2053 } | 2281 } |
| 2054 EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin); | 2282 EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin); |
| 2055 | 2283 |
| 2056 /** | 2284 /** |
| 2057 * snd_soc_dapm_force_enable_pin - force a pin to be enabled | 2285 * snd_soc_dapm_force_enable_pin - force a pin to be enabled |
| 2058 * @codec: SoC codec | 2286 * @dapm: DAPM context |
| 2059 * @pin: pin name | 2287 * @pin: pin name |
| 2060 * | 2288 * |
| 2061 * Enables input/output pin regardless of any other state. This is | 2289 * Enables input/output pin regardless of any other state. This is |
| 2062 * intended for use with microphone bias supplies used in microphone | 2290 * intended for use with microphone bias supplies used in microphone |
| 2063 * jack detection. | 2291 * jack detection. |
| 2064 * | 2292 * |
| 2065 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to | 2293 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to |
| 2066 * do any widget power switching. | 2294 * do any widget power switching. |
| 2067 */ | 2295 */ |
| 2068 int snd_soc_dapm_force_enable_pin(struct snd_soc_codec *codec, const char *pin) | 2296 int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm, |
| 2297 » » » » const char *pin) |
| 2069 { | 2298 { |
| 2070 struct snd_soc_dapm_widget *w; | 2299 struct snd_soc_dapm_widget *w; |
| 2071 | 2300 |
| 2072 » list_for_each_entry(w, &codec->dapm_widgets, list) { | 2301 » list_for_each_entry(w, &dapm->card->widgets, list) { |
| 2302 » » if (w->dapm != dapm) |
| 2303 » » » continue; |
| 2073 if (!strcmp(w->name, pin)) { | 2304 if (!strcmp(w->name, pin)) { |
| 2074 » » » pr_debug("dapm: %s: pin %s\n", codec->name, pin); | 2305 » » » dev_dbg(w->dapm->dev, |
| 2306 » » » » "dapm: force enable pin %s\n", pin); |
| 2075 w->connected = 1; | 2307 w->connected = 1; |
| 2076 w->force = 1; | 2308 w->force = 1; |
| 2077 return 0; | 2309 return 0; |
| 2078 } | 2310 } |
| 2079 } | 2311 } |
| 2080 | 2312 |
| 2081 » pr_err("dapm: %s: configuring unknown pin %s\n", codec->name, pin); | 2313 » dev_err(dapm->dev, "dapm: unknown pin %s\n", pin); |
| 2082 return -EINVAL; | 2314 return -EINVAL; |
| 2083 } | 2315 } |
| 2084 EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin); | 2316 EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin); |
| 2085 | 2317 |
| 2086 /** | 2318 /** |
| 2087 * snd_soc_dapm_disable_pin - disable pin. | 2319 * snd_soc_dapm_disable_pin - disable pin. |
| 2088 * @codec: SoC codec | 2320 * @dapm: DAPM context |
| 2089 * @pin: pin name | 2321 * @pin: pin name |
| 2090 * | 2322 * |
| 2091 * Disables input/output pin and its parents or children widgets. | 2323 * Disables input/output pin and its parents or children widgets. |
| 2092 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to | 2324 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to |
| 2093 * do any widget power switching. | 2325 * do any widget power switching. |
| 2094 */ | 2326 */ |
| 2095 int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, const char *pin) | 2327 int snd_soc_dapm_disable_pin(struct snd_soc_dapm_context *dapm, |
| 2328 » » » const char *pin) |
| 2096 { | 2329 { |
| 2097 » return snd_soc_dapm_set_pin(codec, pin, 0); | 2330 » return snd_soc_dapm_set_pin(dapm, pin, 0); |
| 2098 } | 2331 } |
| 2099 EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin); | 2332 EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin); |
| 2100 | 2333 |
| 2101 /** | 2334 /** |
| 2102 * snd_soc_dapm_nc_pin - permanently disable pin. | 2335 * snd_soc_dapm_nc_pin - permanently disable pin. |
| 2103 * @codec: SoC codec | 2336 * @dapm: DAPM context |
| 2104 * @pin: pin name | 2337 * @pin: pin name |
| 2105 * | 2338 * |
| 2106 * Marks the specified pin as being not connected, disabling it along | 2339 * Marks the specified pin as being not connected, disabling it along |
| 2107 * any parent or child widgets. At present this is identical to | 2340 * any parent or child widgets. At present this is identical to |
| 2108 * snd_soc_dapm_disable_pin() but in future it will be extended to do | 2341 * snd_soc_dapm_disable_pin() but in future it will be extended to do |
| 2109 * additional things such as disabling controls which only affect | 2342 * additional things such as disabling controls which only affect |
| 2110 * paths through the pin. | 2343 * paths through the pin. |
| 2111 * | 2344 * |
| 2112 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to | 2345 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to |
| 2113 * do any widget power switching. | 2346 * do any widget power switching. |
| 2114 */ | 2347 */ |
| 2115 int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, const char *pin) | 2348 int snd_soc_dapm_nc_pin(struct snd_soc_dapm_context *dapm, const char *pin) |
| 2116 { | 2349 { |
| 2117 » return snd_soc_dapm_set_pin(codec, pin, 0); | 2350 » return snd_soc_dapm_set_pin(dapm, pin, 0); |
| 2118 } | 2351 } |
| 2119 EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin); | 2352 EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin); |
| 2120 | 2353 |
| 2121 /** | 2354 /** |
| 2122 * snd_soc_dapm_get_pin_status - get audio pin status | 2355 * snd_soc_dapm_get_pin_status - get audio pin status |
| 2123 * @codec: audio codec | 2356 * @dapm: DAPM context |
| 2124 * @pin: audio signal pin endpoint (or start point) | 2357 * @pin: audio signal pin endpoint (or start point) |
| 2125 * | 2358 * |
| 2126 * Get audio pin status - connected or disconnected. | 2359 * Get audio pin status - connected or disconnected. |
| 2127 * | 2360 * |
| 2128 * Returns 1 for connected otherwise 0. | 2361 * Returns 1 for connected otherwise 0. |
| 2129 */ | 2362 */ |
| 2130 int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, const char *pin) | 2363 int snd_soc_dapm_get_pin_status(struct snd_soc_dapm_context *dapm, |
| 2364 » » » » const char *pin) |
| 2131 { | 2365 { |
| 2132 struct snd_soc_dapm_widget *w; | 2366 struct snd_soc_dapm_widget *w; |
| 2133 | 2367 |
| 2134 » list_for_each_entry(w, &codec->dapm_widgets, list) { | 2368 » list_for_each_entry(w, &dapm->card->widgets, list) { |
| 2369 » » if (w->dapm != dapm) |
| 2370 » » » continue; |
| 2135 if (!strcmp(w->name, pin)) | 2371 if (!strcmp(w->name, pin)) |
| 2136 return w->connected; | 2372 return w->connected; |
| 2137 } | 2373 } |
| 2138 | 2374 |
| 2139 return 0; | 2375 return 0; |
| 2140 } | 2376 } |
| 2141 EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_status); | 2377 EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_status); |
| 2142 | 2378 |
| 2143 /** | 2379 /** |
| 2144 * snd_soc_dapm_ignore_suspend - ignore suspend status for DAPM endpoint | 2380 * snd_soc_dapm_ignore_suspend - ignore suspend status for DAPM endpoint |
| 2145 * @codec: audio codec | 2381 * @dapm: DAPM context |
| 2146 * @pin: audio signal pin endpoint (or start point) | 2382 * @pin: audio signal pin endpoint (or start point) |
| 2147 * | 2383 * |
| 2148 * Mark the given endpoint or pin as ignoring suspend. When the | 2384 * Mark the given endpoint or pin as ignoring suspend. When the |
| 2149 * system is disabled a path between two endpoints flagged as ignoring | 2385 * system is disabled a path between two endpoints flagged as ignoring |
| 2150 * suspend will not be disabled. The path must already be enabled via | 2386 * suspend will not be disabled. The path must already be enabled via |
| 2151 * normal means at suspend time, it will not be turned on if it was not | 2387 * normal means at suspend time, it will not be turned on if it was not |
| 2152 * already enabled. | 2388 * already enabled. |
| 2153 */ | 2389 */ |
| 2154 int snd_soc_dapm_ignore_suspend(struct snd_soc_codec *codec, const char *pin) | 2390 int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm, |
| 2391 » » » » const char *pin) |
| 2155 { | 2392 { |
| 2156 struct snd_soc_dapm_widget *w; | 2393 struct snd_soc_dapm_widget *w; |
| 2157 | 2394 |
| 2158 » list_for_each_entry(w, &codec->dapm_widgets, list) { | 2395 » list_for_each_entry(w, &dapm->card->widgets, list) { |
| 2396 » » if (w->dapm != dapm) |
| 2397 » » » continue; |
| 2159 if (!strcmp(w->name, pin)) { | 2398 if (!strcmp(w->name, pin)) { |
| 2160 w->ignore_suspend = 1; | 2399 w->ignore_suspend = 1; |
| 2161 return 0; | 2400 return 0; |
| 2162 } | 2401 } |
| 2163 } | 2402 } |
| 2164 | 2403 |
| 2165 » pr_err("Unknown DAPM pin: %s\n", pin); | 2404 » dev_err(dapm->dev, "dapm: unknown pin %s\n", pin); |
| 2166 return -EINVAL; | 2405 return -EINVAL; |
| 2167 } | 2406 } |
| 2168 EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend); | 2407 EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend); |
| 2169 | 2408 |
| 2170 /** | 2409 /** |
| 2171 * snd_soc_dapm_free - free dapm resources | 2410 * snd_soc_dapm_free - free dapm resources |
| 2172 * @card: SoC device | 2411 * @card: SoC device |
| 2173 * | 2412 * |
| 2174 * Free all dapm widgets and resources. | 2413 * Free all dapm widgets and resources. |
| 2175 */ | 2414 */ |
| 2176 void snd_soc_dapm_free(struct snd_soc_codec *codec) | 2415 void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm) |
| 2177 { | 2416 { |
| 2178 » snd_soc_dapm_sys_remove(codec->dev); | 2417 » snd_soc_dapm_sys_remove(dapm->dev); |
| 2179 » dapm_free_widgets(codec); | 2418 » dapm_free_widgets(dapm); |
| 2419 » list_del(&dapm->list); |
| 2180 } | 2420 } |
| 2181 EXPORT_SYMBOL_GPL(snd_soc_dapm_free); | 2421 EXPORT_SYMBOL_GPL(snd_soc_dapm_free); |
| 2182 | 2422 |
| 2183 static void soc_dapm_shutdown_codec(struct snd_soc_codec *codec) | 2423 static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm) |
| 2184 { | 2424 { |
| 2185 struct snd_soc_dapm_widget *w; | 2425 struct snd_soc_dapm_widget *w; |
| 2186 LIST_HEAD(down_list); | 2426 LIST_HEAD(down_list); |
| 2187 int powerdown = 0; | 2427 int powerdown = 0; |
| 2188 | 2428 |
| 2189 » list_for_each_entry(w, &codec->dapm_widgets, list) { | 2429 » list_for_each_entry(w, &dapm->card->widgets, list) { |
| 2430 » » if (w->dapm != dapm) |
| 2431 » » » continue; |
| 2190 if (w->power) { | 2432 if (w->power) { |
| 2191 » » » dapm_seq_insert(w, &down_list, dapm_down_seq); | 2433 » » » dapm_seq_insert(w, &down_list, false); |
| 2192 w->power = 0; | 2434 w->power = 0; |
| 2193 powerdown = 1; | 2435 powerdown = 1; |
| 2194 } | 2436 } |
| 2195 } | 2437 } |
| 2196 | 2438 |
| 2197 /* If there were no widgets to power down we're already in | 2439 /* If there were no widgets to power down we're already in |
| 2198 * standby. | 2440 * standby. |
| 2199 */ | 2441 */ |
| 2200 if (powerdown) { | 2442 if (powerdown) { |
| 2201 » » snd_soc_dapm_set_bias_level(NULL, codec, SND_SOC_BIAS_PREPARE); | 2443 » » snd_soc_dapm_set_bias_level(NULL, dapm, SND_SOC_BIAS_PREPARE); |
| 2202 » » dapm_seq_run(codec, &down_list, 0, dapm_down_seq); | 2444 » » dapm_seq_run(dapm, &down_list, 0, false); |
| 2203 » » snd_soc_dapm_set_bias_level(NULL, codec, SND_SOC_BIAS_STANDBY); | 2445 » » snd_soc_dapm_set_bias_level(NULL, dapm, SND_SOC_BIAS_STANDBY); |
| 2204 } | 2446 } |
| 2205 } | 2447 } |
| 2206 | 2448 |
| 2207 /* | 2449 /* |
| 2208 * snd_soc_dapm_shutdown - callback for system shutdown | 2450 * snd_soc_dapm_shutdown - callback for system shutdown |
| 2209 */ | 2451 */ |
| 2210 void snd_soc_dapm_shutdown(struct snd_soc_card *card) | 2452 void snd_soc_dapm_shutdown(struct snd_soc_card *card) |
| 2211 { | 2453 { |
| 2212 struct snd_soc_codec *codec; | 2454 struct snd_soc_codec *codec; |
| 2213 | 2455 |
| 2214 » list_for_each_entry(codec, &card->codec_dev_list, list) | 2456 » list_for_each_entry(codec, &card->codec_dev_list, list) { |
| 2215 » » soc_dapm_shutdown_codec(codec); | 2457 » » soc_dapm_shutdown_codec(&codec->dapm); |
| 2216 | 2458 » » snd_soc_dapm_set_bias_level(card, &codec->dapm, SND_SOC_BIAS_OFF
); |
| 2217 » snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_OFF); | 2459 » } |
| 2218 } | 2460 } |
| 2219 | 2461 |
| 2220 /* Module information */ | 2462 /* Module information */ |
| 2221 MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk"); | 2463 MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk"); |
| 2222 MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC"); | 2464 MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC"); |
| 2223 MODULE_LICENSE("GPL"); | 2465 MODULE_LICENSE("GPL"); |
| OLD | NEW |