Skip to content

Commit 25226ab

Browse files
morimotobroonie
authored andcommitted
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>
1 parent 030c59d commit 25226ab

1 file changed

Lines changed: 38 additions & 1 deletion

File tree

sound/soc/renesas/rcar/msiof.c

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,25 @@
2424
* Clock/Frame Consumer Mode.
2525
*/
2626

27+
/*
28+
* [NOTE-RESET]
29+
*
30+
* MSIOF has TXRST/RXRST to reset FIFO, but it shouldn't be used during SYNC signal was asserted,
31+
* because it will be cause of HW issue.
32+
*
33+
* When MSIOF is used as Sound driver, this driver is assuming it is used as clock consumer mode
34+
* (= Codec is clock provider). This means, it can't control SYNC signal by itself.
35+
*
36+
* We need to use SW reset (= reset_control_xxx()) instead of TXRST/RXRST.
37+
*/
38+
2739
#include <linux/module.h>
2840
#include <linux/of.h>
2941
#include <linux/of_dma.h>
3042
#include <linux/of_graph.h>
3143
#include <linux/platform_device.h>
3244
#include <linux/pm_runtime.h>
45+
#include <linux/reset.h>
3346
#include <linux/spi/sh_msiof.h>
3447
#include <sound/dmaengine_pcm.h>
3548
#include <sound/soc.h>
@@ -60,10 +73,13 @@
6073
struct msiof_priv {
6174
struct device *dev;
6275
struct snd_pcm_substream *substream[SNDRV_PCM_STREAM_LAST + 1];
76+
struct reset_control *reset;
6377
spinlock_t lock;
6478
void __iomem *base;
6579
resource_size_t phy_addr;
6680

81+
int count;
82+
6783
/* for error */
6884
int err_syc[SNDRV_PCM_STREAM_LAST + 1];
6985
int err_ovf[SNDRV_PCM_STREAM_LAST + 1];
@@ -131,6 +147,16 @@ static int msiof_hw_start(struct snd_soc_component *component,
131147
* RX: Fig 109.15
132148
*/
133149

150+
/*
151+
* Use reset_control_xx() instead of TXRST/RXRST.
152+
* see
153+
* [NOTE-RESET]
154+
*/
155+
if (!priv->count)
156+
reset_control_deassert(priv->reset);
157+
158+
priv->count++;
159+
134160
/* reset errors */
135161
priv->err_syc[substream->stream] =
136162
priv->err_ovf[substream->stream] =
@@ -152,7 +178,6 @@ static int msiof_hw_start(struct snd_soc_component *component,
152178
val = FIELD_PREP(SIMDR2_BITLEN1, width - 1);
153179
msiof_write(priv, SITMDR2, val | FIELD_PREP(SIMDR2_GRP, 1));
154180
msiof_write(priv, SITMDR3, val);
155-
156181
}
157182
/* SIRMDRx */
158183
else {
@@ -227,6 +252,11 @@ static int msiof_hw_stop(struct snd_soc_component *component,
227252
priv->err_ovf[substream->stream],
228253
priv->err_udf[substream->stream]);
229254

255+
priv->count--;
256+
257+
if (!priv->count)
258+
reset_control_assert(priv->reset);
259+
230260
return 0;
231261
}
232262

@@ -490,12 +520,19 @@ static int msiof_probe(struct platform_device *pdev)
490520
if (IS_ERR(priv->base))
491521
return PTR_ERR(priv->base);
492522

523+
priv->reset = devm_reset_control_get_exclusive(dev, NULL);
524+
if (IS_ERR(priv->reset))
525+
return PTR_ERR(priv->reset);
526+
527+
reset_control_assert(priv->reset);
528+
493529
ret = devm_request_irq(dev, irq, msiof_interrupt, 0, dev_name(dev), priv);
494530
if (ret)
495531
return ret;
496532

497533
priv->dev = dev;
498534
priv->phy_addr = res->start;
535+
priv->count = 0;
499536

500537
spin_lock_init(&priv->lock);
501538
platform_set_drvdata(pdev, priv);

0 commit comments

Comments
 (0)