aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-dapm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/soc-dapm.c')
-rw-r--r--sound/soc/soc-dapm.c164
1 files changed, 143 insertions, 21 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 89eae93445c..f7a13f72052 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -35,6 +35,7 @@
35#include <linux/debugfs.h> 35#include <linux/debugfs.h>
36#include <linux/pm_runtime.h> 36#include <linux/pm_runtime.h>
37#include <linux/regulator/consumer.h> 37#include <linux/regulator/consumer.h>
38#include <linux/clk.h>
38#include <linux/slab.h> 39#include <linux/slab.h>
39#include <sound/core.h> 40#include <sound/core.h>
40#include <sound/pcm.h> 41#include <sound/pcm.h>
@@ -51,6 +52,7 @@ static int dapm_up_seq[] = {
51 [snd_soc_dapm_pre] = 0, 52 [snd_soc_dapm_pre] = 0,
52 [snd_soc_dapm_supply] = 1, 53 [snd_soc_dapm_supply] = 1,
53 [snd_soc_dapm_regulator_supply] = 1, 54 [snd_soc_dapm_regulator_supply] = 1,
55 [snd_soc_dapm_clock_supply] = 1,
54 [snd_soc_dapm_micbias] = 2, 56 [snd_soc_dapm_micbias] = 2,
55 [snd_soc_dapm_dai_link] = 2, 57 [snd_soc_dapm_dai_link] = 2,
56 [snd_soc_dapm_dai] = 3, 58 [snd_soc_dapm_dai] = 3,
@@ -92,6 +94,7 @@ static int dapm_down_seq[] = {
92 [snd_soc_dapm_aif_out] = 10, 94 [snd_soc_dapm_aif_out] = 10,
93 [snd_soc_dapm_dai] = 10, 95 [snd_soc_dapm_dai] = 10,
94 [snd_soc_dapm_dai_link] = 11, 96 [snd_soc_dapm_dai_link] = 11,
97 [snd_soc_dapm_clock_supply] = 12,
95 [snd_soc_dapm_regulator_supply] = 12, 98 [snd_soc_dapm_regulator_supply] = 12,
96 [snd_soc_dapm_supply] = 12, 99 [snd_soc_dapm_supply] = 12,
97 [snd_soc_dapm_post] = 13, 100 [snd_soc_dapm_post] = 13,
@@ -391,6 +394,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
391 case snd_soc_dapm_vmid: 394 case snd_soc_dapm_vmid:
392 case snd_soc_dapm_supply: 395 case snd_soc_dapm_supply:
393 case snd_soc_dapm_regulator_supply: 396 case snd_soc_dapm_regulator_supply:
397 case snd_soc_dapm_clock_supply:
394 case snd_soc_dapm_aif_in: 398 case snd_soc_dapm_aif_in:
395 case snd_soc_dapm_aif_out: 399 case snd_soc_dapm_aif_out:
396 case snd_soc_dapm_dai: 400 case snd_soc_dapm_dai:
@@ -764,6 +768,7 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
764 switch (widget->id) { 768 switch (widget->id) {
765 case snd_soc_dapm_supply: 769 case snd_soc_dapm_supply:
766 case snd_soc_dapm_regulator_supply: 770 case snd_soc_dapm_regulator_supply:
771 case snd_soc_dapm_clock_supply:
767 return 0; 772 return 0;
768 default: 773 default:
769 break; 774 break;
@@ -850,6 +855,7 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
850 switch (widget->id) { 855 switch (widget->id) {
851 case snd_soc_dapm_supply: 856 case snd_soc_dapm_supply:
852 case snd_soc_dapm_regulator_supply: 857 case snd_soc_dapm_regulator_supply:
858 case snd_soc_dapm_clock_supply:
853 return 0; 859 return 0;
854 default: 860 default:
855 break; 861 break;
@@ -996,6 +1002,27 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w,
996} 1002}
997EXPORT_SYMBOL_GPL(dapm_regulator_event); 1003EXPORT_SYMBOL_GPL(dapm_regulator_event);
998 1004
1005/*
1006 * Handler for clock supply widget.
1007 */
1008int dapm_clock_event(struct snd_soc_dapm_widget *w,
1009 struct snd_kcontrol *kcontrol, int event)
1010{
1011 if (!w->clk)
1012 return -EIO;
1013
1014#ifdef CONFIG_HAVE_CLK
1015 if (SND_SOC_DAPM_EVENT_ON(event)) {
1016 return clk_enable(w->clk);
1017 } else {
1018 clk_disable(w->clk);
1019 return 0;
1020 }
1021#endif
1022 return 0;
1023}
1024EXPORT_SYMBOL_GPL(dapm_clock_event);
1025
999static int dapm_widget_power_check(struct snd_soc_dapm_widget *w) 1026static int dapm_widget_power_check(struct snd_soc_dapm_widget *w)
1000{ 1027{
1001 if (w->power_checked) 1028 if (w->power_checked)
@@ -1487,6 +1514,7 @@ static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power,
1487 switch (w->id) { 1514 switch (w->id) {
1488 case snd_soc_dapm_supply: 1515 case snd_soc_dapm_supply:
1489 case snd_soc_dapm_regulator_supply: 1516 case snd_soc_dapm_regulator_supply:
1517 case snd_soc_dapm_clock_supply:
1490 /* Supplies can't affect their outputs, only their inputs */ 1518 /* Supplies can't affect their outputs, only their inputs */
1491 break; 1519 break;
1492 default: 1520 default:
@@ -1587,6 +1615,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
1587 break; 1615 break;
1588 case snd_soc_dapm_supply: 1616 case snd_soc_dapm_supply:
1589 case snd_soc_dapm_regulator_supply: 1617 case snd_soc_dapm_regulator_supply:
1618 case snd_soc_dapm_clock_supply:
1590 case snd_soc_dapm_micbias: 1619 case snd_soc_dapm_micbias:
1591 if (d->target_bias_level < SND_SOC_BIAS_STANDBY) 1620 if (d->target_bias_level < SND_SOC_BIAS_STANDBY)
1592 d->target_bias_level = SND_SOC_BIAS_STANDBY; 1621 d->target_bias_level = SND_SOC_BIAS_STANDBY;
@@ -1941,6 +1970,7 @@ static ssize_t dapm_widget_show(struct device *dev,
1941 case snd_soc_dapm_mixer_named_ctl: 1970 case snd_soc_dapm_mixer_named_ctl:
1942 case snd_soc_dapm_supply: 1971 case snd_soc_dapm_supply:
1943 case snd_soc_dapm_regulator_supply: 1972 case snd_soc_dapm_regulator_supply:
1973 case snd_soc_dapm_clock_supply:
1944 if (w->name) 1974 if (w->name)
1945 count += sprintf(buf + count, "%s: %s\n", 1975 count += sprintf(buf + count, "%s: %s\n",
1946 w->name, w->power ? "On":"Off"); 1976 w->name, w->power ? "On":"Off");
@@ -2187,6 +2217,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
2187 case snd_soc_dapm_post: 2217 case snd_soc_dapm_post:
2188 case snd_soc_dapm_supply: 2218 case snd_soc_dapm_supply:
2189 case snd_soc_dapm_regulator_supply: 2219 case snd_soc_dapm_regulator_supply:
2220 case snd_soc_dapm_clock_supply:
2190 case snd_soc_dapm_aif_in: 2221 case snd_soc_dapm_aif_in:
2191 case snd_soc_dapm_aif_out: 2222 case snd_soc_dapm_aif_out:
2192 case snd_soc_dapm_dai: 2223 case snd_soc_dapm_dai:
@@ -2221,6 +2252,10 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
2221 path->connect = 0; 2252 path->connect = 0;
2222 return 0; 2253 return 0;
2223 } 2254 }
2255
2256 dapm_mark_dirty(wsource, "Route added");
2257 dapm_mark_dirty(wsink, "Route added");
2258
2224 return 0; 2259 return 0;
2225 2260
2226err: 2261err:
@@ -2230,6 +2265,59 @@ err:
2230 return ret; 2265 return ret;
2231} 2266}
2232 2267
2268static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm,
2269 const struct snd_soc_dapm_route *route)
2270{
2271 struct snd_soc_dapm_path *path, *p;
2272 const char *sink;
2273 const char *source;
2274 char prefixed_sink[80];
2275 char prefixed_source[80];
2276
2277 if (route->control) {
2278 dev_err(dapm->dev,
2279 "Removal of routes with controls not supported\n");
2280 return -EINVAL;
2281 }
2282
2283 if (dapm->codec && dapm->codec->name_prefix) {
2284 snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s",
2285 dapm->codec->name_prefix, route->sink);
2286 sink = prefixed_sink;
2287 snprintf(prefixed_source, sizeof(prefixed_source), "%s %s",
2288 dapm->codec->name_prefix, route->source);
2289 source = prefixed_source;
2290 } else {
2291 sink = route->sink;
2292 source = route->source;
2293 }
2294
2295 path = NULL;
2296 list_for_each_entry(p, &dapm->card->paths, list) {
2297 if (strcmp(p->source->name, source) != 0)
2298 continue;
2299 if (strcmp(p->sink->name, sink) != 0)
2300 continue;
2301 path = p;
2302 break;
2303 }
2304
2305 if (path) {
2306 dapm_mark_dirty(path->source, "Route removed");
2307 dapm_mark_dirty(path->sink, "Route removed");
2308
2309 list_del(&path->list);
2310 list_del(&path->list_sink);
2311 list_del(&path->list_source);
2312 kfree(path);
2313 } else {
2314 dev_warn(dapm->dev, "Route %s->%s does not exist\n",
2315 source, sink);
2316 }
2317
2318 return 0;
2319}
2320
2233/** 2321/**
2234 * snd_soc_dapm_add_routes - Add routes between DAPM widgets 2322 * snd_soc_dapm_add_routes - Add routes between DAPM widgets
2235 * @dapm: DAPM context 2323 * @dapm: DAPM context
@@ -2246,15 +2334,15 @@ err:
2246int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm, 2334int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm,
2247 const struct snd_soc_dapm_route *route, int num) 2335 const struct snd_soc_dapm_route *route, int num)
2248{ 2336{
2249 int i, ret = 0; 2337 int i, r, ret = 0;
2250 2338
2251 mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); 2339 mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
2252 for (i = 0; i < num; i++) { 2340 for (i = 0; i < num; i++) {
2253 ret = snd_soc_dapm_add_route(dapm, route); 2341 r = snd_soc_dapm_add_route(dapm, route);
2254 if (ret < 0) { 2342 if (r < 0) {
2255 dev_err(dapm->dev, "Failed to add route %s->%s\n", 2343 dev_err(dapm->dev, "Failed to add route %s->%s\n",
2256 route->source, route->sink); 2344 route->source, route->sink);
2257 break; 2345 ret = r;
2258 } 2346 }
2259 route++; 2347 route++;
2260 } 2348 }
@@ -2264,6 +2352,30 @@ int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm,
2264} 2352}
2265EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes); 2353EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes);
2266 2354
2355/**
2356 * snd_soc_dapm_del_routes - Remove routes between DAPM widgets
2357 * @dapm: DAPM context
2358 * @route: audio routes
2359 * @num: number of routes
2360 *
2361 * Removes routes from the DAPM context.
2362 */
2363int snd_soc_dapm_del_routes(struct snd_soc_dapm_context *dapm,
2364 const struct snd_soc_dapm_route *route, int num)
2365{
2366 int i, ret = 0;
2367
2368 mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
2369 for (i = 0; i < num; i++) {
2370 snd_soc_dapm_del_route(dapm, route);
2371 route++;
2372 }
2373 mutex_unlock(&dapm->card->dapm_mutex);
2374
2375 return ret;
2376}
2377EXPORT_SYMBOL_GPL(snd_soc_dapm_del_routes);
2378
2267static int snd_soc_dapm_weak_route(struct snd_soc_dapm_context *dapm, 2379static int snd_soc_dapm_weak_route(struct snd_soc_dapm_context *dapm,
2268 const struct snd_soc_dapm_route *route) 2380 const struct snd_soc_dapm_route *route)
2269{ 2381{
@@ -2434,23 +2546,20 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
2434 (struct soc_mixer_control *)kcontrol->private_value; 2546 (struct soc_mixer_control *)kcontrol->private_value;
2435 unsigned int reg = mc->reg; 2547 unsigned int reg = mc->reg;
2436 unsigned int shift = mc->shift; 2548 unsigned int shift = mc->shift;
2437 unsigned int rshift = mc->rshift;
2438 int max = mc->max; 2549 int max = mc->max;
2439 unsigned int invert = mc->invert;
2440 unsigned int mask = (1 << fls(max)) - 1; 2550 unsigned int mask = (1 << fls(max)) - 1;
2551 unsigned int invert = mc->invert;
2552
2553 if (snd_soc_volsw_is_stereo(mc))
2554 dev_warn(widget->dapm->dev,
2555 "Control '%s' is stereo, which is not supported\n",
2556 kcontrol->id.name);
2441 2557
2442 ucontrol->value.integer.value[0] = 2558 ucontrol->value.integer.value[0] =
2443 (snd_soc_read(widget->codec, reg) >> shift) & mask; 2559 (snd_soc_read(widget->codec, reg) >> shift) & mask;
2444 if (shift != rshift) 2560 if (invert)
2445 ucontrol->value.integer.value[1] =
2446 (snd_soc_read(widget->codec, reg) >> rshift) & mask;
2447 if (invert) {
2448 ucontrol->value.integer.value[0] = 2561 ucontrol->value.integer.value[0] =
2449 max - ucontrol->value.integer.value[0]; 2562 max - ucontrol->value.integer.value[0];
2450 if (shift != rshift)
2451 ucontrol->value.integer.value[1] =
2452 max - ucontrol->value.integer.value[1];
2453 }
2454 2563
2455 return 0; 2564 return 0;
2456} 2565}
@@ -2484,20 +2593,19 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
2484 struct snd_soc_dapm_update update; 2593 struct snd_soc_dapm_update update;
2485 int wi; 2594 int wi;
2486 2595
2596 if (snd_soc_volsw_is_stereo(mc))
2597 dev_warn(widget->dapm->dev,
2598 "Control '%s' is stereo, which is not supported\n",
2599 kcontrol->id.name);
2600
2487 val = (ucontrol->value.integer.value[0] & mask); 2601 val = (ucontrol->value.integer.value[0] & mask);
2602 connect = !!val;
2488 2603
2489 if (invert) 2604 if (invert)
2490 val = max - val; 2605 val = max - val;
2491 mask = mask << shift; 2606 mask = mask << shift;
2492 val = val << shift; 2607 val = val << shift;
2493 2608
2494 if (val)
2495 /* new connection */
2496 connect = invert ? 0 : 1;
2497 else
2498 /* old connection must be powered down */
2499 connect = invert ? 1 : 0;
2500
2501 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); 2609 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2502 2610
2503 change = snd_soc_test_bits(widget->codec, reg, mask, val); 2611 change = snd_soc_test_bits(widget->codec, reg, mask, val);
@@ -2873,6 +2981,19 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
2873 return NULL; 2981 return NULL;
2874 } 2982 }
2875 break; 2983 break;
2984 case snd_soc_dapm_clock_supply:
2985#ifdef CONFIG_CLKDEV_LOOKUP
2986 w->clk = devm_clk_get(dapm->dev, w->name);
2987 if (IS_ERR(w->clk)) {
2988 ret = PTR_ERR(w->clk);
2989 dev_err(dapm->dev, "Failed to request %s: %d\n",
2990 w->name, ret);
2991 return NULL;
2992 }
2993#else
2994 return NULL;
2995#endif
2996 break;
2876 default: 2997 default:
2877 break; 2998 break;
2878 } 2999 }
@@ -2924,6 +3045,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
2924 break; 3045 break;
2925 case snd_soc_dapm_supply: 3046 case snd_soc_dapm_supply:
2926 case snd_soc_dapm_regulator_supply: 3047 case snd_soc_dapm_regulator_supply:
3048 case snd_soc_dapm_clock_supply:
2927 w->power_check = dapm_supply_check_power; 3049 w->power_check = dapm_supply_check_power;
2928 break; 3050 break;
2929 case snd_soc_dapm_dai: 3051 case snd_soc_dapm_dai: