lkml.org 
[lkml]   [2019]   [Jul]   [3]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH 2/2] ASoC: meson: axg-tdm-formatter: add reset
Date
Add the optional reset line handling which is present on the new SoC
families, such as the g12a. Triggering this reset is not critical but
it helps solve a channel shift issue on the g12a.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
sound/soc/meson/axg-tdm-formatter.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)

diff --git a/sound/soc/meson/axg-tdm-formatter.c b/sound/soc/meson/axg-tdm-formatter.c
index 0c6cce5c5773..2e498201139f 100644
--- a/sound/soc/meson/axg-tdm-formatter.c
+++ b/sound/soc/meson/axg-tdm-formatter.c
@@ -7,6 +7,7 @@
#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/regmap.h>
+#include <linux/reset.h>
#include <sound/soc.h>

#include "axg-tdm-formatter.h"
@@ -20,6 +21,7 @@ struct axg_tdm_formatter {
struct clk *lrclk;
struct clk *sclk_sel;
struct clk *lrclk_sel;
+ struct reset_control *reset;
bool enabled;
struct regmap *map;
};
@@ -75,6 +77,24 @@ static int axg_tdm_formatter_enable(struct axg_tdm_formatter *formatter)
if (formatter->enabled)
return 0;

+ /*
+ * On the g12a (and possibly other SoCs), when a stream using
+ * multiple lanes is restarted, it will sometimes not start
+ * from the first lane, but randomly from another used one.
+ * The result is an unexpected and random channel shift.
+ *
+ * The hypothesis is that an HW counter is not properly reset
+ * and the formatter simply starts on the lane it stopped
+ * before. Unfortunately, there does not seems to be a way to
+ * reset this through the registers of the block.
+ *
+ * However, the g12a has indenpendent reset lines for each audio
+ * devices. Using this reset before each start solves the issue.
+ */
+ ret = reset_control_reset(formatter->reset);
+ if (ret)
+ return ret;
+
/*
* If sclk is inverted, invert it back and provide the inversion
* required by the formatter
@@ -306,6 +326,15 @@ int axg_tdm_formatter_probe(struct platform_device *pdev)
return ret;
}

+ /* Formatter dedicated reset line */
+ formatter->reset = reset_control_get_optional_exclusive(dev, NULL);
+ if (IS_ERR(formatter->reset)) {
+ ret = PTR_ERR(formatter->reset);
+ if (ret != -EPROBE_DEFER)
+ dev_err(dev, "failed to get reset: %d\n", ret);
+ return ret;
+ }
+
return devm_snd_soc_register_component(dev, drv->component_drv,
NULL, 0);
}
--
2.21.0
\
 
 \ /
  Last update: 2019-07-03 14:09    [W:0.039 / U:3.300 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site