diff options
author | Stephen Warren <swarren@nvidia.com> | 2011-04-28 19:38:00 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2011-05-03 14:29:05 -0400 |
commit | fafd2176f72148e83c64a1f818ff33fceed83d08 (patch) | |
tree | 6b173694ed6026b09b5cc053604f7388908f6670 | |
parent | fad598887dc0d89ffee3e51281a8143beb2ae58c (diff) |
ASoC: Store a list of widgets in a DAPM mux/mixer kcontrol
A future change will allow multiple widgets to be affected by the same
control. For example, a single register bit that controls separate muxes
in both the L and R audio paths.
This change updates the code that handles relevant controls to be able
to iterate over a list of affected widgets. Note that only the put
functions need significant modification to implement the iteration; the
get functions do not need to iterate, nor unify the results, since all
affected widgets reference the same kcontrol.
When creating the list of widgets, always create a 1-sized list, since
the control sharing is not implemented in this change.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Acked-by: Liam Girdwood <lrg@ti.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r-- | include/sound/soc-dapm.h | 6 | ||||
-rw-r--r-- | sound/soc/soc-dapm.c | 187 |
2 files changed, 137 insertions, 56 deletions
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index b25bf0ffc947..c46e7d89561d 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h | |||
@@ -518,4 +518,10 @@ struct snd_soc_dapm_context { | |||
518 | #endif | 518 | #endif |
519 | }; | 519 | }; |
520 | 520 | ||
521 | /* A list of widgets associated with an object, typically a snd_kcontrol */ | ||
522 | struct snd_soc_dapm_widget_list { | ||
523 | int num_widgets; | ||
524 | struct snd_soc_dapm_widget *widgets[0]; | ||
525 | }; | ||
526 | |||
521 | #endif | 527 | #endif |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 85b2c94535f4..79b836c1045d 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -333,6 +333,8 @@ static int dapm_new_mixer(struct snd_soc_dapm_context *dapm, | |||
333 | struct snd_soc_dapm_path *path; | 333 | struct snd_soc_dapm_path *path; |
334 | struct snd_card *card = dapm->card->snd_card; | 334 | struct snd_card *card = dapm->card->snd_card; |
335 | const char *prefix; | 335 | const char *prefix; |
336 | struct snd_soc_dapm_widget_list *wlist; | ||
337 | size_t wlistsize; | ||
336 | 338 | ||
337 | if (dapm->codec) | 339 | if (dapm->codec) |
338 | prefix = dapm->codec->name_prefix; | 340 | prefix = dapm->codec->name_prefix; |
@@ -354,6 +356,18 @@ static int dapm_new_mixer(struct snd_soc_dapm_context *dapm, | |||
354 | if (path->name != (char *)w->kcontrol_news[i].name) | 356 | if (path->name != (char *)w->kcontrol_news[i].name) |
355 | continue; | 357 | continue; |
356 | 358 | ||
359 | wlistsize = sizeof(struct snd_soc_dapm_widget_list) + | ||
360 | sizeof(struct snd_soc_dapm_widget *), | ||
361 | wlist = kzalloc(wlistsize, GFP_KERNEL); | ||
362 | if (wlist == NULL) { | ||
363 | dev_err(dapm->dev, | ||
364 | "asoc: can't allocate widget list for %s\n", | ||
365 | w->name); | ||
366 | return -ENOMEM; | ||
367 | } | ||
368 | wlist->num_widgets = 1; | ||
369 | wlist->widgets[0] = w; | ||
370 | |||
357 | /* add dapm control with long name. | 371 | /* add dapm control with long name. |
358 | * for dapm_mixer this is the concatenation of the | 372 | * for dapm_mixer this is the concatenation of the |
359 | * mixer and kcontrol name. | 373 | * mixer and kcontrol name. |
@@ -366,8 +380,10 @@ static int dapm_new_mixer(struct snd_soc_dapm_context *dapm, | |||
366 | 380 | ||
367 | path->long_name = kmalloc(name_len, GFP_KERNEL); | 381 | path->long_name = kmalloc(name_len, GFP_KERNEL); |
368 | 382 | ||
369 | if (path->long_name == NULL) | 383 | if (path->long_name == NULL) { |
384 | kfree(wlist); | ||
370 | return -ENOMEM; | 385 | return -ENOMEM; |
386 | } | ||
371 | 387 | ||
372 | switch (w->id) { | 388 | switch (w->id) { |
373 | default: | 389 | default: |
@@ -389,13 +405,15 @@ static int dapm_new_mixer(struct snd_soc_dapm_context *dapm, | |||
389 | 405 | ||
390 | path->long_name[name_len - 1] = '\0'; | 406 | path->long_name[name_len - 1] = '\0'; |
391 | 407 | ||
392 | path->kcontrol = snd_soc_cnew(&w->kcontrol_news[i], w, | 408 | path->kcontrol = snd_soc_cnew(&w->kcontrol_news[i], |
393 | path->long_name, prefix); | 409 | wlist, path->long_name, |
410 | prefix); | ||
394 | ret = snd_ctl_add(card, path->kcontrol); | 411 | ret = snd_ctl_add(card, path->kcontrol); |
395 | if (ret < 0) { | 412 | if (ret < 0) { |
396 | dev_err(dapm->dev, | 413 | dev_err(dapm->dev, |
397 | "asoc: failed to add dapm kcontrol %s: %d\n", | 414 | "asoc: failed to add dapm kcontrol %s: %d\n", |
398 | path->long_name, ret); | 415 | path->long_name, ret); |
416 | kfree(wlist); | ||
399 | kfree(path->long_name); | 417 | kfree(path->long_name); |
400 | path->long_name = NULL; | 418 | path->long_name = NULL; |
401 | return ret; | 419 | return ret; |
@@ -416,12 +434,25 @@ static int dapm_new_mux(struct snd_soc_dapm_context *dapm, | |||
416 | const char *prefix; | 434 | const char *prefix; |
417 | size_t prefix_len; | 435 | size_t prefix_len; |
418 | int ret = 0; | 436 | int ret = 0; |
437 | struct snd_soc_dapm_widget_list *wlist; | ||
438 | size_t wlistsize; | ||
419 | 439 | ||
420 | if (!w->num_kcontrols) { | 440 | if (!w->num_kcontrols) { |
421 | dev_err(dapm->dev, "asoc: mux %s has no controls\n", w->name); | 441 | dev_err(dapm->dev, "asoc: mux %s has no controls\n", w->name); |
422 | return -EINVAL; | 442 | return -EINVAL; |
423 | } | 443 | } |
424 | 444 | ||
445 | wlistsize = sizeof(struct snd_soc_dapm_widget_list) + | ||
446 | sizeof(struct snd_soc_dapm_widget *), | ||
447 | wlist = kzalloc(wlistsize, GFP_KERNEL); | ||
448 | if (wlist == NULL) { | ||
449 | dev_err(dapm->dev, | ||
450 | "asoc: can't allocate widget list for %s\n", w->name); | ||
451 | return -ENOMEM; | ||
452 | } | ||
453 | wlist->num_widgets = 1; | ||
454 | wlist->widgets[0] = w; | ||
455 | |||
425 | if (dapm->codec) | 456 | if (dapm->codec) |
426 | prefix = dapm->codec->name_prefix; | 457 | prefix = dapm->codec->name_prefix; |
427 | else | 458 | else |
@@ -436,8 +467,8 @@ static int dapm_new_mux(struct snd_soc_dapm_context *dapm, | |||
436 | * process but we're also using the same prefix for widgets so | 467 | * process but we're also using the same prefix for widgets so |
437 | * cut the prefix off the front of the widget name. | 468 | * cut the prefix off the front of the widget name. |
438 | */ | 469 | */ |
439 | kcontrol = snd_soc_cnew(&w->kcontrol_news[0], w, w->name + prefix_len, | 470 | kcontrol = snd_soc_cnew(&w->kcontrol_news[0], wlist, |
440 | prefix); | 471 | w->name + prefix_len, prefix); |
441 | ret = snd_ctl_add(card, kcontrol); | 472 | ret = snd_ctl_add(card, kcontrol); |
442 | 473 | ||
443 | if (ret < 0) | 474 | if (ret < 0) |
@@ -452,6 +483,7 @@ static int dapm_new_mux(struct snd_soc_dapm_context *dapm, | |||
452 | 483 | ||
453 | err: | 484 | err: |
454 | dev_err(dapm->dev, "asoc: failed to add kcontrol %s\n", w->name); | 485 | dev_err(dapm->dev, "asoc: failed to add kcontrol %s\n", w->name); |
486 | kfree(wlist); | ||
455 | return ret; | 487 | return ret; |
456 | } | 488 | } |
457 | 489 | ||
@@ -1818,7 +1850,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets); | |||
1818 | int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, | 1850 | int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, |
1819 | struct snd_ctl_elem_value *ucontrol) | 1851 | struct snd_ctl_elem_value *ucontrol) |
1820 | { | 1852 | { |
1821 | struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); | 1853 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); |
1854 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | ||
1822 | struct soc_mixer_control *mc = | 1855 | struct soc_mixer_control *mc = |
1823 | (struct soc_mixer_control *)kcontrol->private_value; | 1856 | (struct soc_mixer_control *)kcontrol->private_value; |
1824 | unsigned int reg = mc->reg; | 1857 | unsigned int reg = mc->reg; |
@@ -1857,7 +1890,9 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw); | |||
1857 | int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | 1890 | int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, |
1858 | struct snd_ctl_elem_value *ucontrol) | 1891 | struct snd_ctl_elem_value *ucontrol) |
1859 | { | 1892 | { |
1860 | struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); | 1893 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); |
1894 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | ||
1895 | struct snd_soc_codec *codec = widget->codec; | ||
1861 | struct soc_mixer_control *mc = | 1896 | struct soc_mixer_control *mc = |
1862 | (struct soc_mixer_control *)kcontrol->private_value; | 1897 | (struct soc_mixer_control *)kcontrol->private_value; |
1863 | unsigned int reg = mc->reg; | 1898 | unsigned int reg = mc->reg; |
@@ -1868,6 +1903,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | |||
1868 | unsigned int val; | 1903 | unsigned int val; |
1869 | int connect, change; | 1904 | int connect, change; |
1870 | struct snd_soc_dapm_update update; | 1905 | struct snd_soc_dapm_update update; |
1906 | int wi; | ||
1871 | 1907 | ||
1872 | val = (ucontrol->value.integer.value[0] & mask); | 1908 | val = (ucontrol->value.integer.value[0] & mask); |
1873 | 1909 | ||
@@ -1876,31 +1912,36 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | |||
1876 | mask = mask << shift; | 1912 | mask = mask << shift; |
1877 | val = val << shift; | 1913 | val = val << shift; |
1878 | 1914 | ||
1879 | mutex_lock(&widget->codec->mutex); | 1915 | if (val) |
1880 | widget->value = val; | 1916 | /* new connection */ |
1917 | connect = invert ? 0 : 1; | ||
1918 | else | ||
1919 | /* old connection must be powered down */ | ||
1920 | connect = invert ? 1 : 0; | ||
1921 | |||
1922 | mutex_lock(&codec->mutex); | ||
1881 | 1923 | ||
1882 | change = snd_soc_test_bits(widget->codec, reg, mask, val); | 1924 | change = snd_soc_test_bits(widget->codec, reg, mask, val); |
1883 | if (change) { | 1925 | if (change) { |
1884 | if (val) | 1926 | for (wi = 0; wi < wlist->num_widgets; wi++) { |
1885 | /* new connection */ | 1927 | widget = wlist->widgets[wi]; |
1886 | connect = invert ? 0:1; | ||
1887 | else | ||
1888 | /* old connection must be powered down */ | ||
1889 | connect = invert ? 1:0; | ||
1890 | 1928 | ||
1891 | update.kcontrol = kcontrol; | 1929 | widget->value = val; |
1892 | update.widget = widget; | ||
1893 | update.reg = reg; | ||
1894 | update.mask = mask; | ||
1895 | update.val = val; | ||
1896 | widget->dapm->update = &update; | ||
1897 | 1930 | ||
1898 | dapm_mixer_update_power(widget, kcontrol, connect); | 1931 | update.kcontrol = kcontrol; |
1932 | update.widget = widget; | ||
1933 | update.reg = reg; | ||
1934 | update.mask = mask; | ||
1935 | update.val = val; | ||
1936 | widget->dapm->update = &update; | ||
1899 | 1937 | ||
1900 | widget->dapm->update = NULL; | 1938 | dapm_mixer_update_power(widget, kcontrol, connect); |
1939 | |||
1940 | widget->dapm->update = NULL; | ||
1941 | } | ||
1901 | } | 1942 | } |
1902 | 1943 | ||
1903 | mutex_unlock(&widget->codec->mutex); | 1944 | mutex_unlock(&codec->mutex); |
1904 | return 0; | 1945 | return 0; |
1905 | } | 1946 | } |
1906 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw); | 1947 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw); |
@@ -1917,7 +1958,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw); | |||
1917 | int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, | 1958 | int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, |
1918 | struct snd_ctl_elem_value *ucontrol) | 1959 | struct snd_ctl_elem_value *ucontrol) |
1919 | { | 1960 | { |
1920 | struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); | 1961 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); |
1962 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | ||
1921 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 1963 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
1922 | unsigned int val, bitmask; | 1964 | unsigned int val, bitmask; |
1923 | 1965 | ||
@@ -1945,11 +1987,14 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double); | |||
1945 | int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, | 1987 | int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, |
1946 | struct snd_ctl_elem_value *ucontrol) | 1988 | struct snd_ctl_elem_value *ucontrol) |
1947 | { | 1989 | { |
1948 | struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); | 1990 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); |
1991 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | ||
1992 | struct snd_soc_codec *codec = widget->codec; | ||
1949 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 1993 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
1950 | unsigned int val, mux, change; | 1994 | unsigned int val, mux, change; |
1951 | unsigned int mask, bitmask; | 1995 | unsigned int mask, bitmask; |
1952 | struct snd_soc_dapm_update update; | 1996 | struct snd_soc_dapm_update update; |
1997 | int wi; | ||
1953 | 1998 | ||
1954 | for (bitmask = 1; bitmask < e->max; bitmask <<= 1) | 1999 | for (bitmask = 1; bitmask < e->max; bitmask <<= 1) |
1955 | ; | 2000 | ; |
@@ -1965,22 +2010,29 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, | |||
1965 | mask |= (bitmask - 1) << e->shift_r; | 2010 | mask |= (bitmask - 1) << e->shift_r; |
1966 | } | 2011 | } |
1967 | 2012 | ||
1968 | mutex_lock(&widget->codec->mutex); | 2013 | mutex_lock(&codec->mutex); |
1969 | widget->value = val; | 2014 | |
1970 | change = snd_soc_test_bits(widget->codec, e->reg, mask, val); | 2015 | change = snd_soc_test_bits(widget->codec, e->reg, mask, val); |
2016 | if (change) { | ||
2017 | for (wi = 0; wi < wlist->num_widgets; wi++) { | ||
2018 | widget = wlist->widgets[wi]; | ||
1971 | 2019 | ||
1972 | update.kcontrol = kcontrol; | 2020 | widget->value = val; |
1973 | update.widget = widget; | ||
1974 | update.reg = e->reg; | ||
1975 | update.mask = mask; | ||
1976 | update.val = val; | ||
1977 | widget->dapm->update = &update; | ||
1978 | 2021 | ||
1979 | dapm_mux_update_power(widget, kcontrol, change, mux, e); | 2022 | update.kcontrol = kcontrol; |
2023 | update.widget = widget; | ||
2024 | update.reg = e->reg; | ||
2025 | update.mask = mask; | ||
2026 | update.val = val; | ||
2027 | widget->dapm->update = &update; | ||
1980 | 2028 | ||
1981 | widget->dapm->update = NULL; | 2029 | dapm_mux_update_power(widget, kcontrol, change, mux, e); |
1982 | 2030 | ||
1983 | mutex_unlock(&widget->codec->mutex); | 2031 | widget->dapm->update = NULL; |
2032 | } | ||
2033 | } | ||
2034 | |||
2035 | mutex_unlock(&codec->mutex); | ||
1984 | return change; | 2036 | return change; |
1985 | } | 2037 | } |
1986 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); | 2038 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); |
@@ -1995,7 +2047,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); | |||
1995 | int snd_soc_dapm_get_enum_virt(struct snd_kcontrol *kcontrol, | 2047 | int snd_soc_dapm_get_enum_virt(struct snd_kcontrol *kcontrol, |
1996 | struct snd_ctl_elem_value *ucontrol) | 2048 | struct snd_ctl_elem_value *ucontrol) |
1997 | { | 2049 | { |
1998 | struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); | 2050 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); |
2051 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | ||
1999 | 2052 | ||
2000 | ucontrol->value.enumerated.item[0] = widget->value; | 2053 | ucontrol->value.enumerated.item[0] = widget->value; |
2001 | 2054 | ||
@@ -2013,22 +2066,33 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_virt); | |||
2013 | int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, | 2066 | int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, |
2014 | struct snd_ctl_elem_value *ucontrol) | 2067 | struct snd_ctl_elem_value *ucontrol) |
2015 | { | 2068 | { |
2016 | struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); | 2069 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); |
2070 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | ||
2071 | struct snd_soc_codec *codec = widget->codec; | ||
2017 | struct soc_enum *e = | 2072 | struct soc_enum *e = |
2018 | (struct soc_enum *)kcontrol->private_value; | 2073 | (struct soc_enum *)kcontrol->private_value; |
2019 | int change; | 2074 | int change; |
2020 | int ret = 0; | 2075 | int ret = 0; |
2076 | int wi; | ||
2021 | 2077 | ||
2022 | if (ucontrol->value.enumerated.item[0] >= e->max) | 2078 | if (ucontrol->value.enumerated.item[0] >= e->max) |
2023 | return -EINVAL; | 2079 | return -EINVAL; |
2024 | 2080 | ||
2025 | mutex_lock(&widget->codec->mutex); | 2081 | mutex_lock(&codec->mutex); |
2026 | 2082 | ||
2027 | change = widget->value != ucontrol->value.enumerated.item[0]; | 2083 | change = widget->value != ucontrol->value.enumerated.item[0]; |
2028 | widget->value = ucontrol->value.enumerated.item[0]; | 2084 | if (change) { |
2029 | dapm_mux_update_power(widget, kcontrol, change, widget->value, e); | 2085 | for (wi = 0; wi < wlist->num_widgets; wi++) { |
2086 | widget = wlist->widgets[wi]; | ||
2087 | |||
2088 | widget->value = ucontrol->value.enumerated.item[0]; | ||
2089 | |||
2090 | dapm_mux_update_power(widget, kcontrol, change, | ||
2091 | widget->value, e); | ||
2092 | } | ||
2093 | } | ||
2030 | 2094 | ||
2031 | mutex_unlock(&widget->codec->mutex); | 2095 | mutex_unlock(&codec->mutex); |
2032 | return ret; | 2096 | return ret; |
2033 | } | 2097 | } |
2034 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt); | 2098 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt); |
@@ -2049,7 +2113,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt); | |||
2049 | int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol, | 2113 | int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol, |
2050 | struct snd_ctl_elem_value *ucontrol) | 2114 | struct snd_ctl_elem_value *ucontrol) |
2051 | { | 2115 | { |
2052 | struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); | 2116 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); |
2117 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | ||
2053 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 2118 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
2054 | unsigned int reg_val, val, mux; | 2119 | unsigned int reg_val, val, mux; |
2055 | 2120 | ||
@@ -2089,11 +2154,14 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_value_enum_double); | |||
2089 | int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, | 2154 | int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, |
2090 | struct snd_ctl_elem_value *ucontrol) | 2155 | struct snd_ctl_elem_value *ucontrol) |
2091 | { | 2156 | { |
2092 | struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); | 2157 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); |
2158 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | ||
2159 | struct snd_soc_codec *codec = widget->codec; | ||
2093 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 2160 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
2094 | unsigned int val, mux, change; | 2161 | unsigned int val, mux, change; |
2095 | unsigned int mask; | 2162 | unsigned int mask; |
2096 | struct snd_soc_dapm_update update; | 2163 | struct snd_soc_dapm_update update; |
2164 | int wi; | ||
2097 | 2165 | ||
2098 | if (ucontrol->value.enumerated.item[0] > e->max - 1) | 2166 | if (ucontrol->value.enumerated.item[0] > e->max - 1) |
2099 | return -EINVAL; | 2167 | return -EINVAL; |
@@ -2107,22 +2175,29 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, | |||
2107 | mask |= e->mask << e->shift_r; | 2175 | mask |= e->mask << e->shift_r; |
2108 | } | 2176 | } |
2109 | 2177 | ||
2110 | mutex_lock(&widget->codec->mutex); | 2178 | mutex_lock(&codec->mutex); |
2111 | widget->value = val; | 2179 | |
2112 | change = snd_soc_test_bits(widget->codec, e->reg, mask, val); | 2180 | change = snd_soc_test_bits(widget->codec, e->reg, mask, val); |
2181 | if (change) { | ||
2182 | for (wi = 0; wi < wlist->num_widgets; wi++) { | ||
2183 | widget = wlist->widgets[wi]; | ||
2113 | 2184 | ||
2114 | update.kcontrol = kcontrol; | 2185 | widget->value = val; |
2115 | update.widget = widget; | ||
2116 | update.reg = e->reg; | ||
2117 | update.mask = mask; | ||
2118 | update.val = val; | ||
2119 | widget->dapm->update = &update; | ||
2120 | 2186 | ||
2121 | dapm_mux_update_power(widget, kcontrol, change, mux, e); | 2187 | update.kcontrol = kcontrol; |
2188 | update.widget = widget; | ||
2189 | update.reg = e->reg; | ||
2190 | update.mask = mask; | ||
2191 | update.val = val; | ||
2192 | widget->dapm->update = &update; | ||
2122 | 2193 | ||
2123 | widget->dapm->update = NULL; | 2194 | dapm_mux_update_power(widget, kcontrol, change, mux, e); |
2124 | 2195 | ||
2125 | mutex_unlock(&widget->codec->mutex); | 2196 | widget->dapm->update = NULL; |
2197 | } | ||
2198 | } | ||
2199 | |||
2200 | mutex_unlock(&codec->mutex); | ||
2126 | return change; | 2201 | return change; |
2127 | } | 2202 | } |
2128 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double); | 2203 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double); |