ASoC: Fixes for v5.9

Most of this is various driver specific fixes, none of which are
 terribly exciting in themselves, plus one core fix adding and using a
 new DAI lookup function to deal with a lockdep warning.
 -----BEGIN PGP SIGNATURE-----
 
 iQFHBAABCgAxFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAl9bX1gTHGJyb29uaWVA
 a2VybmVsLm9yZwAKCRAk1otyXVSH0F04B/44DFfhh3KELcZkIiG4CLfoLRl1g3iw
 EEjFHJRJkpVjKJmTGeVgUTYI6UOH4U9abMGey6s4uCZW2AEb5CGODiWlcKAfy7l2
 i7XHbbJacsiJKU6ezR66azpuF+Hb5z/Z9AKfVuCDHHItXuj09A4H7V45AAd1IbEU
 KWdPSAcex18OgEKhYZNxBkMapsTJQl04cDUWiel7PYT7nJYxLAz46JMI2y4IJ3S8
 tXed+T1IDflruk819Mn1XAxYzvOVPcNRD6hHuSUEECV/BZcLJFEHPkvnLKEjKwNe
 so66doBMcAGkuGoYlURh2otZWgoX56e7IYrqX5m2N1fIskSRkOeNl5J4
 =WLI9
 -----END PGP SIGNATURE-----

Merge tag 'asoc-fix-v5.9-rc4' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus

ASoC: Fixes for v5.9

Most of this is various driver specific fixes, none of which are
terribly exciting in themselves, plus one core fix adding and using a
new DAI lookup function to deal with a lockdep warning.
This commit is contained in:
Takashi Iwai 2020-09-11 18:26:04 +02:00
commit 8949b6660c
26 changed files with 207 additions and 140 deletions

View File

@ -1193,6 +1193,8 @@ struct snd_soc_pcm_runtime {
((i) < (rtd)->num_cpus + (rtd)->num_codecs) && \
((dai) = (rtd)->dais[i]); \
(i)++)
#define for_each_rtd_dais_rollback(rtd, i, dai) \
for (; (--(i) >= 0) && ((dai) = (rtd)->dais[i]);)
void snd_soc_close_delayed_work(struct snd_soc_pcm_runtime *rtd);
@ -1361,6 +1363,8 @@ void snd_soc_unregister_dai(struct snd_soc_dai *dai);
struct snd_soc_dai *snd_soc_find_dai(
const struct snd_soc_dai_link_component *dlc);
struct snd_soc_dai *snd_soc_find_dai_with_mutex(
const struct snd_soc_dai_link_component *dlc);
#include <sound/soc-dai.h>

View File

@ -838,8 +838,8 @@ static int max98373_sdw_probe(struct sdw_slave *slave,
/* Regmap Initialization */
regmap = devm_regmap_init_sdw(slave, &max98373_sdw_regmap);
if (!regmap)
return -EINVAL;
if (IS_ERR(regmap))
return PTR_ERR(regmap);
return max98373_init(slave, regmap);
}

View File

@ -306,6 +306,13 @@ static int pcm3168a_set_dai_sysclk(struct snd_soc_dai *dai,
struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(dai->component);
int ret;
/*
* Some sound card sets 0 Hz as reset,
* but it is impossible to set. Ignore it here
*/
if (freq == 0)
return 0;
if (freq > PCM3168A_MAX_SYSCLK)
return -EINVAL;

View File

@ -684,8 +684,8 @@ static int rt1308_sdw_probe(struct sdw_slave *slave,
/* Regmap Initialization */
regmap = devm_regmap_init_sdw(slave, &rt1308_sdw_regmap);
if (!regmap)
return -EINVAL;
if (IS_ERR(regmap))
return PTR_ERR(regmap);
rt1308_sdw_init(&slave->dev, regmap, slave);

View File

@ -452,8 +452,8 @@ static int rt700_sdw_probe(struct sdw_slave *slave,
/* Regmap Initialization */
sdw_regmap = devm_regmap_init_sdw(slave, &rt700_sdw_regmap);
if (!sdw_regmap)
return -EINVAL;
if (IS_ERR(sdw_regmap))
return PTR_ERR(sdw_regmap);
regmap = devm_regmap_init(&slave->dev, NULL,
&slave->dev, &rt700_regmap);

View File

@ -452,8 +452,8 @@ static int rt711_sdw_probe(struct sdw_slave *slave,
/* Regmap Initialization */
sdw_regmap = devm_regmap_init_sdw(slave, &rt711_sdw_regmap);
if (!sdw_regmap)
return -EINVAL;
if (IS_ERR(sdw_regmap))
return PTR_ERR(sdw_regmap);
regmap = devm_regmap_init(&slave->dev, NULL,
&slave->dev, &rt711_regmap);

View File

@ -527,8 +527,8 @@ static int rt715_sdw_probe(struct sdw_slave *slave,
/* Regmap Initialization */
sdw_regmap = devm_regmap_init_sdw(slave, &rt715_sdw_regmap);
if (!sdw_regmap)
return -EINVAL;
if (IS_ERR(sdw_regmap))
return PTR_ERR(sdw_regmap);
regmap = devm_regmap_init(&slave->dev, NULL, &slave->dev,
&rt715_regmap);

View File

@ -842,6 +842,18 @@ static int adcx140_codec_probe(struct snd_soc_component *component)
if (ret)
goto out;
if (adcx140->supply_areg == NULL)
sleep_cfg_val |= ADCX140_AREG_INTERNAL;
ret = regmap_write(adcx140->regmap, ADCX140_SLEEP_CFG, sleep_cfg_val);
if (ret) {
dev_err(adcx140->dev, "setting sleep config failed %d\n", ret);
goto out;
}
/* 8.4.3: Wait >= 1ms after entering active mode. */
usleep_range(1000, 100000);
pdm_count = device_property_count_u32(adcx140->dev,
"ti,pdm-edge-select");
if (pdm_count <= ADCX140_NUM_PDM_EDGES && pdm_count > 0) {
@ -889,18 +901,6 @@ static int adcx140_codec_probe(struct snd_soc_component *component)
if (ret)
goto out;
if (adcx140->supply_areg == NULL)
sleep_cfg_val |= ADCX140_AREG_INTERNAL;
ret = regmap_write(adcx140->regmap, ADCX140_SLEEP_CFG, sleep_cfg_val);
if (ret) {
dev_err(adcx140->dev, "setting sleep config failed %d\n", ret);
goto out;
}
/* 8.4.3: Wait >= 1ms after entering active mode. */
usleep_range(1000, 100000);
ret = regmap_update_bits(adcx140->regmap, ADCX140_BIAS_CFG,
ADCX140_MIC_BIAS_VAL_MSK |
ADCX140_MIC_BIAS_VREF_MSK, bias_cfg);
@ -980,6 +980,8 @@ static int adcx140_i2c_probe(struct i2c_client *i2c,
if (!adcx140)
return -ENOMEM;
adcx140->dev = &i2c->dev;
adcx140->gpio_reset = devm_gpiod_get_optional(adcx140->dev,
"reset", GPIOD_OUT_LOW);
if (IS_ERR(adcx140->gpio_reset))
@ -1007,7 +1009,7 @@ static int adcx140_i2c_probe(struct i2c_client *i2c,
ret);
return ret;
}
adcx140->dev = &i2c->dev;
i2c_set_clientdata(i2c, adcx140);
return devm_snd_soc_register_component(&i2c->dev,

View File

@ -3514,6 +3514,8 @@ int wm8994_mic_detect(struct snd_soc_component *component, struct snd_soc_jack *
return -EINVAL;
}
pm_runtime_get_sync(component->dev);
switch (micbias) {
case 1:
micdet = &wm8994->micdet[0];
@ -3561,6 +3563,8 @@ int wm8994_mic_detect(struct snd_soc_component *component, struct snd_soc_jack *
snd_soc_dapm_sync(dapm);
pm_runtime_put(component->dev);
return 0;
}
EXPORT_SYMBOL_GPL(wm8994_mic_detect);
@ -3932,6 +3936,8 @@ int wm8958_mic_detect(struct snd_soc_component *component, struct snd_soc_jack *
return -EINVAL;
}
pm_runtime_get_sync(component->dev);
if (jack) {
snd_soc_dapm_force_enable_pin(dapm, "CLK_SYS");
snd_soc_dapm_sync(dapm);
@ -4000,6 +4006,8 @@ int wm8958_mic_detect(struct snd_soc_component *component, struct snd_soc_jack *
snd_soc_dapm_sync(dapm);
}
pm_runtime_put(component->dev);
return 0;
}
EXPORT_SYMBOL_GPL(wm8958_mic_detect);
@ -4193,11 +4201,13 @@ static int wm8994_component_probe(struct snd_soc_component *component)
wm8994->hubs.dcs_readback_mode = 2;
break;
}
wm8994->hubs.micd_scthr = true;
break;
case WM8958:
wm8994->hubs.dcs_readback_mode = 1;
wm8994->hubs.hp_startup_mode = 1;
wm8994->hubs.micd_scthr = true;
switch (control->revision) {
case 0:

View File

@ -1223,6 +1223,9 @@ int wm_hubs_handle_analogue_pdata(struct snd_soc_component *component,
snd_soc_component_update_bits(component, WM8993_ADDITIONAL_CONTROL,
WM8993_LINEOUT2_FB, WM8993_LINEOUT2_FB);
if (!hubs->micd_scthr)
return 0;
snd_soc_component_update_bits(component, WM8993_MICBIAS,
WM8993_JD_SCTHR_MASK | WM8993_JD_THR_MASK |
WM8993_MICB1_LVL | WM8993_MICB2_LVL,

View File

@ -27,6 +27,7 @@ struct wm_hubs_data {
int hp_startup_mode;
int series_startup;
int no_series_update;
bool micd_scthr;
bool no_cache_dac_hp_direct;
struct list_head dcs_cache;

View File

@ -333,6 +333,17 @@ static int sst_media_open(struct snd_pcm_substream *substream,
if (ret_val < 0)
goto out_power_up;
/*
* Make sure the period to be multiple of 1ms to align the
* design of firmware. Apply same rule to buffer size to make
* sure alsa could always find a value for period size
* regardless the buffer size given by user space.
*/
snd_pcm_hw_constraint_step(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 48);
snd_pcm_hw_constraint_step(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 48);
/* Make sure, that the period size is always even */
snd_pcm_hw_constraint_step(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_PERIODS, 2);

View File

@ -591,6 +591,16 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
BYT_RT5640_SSP0_AIF1 |
BYT_RT5640_MCLK_EN),
},
{ /* MPMAN Converter 9, similar hw as the I.T.Works TW891 2-in-1 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "MPMAN"),
DMI_MATCH(DMI_PRODUCT_NAME, "Converter9"),
},
.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
BYT_RT5640_MONO_SPEAKER |
BYT_RT5640_SSP0_AIF1 |
BYT_RT5640_MCLK_EN),
},
{
/* MPMAN MPWIN895CL */
.matches = {

View File

@ -181,7 +181,7 @@ static void skl_set_hda_codec_autosuspend_delay(struct snd_soc_card *card)
struct snd_soc_dai *dai;
for_each_card_rtds(card, rtd) {
if (!strstr(rtd->dai_link->codecs->name, "ehdaudio"))
if (!strstr(rtd->dai_link->codecs->name, "ehdaudio0D0"))
continue;
dai = asoc_rtd_to_codec(rtd, 0);
hda_pvt = snd_soc_component_get_drvdata(dai->component);

View File

@ -66,6 +66,10 @@ int max98373_trigger(struct snd_pcm_substream *substream, int cmd)
int j;
int ret = 0;
/* set spk pin by playback only */
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
return 0;
for_each_rtd_codec_dais(rtd, j, codec_dai) {
struct snd_soc_component *component = codec_dai->component;
struct snd_soc_dapm_context *dapm =
@ -86,9 +90,6 @@ int max98373_trigger(struct snd_pcm_substream *substream, int cmd)
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
/* Make sure no streams are active before disable pin */
if (snd_soc_dai_active(codec_dai) != 1)
break;
ret = snd_soc_dapm_disable_pin(dapm, pin_name);
if (!ret)
snd_soc_dapm_sync(dapm);

View File

@ -243,92 +243,45 @@ static irqreturn_t hsw_irq(int irq, void *context)
return ret;
}
#define CSR_DEFAULT_VALUE 0x8480040E
#define ISC_DEFAULT_VALUE 0x0
#define ISD_DEFAULT_VALUE 0x0
#define IMC_DEFAULT_VALUE 0x7FFF0003
#define IMD_DEFAULT_VALUE 0x7FFF0003
#define IPCC_DEFAULT_VALUE 0x0
#define IPCD_DEFAULT_VALUE 0x0
#define CLKCTL_DEFAULT_VALUE 0x7FF
#define CSR2_DEFAULT_VALUE 0x0
#define LTR_CTRL_DEFAULT_VALUE 0x0
#define HMD_CTRL_DEFAULT_VALUE 0x0
static void hsw_set_shim_defaults(struct sst_dsp *sst)
{
sst_dsp_shim_write_unlocked(sst, SST_CSR, CSR_DEFAULT_VALUE);
sst_dsp_shim_write_unlocked(sst, SST_ISRX, ISC_DEFAULT_VALUE);
sst_dsp_shim_write_unlocked(sst, SST_ISRD, ISD_DEFAULT_VALUE);
sst_dsp_shim_write_unlocked(sst, SST_IMRX, IMC_DEFAULT_VALUE);
sst_dsp_shim_write_unlocked(sst, SST_IMRD, IMD_DEFAULT_VALUE);
sst_dsp_shim_write_unlocked(sst, SST_IPCX, IPCC_DEFAULT_VALUE);
sst_dsp_shim_write_unlocked(sst, SST_IPCD, IPCD_DEFAULT_VALUE);
sst_dsp_shim_write_unlocked(sst, SST_CLKCTL, CLKCTL_DEFAULT_VALUE);
sst_dsp_shim_write_unlocked(sst, SST_CSR2, CSR2_DEFAULT_VALUE);
sst_dsp_shim_write_unlocked(sst, SST_LTRC, LTR_CTRL_DEFAULT_VALUE);
sst_dsp_shim_write_unlocked(sst, SST_HMDC, HMD_CTRL_DEFAULT_VALUE);
}
/* all clock-gating minus DCLCGE and DTCGE */
#define SST_VDRTCL2_CG_OTHER 0xB7D
static void hsw_set_dsp_D3(struct sst_dsp *sst)
{
u32 val;
u32 reg;
/* disable clock core gating */
/* Disable core clock gating (VDRTCTL2.DCLCGE = 0) */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
reg &= ~(SST_VDRTCL2_DCLCGE);
reg &= ~(SST_VDRTCL2_DCLCGE | SST_VDRTCL2_DTCGE);
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
/* stall, reset and set 24MHz XOSC */
sst_dsp_shim_update_bits_unlocked(sst, SST_CSR,
SST_CSR_24MHZ_LPCS | SST_CSR_STALL | SST_CSR_RST,
SST_CSR_24MHZ_LPCS | SST_CSR_STALL | SST_CSR_RST);
/* enable power gating and switch off DRAM & IRAM blocks */
val = readl(sst->addr.pci_cfg + SST_VDRTCTL0);
val |= SST_VDRTCL0_DSRAMPGE_MASK |
SST_VDRTCL0_ISRAMPGE_MASK;
val &= ~(SST_VDRTCL0_D3PGD | SST_VDRTCL0_D3SRAMPGD);
writel(val, sst->addr.pci_cfg + SST_VDRTCTL0);
/* DRAM power gating all */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL0);
reg |= SST_VDRTCL0_ISRAMPGE_MASK |
SST_VDRTCL0_DSRAMPGE_MASK;
reg &= ~(SST_VDRTCL0_D3SRAMPGD);
reg |= SST_VDRTCL0_D3PGD;
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL0);
udelay(50);
/* switch off audio PLL */
val = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
val |= SST_VDRTCL2_APLLSE_MASK;
writel(val, sst->addr.pci_cfg + SST_VDRTCTL2);
/* PLL shutdown enable */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
reg |= SST_VDRTCL2_APLLSE_MASK;
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
/* disable MCLK */
/* disable MCLK(clkctl.smos = 0) */
sst_dsp_shim_update_bits_unlocked(sst, SST_CLKCTL,
SST_CLKCTL_MASK, 0);
SST_CLKCTL_MASK, 0);
/* switch clock gating */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
reg |= SST_VDRTCL2_CG_OTHER;
reg &= ~(SST_VDRTCL2_DTCGE);
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
/* enable DTCGE separatelly */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
reg |= SST_VDRTCL2_DTCGE;
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
/* set shim defaults */
hsw_set_shim_defaults(sst);
/* set D3 */
reg = readl(sst->addr.pci_cfg + SST_PMCS);
reg |= SST_PMCS_PS_MASK;
writel(reg, sst->addr.pci_cfg + SST_PMCS);
/* Set D3 state, delay 50 us */
val = readl(sst->addr.pci_cfg + SST_PMCS);
val |= SST_PMCS_PS_MASK;
writel(val, sst->addr.pci_cfg + SST_PMCS);
udelay(50);
/* enable clock core gating */
/* Enable core clock gating (VDRTCTL2.DCLCGE = 1), delay 50 us */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
reg |= SST_VDRTCL2_DCLCGE;
reg |= SST_VDRTCL2_DCLCGE | SST_VDRTCL2_DTCGE;
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
udelay(50);
}
static void hsw_reset(struct sst_dsp *sst)
@ -346,62 +299,75 @@ static void hsw_reset(struct sst_dsp *sst)
SST_CSR_RST | SST_CSR_STALL, SST_CSR_STALL);
}
/* recommended CSR state for power-up */
#define SST_CSR_D0_MASK (0x18A09C0C | SST_CSR_DCS_MASK)
static int hsw_set_dsp_D0(struct sst_dsp *sst)
{
u32 reg;
int tries = 10;
u32 reg, fw_dump_bit;
/* disable clock core gating */
/* Disable core clock gating (VDRTCTL2.DCLCGE = 0) */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
reg &= ~(SST_VDRTCL2_DCLCGE);
reg &= ~(SST_VDRTCL2_DCLCGE | SST_VDRTCL2_DTCGE);
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
/* switch clock gating */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
reg |= SST_VDRTCL2_CG_OTHER;
reg &= ~(SST_VDRTCL2_DTCGE);
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
/* set D0 */
reg = readl(sst->addr.pci_cfg + SST_PMCS);
reg &= ~(SST_PMCS_PS_MASK);
writel(reg, sst->addr.pci_cfg + SST_PMCS);
/* DRAM power gating none */
/* Disable D3PG (VDRTCTL0.D3PGD = 1) */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL0);
reg &= ~(SST_VDRTCL0_ISRAMPGE_MASK |
SST_VDRTCL0_DSRAMPGE_MASK);
reg |= SST_VDRTCL0_D3SRAMPGD;
reg |= SST_VDRTCL0_D3PGD;
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL0);
mdelay(10);
/* set shim defaults */
hsw_set_shim_defaults(sst);
/* Set D0 state */
reg = readl(sst->addr.pci_cfg + SST_PMCS);
reg &= ~SST_PMCS_PS_MASK;
writel(reg, sst->addr.pci_cfg + SST_PMCS);
/* restore MCLK */
/* check that ADSP shim is enabled */
while (tries--) {
reg = readl(sst->addr.pci_cfg + SST_PMCS) & SST_PMCS_PS_MASK;
if (reg == 0)
goto finish;
msleep(1);
}
return -ENODEV;
finish:
/* select SSP1 19.2MHz base clock, SSP clock 0, turn off Low Power Clock */
sst_dsp_shim_update_bits_unlocked(sst, SST_CSR,
SST_CSR_S1IOCS | SST_CSR_SBCS1 | SST_CSR_LPCS, 0x0);
/* stall DSP core, set clk to 192/96Mhz */
sst_dsp_shim_update_bits_unlocked(sst,
SST_CSR, SST_CSR_STALL | SST_CSR_DCS_MASK,
SST_CSR_STALL | SST_CSR_DCS(4));
/* Set 24MHz MCLK, prevent local clock gating, enable SSP0 clock */
sst_dsp_shim_update_bits_unlocked(sst, SST_CLKCTL,
SST_CLKCTL_MASK, SST_CLKCTL_MASK);
SST_CLKCTL_MASK | SST_CLKCTL_DCPLCG | SST_CLKCTL_SCOE0,
SST_CLKCTL_MASK | SST_CLKCTL_DCPLCG | SST_CLKCTL_SCOE0);
/* PLL shutdown disable */
/* Stall and reset core, set CSR */
hsw_reset(sst);
/* Enable core clock gating (VDRTCTL2.DCLCGE = 1), delay 50 us */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
reg &= ~(SST_VDRTCL2_APLLSE_MASK);
reg |= SST_VDRTCL2_DCLCGE | SST_VDRTCL2_DTCGE;
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
sst_dsp_shim_update_bits_unlocked(sst, SST_CSR,
SST_CSR_D0_MASK, SST_CSR_SBCS0 | SST_CSR_SBCS1 |
SST_CSR_STALL | SST_CSR_DCS(4));
udelay(50);
/* enable clock core gating */
/* switch on audio PLL */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
reg |= SST_VDRTCL2_DCLCGE;
reg &= ~SST_VDRTCL2_APLLSE_MASK;
writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
/* clear reset */
sst_dsp_shim_update_bits_unlocked(sst, SST_CSR, SST_CSR_RST, 0);
/* set default power gating control, enable power gating control for all blocks. that is,
can't be accessed, please enable each block before accessing. */
reg = readl(sst->addr.pci_cfg + SST_VDRTCTL0);
reg |= SST_VDRTCL0_DSRAMPGE_MASK | SST_VDRTCL0_ISRAMPGE_MASK;
/* for D0, always enable the block(DSRAM[0]) used for FW dump */
fw_dump_bit = 1 << SST_VDRTCL0_DSRAMPGE_SHIFT;
writel(reg & ~fw_dump_bit, sst->addr.pci_cfg + SST_VDRTCTL0);
/* disable DMA finish function for SSP0 & SSP1 */
sst_dsp_shim_update_bits_unlocked(sst, SST_CSR2, SST_CSR2_SDFD_SSP1,
@ -418,6 +384,12 @@ static int hsw_set_dsp_D0(struct sst_dsp *sst)
sst_dsp_shim_update_bits(sst, SST_IMRD, (SST_IMRD_DONE | SST_IMRD_BUSY |
SST_IMRD_SSP0 | SST_IMRD_DMAC), 0x0);
/* clear IPC registers */
sst_dsp_shim_write(sst, SST_IPCX, 0x0);
sst_dsp_shim_write(sst, SST_IPCD, 0x0);
sst_dsp_shim_write(sst, 0x80, 0x6);
sst_dsp_shim_write(sst, 0xe0, 0x300a);
return 0;
}
@ -443,6 +415,11 @@ static void hsw_sleep(struct sst_dsp *sst)
{
dev_dbg(sst->dev, "HSW_PM dsp runtime suspend\n");
/* put DSP into reset and stall */
sst_dsp_shim_update_bits(sst, SST_CSR,
SST_CSR_24MHZ_LPCS | SST_CSR_RST | SST_CSR_STALL,
SST_CSR_RST | SST_CSR_STALL | SST_CSR_24MHZ_LPCS);
hsw_set_dsp_D3(sst);
dev_dbg(sst->dev, "HSW_PM dsp runtime suspend exit\n");
}

View File

@ -18,6 +18,7 @@
#define CTRL0_TODDR_SEL_RESAMPLE BIT(30)
#define CTRL0_TODDR_EXT_SIGNED BIT(29)
#define CTRL0_TODDR_PP_MODE BIT(28)
#define CTRL0_TODDR_SYNC_CH BIT(27)
#define CTRL0_TODDR_TYPE_MASK GENMASK(15, 13)
#define CTRL0_TODDR_TYPE(x) ((x) << 13)
#define CTRL0_TODDR_MSB_POS_MASK GENMASK(12, 8)
@ -189,10 +190,31 @@ static const struct axg_fifo_match_data axg_toddr_match_data = {
.dai_drv = &axg_toddr_dai_drv
};
static int g12a_toddr_dai_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct axg_fifo *fifo = snd_soc_dai_get_drvdata(dai);
int ret;
ret = axg_toddr_dai_startup(substream, dai);
if (ret)
return ret;
/*
* Make sure the first channel ends up in the at beginning of the output
* As weird as it looks, without this the first channel may be misplaced
* in memory, with a random shift of 2 channels.
*/
regmap_update_bits(fifo->map, FIFO_CTRL0, CTRL0_TODDR_SYNC_CH,
CTRL0_TODDR_SYNC_CH);
return 0;
}
static const struct snd_soc_dai_ops g12a_toddr_ops = {
.prepare = g12a_toddr_dai_prepare,
.hw_params = axg_toddr_dai_hw_params,
.startup = axg_toddr_dai_startup,
.startup = g12a_toddr_dai_startup,
.shutdown = axg_toddr_dai_shutdown,
};

View File

@ -143,6 +143,7 @@ static int apq8016_sbc_platform_probe(struct platform_device *pdev)
card = &data->card;
card->dev = dev;
card->owner = THIS_MODULE;
card->dapm_widgets = apq8016_sbc_dapm_widgets;
card->num_dapm_widgets = ARRAY_SIZE(apq8016_sbc_dapm_widgets);

View File

@ -114,6 +114,7 @@ static int apq8096_platform_probe(struct platform_device *pdev)
return -ENOMEM;
card->dev = dev;
card->owner = THIS_MODULE;
dev_set_drvdata(dev, card);
ret = qcom_snd_parse_of(card);
if (ret)

View File

@ -52,8 +52,10 @@ int qcom_snd_parse_of(struct snd_soc_card *card)
for_each_child_of_node(dev->of_node, np) {
dlc = devm_kzalloc(dev, 2 * sizeof(*dlc), GFP_KERNEL);
if (!dlc)
return -ENOMEM;
if (!dlc) {
ret = -ENOMEM;
goto err;
}
link->cpus = &dlc[0];
link->platforms = &dlc[1];

View File

@ -555,6 +555,7 @@ static int sdm845_snd_platform_probe(struct platform_device *pdev)
card->dapm_widgets = sdm845_snd_widgets;
card->num_dapm_widgets = ARRAY_SIZE(sdm845_snd_widgets);
card->dev = dev;
card->owner = THIS_MODULE;
dev_set_drvdata(dev, card);
ret = qcom_snd_parse_of(card);
if (ret)

View File

@ -96,6 +96,7 @@ static int storm_platform_probe(struct platform_device *pdev)
return -ENOMEM;
card->dev = &pdev->dev;
card->owner = THIS_MODULE;
ret = snd_soc_of_parse_card_name(card, "qcom,model");
if (ret) {

View File

@ -834,6 +834,19 @@ struct snd_soc_dai *snd_soc_find_dai(
}
EXPORT_SYMBOL_GPL(snd_soc_find_dai);
struct snd_soc_dai *snd_soc_find_dai_with_mutex(
const struct snd_soc_dai_link_component *dlc)
{
struct snd_soc_dai *dai;
mutex_lock(&client_mutex);
dai = snd_soc_find_dai(dlc);
mutex_unlock(&client_mutex);
return dai;
}
EXPORT_SYMBOL_GPL(snd_soc_find_dai_with_mutex);
static int soc_dai_link_sanity_check(struct snd_soc_card *card,
struct snd_soc_dai_link *link)
{

View File

@ -412,14 +412,14 @@ void snd_soc_dai_link_set_capabilities(struct snd_soc_dai_link *dai_link)
supported_codec = false;
for_each_link_cpus(dai_link, i, cpu) {
dai = snd_soc_find_dai(cpu);
dai = snd_soc_find_dai_with_mutex(cpu);
if (dai && snd_soc_dai_stream_valid(dai, direction)) {
supported_cpu = true;
break;
}
}
for_each_link_codecs(dai_link, i, codec) {
dai = snd_soc_find_dai(codec);
dai = snd_soc_find_dai_with_mutex(codec);
if (dai && snd_soc_dai_stream_valid(dai, direction)) {
supported_codec = true;
break;

View File

@ -812,7 +812,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
return 0;
config_err:
for_each_rtd_dais(rtd, i, dai)
for_each_rtd_dais_rollback(rtd, i, dai)
snd_soc_dai_shutdown(dai, substream);
snd_soc_link_shutdown(substream);

View File

@ -446,12 +446,12 @@ static const struct snd_soc_dai_ops ams_delta_dai_ops = {
/* Will be used if the codec ever has its own digital_mute function */
static int ams_delta_startup(struct snd_pcm_substream *substream)
{
return ams_delta_digital_mute(NULL, 0, substream->stream);
return ams_delta_mute(NULL, 0, substream->stream);
}
static void ams_delta_shutdown(struct snd_pcm_substream *substream)
{
ams_delta_digital_mute(NULL, 1, substream->stream);
ams_delta_mute(NULL, 1, substream->stream);
}