diff options
author | Takashi Iwai <tiwai@suse.de> | 2021-01-07 18:51:39 +0100 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2021-01-07 18:51:39 +0100 |
commit | 7b62275507232f01f66d3e7d05c77bbd9009b726 (patch) | |
tree | 172dd8a7632877df2b623462bc871ab42e093bcc /sound | |
parent | 91bc156817a3c2007332b64b4f85c32aafbbbea6 (diff) | |
parent | 1f092d1c8819679d78a7d9c62a46d4939d217a9d (diff) |
Merge tag 'asoc-fix-v5.11-rc2' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Fixes for v5.11
A collection of mostly driver specific fixes, plus a maintainership
update for TI and a fix for DAPM driver removal paths.
Diffstat (limited to 'sound')
30 files changed, 188 insertions, 1608 deletions
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index bda3514c7b2d..b7e3d8f44511 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -1129,8 +1129,8 @@ int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, unsigned int cond, if (constrs->rules_num >= constrs->rules_all) { struct snd_pcm_hw_rule *new; unsigned int new_rules = constrs->rules_all + 16; - new = krealloc(constrs->rules, new_rules * sizeof(*c), - GFP_KERNEL); + new = krealloc_array(constrs->rules, new_rules, + sizeof(*c), GFP_KERNEL); if (!new) { va_end(args); return -ENOMEM; diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c index 966b709ee286..631a61ce52f4 100644 --- a/sound/ppc/snd_ps3.c +++ b/sound/ppc/snd_ps3.c @@ -1044,7 +1044,7 @@ clean_open: }; /* snd_ps3_probe */ /* called when module removal */ -static int snd_ps3_driver_remove(struct ps3_system_bus_device *dev) +static void snd_ps3_driver_remove(struct ps3_system_bus_device *dev) { int ret; pr_info("%s:start id=%d\n", __func__, dev->match_id); @@ -1070,7 +1070,6 @@ static int snd_ps3_driver_remove(struct ps3_system_bus_device *dev) lv1_gpu_device_unmap(2); ps3_close_hv_device(dev); pr_info("%s:end id=%d\n", __func__, dev->match_id); - return 0; } /* snd_ps3_remove */ static struct ps3_system_bus_driver snd_ps3_bus_driver_info = { diff --git a/sound/soc/amd/raven/pci-acp3x.c b/sound/soc/amd/raven/pci-acp3x.c index 8c138e490f0c..d3536fd6a124 100644 --- a/sound/soc/amd/raven/pci-acp3x.c +++ b/sound/soc/amd/raven/pci-acp3x.c @@ -140,21 +140,14 @@ static int snd_acp3x_probe(struct pci_dev *pci, goto release_regions; } - /* check for msi interrupt support */ - ret = pci_enable_msi(pci); - if (ret) - /* msi is not enabled */ - irqflags = IRQF_SHARED; - else - /* msi is enabled */ - irqflags = 0; + irqflags = IRQF_SHARED; addr = pci_resource_start(pci, 0); adata->acp3x_base = devm_ioremap(&pci->dev, addr, pci_resource_len(pci, 0)); if (!adata->acp3x_base) { ret = -ENOMEM; - goto disable_msi; + goto release_regions; } pci_set_master(pci); pci_set_drvdata(pci, adata); @@ -162,7 +155,7 @@ static int snd_acp3x_probe(struct pci_dev *pci, adata->pme_en = rv_readl(adata->acp3x_base + mmACP_PME_EN); ret = acp3x_init(adata); if (ret) - goto disable_msi; + goto release_regions; val = rv_readl(adata->acp3x_base + mmACP_I2S_PIN_CONFIG); switch (val) { @@ -251,8 +244,6 @@ unregister_devs: de_init: if (acp3x_deinit(adata->acp3x_base)) dev_err(&pci->dev, "ACP de-init failed\n"); -disable_msi: - pci_disable_msi(pci); release_regions: pci_release_regions(pci); disable_pci: @@ -311,7 +302,6 @@ static void snd_acp3x_remove(struct pci_dev *pci) dev_err(&pci->dev, "ACP de-init failed\n"); pm_runtime_forbid(&pci->dev); pm_runtime_get_noresume(&pci->dev); - pci_disable_msi(pci); pci_release_regions(pci); pci_disable_device(pci); } diff --git a/sound/soc/amd/renoir/rn-pci-acp3x.c b/sound/soc/amd/renoir/rn-pci-acp3x.c index fa169bf09886..deca8c7a0e87 100644 --- a/sound/soc/amd/renoir/rn-pci-acp3x.c +++ b/sound/soc/amd/renoir/rn-pci-acp3x.c @@ -171,6 +171,20 @@ static const struct dmi_system_id rn_acp_quirk_table[] = { DMI_EXACT_MATCH(DMI_BOARD_NAME, "LNVNB161216"), } }, + { + /* Lenovo ThinkPad E14 Gen 2 */ + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_EXACT_MATCH(DMI_BOARD_NAME, "20T6CTO1WW"), + } + }, + { + /* Lenovo ThinkPad X395 */ + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_EXACT_MATCH(DMI_BOARD_NAME, "20NLCTO1WW"), + } + }, {} }; diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig index 142373ec411a..9fe9471f4514 100644 --- a/sound/soc/atmel/Kconfig +++ b/sound/soc/atmel/Kconfig @@ -143,7 +143,7 @@ config SND_MCHP_SOC_SPDIFTX - sama7g5 This S/PDIF TX driver is compliant with IEC-60958 standard and - includes programable User Data and Channel Status fields. + includes programmable User Data and Channel Status fields. config SND_MCHP_SOC_SPDIFRX tristate "Microchip ASoC driver for boards using S/PDIF RX" @@ -157,5 +157,5 @@ config SND_MCHP_SOC_SPDIFRX - sama7g5 This S/PDIF RX driver is compliant with IEC-60958 standard and - includes programable User Data and Channel Status fields. + includes programmable User Data and Channel Status fields. endif diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 5e4e68112791..9bf6bfdaf11e 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -180,7 +180,6 @@ config SND_SOC_ALL_CODECS imply SND_SOC_RT700_SDW imply SND_SOC_RT711_SDW imply SND_SOC_RT715_SDW - imply SND_SOC_RT715_SDCA_SDW imply SND_SOC_RT1308_SDW imply SND_SOC_SGTL5000 imply SND_SOC_SI476X @@ -458,7 +457,7 @@ config SND_SOC_ADAU7118_HW help Enable support for the Analog Devices ADAU7118 8 Channel PDM-to-I2S/TDM Converter. In this mode, the device works in standalone mode which - means that there is no bus to comunicate with it. Stereo mode is not + means that there is no bus to communicate with it. Stereo mode is not supported in this mode. To compile this driver as a module, choose M here: the module @@ -1237,12 +1236,6 @@ config SND_SOC_RT715_SDW select SND_SOC_RT715 select REGMAP_SOUNDWIRE -config SND_SOC_RT715_SDCA_SDW - tristate "Realtek RT715 SDCA Codec - SDW" - depends on SOUNDWIRE - select REGMAP_SOUNDWIRE - select REGMAP_SOUNDWIRE_MBQ - #Freescale sgtl5000 codec config SND_SOC_SGTL5000 tristate "Freescale SGTL5000 CODEC" diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index f255ec74333c..d277f0366e09 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -194,7 +194,6 @@ snd-soc-rt5682-i2c-objs := rt5682-i2c.o snd-soc-rt700-objs := rt700.o rt700-sdw.o snd-soc-rt711-objs := rt711.o rt711-sdw.o snd-soc-rt715-objs := rt715.o rt715-sdw.o -snd-soc-rt715-sdca-objs := rt715-sdca.o rt715-sdca-sdw.o snd-soc-sgtl5000-objs := sgtl5000.o snd-soc-alc5623-objs := alc5623.o snd-soc-alc5632-objs := alc5632.o @@ -511,7 +510,6 @@ obj-$(CONFIG_SND_SOC_RT5682_SDW) += snd-soc-rt5682-sdw.o obj-$(CONFIG_SND_SOC_RT700) += snd-soc-rt700.o obj-$(CONFIG_SND_SOC_RT711) += snd-soc-rt711.o obj-$(CONFIG_SND_SOC_RT715) += snd-soc-rt715.o -obj-$(CONFIG_SND_SOC_RT715_SDCA_SDW) += snd-soc-rt715-sdca.o obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o obj-$(CONFIG_SND_SOC_SIGMADSP_I2C) += snd-soc-sigmadsp-i2c.o diff --git a/sound/soc/codecs/cros_ec_codec.c b/sound/soc/codecs/cros_ec_codec.c index 5c3b7e5e55d2..f33a2a9654e7 100644 --- a/sound/soc/codecs/cros_ec_codec.c +++ b/sound/soc/codecs/cros_ec_codec.c @@ -8,7 +8,7 @@ * EC for audio function. */ -#include <crypto/sha.h> +#include <crypto/sha2.h> #include <linux/acpi.h> #include <linux/delay.h> #include <linux/device.h> diff --git a/sound/soc/codecs/max98373-i2c.c b/sound/soc/codecs/max98373-i2c.c index 92921e34f948..85f6865019d4 100644 --- a/sound/soc/codecs/max98373-i2c.c +++ b/sound/soc/codecs/max98373-i2c.c @@ -19,6 +19,12 @@ #include <sound/tlv.h> #include "max98373.h" +static const u32 max98373_i2c_cache_reg[] = { + MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK, + MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK, + MAX98373_R20B6_BDE_CUR_STATE_READBACK, +}; + static struct reg_default max98373_reg[] = { {MAX98373_R2000_SW_RESET, 0x00}, {MAX98373_R2001_INT_RAW1, 0x00}, @@ -472,6 +478,11 @@ static struct snd_soc_dai_driver max98373_dai[] = { static int max98373_suspend(struct device *dev) { struct max98373_priv *max98373 = dev_get_drvdata(dev); + int i; + + /* cache feedback register values before suspend */ + for (i = 0; i < max98373->cache_num; i++) + regmap_read(max98373->regmap, max98373->cache[i].reg, &max98373->cache[i].val); regcache_cache_only(max98373->regmap, true); regcache_mark_dirty(max98373->regmap); @@ -509,6 +520,7 @@ static int max98373_i2c_probe(struct i2c_client *i2c, { int ret = 0; int reg = 0; + int i; struct max98373_priv *max98373 = NULL; max98373 = devm_kzalloc(&i2c->dev, sizeof(*max98373), GFP_KERNEL); @@ -534,6 +546,14 @@ static int max98373_i2c_probe(struct i2c_client *i2c, return ret; } + max98373->cache_num = ARRAY_SIZE(max98373_i2c_cache_reg); + max98373->cache = devm_kcalloc(&i2c->dev, max98373->cache_num, + sizeof(*max98373->cache), + GFP_KERNEL); + + for (i = 0; i < max98373->cache_num; i++) + max98373->cache[i].reg = max98373_i2c_cache_reg[i]; + /* voltage/current slot & gpio configuration */ max98373_slot_config(&i2c->dev, max98373); diff --git a/sound/soc/codecs/max98373-sdw.c b/sound/soc/codecs/max98373-sdw.c index ec2e79c57357..b8d471d79e93 100644 --- a/sound/soc/codecs/max98373-sdw.c +++ b/sound/soc/codecs/max98373-sdw.c @@ -23,6 +23,12 @@ struct sdw_stream_data { struct sdw_stream_runtime *sdw_stream; }; +static const u32 max98373_sdw_cache_reg[] = { + MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK, + MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK, + MAX98373_R20B6_BDE_CUR_STATE_READBACK, +}; + static struct reg_default max98373_reg[] = { {MAX98373_R0040_SCP_INIT_STAT_1, 0x00}, {MAX98373_R0041_SCP_INIT_MASK_1, 0x00}, @@ -245,6 +251,11 @@ static const struct regmap_config max98373_sdw_regmap = { static __maybe_unused int max98373_suspend(struct device *dev) { struct max98373_priv *max98373 = dev_get_drvdata(dev); + int i; + + /* cache feedback register values before suspend */ + for (i = 0; i < max98373->cache_num; i++) + regmap_read(max98373->regmap, max98373->cache[i].reg, &max98373->cache[i].val); regcache_cache_only(max98373->regmap, true); @@ -757,6 +768,7 @@ static int max98373_init(struct sdw_slave *slave, struct regmap *regmap) { struct max98373_priv *max98373; int ret; + int i; struct device *dev = &slave->dev; /* Allocate and assign private driver data structure */ @@ -768,6 +780,14 @@ static int max98373_init(struct sdw_slave *slave, struct regmap *regmap) max98373->regmap = regmap; max98373->slave = slave; + max98373->cache_num = ARRAY_SIZE(max98373_sdw_cache_reg); + max98373->cache = devm_kcalloc(dev, max98373->cache_num, + sizeof(*max98373->cache), + GFP_KERNEL); + + for (i = 0; i < max98373->cache_num; i++) + max98373->cache[i].reg = max98373_sdw_cache_reg[i]; + /* Read voltage and slot configuration */ max98373_slot_config(dev, max98373); diff --git a/sound/soc/codecs/max98373.c b/sound/soc/codecs/max98373.c index 929bb1798c43..31d571d4fac1 100644 --- a/sound/soc/codecs/max98373.c +++ b/sound/soc/codecs/max98373.c @@ -168,6 +168,31 @@ static SOC_ENUM_SINGLE_DECL(max98373_adc_samplerate_enum, MAX98373_R2051_MEAS_ADC_SAMPLING_RATE, 0, max98373_ADC_samplerate_text); +static int max98373_feedback_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct max98373_priv *max98373 = snd_soc_component_get_drvdata(component); + int i; + + if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) { + /* + * Register values will be cached before suspend. The cached value + * will be a valid value and userspace will happy with that. + */ + for (i = 0; i < max98373->cache_num; i++) { + if (mc->reg == max98373->cache[i].reg) { + ucontrol->value.integer.value[0] = max98373->cache[i].val; + return 0; + } + } + } + + return snd_soc_put_volsw(kcontrol, ucontrol); +} + static const struct snd_kcontrol_new max98373_snd_controls[] = { SOC_SINGLE("Digital Vol Sel Switch", MAX98373_R203F_AMP_DSP_CFG, MAX98373_AMP_VOL_SEL_SHIFT, 1, 0), @@ -209,8 +234,10 @@ SOC_SINGLE("ADC PVDD FLT Switch", MAX98373_R2052_MEAS_ADC_PVDD_FLT_CFG, MAX98373_FLT_EN_SHIFT, 1, 0), SOC_SINGLE("ADC TEMP FLT Switch", MAX98373_R2053_MEAS_ADC_THERM_FLT_CFG, MAX98373_FLT_EN_SHIFT, 1, 0), -SOC_SINGLE("ADC PVDD", MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK, 0, 0xFF, 0), -SOC_SINGLE("ADC TEMP", MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK, 0, 0xFF, 0), +SOC_SINGLE_EXT("ADC PVDD", MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK, 0, 0xFF, 0, + max98373_feedback_get, NULL), +SOC_SINGLE_EXT("ADC TEMP", MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK, 0, 0xFF, 0, + max98373_feedback_get, NULL), SOC_SINGLE("ADC PVDD FLT Coeff", MAX98373_R2052_MEAS_ADC_PVDD_FLT_CFG, 0, 0x3, 0), SOC_SINGLE("ADC TEMP FLT Coeff", MAX98373_R2053_MEAS_ADC_THERM_FLT_CFG, @@ -226,7 +253,8 @@ SOC_SINGLE("BDE LVL1 Thresh", MAX98373_R2097_BDE_L1_THRESH, 0, 0xFF, 0), SOC_SINGLE("BDE LVL2 Thresh", MAX98373_R2098_BDE_L2_THRESH, 0, 0xFF, 0), SOC_SINGLE("BDE LVL3 Thresh", MAX98373_R2099_BDE_L3_THRESH, 0, 0xFF, 0), SOC_SINGLE("BDE LVL4 Thresh", MAX98373_R209A_BDE_L4_THRESH, 0, 0xFF, 0), -SOC_SINGLE("BDE Active Level", MAX98373_R20B6_BDE_CUR_STATE_READBACK, 0, 8, 0), +SOC_SINGLE_EXT("BDE Active Level", MAX98373_R20B6_BDE_CUR_STATE_READBACK, 0, 8, 0, + max98373_feedback_get, NULL), SOC_SINGLE("BDE Clip Mode Switch", MAX98373_R2092_BDE_CLIPPER_MODE, 0, 1, 0), SOC_SINGLE("BDE Thresh Hysteresis", MAX98373_R209B_BDE_THRESH_HYST, 0, 0xFF, 0), SOC_SINGLE("BDE Hold Time", MAX98373_R2090_BDE_LVL_HOLD, 0, 0xFF, 0), diff --git a/sound/soc/codecs/max98373.h b/sound/soc/codecs/max98373.h index 4ab29b9d51c7..71f5a5228f34 100644 --- a/sound/soc/codecs/max98373.h +++ b/sound/soc/codecs/max98373.h @@ -203,6 +203,11 @@ /* MAX98373_R2000_SW_RESET */ #define MAX98373_SOFT_RESET (0x1 << 0) +struct max98373_cache { + u32 reg; + u32 val; +}; + struct max98373_priv { struct regmap *regmap; int reset_gpio; @@ -212,6 +217,9 @@ struct max98373_priv { bool interleave_mode; unsigned int ch_size; bool tdm_mode; + /* cache for reading a valid fake feedback value */ + struct max98373_cache *cache; + int cache_num; /* variables to support soundwire */ struct sdw_slave *slave; bool hw_init; diff --git a/sound/soc/codecs/rt711.c b/sound/soc/codecs/rt711.c index 5771c02c3459..85f744184a60 100644 --- a/sound/soc/codecs/rt711.c +++ b/sound/soc/codecs/rt711.c @@ -462,6 +462,8 @@ static int rt711_set_amp_gain_put(struct snd_kcontrol *kcontrol, unsigned int read_ll, read_rl; int i; + mutex_lock(&rt711->calibrate_mutex); + /* Can't use update bit function, so read the original value first */ addr_h = mc->reg; addr_l = mc->rreg; @@ -547,6 +549,8 @@ static int rt711_set_amp_gain_put(struct snd_kcontrol *kcontrol, if (dapm->bias_level <= SND_SOC_BIAS_STANDBY) regmap_write(rt711->regmap, RT711_SET_AUDIO_POWER_STATE, AC_PWRST_D3); + + mutex_unlock(&rt711->calibrate_mutex); return 0; } @@ -859,9 +863,11 @@ static int rt711_set_bias_level(struct snd_soc_component *component, break; case SND_SOC_BIAS_STANDBY: + mutex_lock(&rt711->calibrate_mutex); regmap_write(rt711->regmap, RT711_SET_AUDIO_POWER_STATE, AC_PWRST_D3); + mutex_unlock(&rt711->calibrate_mutex); break; default: diff --git a/sound/soc/codecs/rt715-sdca-sdw.c b/sound/soc/codecs/rt715-sdca-sdw.c deleted file mode 100644 index 889b6b3b0009..000000000000 --- a/sound/soc/codecs/rt715-sdca-sdw.c +++ /dev/null @@ -1,278 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -// -// rt715-sdca-sdw.c -- rt715 ALSA SoC audio driver -// -// Copyright(c) 2020 Realtek Semiconductor Corp. -// -// - -#include <linux/delay.h> -#include <linux/device.h> -#include <linux/mod_devicetable.h> -#include <linux/soundwire/sdw.h> -#include <linux/soundwire/sdw_type.h> -#include <linux/soundwire/sdw_registers.h> -#include <linux/module.h> -#include <linux/regmap.h> -#include <sound/soc.h> -#include "rt715-sdca.h" -#include "rt715-sdca-sdw.h" - -static bool rt715_sdca_readable_register(struct device *dev, unsigned int reg) -{ - switch (reg) { - case 0x201a ... 0x2027: - case 0x2029 ... 0x202a: - case 0x202d ... 0x2034: - case 0x2200 ... 0x2204: - case 0x2206 ... 0x2212: - case 0x2230 ... 0x2239: - case 0x2f5b: - case SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_SMPU_TRIG_ST_EN, - RT715_SDCA_SMPU_TRIG_ST_CTRL, CH_00): - return true; - default: - return false; - } -} - -static bool rt715_sdca_volatile_register(struct device *dev, unsigned int reg) -{ - switch (reg) { - case 0x201b: - case 0x201c: - case 0x201d: - case 0x201f: - case 0x2021: - case 0x2023: - case 0x2230: - case 0x202d ... 0x202f: /* BRA */ - case 0x2200 ... 0x2212: /* i2c debug */ - case 0x2f07: - case 0x2f1b ... 0x2f1e: - case 0x2f30 ... 0x2f34: - case 0x2f50 ... 0x2f51: - case 0x2f53 ... 0x2f59: - case 0x2f5c ... 0x2f5f: - case SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_SMPU_TRIG_ST_EN, - RT715_SDCA_SMPU_TRIG_ST_CTRL, CH_00): /* VAD Searching status */ - return true; - default: - return false; - } -} - -static bool rt715_sdca_mbq_readable_register(struct device *dev, unsigned int reg) -{ - switch (reg) { - case 0x2000000: - case 0x200002b: - case 0x2000036: - case 0x2000037: - case 0x2000039: - case 0x6100000: - return true; - default: - return false; - } -} - -static bool rt715_sdca_mbq_volatile_register(struct device *dev, unsigned int reg) -{ - switch (reg) { - case 0x2000000: - return true; - default: - return false; - } -} - -static const struct regmap_config rt715_sdca_regmap = { - .reg_bits = 32, - .val_bits = 8, - .readable_reg = rt715_sdca_readable_register, - .volatile_reg = rt715_sdca_volatile_register, - .max_register = 0x43ffffff, - .reg_defaults = rt715_reg_defaults_sdca, - .num_reg_defaults = ARRAY_SIZE(rt715_reg_defaults_sdca), - .cache_type = REGCACHE_RBTREE, - .use_single_read = true, - .use_single_write = true, -}; - -static const struct regmap_config rt715_sdca_mbq_regmap = { - .name = "sdw-mbq", - .reg_bits = 32, - .val_bits = 16, - .readable_reg = rt715_sdca_mbq_readable_register, - .volatile_reg = rt715_sdca_mbq_volatile_register, - .max_register = 0x43ffffff, - .reg_defaults = rt715_mbq_reg_defaults_sdca, - .num_reg_defaults = ARRAY_SIZE(rt715_mbq_reg_defaults_sdca), - .cache_type = REGCACHE_RBTREE, - .use_single_read = true, - .use_single_write = true, -}; - -static int rt715_update_status(struct sdw_slave *slave, - enum sdw_slave_status status) -{ - struct rt715_sdca_priv *rt715 = dev_get_drvdata(&slave->dev); - - /* Update the status */ - rt715->status = status; - - /* - * Perform initialization only if slave status is present and - * hw_init flag is false - */ - if (rt715->hw_init || rt715->status != SDW_SLAVE_ATTACHED) - return 0; - - /* perform I/O transfers required for Slave initialization */ - return rt715_io_init(&slave->dev, slave); -} - -static int rt715_read_prop(struct sdw_slave *slave) -{ - struct sdw_slave_prop *prop = &slave->prop; - int nval, i; - u32 bit; - unsigned long addr; - struct sdw_dpn_prop *dpn; - - prop->paging_support = true; - - /* first we need to allocate memory for set bits in port lists */ - prop->source_ports = 0x50;/* BITMAP: 01010000 */ - prop->sink_ports = 0x0; /* BITMAP: 00000000 */ - - nval = hweight32(prop->source_ports); - prop->src_dpn_prop = devm_kcalloc(&slave->dev, nval, - sizeof(*prop->src_dpn_prop), - GFP_KERNEL); - if (!prop->src_dpn_prop) - return -ENOMEM; - - dpn = prop->src_dpn_prop; - i = 0; - addr = prop->source_ports; - for_each_set_bit(bit, &addr, 32) { - dpn[i].num = bit; - dpn[i].simple_ch_prep_sm = true; - dpn[i].ch_prep_timeout = 10; - i++; - } - - /* set the timeout values */ - prop->clk_stop_timeout = 20; - - return 0; -} - -static struct sdw_slave_ops rt715_sdca_slave_ops = { - .read_prop = rt715_read_prop, - .update_status = rt715_update_status, -}; - -static int rt715_sdca_sdw_probe(struct sdw_slave *slave, - const struct sdw_device_id *id) -{ - struct regmap *mbq_regmap, *regmap; - - slave->ops = &rt715_sdca_slave_ops; - - /* Regmap Initialization */ - mbq_regmap = devm_regmap_init_sdw_mbq(slave, &rt715_sdca_mbq_regmap); - if (!mbq_regmap) - return -EINVAL; - - regmap = devm_regmap_init_sdw(slave, &rt715_sdca_regmap); - if (!regmap) - return -EINVAL; - - return rt715_init(&slave->dev, mbq_regmap, regmap, slave); -} - -static const struct sdw_device_id rt715_sdca_id[] = { - SDW_SLAVE_ENTRY_EXT(0x025d, 0x715, 0x3, 0x1, 0), - SDW_SLAVE_ENTRY_EXT(0x025d, 0x714, 0x3, 0x1, 0), - {}, -}; -MODULE_DEVICE_TABLE(sdw, rt715_sdca_id); - -static int __maybe_unused rt715_dev_suspend(struct device *dev) -{ - struct rt715_sdca_priv *rt715 = dev_get_drvdata(dev); - - if (!rt715->hw_init) - return 0; - - regcache_cache_only(rt715->regmap, true); - regcache_mark_dirty(rt715->regmap); - regcache_cache_only(rt715->mbq_regmap, true); - regcache_mark_dirty(rt715->mbq_regmap); - - return 0; -} - -#define RT715_PROBE_TIMEOUT 2000 - -static int __maybe_unused rt715_dev_resume(struct device *dev) -{ - struct sdw_slave *slave = dev_to_sdw_dev(dev); - struct rt715_sdca_priv *rt715 = dev_get_drvdata(dev); - unsigned long time; - - if (!rt715->hw_init) - return 0; - - if (!slave->unattach_request) - goto regmap_sync; - - time = wait_for_completion_timeout(&slave->enumeration_complete, - msecs_to_jiffies(RT715_PROBE_TIMEOUT)); - if (!time) { - dev_err(&slave->dev, "Enumeration not complete, timed out\n"); - return -ETIMEDOUT; - } - -regmap_sync: - slave->unattach_request = 0; - regcache_cache_only(rt715->regmap, false); - regcache_sync_region(rt715->regmap, - SDW_SDCA_CTL(FUN_JACK_CODEC, RT715_SDCA_ST_EN, RT715_SDCA_ST_CTRL, - CH_00), - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_SMPU_TRIG_ST_EN, - RT715_SDCA_SMPU_TRIG_ST_CTRL, CH_00)); - regcache_cache_only(rt715->mbq_regmap, false); - regcache_sync_region(rt715->mbq_regmap, 0x2000000, 0x61020ff); - regcache_sync_region(rt715->mbq_regmap, - SDW_SDCA_CTL(FUN_JACK_CODEC, RT715_SDCA_ST_EN, RT715_SDCA_ST_CTRL, - CH_00), - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_SMPU_TRIG_ST_EN, - RT715_SDCA_SMPU_TRIG_ST_CTRL, CH_00)); - - return 0; -} - -static const struct dev_pm_ops rt715_pm = { - SET_SYSTEM_SLEEP_PM_OPS(rt715_dev_suspend, rt715_dev_resume) - SET_RUNTIME_PM_OPS(rt715_dev_suspend, rt715_dev_resume, NULL) -}; - -static struct sdw_driver rt715_sdw_driver = { - .driver = { - .name = "rt715-sdca", - .owner = THIS_MODULE, - .pm = &rt715_pm, - }, - .probe = rt715_sdca_sdw_probe, - .ops = &rt715_sdca_slave_ops, - .id_table = rt715_sdca_id, -}; -module_sdw_driver(rt715_sdw_driver); - -MODULE_DESCRIPTION("ASoC RT715 driver SDW SDCA"); -MODULE_AUTHOR("Jack Yu <jack.yu@realtek.com>"); -MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/rt715-sdca-sdw.h b/sound/soc/codecs/rt715-sdca-sdw.h deleted file mode 100644 index cd365bb60747..000000000000 --- a/sound/soc/codecs/rt715-sdca-sdw.h +++ /dev/null @@ -1,170 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * rt715-sdca-sdw.h -- RT715 ALSA SoC audio driver header - * - * Copyright(c) 2020 Realtek Semiconductor Corp. - */ - -#ifndef __RT715_SDW_SDCA_H__ -#define __RT715_SDW_SDCA_H__ - -#include <linux/soundwire/sdw_registers.h> - -static const struct reg_default rt715_reg_defaults_sdca[] = { - { 0x201a, 0x00 }, - { 0x201e, 0x00 }, - { 0x2020, 0x00 }, - { 0x2021, 0x00 }, - { 0x2022, 0x00 }, - { 0x2023, 0x00 }, - { 0x2024, 0x00 }, - { 0x2025, 0x01 }, - { 0x2026, 0x00 }, - { 0x2027, 0x00 }, - { 0x2029, 0x00 }, - { 0x202a, 0x00 }, - { 0x202d, 0x00 }, - { 0x202e, 0x00 }, - { 0x202f, 0x00 }, - { 0x2030, 0x00 }, - { 0x2031, 0x00 }, - { 0x2032, 0x00 }, - { 0x2033, 0x00 }, - { 0x2034, 0x00 }, - { 0x2230, 0x00 }, - { 0x2231, 0x2f }, - { 0x2232, 0x80 }, - { 0x2233, 0x00 }, - { 0x2234, 0x00 }, - { 0x2235, 0x00 }, - { 0x2236, 0x00 }, - { 0x2237, 0x00 }, - { 0x2238, 0x00 }, - { 0x2239, 0x00 }, - { 0x2f01, 0x00 }, - { 0x2f02, 0x09 }, - { 0x2f03, 0x0b }, - { 0x2f04, 0x00 }, - { 0x2f05, 0x0e }, - { 0x2f06, 0x01 }, - { 0x2f08, 0x00 }, - { 0x2f09, 0x00 }, - { 0x2f0a, 0x00 }, - { 0x2f0b, 0x00 }, - { 0x2f0c, 0x00 }, - { 0x2f0d, 0x00 }, - { 0x2f0e, 0x12 }, - { 0x2f0f, 0x00 }, - { 0x2f10, 0x00 }, - { 0x2f11, 0x00 }, - { 0x2f12, 0x00 }, - { 0x2f13, 0x00 }, - { 0x2f14, 0x00 }, - { 0x2f15, 0x00 }, - { 0x2f16, 0x00 }, - { 0x2f17, 0x00 }, - { 0x2f18, 0x00 }, - { 0x2f19, 0x03 }, - { 0x2f1a, 0x00 }, - { 0x2f1f, 0x10 }, - { 0x2f20, 0x00 }, - { 0x2f21, 0x00 }, - { 0x2f22, 0x00 }, - { 0x2f23, 0x00 }, - { 0x2f24, 0x00 }, - { 0x2f25, 0x00 }, - { 0x2f52, 0x01 }, - { 0x2f5a, 0x02 }, - { 0x2f5b, 0x05 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_CX_CLK_SEL_EN, - RT715_SDCA_CX_CLK_SEL_CTRL, CH_00), 0x1 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC8_9_VOL, - RT715_SDCA_FU_MUTE_CTRL, CH_01), 0x01 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC8_9_VOL, - RT715_SDCA_FU_MUTE_CTRL, CH_02), 0x01 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC8_9_VOL, - RT715_SDCA_FU_MUTE_CTRL, CH_03), 0x01 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC8_9_VOL, - RT715_SDCA_FU_MUTE_CTRL, CH_04), 0x01 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC10_11_VOL, - RT715_SDCA_FU_MUTE_CTRL, CH_01), 0x01 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC10_11_VOL, - RT715_SDCA_FU_MUTE_CTRL, CH_02), 0x01 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC10_11_VOL, - RT715_SDCA_FU_MUTE_CTRL, CH_03), 0x01 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC10_11_VOL, - RT715_SDCA_FU_MUTE_CTRL, CH_04), 0x01 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC7_27_VOL, - RT715_SDCA_FU_MUTE_CTRL, CH_01), 0x01 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC7_27_VOL, - RT715_SDCA_FU_MUTE_CTRL, CH_02), 0x01 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_SMPU_TRIG_ST_EN, - RT715_SDCA_SMPU_TRIG_EN_CTRL, CH_00), 0x02 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_SMPU_TRIG_ST_EN, - RT715_SDCA_SMPU_TRIG_ST_CTRL, CH_00), 0x00 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC7_27_VOL, - RT715_SDCA_FU_MUTE_CTRL, CH_01), 0x01 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC7_27_VOL, - RT715_SDCA_FU_MUTE_CTRL, CH_02), 0x01 }, -}; - -static const struct reg_default rt715_mbq_reg_defaults_sdca[] = { - { 0x200002b, 0x0420 }, - { 0x2000036, 0x0000 }, - { 0x2000037, 0x0000 }, - { 0x2000039, 0xaa81 }, - { 0x6100000, 0x0100 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC8_9_VOL, - RT715_SDCA_FU_VOL_CTRL, CH_01), 0x00 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC8_9_VOL, - RT715_SDCA_FU_VOL_CTRL, CH_02), 0x00 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC8_9_VOL, - RT715_SDCA_FU_VOL_CTRL, CH_03), 0x00 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC8_9_VOL, - RT715_SDCA_FU_VOL_CTRL, CH_04), 0x00 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC10_11_VOL, - RT715_SDCA_FU_VOL_CTRL, CH_01), 0x00 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC10_11_VOL, - RT715_SDCA_FU_VOL_CTRL, CH_02), 0x00 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC10_11_VOL, - RT715_SDCA_FU_VOL_CTRL, CH_03), 0x00 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC10_11_VOL, - RT715_SDCA_FU_VOL_CTRL, CH_04), 0x00 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC7_27_VOL, - RT715_SDCA_FU_VOL_CTRL, CH_01), 0x00 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC7_27_VOL, - RT715_SDCA_FU_VOL_CTRL, CH_02), 0x00 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_AMIC_GAIN_EN, - RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_01), 0x00 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_AMIC_GAIN_EN, - RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_02), 0x00 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_AMIC_GAIN_EN, - RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_03), 0x00 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_AMIC_GAIN_EN, - RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_04), 0x00 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_AMIC_GAIN_EN, - RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_05), 0x00 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_AMIC_GAIN_EN, - RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_06), 0x00 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_AMIC_GAIN_EN, - RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_07), 0x00 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_AMIC_GAIN_EN, - RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_08), 0x00 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_DMIC_GAIN_EN, - RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_01), 0x00 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_DMIC_GAIN_EN, - RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_02), 0x00 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_DMIC_GAIN_EN, - RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_03), 0x00 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_DMIC_GAIN_EN, - RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_04), 0x00 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_DMIC_GAIN_EN, - RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_05), 0x00 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_DMIC_GAIN_EN, - RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_06), 0x00 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_DMIC_GAIN_EN, - RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_07), 0x00 }, - { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_DMIC_GAIN_EN, - RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_08), 0x00 }, -}; -#endif /* __RT715_SDW_SDCA_H__ */ diff --git a/sound/soc/codecs/rt715-sdca.c b/sound/soc/codecs/rt715-sdca.c deleted file mode 100644 index b843e47eb25b..000000000000 --- a/sound/soc/codecs/rt715-sdca.c +++ /dev/null @@ -1,936 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -// -// rt715-sdca.c -- rt715 ALSA SoC audio driver -// -// Copyright(c) 2020 Realtek Semiconductor Corp. -// -// -// - -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/version.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/pm_runtime.h> -#include <linux/pm.h> -#include <linux/soundwire/sdw.h> -#include <linux/regmap.h> -#include <linux/slab.h> -#include <linux/platform_device.h> -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include <sound/soc.h> -#include <sound/soc-dapm.h> -#include <sound/initval.h> -#include <sound/tlv.h> -#include <linux/soundwire/sdw_registers.h> - -#include "rt715-sdca.h" - -static int rt715_index_write(struct rt715_sdca_priv *rt715, unsigned int nid, - unsigned int reg, unsigned int value) -{ - struct regmap *regmap = rt715->mbq_regmap; - unsigned int addr; - int ret; - - addr = (nid << 20) | reg; - - ret = regmap_write(regmap, addr, value); - if (ret < 0) - dev_err(&rt715->slave->dev, - "Failed to set private value: %08x <= %04x %d\n", ret, addr, - value); - - return ret; -} - -static int rt715_index_read(struct rt715_sdca_priv *rt715, - unsigned int nid, unsigned int reg, unsigned int *value) -{ - struct regmap *regmap = rt715->mbq_regmap; - unsigned int addr; - int ret; - - addr = (nid << 20) | reg; - - ret = regmap_read(regmap, addr, value); - if (ret < 0) - dev_err(&rt715->slave->dev, - "Failed to get private value: %06x => %04x ret=%d\n", - addr, *value, ret); - - return ret; -} - -static int rt715_index_update_bits(struct rt715_sdca_priv *rt715, - unsigned int nid, unsigned int reg, unsigned int mask, unsigned int val) -{ - unsigned int tmp; - int ret; - - ret = rt715_index_read(rt715, nid, reg, &tmp); - if (ret < 0) - return ret; - - set_mask_bits(&tmp, mask, val); - - return rt715_index_write(rt715, nid, reg, tmp); -} - -/* SDCA Volume/Boost control */ -static int rt715_set_amp_gain_put_sdca(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); - unsigned int val_l, val_r, gain_l_val, gain_r_val; - int ret; - - /* control value to 2s complement */ - /* L channel */ - gain_l_val = ucontrol->value.integer.value[0]; - if (gain_l_val > mc->max) - gain_l_val = mc->max; - val_l = gain_l_val; - - if (mc->shift == 8) { - gain_l_val = (gain_l_val * 10) << mc->shift; - } else { - gain_l_val = - ((abs(gain_l_val - mc->shift) * RT715_SDCA_DB_STEP) << 8) / 1000; - if (val_l <= mc->shift) { - gain_l_val = ~gain_l_val; - gain_l_val += 1; - } - gain_l_val &= 0xffff; - } - - /* R channel */ - gain_r_val = ucontrol->value.integer.value[1]; - if (gain_r_val > mc->max) - gain_r_val = mc->max; - val_r = gain_r_val; - - if (mc->shift == 8) { - gain_r_val = (gain_r_val * 10) << mc->shift; - } else { - gain_r_val = - ((abs(gain_r_val - mc->shift) * RT715_SDCA_DB_STEP) << 8) / 1000; - if (val_r <= mc->shift) { - gain_r_val = ~gain_r_val; - gain_r_val += 1; - } - gain_r_val &= 0xffff; - } - - /* Lch*/ - ret = regmap_write(rt715->mbq_regmap, mc->reg, gain_l_val); - if (ret != 0) { - dev_err(component->dev, "Failed to write 0x%x=0x%x\n", mc->reg, - gain_l_val); - return ret; - } - /* Rch */ - ret = regmap_write(rt715->mbq_regmap, mc->rreg, gain_r_val); - if (ret != 0) { - dev_err(component->dev, "Failed to write 0x%x=0x%x\n", mc->rreg, - gain_r_val); - return ret; - } - - return 0; -} - -static int rt715_set_amp_gain_get_sdca(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); - unsigned int val_l, val_r, ctl_l, ctl_r, neg_flag = 0; - int ret; - - ret = regmap_read(rt715->mbq_regmap, mc->reg, &val_l); - if (ret < 0) - dev_err(component->dev, "Failed to read 0x%x, ret=%d\n", mc->reg, ret); - ret = regmap_read(rt715->mbq_regmap, mc->rreg, &val_r); - if (ret < 0) - dev_err(component->dev, "Failed to read 0x%x, ret=%d\n", mc->rreg, - ret); - - /* L channel */ - if (mc->shift == 8) { - ctl_l = (val_l >> mc->shift) / 10; - } else { - ctl_l = val_l; - if (ctl_l & BIT(15)) { - ctl_l = ~(val_l - 1) & 0xffff; - neg_flag = 1; - } - ctl_l *= 1000; - ctl_l >>= 8; - if (neg_flag) - ctl_l = mc->shift - ctl_l / RT715_SDCA_DB_STEP; - else - ctl_l = mc->shift + ctl_l / RT715_SDCA_DB_STEP; - } - - neg_flag = 0; - /* R channel */ - if (mc->shift == 8) { - ctl_r = (val_r >> mc->shift) / 10; - } else { - ctl_r = val_r; - if (ctl_r & BIT(15)) { - ctl_r = ~(val_r - 1) & 0xffff; - neg_flag = 1; - } - ctl_r *= 1000; - ctl_r >>= 8; - if (neg_flag) - ctl_r = mc->shift - ctl_r / RT715_SDCA_DB_STEP; - else - ctl_r = mc->shift + ctl_r / RT715_SDCA_DB_STEP; - } - - ucontrol->value.integer.value[0] = ctl_l; - ucontrol->value.integer.value[1] = ctl_r; - - return 0; -} - -static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -17625, 375, 0); -static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0); - -#define SOC_DOUBLE_R_EXT(xname, reg_left, reg_right, xshift, xmax, xinvert,\ - xhandler_get, xhandler_put) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ - .info = snd_soc_info_volsw, \ - .get = xhandler_get, .put = xhandler_put, \ - .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ - xmax, xinvert) } - -static const struct snd_kcontrol_new rt715_snd_controls_sdca[] = { - /* Capture switch */ - SOC_DOUBLE_R("FU0A Capture Switch", - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC7_27_VOL, - RT715_SDCA_FU_MUTE_CTRL, CH_01), - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC7_27_VOL, - RT715_SDCA_FU_MUTE_CTRL, CH_02), - 0, 1, 1), - SOC_DOUBLE_R("FU02 1_2 Capture Switch", - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC8_9_VOL, - RT715_SDCA_FU_MUTE_CTRL, CH_01), - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC8_9_VOL, - RT715_SDCA_FU_MUTE_CTRL, CH_02), - 0, 1, 1), - SOC_DOUBLE_R("FU02 3_4 Capture Switch", - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC8_9_VOL, - RT715_SDCA_FU_MUTE_CTRL, CH_03), - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC8_9_VOL, - RT715_SDCA_FU_MUTE_CTRL, CH_04), - 0, 1, 1), - SOC_DOUBLE_R("FU06 1_2 Capture Switch", - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC10_11_VOL, - RT715_SDCA_FU_MUTE_CTRL, CH_01), - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC10_11_VOL, - RT715_SDCA_FU_MUTE_CTRL, CH_02), - 0, 1, 1), - SOC_DOUBLE_R("FU06 3_4 Capture Switch", - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC10_11_VOL, - RT715_SDCA_FU_MUTE_CTRL, CH_03), - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC10_11_VOL, - RT715_SDCA_FU_MUTE_CTRL, CH_04), - 0, 1, 1), - /* Volume Control */ - SOC_DOUBLE_R_EXT_TLV("FU0A Capture Volume", - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC7_27_VOL, - RT715_SDCA_FU_VOL_CTRL, CH_01), - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC7_27_VOL, - RT715_SDCA_FU_VOL_CTRL, CH_02), - 0x2f, 0x7f, 0, - rt715_set_amp_gain_get_sdca, rt715_set_amp_gain_put_sdca, - in_vol_tlv), - SOC_DOUBLE_R_EXT_TLV("FU02 1_2 Capture Volume", - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC8_9_VOL, - RT715_SDCA_FU_VOL_CTRL, CH_01), - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC8_9_VOL, - RT715_SDCA_FU_VOL_CTRL, CH_02), - 0x2f, 0x7f, 0, - rt715_set_amp_gain_get_sdca, rt715_set_amp_gain_put_sdca, - in_vol_tlv), - SOC_DOUBLE_R_EXT_TLV("FU02 3_4 Capture Volume", - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC8_9_VOL, - RT715_SDCA_FU_VOL_CTRL, - CH_03), - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC8_9_VOL, - RT715_SDCA_FU_VOL_CTRL, - CH_04), 0x2f, 0x7f, 0, - rt715_set_amp_gain_get_sdca, rt715_set_amp_gain_put_sdca, - in_vol_tlv), - SOC_DOUBLE_R_EXT_TLV("FU06 1_2 Capture Volume", - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC10_11_VOL, - RT715_SDCA_FU_VOL_CTRL, - CH_01), - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC10_11_VOL, - RT715_SDCA_FU_VOL_CTRL, - CH_02), 0x2f, 0x7f, 0, - rt715_set_amp_gain_get_sdca, rt715_set_amp_gain_put_sdca, - in_vol_tlv), - SOC_DOUBLE_R_EXT_TLV("FU06 3_4 Capture Volume", - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC10_11_VOL, - RT715_SDCA_FU_VOL_CTRL, - CH_03), - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC10_11_VOL, - RT715_SDCA_FU_VOL_CTRL, - CH_04), 0x2f, 0x7f, 0, - rt715_set_amp_gain_get_sdca, rt715_set_amp_gain_put_sdca, - in_vol_tlv), - /* MIC Boost Control */ - SOC_DOUBLE_R_EXT_TLV("FU0E 1_2 Boost", - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_DMIC_GAIN_EN, - RT715_SDCA_FU_DMIC_GAIN_CTRL, - CH_01), - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_DMIC_GAIN_EN, - RT715_SDCA_FU_DMIC_GAIN_CTRL, - CH_02), 8, 3, 0, - rt715_set_amp_gain_get_sdca, rt715_set_amp_gain_put_sdca, - mic_vol_tlv), - SOC_DOUBLE_R_EXT_TLV("FU0E 3_4 Boost", - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_DMIC_GAIN_EN, - RT715_SDCA_FU_DMIC_GAIN_CTRL, - CH_03), - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_DMIC_GAIN_EN, - RT715_SDCA_FU_DMIC_GAIN_CTRL, - CH_04), 8, 3, 0, - rt715_set_amp_gain_get_sdca, rt715_set_amp_gain_put_sdca, - mic_vol_tlv), - SOC_DOUBLE_R_EXT_TLV("FU0E 5_6 Boost", - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_DMIC_GAIN_EN, - RT715_SDCA_FU_DMIC_GAIN_CTRL, - CH_05), - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_DMIC_GAIN_EN, - RT715_SDCA_FU_DMIC_GAIN_CTRL, - CH_06), 8, 3, 0, - rt715_set_amp_gain_get_sdca, rt715_set_amp_gain_put_sdca, - mic_vol_tlv), - SOC_DOUBLE_R_EXT_TLV("FU0E 7_8 Boost", - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_DMIC_GAIN_EN, - RT715_SDCA_FU_DMIC_GAIN_CTRL, - CH_07), - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_DMIC_GAIN_EN, - RT715_SDCA_FU_DMIC_GAIN_CTRL, - CH_08), 8, 3, 0, - rt715_set_amp_gain_get_sdca, rt715_set_amp_gain_put_sdca, - mic_vol_tlv), - SOC_DOUBLE_R_EXT_TLV("FU0C 1_2 Boost", - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_AMIC_GAIN_EN, - RT715_SDCA_FU_DMIC_GAIN_CTRL, - CH_01), - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_AMIC_GAIN_EN, - RT715_SDCA_FU_DMIC_GAIN_CTRL, - CH_02), 8, 3, 0, - rt715_set_amp_gain_get_sdca, rt715_set_amp_gain_put_sdca, - mic_vol_tlv), - SOC_DOUBLE_R_EXT_TLV("FU0C 3_4 Boost", - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_AMIC_GAIN_EN, - RT715_SDCA_FU_DMIC_GAIN_CTRL, - CH_03), - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_AMIC_GAIN_EN, - RT715_SDCA_FU_DMIC_GAIN_CTRL, - CH_04), 8, 3, 0, - rt715_set_amp_gain_get_sdca, rt715_set_amp_gain_put_sdca, - mic_vol_tlv), - SOC_DOUBLE_R_EXT_TLV("FU0C 5_6 Boost", - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_AMIC_GAIN_EN, - RT715_SDCA_FU_DMIC_GAIN_CTRL, - CH_05), - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_AMIC_GAIN_EN, - RT715_SDCA_FU_DMIC_GAIN_CTRL, - CH_06), 8, 3, 0, - rt715_set_amp_gain_get_sdca, rt715_set_amp_gain_put_sdca, - mic_vol_tlv), - SOC_DOUBLE_R_EXT_TLV("FU0C 7_8 Boost", - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_AMIC_GAIN_EN, - RT715_SDCA_FU_DMIC_GAIN_CTRL, - CH_07), - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_AMIC_GAIN_EN, - RT715_SDCA_FU_DMIC_GAIN_CTRL, - CH_08), 8, 3, 0, - rt715_set_amp_gain_get_sdca, rt715_set_amp_gain_put_sdca, - mic_vol_tlv), -}; - -static int rt715_mux_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_component *component = - snd_soc_dapm_kcontrol_component(kcontrol); - struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); - unsigned int val, mask_sft; - - if (strstr(ucontrol->id.name, "ADC 22 Mux")) - mask_sft = 12; - else if (strstr(ucontrol->id.name, "ADC 23 Mux")) - mask_sft = 8; - else if (strstr(ucontrol->id.name, "ADC 24 Mux")) - mask_sft = 4; - else if (strstr(ucontrol->id.name, "ADC 25 Mux")) - mask_sft = 0; - else - return -EINVAL; - - rt715_index_read(rt715, RT715_VENDOR_HDA_CTL, - RT715_HDA_LEGACY_MUX_CTL1, &val); - val = (val >> mask_sft) & 0xf; - - /* - * The first two indices of ADC Mux 24/25 are routed to the same - * hardware source. ie, ADC Mux 24 0/1 will both connect to MIC2. - * To have a unique set of inputs, we skip the index1 of the muxes. - */ - if ((strstr(ucontrol->id.name, "ADC 24 Mux") || - strstr(ucontrol->id.name, "ADC 25 Mux")) && val > 0) - val -= 1; - ucontrol->value.enumerated.item[0] = val; - - return 0; -} - -static int rt715_mux_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_component *component = - snd_soc_dapm_kcontrol_component(kcontrol); - struct snd_soc_dapm_context *dapm = - snd_soc_dapm_kcontrol_dapm(kcontrol); - struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int *item = ucontrol->value.enumerated.item; - unsigned int val, val2 = 0, change, mask_sft; - - if (item[0] >= e->items) - return -EINVAL; - - if (strstr(ucontrol->id.name, "ADC 22 Mux")) - mask_sft = 12; - else if (strstr(ucontrol->id.name, "ADC 23 Mux")) - mask_sft = 8; - else if (strstr(ucontrol->id.name, "ADC 24 Mux")) - mask_sft = 4; - else if (strstr(ucontrol->id.name, "ADC 25 Mux")) - mask_sft = 0; - else - return -EINVAL; - - /* Verb ID = 0x701h, nid = e->reg */ - val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l; - - rt715_index_read(rt715, RT715_VENDOR_HDA_CTL, - RT715_HDA_LEGACY_MUX_CTL1, &val2); - val2 = (val2 >> mask_sft) & 0xf; - - change = val != val2; - - if (change) - rt715_index_update_bits(rt715, RT715_VENDOR_HDA_CTL, - RT715_HDA_LEGACY_MUX_CTL1, 0xf << mask_sft, val << mask_sft); - - snd_soc_dapm_mux_update_power(dapm, kcontrol, item[0], e, NULL); - - return change; -} - -static const char * const adc_22_23_mux_text[] = { - "MIC1", - "MIC2", - "LINE1", - "LINE2", - "DMIC1", - "DMIC2", - "DMIC3", - "DMIC4", -}; - -/* - * Due to mux design for nid 24 (MUX_IN3)/25 (MUX_IN4), connection index 0 and - * 1 will be connected to the same dmic source, therefore we skip index 1 to - * avoid misunderstanding on usage of dapm routing. - */ -static int rt715_adc_24_25_values[] = { - 0, - 2, - 3, - 4, - 5, -}; - -static const char * const adc_24_mux_text[] = { - "MIC2", - "DMIC1", - "DMIC2", - "DMIC3", - "DMIC4", -}; - -static const char * const adc_25_mux_text[] = { - "MIC1", - "DMIC1", - "DMIC2", - "DMIC3", - "DMIC4", -}; - -static SOC_ENUM_SINGLE_DECL(rt715_adc22_enum, SND_SOC_NOPM, 0, - adc_22_23_mux_text); - -static SOC_ENUM_SINGLE_DECL(rt715_adc23_enum, SND_SOC_NOPM, 0, - adc_22_23_mux_text); - -static SOC_VALUE_ENUM_SINGLE_DECL(rt715_adc24_enum, - SND_SOC_NOPM, 0, 0xf, - adc_24_mux_text, rt715_adc_24_25_values); -static SOC_VALUE_ENUM_SINGLE_DECL(rt715_adc25_enum, - SND_SOC_NOPM, 0, 0xf, - adc_25_mux_text, rt715_adc_24_25_values); - -static const struct snd_kcontrol_new rt715_adc22_mux = - SOC_DAPM_ENUM_EXT("ADC 22 Mux", rt715_adc22_enum, - rt715_mux_get, rt715_mux_put); - -static const struct snd_kcontrol_new rt715_adc23_mux = - SOC_DAPM_ENUM_EXT("ADC 23 Mux", rt715_adc23_enum, - rt715_mux_get, rt715_mux_put); - -static const struct snd_kcontrol_new rt715_adc24_mux = - SOC_DAPM_ENUM_EXT("ADC 24 Mux", rt715_adc24_enum, - rt715_mux_get, rt715_mux_put); - -static const struct snd_kcontrol_new rt715_adc25_mux = - SOC_DAPM_ENUM_EXT("ADC 25 Mux", rt715_adc25_enum, - rt715_mux_get, rt715_mux_put); - -static int rt715_pde23_24_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_component *component = - snd_soc_dapm_to_component(w->dapm); - struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); - - switch (event) { - case SND_SOC_DAPM_POST_PMU: - regmap_write(rt715->regmap, - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_CREQ_POW_EN, - RT715_SDCA_REQ_POW_CTRL, - CH_00), 0x00); - break; - case SND_SOC_DAPM_PRE_PMD: - regmap_write(rt715->regmap, - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_CREQ_POW_EN, - RT715_SDCA_REQ_POW_CTRL, - CH_00), 0x03); - break; - } - return 0; -} - -static const struct snd_soc_dapm_widget rt715_dapm_widgets[] = { - SND_SOC_DAPM_INPUT("DMIC1"), - SND_SOC_DAPM_INPUT("DMIC2"), - SND_SOC_DAPM_INPUT("DMIC3"), - SND_SOC_DAPM_INPUT("DMIC4"), - SND_SOC_DAPM_INPUT("MIC1"), - SND_SOC_DAPM_INPUT("MIC2"), - SND_SOC_DAPM_INPUT("LINE1"), - SND_SOC_DAPM_INPUT("LINE2"), - - SND_SOC_DAPM_SUPPLY("PDE23_24", SND_SOC_NOPM, 0, 0, - rt715_pde23_24_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - - SND_SOC_DAPM_ADC("ADC 07", NULL, SND_SOC_NOPM, 4, 0), - SND_SOC_DAPM_ADC("ADC 08", NULL, SND_SOC_NOPM, 4, 0), - SND_SOC_DAPM_ADC("ADC 09", NULL, SND_SOC_NOPM, 4, 0), - SND_SOC_DAPM_ADC("ADC 27", NULL, SND_SOC_NOPM, 4, 0), - SND_SOC_DAPM_MUX("ADC 22 Mux", SND_SOC_NOPM, 0, 0, - &rt715_adc22_mux), - SND_SOC_DAPM_MUX("ADC 23 Mux", SND_SOC_NOPM, 0, 0, - &rt715_adc23_mux), - SND_SOC_DAPM_MUX("ADC 24 Mux", SND_SOC_NOPM, 0, 0, - &rt715_adc24_mux), - SND_SOC_DAPM_MUX("ADC 25 Mux", SND_SOC_NOPM, 0, 0, - &rt715_adc25_mux), - SND_SOC_DAPM_AIF_OUT("DP4TX", "DP4 Capture", 0, SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_AIF_OUT("DP6TX", "DP6 Capture", 0, SND_SOC_NOPM, 0, 0), -}; - -static const struct snd_soc_dapm_route rt715_audio_map[] = { - {"DP6TX", NULL, "ADC 09"}, - {"DP6TX", NULL, "ADC 08"}, - {"DP4TX", NULL, "ADC 07"}, - {"DP4TX", NULL, "ADC 27"}, - {"DP4TX", NULL, "ADC 09"}, - {"DP4TX", NULL, "ADC 08"}, - - {"LINE1", NULL, "PDE23_24"}, - {"LINE2", NULL, "PDE23_24"}, - {"MIC1", NULL, "PDE23_24"}, - {"MIC2", NULL, "PDE23_24"}, - {"DMIC1", NULL, "PDE23_24"}, - {"DMIC2", NULL, "PDE23_24"}, - {"DMIC3", NULL, "PDE23_24"}, - {"DMIC4", NULL, "PDE23_24"}, - - {"ADC 09", NULL, "ADC 22 Mux"}, - {"ADC 08", NULL, "ADC 23 Mux"}, - {"ADC 07", NULL, "ADC 24 Mux"}, - {"ADC 27", NULL, "ADC 25 Mux"}, - {"ADC 22 Mux", "MIC1", "MIC1"}, - {"ADC 22 Mux", "MIC2", "MIC2"}, - {"ADC 22 Mux", "LINE1", "LINE1"}, - {"ADC 22 Mux", "LINE2", "LINE2"}, - {"ADC 22 Mux", "DMIC1", "DMIC1"}, - {"ADC 22 Mux", "DMIC2", "DMIC2"}, - {"ADC 22 Mux", "DMIC3", "DMIC3"}, - {"ADC 22 Mux", "DMIC4", "DMIC4"}, - {"ADC 23 Mux", "MIC1", "MIC1"}, - {"ADC 23 Mux", "MIC2", "MIC2"}, - {"ADC 23 Mux", "LINE1", "LINE1"}, - {"ADC 23 Mux", "LINE2", "LINE2"}, - {"ADC 23 Mux", "DMIC1", "DMIC1"}, - {"ADC 23 Mux", "DMIC2", "DMIC2"}, - {"ADC 23 Mux", "DMIC3", "DMIC3"}, - {"ADC 23 Mux", "DMIC4", "DMIC4"}, - {"ADC 24 Mux", "MIC2", "MIC2"}, - {"ADC 24 Mux", "DMIC1", "DMIC1"}, - {"ADC 24 Mux", "DMIC2", "DMIC2"}, - {"ADC 24 Mux", "DMIC3", "DMIC3"}, - {"ADC 24 Mux", "DMIC4", "DMIC4"}, - {"ADC 25 Mux", "MIC1", "MIC1"}, - {"ADC 25 Mux", "DMIC1", "DMIC1"}, - {"ADC 25 Mux", "DMIC2", "DMIC2"}, - {"ADC 25 Mux", "DMIC3", "DMIC3"}, - {"ADC 25 Mux", "DMIC4", "DMIC4"}, -}; - -static const struct snd_soc_component_driver soc_codec_dev_rt715_sdca = { - .controls = rt715_snd_controls_sdca, - .num_controls = ARRAY_SIZE(rt715_snd_controls_sdca), - .dapm_widgets = rt715_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(rt715_dapm_widgets), - .dapm_routes = rt715_audio_map, - .num_dapm_routes = ARRAY_SIZE(rt715_audio_map), -}; - -static int rt715_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, - int direction) -{ - struct rt715_sdw_stream_data *stream; - - stream = kzalloc(sizeof(*stream), GFP_KERNEL); - if (!stream) - return -ENOMEM; - - stream->sdw_stream = sdw_stream; - - /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ - if (direction == SNDRV_PCM_STREAM_PLAYBACK) - dai->playback_dma_data = stream; - else - dai->capture_dma_data = stream; - - return 0; -} - -static void rt715_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) - -{ - struct rt715_sdw_stream_data *stream; - - stream = snd_soc_dai_get_dma_data(dai, substream); - if (!stream) - return; - - snd_soc_dai_set_dma_data(dai, substream, NULL); - kfree(stream); -} - -static int rt715_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_component *component = dai->component; - struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); - struct sdw_stream_config stream_config; - struct sdw_port_config port_config; - enum sdw_data_direction direction; - struct rt715_sdw_stream_data *stream; - int retval, port, num_channels; - unsigned int val; - - stream = snd_soc_dai_get_dma_data(dai, substream); - - if (!stream) - return -EINVAL; - - if (!rt715->slave) - return -EINVAL; - - switch (dai->id) { - case RT715_AIF1: - direction = SDW_DATA_DIR_TX; - port = 6; - rt715_index_write(rt715, RT715_VENDOR_REG, RT715_SDW_INPUT_SEL, - 0xa500); - break; - case RT715_AIF2: - direction = SDW_DATA_DIR_TX; - port = 4; - rt715_index_write(rt715, RT715_VENDOR_REG, RT715_SDW_INPUT_SEL, - 0xaf00); - break; - default: - dev_err(component->dev, "Invalid DAI id %d\n", dai->id); - return -EINVAL; - } - - stream_config.frame_rate = params_rate(params); - stream_config.ch_count = params_channels(params); - stream_config.bps = snd_pcm_format_width(params_format(params)); - stream_config.direction = direction; - - num_channels = params_channels(params); - port_config.ch_mask = GENMASK(num_channels - 1, 0); - port_config.num = port; - - retval = sdw_stream_add_slave(rt715->slave, &stream_config, - &port_config, 1, stream->sdw_stream); - if (retval) { - dev_err(component->dev, "Unable to configure port, retval:%d\n", - retval); - return retval; - } - - switch (params_rate(params)) { - case 8000: - val = 0x1; - break; - case 11025: - val = 0x2; - break; - case 12000: - val = 0x3; - break; - case 16000: - val = 0x4; - break; - case 22050: - val = 0x5; - break; - case 24000: - val = 0x6; - break; - case 32000: - val = 0x7; - break; - case 44100: - val = 0x8; - break; - case 48000: - val = 0x9; - break; - case 88200: - val = 0xa; - break; - case 96000: - val = 0xb; - break; - case 176400: - val = 0xc; - break; - case 192000: - val = 0xd; - break; - case 384000: - val = 0xe; - break; - case 768000: - val = 0xf; - break; - default: - dev_err(component->dev, "Unsupported sample rate %d\n", - params_rate(params)); - return -EINVAL; - } - - regmap_write(rt715->regmap, - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_CS_FREQ_IND_EN, - RT715_SDCA_FREQ_IND_CTRL, CH_00), val); - - return 0; -} - -static int rt715_pcm_hw_free(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_component *component = dai->component; - struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); - struct rt715_sdw_stream_data *stream = - snd_soc_dai_get_dma_data(dai, substream); - - if (!rt715->slave) - return -EINVAL; - - sdw_stream_remove_slave(rt715->slave, stream->sdw_stream); - return 0; -} - -#define RT715_STEREO_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) -#define RT715_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) - -static struct snd_soc_dai_ops rt715_ops = { - .hw_params = rt715_pcm_hw_params, - .hw_free = rt715_pcm_hw_free, - .set_sdw_stream = rt715_set_sdw_stream, - .shutdown = rt715_shutdown, -}; - -static struct snd_soc_dai_driver rt715_dai[] = { - { - .name = "rt715-aif1", - .id = RT715_AIF1, - .capture = { - .stream_name = "DP6 Capture", - .channels_min = 1, - .channels_max = 2, - .rates = RT715_STEREO_RATES, - .formats = RT715_FORMATS, - }, - .ops = &rt715_ops, - }, - { - .name = "rt715-aif2", - .id = RT715_AIF2, - .capture = { - .stream_name = "DP4 Capture", - .channels_min = 1, - .channels_max = 2, - .rates = RT715_STEREO_RATES, - .formats = RT715_FORMATS, - }, - .ops = &rt715_ops, - }, -}; - -/* Bus clock frequency */ -#define RT715_CLK_FREQ_9600000HZ 9600000 -#define RT715_CLK_FREQ_12000000HZ 12000000 -#define RT715_CLK_FREQ_6000000HZ 6000000 -#define RT715_CLK_FREQ_4800000HZ 4800000 -#define RT715_CLK_FREQ_2400000HZ 2400000 -#define RT715_CLK_FREQ_12288000HZ 12288000 - -int rt715_init(struct device *dev, struct regmap *mbq_regmap, - struct regmap *regmap, struct sdw_slave *slave) -{ - struct rt715_sdca_priv *rt715; - int ret; - - rt715 = devm_kzalloc(dev, sizeof(*rt715), GFP_KERNEL); - if (!rt715) - return -ENOMEM; - - dev_set_drvdata(dev, rt715); - rt715->slave = slave; - rt715->regmap = regmap; - rt715->mbq_regmap = mbq_regmap; - rt715->hw_sdw_ver = slave->id.sdw_version; - /* - * Mark hw_init to false - * HW init will be performed when device reports present - */ - rt715->hw_init = false; - rt715->first_init = false; - - ret = devm_snd_soc_register_component(dev, - &soc_codec_dev_rt715_sdca, - rt715_dai, - ARRAY_SIZE(rt715_dai)); - - return ret; -} - -int rt715_io_init(struct device *dev, struct sdw_slave *slave) -{ - struct rt715_sdca_priv *rt715 = dev_get_drvdata(dev); - unsigned int hw_ver; - - if (rt715->hw_init) - return 0; - - /* - * PM runtime is only enabled when a Slave reports as Attached - */ - if (!rt715->first_init) { - /* set autosuspend parameters */ - pm_runtime_set_autosuspend_delay(&slave->dev, 3000); - pm_runtime_use_autosuspend(&slave->dev); - - /* update count of parent 'active' children */ - pm_runtime_set_active(&slave->dev); - - /* make sure the device does not suspend immediately */ - pm_runtime_mark_last_busy(&slave->dev); - - pm_runtime_enable(&slave->dev); - - rt715->first_init = true; - } - - pm_runtime_get_noresume(&slave->dev); - - rt715_index_read(rt715, RT715_VENDOR_REG, - RT715_PRODUCT_NUM, &hw_ver); - hw_ver = hw_ver & 0x000f; - - /* set clock selector = external */ - regmap_write(rt715->regmap, - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_CX_CLK_SEL_EN, - RT715_SDCA_CX_CLK_SEL_CTRL, CH_00), 0x1); - /* set GPIO_4/5/6 to be 3rd/4th DMIC usage */ - if (hw_ver == 0x0) - rt715_index_update_bits(rt715, RT715_VENDOR_REG, - RT715_AD_FUNC_EN, 0x54, 0x54); - else if (hw_ver == 0x1) { - rt715_index_update_bits(rt715, RT715_VENDOR_REG, - RT715_AD_FUNC_EN, 0x55, 0x55); - rt715_index_update_bits(rt715, RT715_VENDOR_REG, - RT715_REV_1, 0x40, 0x40); - } - /* trigger mode = VAD enable */ - regmap_write(rt715->regmap, - SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_SMPU_TRIG_ST_EN, - RT715_SDCA_SMPU_TRIG_EN_CTRL, CH_00), 0x2); - /* SMPU-1 interrupt enable mask */ - regmap_update_bits(rt715->regmap, RT715_INT_MASK, 0x1, 0x1); - - /* Mark Slave initialization complete */ - rt715->hw_init = true; - - pm_runtime_mark_last_busy(&slave->dev); - pm_runtime_put_autosuspend(&slave->dev); - - return 0; -} - -MODULE_DESCRIPTION("ASoC rt715 driver SDW SDCA"); -MODULE_AUTHOR("Jack Yu <jack.yu@realtek.com>"); -MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/rt715-sdca.h b/sound/soc/codecs/rt715-sdca.h deleted file mode 100644 index 6326cd8c374e..000000000000 --- a/sound/soc/codecs/rt715-sdca.h +++ /dev/null @@ -1,124 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * rt715-sdca.h -- RT715 ALSA SoC audio driver header - * - * Copyright(c) 2020 Realtek Semiconductor Corp. - */ - -#ifndef __RT715_SDCA_H__ -#define __RT715_SDCA_H__ - -#include <linux/regmap.h> -#include <linux/soundwire/sdw.h> -#include <linux/soundwire/sdw_type.h> -#include <sound/soc.h> -#include <linux/workqueue.h> -#include <linux/device.h> - -struct rt715_sdca_priv { - struct regmap *regmap; - struct regmap *mbq_regmap; - struct snd_soc_codec *codec; - struct sdw_slave *slave; - struct delayed_work adc_mute_work; - int dbg_nid; - int dbg_vid; - int dbg_payload; - enum sdw_slave_status status; - struct sdw_bus_params params; - bool hw_init; - bool first_init; - int l_is_unmute; - int r_is_unmute; - int hw_sdw_ver; -}; - -struct rt715_sdw_stream_data { - struct sdw_stream_runtime *sdw_stream; -}; - -/* MIPI Register */ -#define RT715_INT_CTRL 0x005a -#define RT715_INT_MASK 0x005e - -/* NID */ -#define RT715_AUDIO_FUNCTION_GROUP 0x01 -#define RT715_MIC_ADC 0x07 -#define RT715_LINE_ADC 0x08 -#define RT715_MIX_ADC 0x09 -#define RT715_DMIC1 0x12 -#define RT715_DMIC2 0x13 -#define RT715_MIC1 0x18 -#define RT715_MIC2 0x19 -#define RT715_LINE1 0x1a -#define RT715_LINE2 0x1b -#define RT715_DMIC3 0x1d -#define RT715_DMIC4 0x29 -#define RT715_VENDOR_REG 0x20 -#define RT715_MUX_IN1 0x22 -#define RT715_MUX_IN2 0x23 -#define RT715_MUX_IN3 0x24 -#define RT715_MUX_IN4 0x25 -#define RT715_MIX_ADC2 0x27 -#define RT715_INLINE_CMD 0x55 -#define RT715_VENDOR_HDA_CTL 0x61 - -/* Index (NID:20h) */ -#define RT715_PRODUCT_NUM 0x0 -#define RT715_IRQ_CTRL 0x2b -#define RT715_AD_FUNC_EN 0x36 -#define RT715_REV_1 0x37 -#define RT715_SDW_INPUT_SEL 0x39 -#define RT715_EXT_DMIC_CLK_CTRL2 0x54 - -/* Index (NID:61h) */ -#define RT715_HDA_LEGACY_MUX_CTL1 0x00 - -/* SDCA (Function) */ -#define FUN_JACK_CODEC 0x01 -#define FUN_MIC_ARRAY 0x02 -#define FUN_HID 0x03 -/* SDCA (Entity) */ -#define RT715_SDCA_ST_EN 0x00 -#define RT715_SDCA_CS_FREQ_IND_EN 0x01 -#define RT715_SDCA_FU_ADC8_9_VOL 0x02 -#define RT715_SDCA_SMPU_TRIG_ST_EN 0x05 -#define RT715_SDCA_FU_ADC10_11_VOL 0x06 -#define RT715_SDCA_FU_ADC7_27_VOL 0x0a -#define RT715_SDCA_FU_AMIC_GAIN_EN 0x0c -#define RT715_SDCA_FU_DMIC_GAIN_EN 0x0e -#define RT715_SDCA_CX_CLK_SEL_EN 0x10 -#define RT715_SDCA_CREQ_POW_EN 0x18 -/* SDCA (Control) */ -#define RT715_SDCA_ST_CTRL 0x00 -#define RT715_SDCA_CX_CLK_SEL_CTRL 0x01 -#define RT715_SDCA_REQ_POW_CTRL 0x01 -#define RT715_SDCA_FU_MUTE_CTRL 0x01 -#define RT715_SDCA_FU_VOL_CTRL 0x02 -#define RT715_SDCA_FU_DMIC_GAIN_CTRL 0x0b -#define RT715_SDCA_FREQ_IND_CTRL 0x10 -#define RT715_SDCA_SMPU_TRIG_EN_CTRL 0x10 -#define RT715_SDCA_SMPU_TRIG_ST_CTRL 0x11 -/* SDCA (Channel) */ -#define CH_00 0x00 -#define CH_01 0x01 -#define CH_02 0x02 -#define CH_03 0x03 -#define CH_04 0x04 -#define CH_05 0x05 -#define CH_06 0x06 -#define CH_07 0x07 -#define CH_08 0x08 - -#define RT715_SDCA_DB_STEP 375 - -enum { - RT715_AIF1, - RT715_AIF2, -}; - -int rt715_io_init(struct device *dev, struct sdw_slave *slave); -int rt715_init(struct device *dev, struct regmap *mbq_regmap, - struct regmap *regmap, struct sdw_slave *slave); - -#endif /* __RT715_SDCA_H__ */ diff --git a/sound/soc/fsl/imx-hdmi.c b/sound/soc/fsl/imx-hdmi.c index 2c2a76a71940..ede4a9ad1054 100644 --- a/sound/soc/fsl/imx-hdmi.c +++ b/sound/soc/fsl/imx-hdmi.c @@ -164,6 +164,7 @@ static int imx_hdmi_probe(struct platform_device *pdev) if ((hdmi_out && hdmi_in) || (!hdmi_out && !hdmi_in)) { dev_err(&pdev->dev, "Invalid HDMI DAI link\n"); + ret = -EINVAL; goto fail; } diff --git a/sound/soc/intel/boards/haswell.c b/sound/soc/intel/boards/haswell.c index c55d1239e705..c763bfeb1f38 100644 --- a/sound/soc/intel/boards/haswell.c +++ b/sound/soc/intel/boards/haswell.c @@ -189,6 +189,7 @@ static struct platform_driver haswell_audio = { .probe = haswell_audio_probe, .driver = { .name = "haswell-audio", + .pm = &snd_soc_pm_ops, }, }; diff --git a/sound/soc/intel/catpt/core.h b/sound/soc/intel/catpt/core.h index 0f53a0d43254..a64a0a77dcb7 100644 --- a/sound/soc/intel/catpt/core.h +++ b/sound/soc/intel/catpt/core.h @@ -22,17 +22,6 @@ void catpt_sram_free(struct resource *sram); struct resource * catpt_request_region(struct resource *root, resource_size_t size); -static inline bool catpt_resource_overlapping(struct resource *r1, - struct resource *r2, - struct resource *ret) -{ - if (!resource_overlaps(r1, r2)) - return false; - ret->start = max(r1->start, r2->start); - ret->end = min(r1->end, r2->end); - return true; -} - struct catpt_ipc_msg { union { u32 header; diff --git a/sound/soc/intel/catpt/loader.c b/sound/soc/intel/catpt/loader.c index 40c22e4bb263..ff7b8f0d34ac 100644 --- a/sound/soc/intel/catpt/loader.c +++ b/sound/soc/intel/catpt/loader.c @@ -267,7 +267,7 @@ static int catpt_restore_fwimage(struct catpt_dev *cdev, r2.start = off; r2.end = r2.start + info->size - 1; - if (!catpt_resource_overlapping(&r2, &r1, &common)) + if (!resource_intersection(&r2, &r1, &common)) continue; /* calculate start offset of common data area */ off = common.start - r1.start; diff --git a/sound/soc/intel/skylake/cnl-sst.c b/sound/soc/intel/skylake/cnl-sst.c index fcd8dff27ae8..1275c149acc0 100644 --- a/sound/soc/intel/skylake/cnl-sst.c +++ b/sound/soc/intel/skylake/cnl-sst.c @@ -224,6 +224,7 @@ static int cnl_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id) "dsp boot timeout, status=%#x error=%#x\n", sst_dsp_shim_read(ctx, CNL_ADSP_FW_STATUS), sst_dsp_shim_read(ctx, CNL_ADSP_ERROR_CODE)); + ret = -ETIMEDOUT; goto err; } } else { diff --git a/sound/soc/meson/axg-tdm-interface.c b/sound/soc/meson/axg-tdm-interface.c index c8664ab80d45..87cac440b369 100644 --- a/sound/soc/meson/axg-tdm-interface.c +++ b/sound/soc/meson/axg-tdm-interface.c @@ -467,8 +467,20 @@ static int axg_tdm_iface_set_bias_level(struct snd_soc_component *component, return ret; } +static const struct snd_soc_dapm_widget axg_tdm_iface_dapm_widgets[] = { + SND_SOC_DAPM_SIGGEN("Playback Signal"), +}; + +static const struct snd_soc_dapm_route axg_tdm_iface_dapm_routes[] = { + { "Loopback", NULL, "Playback Signal" }, +}; + static const struct snd_soc_component_driver axg_tdm_iface_component_drv = { - .set_bias_level = axg_tdm_iface_set_bias_level, + .dapm_widgets = axg_tdm_iface_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(axg_tdm_iface_dapm_widgets), + .dapm_routes = axg_tdm_iface_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(axg_tdm_iface_dapm_routes), + .set_bias_level = axg_tdm_iface_set_bias_level, }; static const struct of_device_id axg_tdm_iface_of_match[] = { diff --git a/sound/soc/meson/axg-tdmin.c b/sound/soc/meson/axg-tdmin.c index 88ed95ae886b..b4faf9d5c1aa 100644 --- a/sound/soc/meson/axg-tdmin.c +++ b/sound/soc/meson/axg-tdmin.c @@ -228,15 +228,6 @@ static const struct axg_tdm_formatter_driver axg_tdmin_drv = { .regmap_cfg = &axg_tdmin_regmap_cfg, .ops = &axg_tdmin_ops, .quirks = &(const struct axg_tdm_formatter_hw) { - .skew_offset = 2, - }, -}; - -static const struct axg_tdm_formatter_driver g12a_tdmin_drv = { - .component_drv = &axg_tdmin_component_drv, - .regmap_cfg = &axg_tdmin_regmap_cfg, - .ops = &axg_tdmin_ops, - .quirks = &(const struct axg_tdm_formatter_hw) { .skew_offset = 3, }, }; @@ -247,10 +238,10 @@ static const struct of_device_id axg_tdmin_of_match[] = { .data = &axg_tdmin_drv, }, { .compatible = "amlogic,g12a-tdmin", - .data = &g12a_tdmin_drv, + .data = &axg_tdmin_drv, }, { .compatible = "amlogic,sm1-tdmin", - .data = &g12a_tdmin_drv, + .data = &axg_tdmin_drv, }, {} }; MODULE_DEVICE_TABLE(of, axg_tdmin_of_match); diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index af684fd19ab9..c5e99c2d89c7 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -270,18 +270,6 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream, struct lpaif_i2sctl *i2sctl = drvdata->i2sctl; unsigned int id = dai->driver->id; int ret = -EINVAL; - unsigned int val = 0; - - ret = regmap_read(drvdata->lpaif_map, - LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id), &val); - if (ret) { - dev_err(dai->dev, "error reading from i2sctl reg: %d\n", ret); - return ret; - } - if (val == LPAIF_I2SCTL_RESET_STATE) { - dev_err(dai->dev, "error in i2sctl register state\n"); - return -ENOTRECOVERABLE; - } switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -454,20 +442,16 @@ static bool lpass_cpu_regmap_volatile(struct device *dev, unsigned int reg) struct lpass_variant *v = drvdata->variant; int i; - for (i = 0; i < v->i2s_ports; ++i) - if (reg == LPAIF_I2SCTL_REG(v, i)) - return true; for (i = 0; i < v->irq_ports; ++i) if (reg == LPAIF_IRQSTAT_REG(v, i)) return true; for (i = 0; i < v->rdma_channels; ++i) - if (reg == LPAIF_RDMACURR_REG(v, i) || reg == LPAIF_RDMACTL_REG(v, i)) + if (reg == LPAIF_RDMACURR_REG(v, i)) return true; for (i = 0; i < v->wrdma_channels; ++i) - if (reg == LPAIF_WRDMACURR_REG(v, i + v->wrdma_channel_start) || - reg == LPAIF_WRDMACTL_REG(v, i + v->wrdma_channel_start)) + if (reg == LPAIF_WRDMACURR_REG(v, i + v->wrdma_channel_start)) return true; return false; diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c index 80b09dede5f9..d1c248590f3a 100644 --- a/sound/soc/qcom/lpass-platform.c +++ b/sound/soc/qcom/lpass-platform.c @@ -452,7 +452,6 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component, unsigned int reg_irqclr = 0, val_irqclr = 0; unsigned int reg_irqen = 0, val_irqen = 0, val_mask = 0; unsigned int dai_id = cpu_dai->driver->id; - unsigned int dma_ctrl_reg = 0; ch = pcm_data->dma_ch; if (dir == SNDRV_PCM_STREAM_PLAYBACK) { @@ -469,17 +468,7 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component, id = pcm_data->dma_ch - v->wrdma_channel_start; map = drvdata->lpaif_map; } - ret = regmap_read(map, LPAIF_DMACTL_REG(v, ch, dir, dai_id), &dma_ctrl_reg); - if (ret) { - dev_err(soc_runtime->dev, "error reading from rdmactl reg: %d\n", ret); - return ret; - } - if (dma_ctrl_reg == LPAIF_DMACTL_RESET_STATE || - dma_ctrl_reg == LPAIF_DMACTL_RESET_STATE + 1) { - dev_err(soc_runtime->dev, "error in rdmactl register state\n"); - return -ENOTRECOVERABLE; - } switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: @@ -500,7 +489,6 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component, "error writing to rdmactl reg: %d\n", ret); return ret; } - map = drvdata->hdmiif_map; reg_irqclr = LPASS_HDMITX_APP_IRQCLEAR_REG(v); val_irqclr = (LPAIF_IRQ_ALL(ch) | LPAIF_IRQ_HDMI_REQ_ON_PRELOAD(ch) | @@ -519,7 +507,6 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component, break; case MI2S_PRIMARY: case MI2S_SECONDARY: - map = drvdata->lpaif_map; reg_irqclr = LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST); val_irqclr = LPAIF_IRQ_ALL(ch); @@ -563,7 +550,6 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component, "error writing to rdmactl reg: %d\n", ret); return ret; } - map = drvdata->hdmiif_map; reg_irqen = LPASS_HDMITX_APP_IRQEN_REG(v); val_mask = (LPAIF_IRQ_ALL(ch) | LPAIF_IRQ_HDMI_REQ_ON_PRELOAD(ch) | @@ -573,7 +559,6 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component, break; case MI2S_PRIMARY: case MI2S_SECONDARY: - map = drvdata->lpaif_map; reg_irqen = LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST); val_mask = LPAIF_IRQ_ALL(ch); val_irqen = 0; @@ -838,6 +823,39 @@ static void lpass_platform_pcm_free(struct snd_soc_component *component, } } +static int lpass_platform_pcmops_suspend(struct snd_soc_component *component) +{ + struct lpass_data *drvdata = snd_soc_component_get_drvdata(component); + struct regmap *map; + unsigned int dai_id = component->id; + + if (dai_id == LPASS_DP_RX) + map = drvdata->hdmiif_map; + else + map = drvdata->lpaif_map; + + regcache_cache_only(map, true); + regcache_mark_dirty(map); + + return 0; +} + +static int lpass_platform_pcmops_resume(struct snd_soc_component *component) +{ + struct lpass_data *drvdata = snd_soc_component_get_drvdata(component); + struct regmap *map; + unsigned int dai_id = component->id; + + if (dai_id == LPASS_DP_RX) + map = drvdata->hdmiif_map; + else + map = drvdata->lpaif_map; + + regcache_cache_only(map, false); + return regcache_sync(map); +} + + static const struct snd_soc_component_driver lpass_component_driver = { .name = DRV_NAME, .open = lpass_platform_pcmops_open, @@ -850,6 +868,8 @@ static const struct snd_soc_component_driver lpass_component_driver = { .mmap = lpass_platform_pcmops_mmap, .pcm_construct = lpass_platform_pcm_new, .pcm_destruct = lpass_platform_pcm_free, + .suspend = lpass_platform_pcmops_suspend, + .resume = lpass_platform_pcmops_resume, }; diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index b9aacf3d3b29..abdfd9cf91e2 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -366,25 +366,27 @@ void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable) struct rsnd_adg *adg = rsnd_priv_to_adg(priv); struct device *dev = rsnd_priv_to_dev(priv); struct clk *clk; - int i, ret; + int i; for_each_rsnd_clk(clk, adg, i) { - ret = 0; if (enable) { - ret = clk_prepare_enable(clk); + int ret = clk_prepare_enable(clk); /* * We shouldn't use clk_get_rate() under * atomic context. Let's keep it when * rsnd_adg_clk_enable() was called */ - adg->clk_rate[i] = clk_get_rate(adg->clk[i]); + adg->clk_rate[i] = 0; + if (ret < 0) + dev_warn(dev, "can't use clk %d\n", i); + else + adg->clk_rate[i] = clk_get_rate(clk); } else { - clk_disable_unprepare(clk); + if (adg->clk_rate[i]) + clk_disable_unprepare(clk); + adg->clk_rate[i] = 0; } - - if (ret < 0) - dev_warn(dev, "can't use clk %d\n", i); } } diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 9f0c86cbdcca..2b75d0139e47 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -2486,6 +2486,7 @@ void snd_soc_dapm_free_widget(struct snd_soc_dapm_widget *w) enum snd_soc_dapm_direction dir; list_del(&w->list); + list_del(&w->dirty); /* * remove source and sink paths associated to this widget. * While removing the path, remove reference to it from both diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig index 031dad5fc4c7..3e8b6c035ce3 100644 --- a/sound/soc/sof/Kconfig +++ b/sound/soc/sof/Kconfig @@ -122,7 +122,7 @@ config SND_SOC_SOF_DEBUG_XRUN_STOP bool "SOF stop on XRUN" help This option forces PCMs to stop on any XRUN event. This is useful to - preserve any trace data ond pipeline status prior to the XRUN. + preserve any trace data and pipeline status prior to the XRUN. Say Y if you are debugging SOF FW pipeline XRUNs. If unsure select "N". diff --git a/sound/soc/stm/stm32_adfsdm.c b/sound/soc/stm/stm32_adfsdm.c index c4031988f981..47fae8dd20b4 100644 --- a/sound/soc/stm/stm32_adfsdm.c +++ b/sound/soc/stm/stm32_adfsdm.c @@ -293,6 +293,16 @@ static int stm32_adfsdm_pcm_new(struct snd_soc_component *component, return 0; } +static int stm32_adfsdm_dummy_cb(const void *data, void *private) +{ + /* + * This dummmy callback is requested by iio_channel_get_all_cb() API, + * but the stm32_dfsdm_get_buff_cb() API is used instead, to optimize + * DMA transfers. + */ + return 0; +} + static struct snd_soc_component_driver stm32_adfsdm_soc_platform = { .open = stm32_adfsdm_pcm_open, .close = stm32_adfsdm_pcm_close, @@ -335,7 +345,7 @@ static int stm32_adfsdm_probe(struct platform_device *pdev) if (IS_ERR(priv->iio_ch)) return PTR_ERR(priv->iio_ch); - priv->iio_cb = iio_channel_get_all_cb(&pdev->dev, NULL, NULL); + priv->iio_cb = iio_channel_get_all_cb(&pdev->dev, &stm32_adfsdm_dummy_cb, NULL); if (IS_ERR(priv->iio_cb)) return PTR_ERR(priv->iio_cb); |