Commit fbca72c1 authored by Takashi Iwai's avatar Takashi Iwai

Merge tag 'asoc-fix-v5.5-rc5' of...

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

ASoC: Fixes for v5.5

More fixes that have been collected, nothing super remarkable here - the
few core fixes are mainly error handling related as are many of the
driver fixes.
parents 51d4efab ff3b5741
...@@ -505,15 +505,20 @@ static int fsl_audmix_probe(struct platform_device *pdev) ...@@ -505,15 +505,20 @@ static int fsl_audmix_probe(struct platform_device *pdev)
ARRAY_SIZE(fsl_audmix_dai)); ARRAY_SIZE(fsl_audmix_dai));
if (ret) { if (ret) {
dev_err(dev, "failed to register ASoC DAI\n"); dev_err(dev, "failed to register ASoC DAI\n");
return ret; goto err_disable_pm;
} }
priv->pdev = platform_device_register_data(dev, mdrv, 0, NULL, 0); priv->pdev = platform_device_register_data(dev, mdrv, 0, NULL, 0);
if (IS_ERR(priv->pdev)) { if (IS_ERR(priv->pdev)) {
ret = PTR_ERR(priv->pdev); ret = PTR_ERR(priv->pdev);
dev_err(dev, "failed to register platform %s: %d\n", mdrv, ret); dev_err(dev, "failed to register platform %s: %d\n", mdrv, ret);
goto err_disable_pm;
} }
return 0;
err_disable_pm:
pm_runtime_disable(dev);
return ret; return ret;
} }
...@@ -521,6 +526,8 @@ static int fsl_audmix_remove(struct platform_device *pdev) ...@@ -521,6 +526,8 @@ static int fsl_audmix_remove(struct platform_device *pdev)
{ {
struct fsl_audmix *priv = dev_get_drvdata(&pdev->dev); struct fsl_audmix *priv = dev_get_drvdata(&pdev->dev);
pm_runtime_disable(&pdev->dev);
if (priv->pdev) if (priv->pdev)
platform_device_unregister(priv->pdev); platform_device_unregister(priv->pdev);
......
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/dmi.h> #include <linux/dmi.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <asm/cpu_device_id.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/jack.h> #include <sound/jack.h>
......
...@@ -479,6 +479,12 @@ static struct snd_soc_pcm_runtime *soc_new_pcm_runtime( ...@@ -479,6 +479,12 @@ static struct snd_soc_pcm_runtime *soc_new_pcm_runtime(
goto free_rtd; goto free_rtd;
rtd->dev = dev; rtd->dev = dev;
INIT_LIST_HEAD(&rtd->list);
INIT_LIST_HEAD(&rtd->component_list);
INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients);
INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients);
INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_PLAYBACK].fe_clients);
INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_CAPTURE].fe_clients);
dev_set_drvdata(dev, rtd); dev_set_drvdata(dev, rtd);
INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work); INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
...@@ -494,12 +500,6 @@ static struct snd_soc_pcm_runtime *soc_new_pcm_runtime( ...@@ -494,12 +500,6 @@ static struct snd_soc_pcm_runtime *soc_new_pcm_runtime(
/* /*
* rtd remaining settings * rtd remaining settings
*/ */
INIT_LIST_HEAD(&rtd->component_list);
INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients);
INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients);
INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_PLAYBACK].fe_clients);
INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_CAPTURE].fe_clients);
rtd->card = card; rtd->card = card;
rtd->dai_link = dai_link; rtd->dai_link = dai_link;
if (!rtd->dai_link->ops) if (!rtd->dai_link->ops)
...@@ -1871,6 +1871,8 @@ static void soc_check_tplg_fes(struct snd_soc_card *card) ...@@ -1871,6 +1871,8 @@ static void soc_check_tplg_fes(struct snd_soc_card *card)
/* convert non BE into BE */ /* convert non BE into BE */
dai_link->no_pcm = 1; dai_link->no_pcm = 1;
dai_link->dpcm_playback = 1;
dai_link->dpcm_capture = 1;
/* override any BE fixups */ /* override any BE fixups */
dai_link->be_hw_params_fixup = dai_link->be_hw_params_fixup =
......
...@@ -548,12 +548,12 @@ static void remove_link(struct snd_soc_component *comp, ...@@ -548,12 +548,12 @@ static void remove_link(struct snd_soc_component *comp,
if (dobj->ops && dobj->ops->link_unload) if (dobj->ops && dobj->ops->link_unload)
dobj->ops->link_unload(comp, dobj); dobj->ops->link_unload(comp, dobj);
list_del(&dobj->list);
snd_soc_remove_dai_link(comp->card, link);
kfree(link->name); kfree(link->name);
kfree(link->stream_name); kfree(link->stream_name);
kfree(link->cpus->dai_name); kfree(link->cpus->dai_name);
list_del(&dobj->list);
snd_soc_remove_dai_link(comp->card, link);
kfree(link); kfree(link);
} }
......
...@@ -209,7 +209,7 @@ static int imx8_probe(struct snd_sof_dev *sdev) ...@@ -209,7 +209,7 @@ static int imx8_probe(struct snd_sof_dev *sdev)
priv->pd_dev = devm_kmalloc_array(&pdev->dev, priv->num_domains, priv->pd_dev = devm_kmalloc_array(&pdev->dev, priv->num_domains,
sizeof(*priv->pd_dev), GFP_KERNEL); sizeof(*priv->pd_dev), GFP_KERNEL);
if (!priv) if (!priv->pd_dev)
return -ENOMEM; return -ENOMEM;
priv->link = devm_kmalloc_array(&pdev->dev, priv->num_domains, priv->link = devm_kmalloc_array(&pdev->dev, priv->num_domains,
...@@ -304,6 +304,9 @@ static int imx8_probe(struct snd_sof_dev *sdev) ...@@ -304,6 +304,9 @@ static int imx8_probe(struct snd_sof_dev *sdev)
} }
sdev->mailbox_bar = SOF_FW_BLK_TYPE_SRAM; sdev->mailbox_bar = SOF_FW_BLK_TYPE_SRAM;
/* set default mailbox offset for FW ready message */
sdev->dsp_box.offset = MBOX_OFFSET;
return 0; return 0;
exit_pdev_unregister: exit_pdev_unregister:
......
...@@ -216,6 +216,8 @@ static int hda_link_hw_params(struct snd_pcm_substream *substream, ...@@ -216,6 +216,8 @@ static int hda_link_hw_params(struct snd_pcm_substream *substream,
link_dev = hda_link_stream_assign(bus, substream); link_dev = hda_link_stream_assign(bus, substream);
if (!link_dev) if (!link_dev)
return -EBUSY; return -EBUSY;
snd_soc_dai_set_dma_data(dai, substream, (void *)link_dev);
} }
stream_tag = hdac_stream(link_dev)->stream_tag; stream_tag = hdac_stream(link_dev)->stream_tag;
...@@ -228,8 +230,6 @@ static int hda_link_hw_params(struct snd_pcm_substream *substream, ...@@ -228,8 +230,6 @@ static int hda_link_hw_params(struct snd_pcm_substream *substream,
if (ret < 0) if (ret < 0)
return ret; return ret;
snd_soc_dai_set_dma_data(dai, substream, (void *)link_dev);
link = snd_hdac_ext_bus_get_link(bus, codec_dai->component->name); link = snd_hdac_ext_bus_get_link(bus, codec_dai->component->name);
if (!link) if (!link)
return -EINVAL; return -EINVAL;
...@@ -361,6 +361,13 @@ static int hda_link_hw_free(struct snd_pcm_substream *substream, ...@@ -361,6 +361,13 @@ static int hda_link_hw_free(struct snd_pcm_substream *substream,
bus = hstream->bus; bus = hstream->bus;
rtd = snd_pcm_substream_chip(substream); rtd = snd_pcm_substream_chip(substream);
link_dev = snd_soc_dai_get_dma_data(dai, substream); link_dev = snd_soc_dai_get_dma_data(dai, substream);
if (!link_dev) {
dev_dbg(dai->dev,
"%s: link_dev is not assigned\n", __func__);
return -EINVAL;
}
hda_stream = hstream_to_sof_hda_stream(link_dev); hda_stream = hstream_to_sof_hda_stream(link_dev);
/* free the link DMA channel in the FW */ /* free the link DMA channel in the FW */
......
...@@ -826,6 +826,9 @@ void snd_sof_ipc_free(struct snd_sof_dev *sdev) ...@@ -826,6 +826,9 @@ void snd_sof_ipc_free(struct snd_sof_dev *sdev)
{ {
struct snd_sof_ipc *ipc = sdev->ipc; struct snd_sof_ipc *ipc = sdev->ipc;
if (!ipc)
return;
/* disable sending of ipc's */ /* disable sending of ipc's */
mutex_lock(&ipc->tx_mutex); mutex_lock(&ipc->tx_mutex);
ipc->disable_ipc_tx = true; ipc->disable_ipc_tx = true;
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/pinctrl/consumer.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/reset.h> #include <linux/reset.h>
...@@ -220,6 +219,7 @@ ...@@ -220,6 +219,7 @@
* @slave_config: dma slave channel runtime config pointer * @slave_config: dma slave channel runtime config pointer
* @phys_addr: SPDIFRX registers physical base address * @phys_addr: SPDIFRX registers physical base address
* @lock: synchronization enabling lock * @lock: synchronization enabling lock
* @irq_lock: prevent race condition with IRQ on stream state
* @cs: channel status buffer * @cs: channel status buffer
* @ub: user data buffer * @ub: user data buffer
* @irq: SPDIFRX interrupt line * @irq: SPDIFRX interrupt line
...@@ -240,6 +240,7 @@ struct stm32_spdifrx_data { ...@@ -240,6 +240,7 @@ struct stm32_spdifrx_data {
struct dma_slave_config slave_config; struct dma_slave_config slave_config;
dma_addr_t phys_addr; dma_addr_t phys_addr;
spinlock_t lock; /* Sync enabling lock */ spinlock_t lock; /* Sync enabling lock */
spinlock_t irq_lock; /* Prevent race condition on stream state */
unsigned char cs[SPDIFRX_CS_BYTES_NB]; unsigned char cs[SPDIFRX_CS_BYTES_NB];
unsigned char ub[SPDIFRX_UB_BYTES_NB]; unsigned char ub[SPDIFRX_UB_BYTES_NB];
int irq; int irq;
...@@ -320,6 +321,7 @@ static void stm32_spdifrx_dma_ctrl_stop(struct stm32_spdifrx_data *spdifrx) ...@@ -320,6 +321,7 @@ static void stm32_spdifrx_dma_ctrl_stop(struct stm32_spdifrx_data *spdifrx)
static int stm32_spdifrx_start_sync(struct stm32_spdifrx_data *spdifrx) static int stm32_spdifrx_start_sync(struct stm32_spdifrx_data *spdifrx)
{ {
int cr, cr_mask, imr, ret; int cr, cr_mask, imr, ret;
unsigned long flags;
/* Enable IRQs */ /* Enable IRQs */
imr = SPDIFRX_IMR_IFEIE | SPDIFRX_IMR_SYNCDIE | SPDIFRX_IMR_PERRIE; imr = SPDIFRX_IMR_IFEIE | SPDIFRX_IMR_SYNCDIE | SPDIFRX_IMR_PERRIE;
...@@ -327,7 +329,7 @@ static int stm32_spdifrx_start_sync(struct stm32_spdifrx_data *spdifrx) ...@@ -327,7 +329,7 @@ static int stm32_spdifrx_start_sync(struct stm32_spdifrx_data *spdifrx)
if (ret) if (ret)
return ret; return ret;
spin_lock(&spdifrx->lock); spin_lock_irqsave(&spdifrx->lock, flags);
spdifrx->refcount++; spdifrx->refcount++;
...@@ -362,7 +364,7 @@ static int stm32_spdifrx_start_sync(struct stm32_spdifrx_data *spdifrx) ...@@ -362,7 +364,7 @@ static int stm32_spdifrx_start_sync(struct stm32_spdifrx_data *spdifrx)
"Failed to start synchronization\n"); "Failed to start synchronization\n");
} }
spin_unlock(&spdifrx->lock); spin_unlock_irqrestore(&spdifrx->lock, flags);
return ret; return ret;
} }
...@@ -370,11 +372,12 @@ static int stm32_spdifrx_start_sync(struct stm32_spdifrx_data *spdifrx) ...@@ -370,11 +372,12 @@ static int stm32_spdifrx_start_sync(struct stm32_spdifrx_data *spdifrx)
static void stm32_spdifrx_stop(struct stm32_spdifrx_data *spdifrx) static void stm32_spdifrx_stop(struct stm32_spdifrx_data *spdifrx)
{ {
int cr, cr_mask, reg; int cr, cr_mask, reg;
unsigned long flags;
spin_lock(&spdifrx->lock); spin_lock_irqsave(&spdifrx->lock, flags);
if (--spdifrx->refcount) { if (--spdifrx->refcount) {
spin_unlock(&spdifrx->lock); spin_unlock_irqrestore(&spdifrx->lock, flags);
return; return;
} }
...@@ -393,7 +396,7 @@ static void stm32_spdifrx_stop(struct stm32_spdifrx_data *spdifrx) ...@@ -393,7 +396,7 @@ static void stm32_spdifrx_stop(struct stm32_spdifrx_data *spdifrx)
regmap_read(spdifrx->regmap, STM32_SPDIFRX_DR, &reg); regmap_read(spdifrx->regmap, STM32_SPDIFRX_DR, &reg);
regmap_read(spdifrx->regmap, STM32_SPDIFRX_CSR, &reg); regmap_read(spdifrx->regmap, STM32_SPDIFRX_CSR, &reg);
spin_unlock(&spdifrx->lock); spin_unlock_irqrestore(&spdifrx->lock, flags);
} }
static int stm32_spdifrx_dma_ctrl_register(struct device *dev, static int stm32_spdifrx_dma_ctrl_register(struct device *dev,
...@@ -480,8 +483,6 @@ static int stm32_spdifrx_get_ctrl_data(struct stm32_spdifrx_data *spdifrx) ...@@ -480,8 +483,6 @@ static int stm32_spdifrx_get_ctrl_data(struct stm32_spdifrx_data *spdifrx)
memset(spdifrx->cs, 0, SPDIFRX_CS_BYTES_NB); memset(spdifrx->cs, 0, SPDIFRX_CS_BYTES_NB);
memset(spdifrx->ub, 0, SPDIFRX_UB_BYTES_NB); memset(spdifrx->ub, 0, SPDIFRX_UB_BYTES_NB);
pinctrl_pm_select_default_state(&spdifrx->pdev->dev);
ret = stm32_spdifrx_dma_ctrl_start(spdifrx); ret = stm32_spdifrx_dma_ctrl_start(spdifrx);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -513,7 +514,6 @@ static int stm32_spdifrx_get_ctrl_data(struct stm32_spdifrx_data *spdifrx) ...@@ -513,7 +514,6 @@ static int stm32_spdifrx_get_ctrl_data(struct stm32_spdifrx_data *spdifrx)
end: end:
clk_disable_unprepare(spdifrx->kclk); clk_disable_unprepare(spdifrx->kclk);
pinctrl_pm_select_sleep_state(&spdifrx->pdev->dev);
return ret; return ret;
} }
...@@ -665,7 +665,6 @@ static const struct regmap_config stm32_h7_spdifrx_regmap_conf = { ...@@ -665,7 +665,6 @@ static const struct regmap_config stm32_h7_spdifrx_regmap_conf = {
static irqreturn_t stm32_spdifrx_isr(int irq, void *devid) static irqreturn_t stm32_spdifrx_isr(int irq, void *devid)
{ {
struct stm32_spdifrx_data *spdifrx = (struct stm32_spdifrx_data *)devid; struct stm32_spdifrx_data *spdifrx = (struct stm32_spdifrx_data *)devid;
struct snd_pcm_substream *substream = spdifrx->substream;
struct platform_device *pdev = spdifrx->pdev; struct platform_device *pdev = spdifrx->pdev;
unsigned int cr, mask, sr, imr; unsigned int cr, mask, sr, imr;
unsigned int flags, sync_state; unsigned int flags, sync_state;
...@@ -745,14 +744,19 @@ static irqreturn_t stm32_spdifrx_isr(int irq, void *devid) ...@@ -745,14 +744,19 @@ static irqreturn_t stm32_spdifrx_isr(int irq, void *devid)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
if (substream) spin_lock(&spdifrx->irq_lock);
snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED); if (spdifrx->substream)
snd_pcm_stop(spdifrx->substream,
SNDRV_PCM_STATE_DISCONNECTED);
spin_unlock(&spdifrx->irq_lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
if (err_xrun && substream) spin_lock(&spdifrx->irq_lock);
snd_pcm_stop_xrun(substream); if (err_xrun && spdifrx->substream)
snd_pcm_stop_xrun(spdifrx->substream);
spin_unlock(&spdifrx->irq_lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -761,9 +765,12 @@ static int stm32_spdifrx_startup(struct snd_pcm_substream *substream, ...@@ -761,9 +765,12 @@ static int stm32_spdifrx_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai) struct snd_soc_dai *cpu_dai)
{ {
struct stm32_spdifrx_data *spdifrx = snd_soc_dai_get_drvdata(cpu_dai); struct stm32_spdifrx_data *spdifrx = snd_soc_dai_get_drvdata(cpu_dai);
unsigned long flags;
int ret; int ret;
spin_lock_irqsave(&spdifrx->irq_lock, flags);
spdifrx->substream = substream; spdifrx->substream = substream;
spin_unlock_irqrestore(&spdifrx->irq_lock, flags);
ret = clk_prepare_enable(spdifrx->kclk); ret = clk_prepare_enable(spdifrx->kclk);
if (ret) if (ret)
...@@ -839,8 +846,12 @@ static void stm32_spdifrx_shutdown(struct snd_pcm_substream *substream, ...@@ -839,8 +846,12 @@ static void stm32_spdifrx_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai) struct snd_soc_dai *cpu_dai)
{ {
struct stm32_spdifrx_data *spdifrx = snd_soc_dai_get_drvdata(cpu_dai); struct stm32_spdifrx_data *spdifrx = snd_soc_dai_get_drvdata(cpu_dai);
unsigned long flags;
spin_lock_irqsave(&spdifrx->irq_lock, flags);
spdifrx->substream = NULL; spdifrx->substream = NULL;
spin_unlock_irqrestore(&spdifrx->irq_lock, flags);
clk_disable_unprepare(spdifrx->kclk); clk_disable_unprepare(spdifrx->kclk);
} }
...@@ -944,6 +955,7 @@ static int stm32_spdifrx_probe(struct platform_device *pdev) ...@@ -944,6 +955,7 @@ static int stm32_spdifrx_probe(struct platform_device *pdev)
spdifrx->pdev = pdev; spdifrx->pdev = pdev;
init_completion(&spdifrx->cs_completion); init_completion(&spdifrx->cs_completion);
spin_lock_init(&spdifrx->lock); spin_lock_init(&spdifrx->lock);
spin_lock_init(&spdifrx->irq_lock);
platform_set_drvdata(pdev, spdifrx); platform_set_drvdata(pdev, spdifrx);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment