diff options
Diffstat (limited to 'sound/soc/soc-core.c')
-rw-r--r-- | sound/soc/soc-core.c | 143 |
1 files changed, 93 insertions, 50 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 83f1190293a8..462e635dfc74 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -4,8 +4,7 @@ | |||
4 | * Copyright 2005 Wolfson Microelectronics PLC. | 4 | * Copyright 2005 Wolfson Microelectronics PLC. |
5 | * Copyright 2005 Openedhand Ltd. | 5 | * Copyright 2005 Openedhand Ltd. |
6 | * | 6 | * |
7 | * Author: Liam Girdwood | 7 | * Author: Liam Girdwood <lrg@slimlogic.co.uk> |
8 | * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com | ||
9 | * with code, comments and ideas from :- | 8 | * with code, comments and ideas from :- |
10 | * Richard Purdie <richard@openedhand.com> | 9 | * Richard Purdie <richard@openedhand.com> |
11 | * | 10 | * |
@@ -340,6 +339,12 @@ static int soc_codec_close(struct snd_pcm_substream *substream) | |||
340 | } | 339 | } |
341 | codec->active--; | 340 | codec->active--; |
342 | 341 | ||
342 | /* Muting the DAC suppresses artifacts caused during digital | ||
343 | * shutdown, for example from stopping clocks. | ||
344 | */ | ||
345 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
346 | snd_soc_dai_digital_mute(codec_dai, 1); | ||
347 | |||
343 | if (cpu_dai->ops.shutdown) | 348 | if (cpu_dai->ops.shutdown) |
344 | cpu_dai->ops.shutdown(substream); | 349 | cpu_dai->ops.shutdown(substream); |
345 | 350 | ||
@@ -970,9 +975,29 @@ static ssize_t codec_reg_show(struct device *dev, | |||
970 | step = codec->reg_cache_step; | 975 | step = codec->reg_cache_step; |
971 | 976 | ||
972 | count += sprintf(buf, "%s registers\n", codec->name); | 977 | count += sprintf(buf, "%s registers\n", codec->name); |
973 | for (i = 0; i < codec->reg_cache_size; i += step) | 978 | for (i = 0; i < codec->reg_cache_size; i += step) { |
974 | count += sprintf(buf + count, "%2x: %4x\n", i, | 979 | count += sprintf(buf + count, "%2x: ", i); |
975 | codec->read(codec, i)); | 980 | if (count >= PAGE_SIZE - 1) |
981 | break; | ||
982 | |||
983 | if (codec->display_register) | ||
984 | count += codec->display_register(codec, buf + count, | ||
985 | PAGE_SIZE - count, i); | ||
986 | else | ||
987 | count += snprintf(buf + count, PAGE_SIZE - count, | ||
988 | "%4x", codec->read(codec, i)); | ||
989 | |||
990 | if (count >= PAGE_SIZE - 1) | ||
991 | break; | ||
992 | |||
993 | count += snprintf(buf + count, PAGE_SIZE - count, "\n"); | ||
994 | if (count >= PAGE_SIZE - 1) | ||
995 | break; | ||
996 | } | ||
997 | |||
998 | /* Truncate count; min() would cause a warning */ | ||
999 | if (count >= PAGE_SIZE) | ||
1000 | count = PAGE_SIZE - 1; | ||
976 | 1001 | ||
977 | return count; | 1002 | return count; |
978 | } | 1003 | } |
@@ -1296,10 +1321,10 @@ int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol, | |||
1296 | 1321 | ||
1297 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 1322 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
1298 | uinfo->count = e->shift_l == e->shift_r ? 1 : 2; | 1323 | uinfo->count = e->shift_l == e->shift_r ? 1 : 2; |
1299 | uinfo->value.enumerated.items = e->mask; | 1324 | uinfo->value.enumerated.items = e->max; |
1300 | 1325 | ||
1301 | if (uinfo->value.enumerated.item > e->mask - 1) | 1326 | if (uinfo->value.enumerated.item > e->max - 1) |
1302 | uinfo->value.enumerated.item = e->mask - 1; | 1327 | uinfo->value.enumerated.item = e->max - 1; |
1303 | strcpy(uinfo->value.enumerated.name, | 1328 | strcpy(uinfo->value.enumerated.name, |
1304 | e->texts[uinfo->value.enumerated.item]); | 1329 | e->texts[uinfo->value.enumerated.item]); |
1305 | return 0; | 1330 | return 0; |
@@ -1322,7 +1347,7 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol, | |||
1322 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 1347 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
1323 | unsigned short val, bitmask; | 1348 | unsigned short val, bitmask; |
1324 | 1349 | ||
1325 | for (bitmask = 1; bitmask < e->mask; bitmask <<= 1) | 1350 | for (bitmask = 1; bitmask < e->max; bitmask <<= 1) |
1326 | ; | 1351 | ; |
1327 | val = snd_soc_read(codec, e->reg); | 1352 | val = snd_soc_read(codec, e->reg); |
1328 | ucontrol->value.enumerated.item[0] | 1353 | ucontrol->value.enumerated.item[0] |
@@ -1352,14 +1377,14 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, | |||
1352 | unsigned short val; | 1377 | unsigned short val; |
1353 | unsigned short mask, bitmask; | 1378 | unsigned short mask, bitmask; |
1354 | 1379 | ||
1355 | for (bitmask = 1; bitmask < e->mask; bitmask <<= 1) | 1380 | for (bitmask = 1; bitmask < e->max; bitmask <<= 1) |
1356 | ; | 1381 | ; |
1357 | if (ucontrol->value.enumerated.item[0] > e->mask - 1) | 1382 | if (ucontrol->value.enumerated.item[0] > e->max - 1) |
1358 | return -EINVAL; | 1383 | return -EINVAL; |
1359 | val = ucontrol->value.enumerated.item[0] << e->shift_l; | 1384 | val = ucontrol->value.enumerated.item[0] << e->shift_l; |
1360 | mask = (bitmask - 1) << e->shift_l; | 1385 | mask = (bitmask - 1) << e->shift_l; |
1361 | if (e->shift_l != e->shift_r) { | 1386 | if (e->shift_l != e->shift_r) { |
1362 | if (ucontrol->value.enumerated.item[1] > e->mask - 1) | 1387 | if (ucontrol->value.enumerated.item[1] > e->max - 1) |
1363 | return -EINVAL; | 1388 | return -EINVAL; |
1364 | val |= ucontrol->value.enumerated.item[1] << e->shift_r; | 1389 | val |= ucontrol->value.enumerated.item[1] << e->shift_r; |
1365 | mask |= (bitmask - 1) << e->shift_r; | 1390 | mask |= (bitmask - 1) << e->shift_r; |
@@ -1386,10 +1411,10 @@ int snd_soc_info_enum_ext(struct snd_kcontrol *kcontrol, | |||
1386 | 1411 | ||
1387 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 1412 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
1388 | uinfo->count = 1; | 1413 | uinfo->count = 1; |
1389 | uinfo->value.enumerated.items = e->mask; | 1414 | uinfo->value.enumerated.items = e->max; |
1390 | 1415 | ||
1391 | if (uinfo->value.enumerated.item > e->mask - 1) | 1416 | if (uinfo->value.enumerated.item > e->max - 1) |
1392 | uinfo->value.enumerated.item = e->mask - 1; | 1417 | uinfo->value.enumerated.item = e->max - 1; |
1393 | strcpy(uinfo->value.enumerated.name, | 1418 | strcpy(uinfo->value.enumerated.name, |
1394 | e->texts[uinfo->value.enumerated.item]); | 1419 | e->texts[uinfo->value.enumerated.item]); |
1395 | return 0; | 1420 | return 0; |
@@ -1434,9 +1459,11 @@ EXPORT_SYMBOL_GPL(snd_soc_info_volsw_ext); | |||
1434 | int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, | 1459 | int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, |
1435 | struct snd_ctl_elem_info *uinfo) | 1460 | struct snd_ctl_elem_info *uinfo) |
1436 | { | 1461 | { |
1437 | int max = (kcontrol->private_value >> 16) & 0xff; | 1462 | struct soc_mixer_control *mc = |
1438 | int shift = (kcontrol->private_value >> 8) & 0x0f; | 1463 | (struct soc_mixer_control *)kcontrol->private_value; |
1439 | int rshift = (kcontrol->private_value >> 12) & 0x0f; | 1464 | int max = mc->max; |
1465 | unsigned int shift = mc->min; | ||
1466 | unsigned int rshift = mc->rshift; | ||
1440 | 1467 | ||
1441 | if (max == 1) | 1468 | if (max == 1) |
1442 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | 1469 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; |
@@ -1462,13 +1489,15 @@ EXPORT_SYMBOL_GPL(snd_soc_info_volsw); | |||
1462 | int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, | 1489 | int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, |
1463 | struct snd_ctl_elem_value *ucontrol) | 1490 | struct snd_ctl_elem_value *ucontrol) |
1464 | { | 1491 | { |
1492 | struct soc_mixer_control *mc = | ||
1493 | (struct soc_mixer_control *)kcontrol->private_value; | ||
1465 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 1494 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
1466 | int reg = kcontrol->private_value & 0xff; | 1495 | unsigned int reg = mc->reg; |
1467 | int shift = (kcontrol->private_value >> 8) & 0x0f; | 1496 | unsigned int shift = mc->shift; |
1468 | int rshift = (kcontrol->private_value >> 12) & 0x0f; | 1497 | unsigned int rshift = mc->rshift; |
1469 | int max = (kcontrol->private_value >> 16) & 0xff; | 1498 | int max = mc->max; |
1470 | int mask = (1 << fls(max)) - 1; | 1499 | unsigned int mask = (1 << fls(max)) - 1; |
1471 | int invert = (kcontrol->private_value >> 24) & 0x01; | 1500 | unsigned int invert = mc->invert; |
1472 | 1501 | ||
1473 | ucontrol->value.integer.value[0] = | 1502 | ucontrol->value.integer.value[0] = |
1474 | (snd_soc_read(codec, reg) >> shift) & mask; | 1503 | (snd_soc_read(codec, reg) >> shift) & mask; |
@@ -1499,13 +1528,15 @@ EXPORT_SYMBOL_GPL(snd_soc_get_volsw); | |||
1499 | int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, | 1528 | int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, |
1500 | struct snd_ctl_elem_value *ucontrol) | 1529 | struct snd_ctl_elem_value *ucontrol) |
1501 | { | 1530 | { |
1531 | struct soc_mixer_control *mc = | ||
1532 | (struct soc_mixer_control *)kcontrol->private_value; | ||
1502 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 1533 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
1503 | int reg = kcontrol->private_value & 0xff; | 1534 | unsigned int reg = mc->reg; |
1504 | int shift = (kcontrol->private_value >> 8) & 0x0f; | 1535 | unsigned int shift = mc->shift; |
1505 | int rshift = (kcontrol->private_value >> 12) & 0x0f; | 1536 | unsigned int rshift = mc->rshift; |
1506 | int max = (kcontrol->private_value >> 16) & 0xff; | 1537 | int max = mc->max; |
1507 | int mask = (1 << fls(max)) - 1; | 1538 | unsigned int mask = (1 << fls(max)) - 1; |
1508 | int invert = (kcontrol->private_value >> 24) & 0x01; | 1539 | unsigned int invert = mc->invert; |
1509 | unsigned short val, val2, val_mask; | 1540 | unsigned short val, val2, val_mask; |
1510 | 1541 | ||
1511 | val = (ucontrol->value.integer.value[0] & mask); | 1542 | val = (ucontrol->value.integer.value[0] & mask); |
@@ -1537,7 +1568,9 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw); | |||
1537 | int snd_soc_info_volsw_2r(struct snd_kcontrol *kcontrol, | 1568 | int snd_soc_info_volsw_2r(struct snd_kcontrol *kcontrol, |
1538 | struct snd_ctl_elem_info *uinfo) | 1569 | struct snd_ctl_elem_info *uinfo) |
1539 | { | 1570 | { |
1540 | int max = (kcontrol->private_value >> 12) & 0xff; | 1571 | struct soc_mixer_control *mc = |
1572 | (struct soc_mixer_control *)kcontrol->private_value; | ||
1573 | int max = mc->max; | ||
1541 | 1574 | ||
1542 | if (max == 1) | 1575 | if (max == 1) |
1543 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | 1576 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; |
@@ -1563,13 +1596,15 @@ EXPORT_SYMBOL_GPL(snd_soc_info_volsw_2r); | |||
1563 | int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol, | 1596 | int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol, |
1564 | struct snd_ctl_elem_value *ucontrol) | 1597 | struct snd_ctl_elem_value *ucontrol) |
1565 | { | 1598 | { |
1599 | struct soc_mixer_control *mc = | ||
1600 | (struct soc_mixer_control *)kcontrol->private_value; | ||
1566 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 1601 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
1567 | int reg = kcontrol->private_value & 0xff; | 1602 | unsigned int reg = mc->reg; |
1568 | int reg2 = (kcontrol->private_value >> 24) & 0xff; | 1603 | unsigned int reg2 = mc->rreg; |
1569 | int shift = (kcontrol->private_value >> 8) & 0x0f; | 1604 | unsigned int shift = mc->shift; |
1570 | int max = (kcontrol->private_value >> 12) & 0xff; | 1605 | int max = mc->max; |
1571 | int mask = (1<<fls(max))-1; | 1606 | unsigned int mask = (1<<fls(max))-1; |
1572 | int invert = (kcontrol->private_value >> 20) & 0x01; | 1607 | unsigned int invert = mc->invert; |
1573 | 1608 | ||
1574 | ucontrol->value.integer.value[0] = | 1609 | ucontrol->value.integer.value[0] = |
1575 | (snd_soc_read(codec, reg) >> shift) & mask; | 1610 | (snd_soc_read(codec, reg) >> shift) & mask; |
@@ -1598,13 +1633,15 @@ EXPORT_SYMBOL_GPL(snd_soc_get_volsw_2r); | |||
1598 | int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol, | 1633 | int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol, |
1599 | struct snd_ctl_elem_value *ucontrol) | 1634 | struct snd_ctl_elem_value *ucontrol) |
1600 | { | 1635 | { |
1636 | struct soc_mixer_control *mc = | ||
1637 | (struct soc_mixer_control *)kcontrol->private_value; | ||
1601 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 1638 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
1602 | int reg = kcontrol->private_value & 0xff; | 1639 | unsigned int reg = mc->reg; |
1603 | int reg2 = (kcontrol->private_value >> 24) & 0xff; | 1640 | unsigned int reg2 = mc->rreg; |
1604 | int shift = (kcontrol->private_value >> 8) & 0x0f; | 1641 | unsigned int shift = mc->shift; |
1605 | int max = (kcontrol->private_value >> 12) & 0xff; | 1642 | int max = mc->max; |
1606 | int mask = (1 << fls(max)) - 1; | 1643 | unsigned int mask = (1 << fls(max)) - 1; |
1607 | int invert = (kcontrol->private_value >> 20) & 0x01; | 1644 | unsigned int invert = mc->invert; |
1608 | int err; | 1645 | int err; |
1609 | unsigned short val, val2, val_mask; | 1646 | unsigned short val, val2, val_mask; |
1610 | 1647 | ||
@@ -1641,8 +1678,10 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r); | |||
1641 | int snd_soc_info_volsw_s8(struct snd_kcontrol *kcontrol, | 1678 | int snd_soc_info_volsw_s8(struct snd_kcontrol *kcontrol, |
1642 | struct snd_ctl_elem_info *uinfo) | 1679 | struct snd_ctl_elem_info *uinfo) |
1643 | { | 1680 | { |
1644 | int max = (signed char)((kcontrol->private_value >> 16) & 0xff); | 1681 | struct soc_mixer_control *mc = |
1645 | int min = (signed char)((kcontrol->private_value >> 24) & 0xff); | 1682 | (struct soc_mixer_control *)kcontrol->private_value; |
1683 | int max = mc->max; | ||
1684 | int min = mc->min; | ||
1646 | 1685 | ||
1647 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 1686 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
1648 | uinfo->count = 2; | 1687 | uinfo->count = 2; |
@@ -1664,9 +1703,11 @@ EXPORT_SYMBOL_GPL(snd_soc_info_volsw_s8); | |||
1664 | int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol, | 1703 | int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol, |
1665 | struct snd_ctl_elem_value *ucontrol) | 1704 | struct snd_ctl_elem_value *ucontrol) |
1666 | { | 1705 | { |
1706 | struct soc_mixer_control *mc = | ||
1707 | (struct soc_mixer_control *)kcontrol->private_value; | ||
1667 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 1708 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
1668 | int reg = kcontrol->private_value & 0xff; | 1709 | unsigned int reg = mc->reg; |
1669 | int min = (signed char)((kcontrol->private_value >> 24) & 0xff); | 1710 | int min = mc->min; |
1670 | int val = snd_soc_read(codec, reg); | 1711 | int val = snd_soc_read(codec, reg); |
1671 | 1712 | ||
1672 | ucontrol->value.integer.value[0] = | 1713 | ucontrol->value.integer.value[0] = |
@@ -1689,9 +1730,11 @@ EXPORT_SYMBOL_GPL(snd_soc_get_volsw_s8); | |||
1689 | int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol, | 1730 | int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol, |
1690 | struct snd_ctl_elem_value *ucontrol) | 1731 | struct snd_ctl_elem_value *ucontrol) |
1691 | { | 1732 | { |
1733 | struct soc_mixer_control *mc = | ||
1734 | (struct soc_mixer_control *)kcontrol->private_value; | ||
1692 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 1735 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
1693 | int reg = kcontrol->private_value & 0xff; | 1736 | unsigned int reg = mc->reg; |
1694 | int min = (signed char)((kcontrol->private_value >> 24) & 0xff); | 1737 | int min = mc->min; |
1695 | unsigned short val; | 1738 | unsigned short val; |
1696 | 1739 | ||
1697 | val = (ucontrol->value.integer.value[0]+min) & 0xff; | 1740 | val = (ucontrol->value.integer.value[0]+min) & 0xff; |
@@ -1842,7 +1885,7 @@ module_init(snd_soc_init); | |||
1842 | module_exit(snd_soc_exit); | 1885 | module_exit(snd_soc_exit); |
1843 | 1886 | ||
1844 | /* Module information */ | 1887 | /* Module information */ |
1845 | MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com"); | 1888 | MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk"); |
1846 | MODULE_DESCRIPTION("ALSA SoC Core"); | 1889 | MODULE_DESCRIPTION("ALSA SoC Core"); |
1847 | MODULE_LICENSE("GPL"); | 1890 | MODULE_LICENSE("GPL"); |
1848 | MODULE_ALIAS("platform:soc-audio"); | 1891 | MODULE_ALIAS("platform:soc-audio"); |