mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 01:49:46 +00:00
ASoC: renesas: msiof: use reset controller
MSIOF has TXRST/RXRST to reset FIFO, but it shouldn't be used during SYNC signal was asserted, because it will be cause of HW issue. When MSIOF is used as Sound driver, this driver is assuming it is used as clock consumer mode (= Codec is clock provider). This means, it can't control SYNC signal by itself. We need to use SW reset (= reset_control_xxx()) instead of TXRST/RXRST. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Tested-by: Yusuke Goda <yusuke.goda.sx@renesas.com> Link: https://patch.msgid.link/87cy7fyuug.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
committed by
Mark Brown
parent
030c59df83
commit
25226abc1a
@@ -24,12 +24,25 @@
|
||||
* Clock/Frame Consumer Mode.
|
||||
*/
|
||||
|
||||
/*
|
||||
* [NOTE-RESET]
|
||||
*
|
||||
* MSIOF has TXRST/RXRST to reset FIFO, but it shouldn't be used during SYNC signal was asserted,
|
||||
* because it will be cause of HW issue.
|
||||
*
|
||||
* When MSIOF is used as Sound driver, this driver is assuming it is used as clock consumer mode
|
||||
* (= Codec is clock provider). This means, it can't control SYNC signal by itself.
|
||||
*
|
||||
* We need to use SW reset (= reset_control_xxx()) instead of TXRST/RXRST.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_dma.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/spi/sh_msiof.h>
|
||||
#include <sound/dmaengine_pcm.h>
|
||||
#include <sound/soc.h>
|
||||
@@ -60,10 +73,13 @@
|
||||
struct msiof_priv {
|
||||
struct device *dev;
|
||||
struct snd_pcm_substream *substream[SNDRV_PCM_STREAM_LAST + 1];
|
||||
struct reset_control *reset;
|
||||
spinlock_t lock;
|
||||
void __iomem *base;
|
||||
resource_size_t phy_addr;
|
||||
|
||||
int count;
|
||||
|
||||
/* for error */
|
||||
int err_syc[SNDRV_PCM_STREAM_LAST + 1];
|
||||
int err_ovf[SNDRV_PCM_STREAM_LAST + 1];
|
||||
@@ -131,6 +147,16 @@ static int msiof_hw_start(struct snd_soc_component *component,
|
||||
* RX: Fig 109.15
|
||||
*/
|
||||
|
||||
/*
|
||||
* Use reset_control_xx() instead of TXRST/RXRST.
|
||||
* see
|
||||
* [NOTE-RESET]
|
||||
*/
|
||||
if (!priv->count)
|
||||
reset_control_deassert(priv->reset);
|
||||
|
||||
priv->count++;
|
||||
|
||||
/* reset errors */
|
||||
priv->err_syc[substream->stream] =
|
||||
priv->err_ovf[substream->stream] =
|
||||
@@ -152,7 +178,6 @@ static int msiof_hw_start(struct snd_soc_component *component,
|
||||
val = FIELD_PREP(SIMDR2_BITLEN1, width - 1);
|
||||
msiof_write(priv, SITMDR2, val | FIELD_PREP(SIMDR2_GRP, 1));
|
||||
msiof_write(priv, SITMDR3, val);
|
||||
|
||||
}
|
||||
/* SIRMDRx */
|
||||
else {
|
||||
@@ -227,6 +252,11 @@ static int msiof_hw_stop(struct snd_soc_component *component,
|
||||
priv->err_ovf[substream->stream],
|
||||
priv->err_udf[substream->stream]);
|
||||
|
||||
priv->count--;
|
||||
|
||||
if (!priv->count)
|
||||
reset_control_assert(priv->reset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -490,12 +520,19 @@ static int msiof_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(priv->base))
|
||||
return PTR_ERR(priv->base);
|
||||
|
||||
priv->reset = devm_reset_control_get_exclusive(dev, NULL);
|
||||
if (IS_ERR(priv->reset))
|
||||
return PTR_ERR(priv->reset);
|
||||
|
||||
reset_control_assert(priv->reset);
|
||||
|
||||
ret = devm_request_irq(dev, irq, msiof_interrupt, 0, dev_name(dev), priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->dev = dev;
|
||||
priv->phy_addr = res->start;
|
||||
priv->count = 0;
|
||||
|
||||
spin_lock_init(&priv->lock);
|
||||
platform_set_drvdata(pdev, priv);
|
||||
|
||||
Reference in New Issue
Block a user