aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2011-04-28 19:38:00 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-05-03 14:29:05 -0400
commitfafd2176f72148e83c64a1f818ff33fceed83d08 (patch)
tree6b173694ed6026b09b5cc053604f7388908f6670
parentfad598887dc0d89ffee3e51281a8143beb2ae58c (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.h6
-rw-r--r--sound/soc/soc-dapm.c187
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 */
522struct 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
453err: 484err:
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);
1818int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, 1850int 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);
1857int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, 1890int 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}
1906EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw); 1947EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw);
@@ -1917,7 +1958,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw);
1917int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, 1958int 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);
1945int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, 1987int 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}
1986EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); 2038EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);
@@ -1995,7 +2047,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);
1995int snd_soc_dapm_get_enum_virt(struct snd_kcontrol *kcontrol, 2047int 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);
2013int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, 2066int 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}
2034EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt); 2098EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt);
@@ -2049,7 +2113,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt);
2049int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol, 2113int 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);
2089int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, 2154int 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}
2128EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double); 2203EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double);