.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * ALSA SoC TLV320AIC3X codec driver |
---|
3 | 4 | * |
---|
.. | .. |
---|
5 | 6 | * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com> |
---|
6 | 7 | * |
---|
7 | 8 | * Based on sound/soc/codecs/wm8753.c by Liam Girdwood |
---|
8 | | - * |
---|
9 | | - * This program is free software; you can redistribute it and/or modify |
---|
10 | | - * it under the terms of the GNU General Public License version 2 as |
---|
11 | | - * published by the Free Software Foundation. |
---|
12 | 9 | * |
---|
13 | 10 | * Notes: |
---|
14 | 11 | * The AIC3X is a driver for a low power stereo audio |
---|
.. | .. |
---|
324 | 321 | */ |
---|
325 | 322 | static DECLARE_TLV_DB_SCALE(output_stage_tlv, -5900, 50, 1); |
---|
326 | 323 | |
---|
| 324 | +/* Output volumes. From 0 to 9 dB in 1 dB steps */ |
---|
| 325 | +static const DECLARE_TLV_DB_SCALE(out_tlv, 0, 100, 0); |
---|
| 326 | + |
---|
327 | 327 | static const struct snd_kcontrol_new aic3x_snd_controls[] = { |
---|
328 | 328 | /* Output */ |
---|
329 | 329 | SOC_DOUBLE_R_TLV("PCM Playback Volume", |
---|
.. | .. |
---|
386 | 386 | DACL1_2_HPLCOM_VOL, DACR1_2_HPRCOM_VOL, |
---|
387 | 387 | 0, 118, 1, output_stage_tlv), |
---|
388 | 388 | |
---|
389 | | - /* Output pin mute controls */ |
---|
| 389 | + /* Output pin controls */ |
---|
| 390 | + SOC_DOUBLE_R_TLV("Line Playback Volume", LLOPM_CTRL, RLOPM_CTRL, 4, |
---|
| 391 | + 9, 0, out_tlv), |
---|
390 | 392 | SOC_DOUBLE_R("Line Playback Switch", LLOPM_CTRL, RLOPM_CTRL, 3, |
---|
391 | 393 | 0x01, 0), |
---|
| 394 | + SOC_DOUBLE_R_TLV("HP Playback Volume", HPLOUT_CTRL, HPROUT_CTRL, 4, |
---|
| 395 | + 9, 0, out_tlv), |
---|
392 | 396 | SOC_DOUBLE_R("HP Playback Switch", HPLOUT_CTRL, HPROUT_CTRL, 3, |
---|
393 | 397 | 0x01, 0), |
---|
| 398 | + SOC_DOUBLE_R_TLV("HPCOM Playback Volume", HPLCOM_CTRL, HPRCOM_CTRL, |
---|
| 399 | + 4, 9, 0, out_tlv), |
---|
394 | 400 | SOC_DOUBLE_R("HPCOM Playback Switch", HPLCOM_CTRL, HPRCOM_CTRL, 3, |
---|
395 | 401 | 0x01, 0), |
---|
396 | 402 | |
---|
.. | .. |
---|
472 | 478 | 0, 118, 1, output_stage_tlv), |
---|
473 | 479 | |
---|
474 | 480 | SOC_SINGLE("Mono Playback Switch", MONOLOPM_CTRL, 3, 0x01, 0), |
---|
| 481 | + SOC_SINGLE_TLV("Mono Playback Volume", MONOLOPM_CTRL, 4, 9, 0, |
---|
| 482 | + out_tlv), |
---|
| 483 | + |
---|
475 | 484 | }; |
---|
476 | 485 | |
---|
477 | 486 | /* |
---|
.. | .. |
---|
1047 | 1056 | width = params_width(params); |
---|
1048 | 1057 | |
---|
1049 | 1058 | /* select data word length */ |
---|
1050 | | - data = snd_soc_component_read32(component, AIC3X_ASD_INTF_CTRLB) & (~(0x3 << 4)); |
---|
| 1059 | + data = snd_soc_component_read(component, AIC3X_ASD_INTF_CTRLB) & (~(0x3 << 4)); |
---|
1051 | 1060 | switch (width) { |
---|
1052 | 1061 | case 16: |
---|
1053 | 1062 | break; |
---|
.. | .. |
---|
1207 | 1216 | return 0; |
---|
1208 | 1217 | } |
---|
1209 | 1218 | |
---|
1210 | | -static int aic3x_mute(struct snd_soc_dai *dai, int mute) |
---|
| 1219 | +static int aic3x_mute(struct snd_soc_dai *dai, int mute, int direction) |
---|
1211 | 1220 | { |
---|
1212 | 1221 | struct snd_soc_component *component = dai->component; |
---|
1213 | | - u8 ldac_reg = snd_soc_component_read32(component, LDAC_VOL) & ~MUTE_ON; |
---|
1214 | | - u8 rdac_reg = snd_soc_component_read32(component, RDAC_VOL) & ~MUTE_ON; |
---|
| 1222 | + u8 ldac_reg = snd_soc_component_read(component, LDAC_VOL) & ~MUTE_ON; |
---|
| 1223 | + u8 rdac_reg = snd_soc_component_read(component, RDAC_VOL) & ~MUTE_ON; |
---|
1215 | 1224 | |
---|
1216 | 1225 | if (mute) { |
---|
1217 | 1226 | snd_soc_component_write(component, LDAC_VOL, ldac_reg | MUTE_ON); |
---|
.. | .. |
---|
1247 | 1256 | struct aic3x_priv *aic3x = snd_soc_component_get_drvdata(component); |
---|
1248 | 1257 | u8 iface_areg, iface_breg; |
---|
1249 | 1258 | |
---|
1250 | | - iface_areg = snd_soc_component_read32(component, AIC3X_ASD_INTF_CTRLA) & 0x3f; |
---|
1251 | | - iface_breg = snd_soc_component_read32(component, AIC3X_ASD_INTF_CTRLB) & 0x3f; |
---|
| 1259 | + iface_areg = snd_soc_component_read(component, AIC3X_ASD_INTF_CTRLA) & 0x3f; |
---|
| 1260 | + iface_breg = snd_soc_component_read(component, AIC3X_ASD_INTF_CTRLB) & 0x3f; |
---|
1252 | 1261 | |
---|
1253 | 1262 | /* set master/slave audio interface */ |
---|
1254 | 1263 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
---|
.. | .. |
---|
1259 | 1268 | case SND_SOC_DAIFMT_CBS_CFS: |
---|
1260 | 1269 | aic3x->master = 0; |
---|
1261 | 1270 | iface_areg &= ~(BIT_CLK_MASTER | WORD_CLK_MASTER); |
---|
| 1271 | + break; |
---|
| 1272 | + case SND_SOC_DAIFMT_CBM_CFS: |
---|
| 1273 | + aic3x->master = 1; |
---|
| 1274 | + iface_areg |= BIT_CLK_MASTER; |
---|
| 1275 | + iface_areg &= ~WORD_CLK_MASTER; |
---|
| 1276 | + break; |
---|
| 1277 | + case SND_SOC_DAIFMT_CBS_CFM: |
---|
| 1278 | + aic3x->master = 1; |
---|
| 1279 | + iface_areg |= WORD_CLK_MASTER; |
---|
| 1280 | + iface_areg &= ~BIT_CLK_MASTER; |
---|
1262 | 1281 | break; |
---|
1263 | 1282 | default: |
---|
1264 | 1283 | return -EINVAL; |
---|
.. | .. |
---|
1388 | 1407 | * writing one of them and thus caused other one also not |
---|
1389 | 1408 | * being written |
---|
1390 | 1409 | */ |
---|
1391 | | - pll_c = snd_soc_component_read32(component, AIC3X_PLL_PROGC_REG); |
---|
1392 | | - pll_d = snd_soc_component_read32(component, AIC3X_PLL_PROGD_REG); |
---|
| 1410 | + pll_c = snd_soc_component_read(component, AIC3X_PLL_PROGC_REG); |
---|
| 1411 | + pll_d = snd_soc_component_read(component, AIC3X_PLL_PROGD_REG); |
---|
1393 | 1412 | if (pll_c == aic3x_reg[AIC3X_PLL_PROGC_REG].def || |
---|
1394 | 1413 | pll_d == aic3x_reg[AIC3X_PLL_PROGD_REG].def) { |
---|
1395 | 1414 | snd_soc_component_write(component, AIC3X_PLL_PROGC_REG, pll_c); |
---|
.. | .. |
---|
1462 | 1481 | static const struct snd_soc_dai_ops aic3x_dai_ops = { |
---|
1463 | 1482 | .hw_params = aic3x_hw_params, |
---|
1464 | 1483 | .prepare = aic3x_prepare, |
---|
1465 | | - .digital_mute = aic3x_mute, |
---|
| 1484 | + .mute_stream = aic3x_mute, |
---|
1466 | 1485 | .set_sysclk = aic3x_set_dai_sysclk, |
---|
1467 | 1486 | .set_fmt = aic3x_set_dai_fmt, |
---|
1468 | 1487 | .set_tdm_slot = aic3x_set_dai_tdm_slot, |
---|
| 1488 | + .no_capture_mute = 1, |
---|
1469 | 1489 | }; |
---|
1470 | 1490 | |
---|
1471 | 1491 | static struct snd_soc_dai_driver aic3x_dai = { |
---|
.. | .. |
---|
1604 | 1624 | for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) { |
---|
1605 | 1625 | aic3x->disable_nb[i].nb.notifier_call = aic3x_regulator_event; |
---|
1606 | 1626 | aic3x->disable_nb[i].aic3x = aic3x; |
---|
1607 | | - ret = regulator_register_notifier(aic3x->supplies[i].consumer, |
---|
1608 | | - &aic3x->disable_nb[i].nb); |
---|
| 1627 | + ret = devm_regulator_register_notifier( |
---|
| 1628 | + aic3x->supplies[i].consumer, |
---|
| 1629 | + &aic3x->disable_nb[i].nb); |
---|
1609 | 1630 | if (ret) { |
---|
1610 | 1631 | dev_err(component->dev, |
---|
1611 | 1632 | "Failed to request regulator notifier: %d\n", |
---|
1612 | 1633 | ret); |
---|
1613 | | - goto err_notif; |
---|
| 1634 | + return ret; |
---|
1614 | 1635 | } |
---|
1615 | 1636 | } |
---|
1616 | 1637 | |
---|
.. | .. |
---|
1668 | 1689 | aic3x_add_widgets(component); |
---|
1669 | 1690 | |
---|
1670 | 1691 | return 0; |
---|
1671 | | - |
---|
1672 | | -err_notif: |
---|
1673 | | - while (i--) |
---|
1674 | | - regulator_unregister_notifier(aic3x->supplies[i].consumer, |
---|
1675 | | - &aic3x->disable_nb[i].nb); |
---|
1676 | | - return ret; |
---|
1677 | | -} |
---|
1678 | | - |
---|
1679 | | -static void aic3x_remove(struct snd_soc_component *component) |
---|
1680 | | -{ |
---|
1681 | | - struct aic3x_priv *aic3x = snd_soc_component_get_drvdata(component); |
---|
1682 | | - int i; |
---|
1683 | | - |
---|
1684 | | - for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) |
---|
1685 | | - regulator_unregister_notifier(aic3x->supplies[i].consumer, |
---|
1686 | | - &aic3x->disable_nb[i].nb); |
---|
1687 | 1692 | } |
---|
1688 | 1693 | |
---|
1689 | 1694 | static const struct snd_soc_component_driver soc_component_dev_aic3x = { |
---|
1690 | 1695 | .set_bias_level = aic3x_set_bias_level, |
---|
1691 | 1696 | .probe = aic3x_probe, |
---|
1692 | | - .remove = aic3x_remove, |
---|
1693 | 1697 | .controls = aic3x_snd_controls, |
---|
1694 | 1698 | .num_controls = ARRAY_SIZE(aic3x_snd_controls), |
---|
1695 | 1699 | .dapm_widgets = aic3x_dapm_widgets, |
---|