[PATCH 0/7] soundwire: filter out invalid PARITY errors
Some codecs may report fake PARITY errors in the initial state. This series will filter them out.
Pierre-Louis Bossart (7): soundwire: bus: use property to set interrupt masks soundwire: bus: filter-out unwanted interrupt reports soundwire: slave: add first_interrupt_done status soundwire: bus: use quirk to filter out invalid parity errors ASoC: codecs: realtek-soundwire: ignore initial PARITY errors soundwire: bus: export broadcast read/write capability for tests soundwire: cadence: add parity error injection through debugfs
drivers/soundwire/bus.c | 93 ++++++++++++++++++++++++------ drivers/soundwire/bus.h | 4 ++ drivers/soundwire/cadence_master.c | 86 +++++++++++++++++++++++++++ drivers/soundwire/slave.c | 1 + include/linux/soundwire/sdw.h | 9 +++ sound/soc/codecs/max98373-sdw.c | 3 + sound/soc/codecs/rt1308-sdw.c | 3 + sound/soc/codecs/rt5682-sdw.c | 5 ++ sound/soc/codecs/rt700-sdw.c | 5 ++ sound/soc/codecs/rt711-sdw.c | 5 ++ sound/soc/codecs/rt715-sdw.c | 5 ++ sound/soc/codecs/wsa881x.c | 1 + 12 files changed, 202 insertions(+), 18 deletions(-)
From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com
Add a slave-level property and program the SCP_INT1_MASK as desired by the codec driver. Since there is no DisCo property this has to be an implementation-specific firmware property or hard-coded in the driver.
The only functionality change is that implementation-defined interrupts are no longer set for amplifiers - those interrupts are typically for jack detection or acoustic event detection/hotwording.
Tested-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Reviewed-by: Kai Vehmanen kai.vehmanen@linux.intel.com Reviewed-by: Guennadi Liakhovetski guennadi.liakhovetski@linux.intel.com Signed-off-by: Bard Liao yung-chuan.liao@linux.intel.com --- drivers/soundwire/bus.c | 12 ++++++------ include/linux/soundwire/sdw.h | 2 ++ sound/soc/codecs/max98373-sdw.c | 3 +++ sound/soc/codecs/rt1308-sdw.c | 2 ++ sound/soc/codecs/rt5682-sdw.c | 4 ++++ sound/soc/codecs/rt700-sdw.c | 4 ++++ sound/soc/codecs/rt711-sdw.c | 4 ++++ sound/soc/codecs/rt715-sdw.c | 4 ++++ sound/soc/codecs/wsa881x.c | 1 + 9 files changed, 30 insertions(+), 6 deletions(-)
diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index e6e0fb9a81b4..3b6a87bc254e 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -1184,13 +1184,13 @@ static int sdw_initialize_slave(struct sdw_slave *slave) return ret;
/* - * Set bus clash, parity and SCP implementation - * defined interrupt mask - * TODO: Read implementation defined interrupt mask - * from Slave property + * Set SCP_INT1_MASK register, typically bus clash and + * implementation-defined interrupt mask. The Parity detection + * may not always be correct on startup so its use is + * device-dependent, it might e.g. only be enabled in + * steady-state after a couple of frames. */ - val = SDW_SCP_INT1_IMPL_DEF | SDW_SCP_INT1_BUS_CLASH | - SDW_SCP_INT1_PARITY; + val = slave->prop.scp_int1_mask;
/* Enable SCP interrupts */ ret = sdw_update(slave, SDW_SCP_INTMASK1, val, val); diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index 76052f12c9f7..6d91f2ca20b2 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -355,6 +355,7 @@ struct sdw_dpn_prop { * @dp0_prop: Data Port 0 properties * @src_dpn_prop: Source Data Port N properties * @sink_dpn_prop: Sink Data Port N properties + * @scp_int1_mask: SCP_INT1_MASK desired settings */ struct sdw_slave_prop { u32 mipi_revision; @@ -376,6 +377,7 @@ struct sdw_slave_prop { struct sdw_dp0_prop *dp0_prop; struct sdw_dpn_prop *src_dpn_prop; struct sdw_dpn_prop *sink_dpn_prop; + u8 scp_int1_mask; };
/** diff --git a/sound/soc/codecs/max98373-sdw.c b/sound/soc/codecs/max98373-sdw.c index 5fe724728e84..17fd1989e873 100644 --- a/sound/soc/codecs/max98373-sdw.c +++ b/sound/soc/codecs/max98373-sdw.c @@ -15,6 +15,7 @@ #include <linux/of.h> #include <linux/soundwire/sdw.h> #include <linux/soundwire/sdw_type.h> +#include <linux/soundwire/sdw_registers.h> #include "max98373.h" #include "max98373-sdw.h"
@@ -287,6 +288,8 @@ static int max98373_read_prop(struct sdw_slave *slave) unsigned long addr; struct sdw_dpn_prop *dpn;
+ prop->scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; + /* BITMAP: 00001000 Dataport 3 is active */ prop->source_ports = BIT(3); /* BITMAP: 00000010 Dataport 1 is active */ diff --git a/sound/soc/codecs/rt1308-sdw.c b/sound/soc/codecs/rt1308-sdw.c index b0ba0d2acbdd..5cf10fd447eb 100644 --- a/sound/soc/codecs/rt1308-sdw.c +++ b/sound/soc/codecs/rt1308-sdw.c @@ -123,6 +123,8 @@ static int rt1308_read_prop(struct sdw_slave *slave) unsigned long addr; struct sdw_dpn_prop *dpn;
+ prop->scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; + prop->paging_support = true;
/* first we need to allocate memory for set bits in port lists */ diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c index 94bf6bee78e6..544073975020 100644 --- a/sound/soc/codecs/rt5682-sdw.c +++ b/sound/soc/codecs/rt5682-sdw.c @@ -19,6 +19,7 @@ #include <linux/mutex.h> #include <linux/soundwire/sdw.h> #include <linux/soundwire/sdw_type.h> +#include <linux/soundwire/sdw_registers.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> @@ -542,6 +543,9 @@ static int rt5682_read_prop(struct sdw_slave *slave) unsigned long addr; struct sdw_dpn_prop *dpn;
+ prop->scp_int1_mask = SDW_SCP_INT1_IMPL_DEF | SDW_SCP_INT1_BUS_CLASH | + SDW_SCP_INT1_PARITY; + prop->paging_support = false;
/* first we need to allocate memory for set bits in port lists */ diff --git a/sound/soc/codecs/rt700-sdw.c b/sound/soc/codecs/rt700-sdw.c index 4d14048d1197..a46b957a3f1b 100644 --- a/sound/soc/codecs/rt700-sdw.c +++ b/sound/soc/codecs/rt700-sdw.c @@ -11,6 +11,7 @@ #include <linux/mod_devicetable.h> #include <linux/soundwire/sdw.h> #include <linux/soundwire/sdw_type.h> +#include <linux/soundwire/sdw_registers.h> #include <linux/module.h> #include <linux/regmap.h> #include <sound/soc.h> @@ -338,6 +339,9 @@ static int rt700_read_prop(struct sdw_slave *slave) unsigned long addr; struct sdw_dpn_prop *dpn;
+ prop->scp_int1_mask = SDW_SCP_INT1_IMPL_DEF | SDW_SCP_INT1_BUS_CLASH | + SDW_SCP_INT1_PARITY; + prop->paging_support = false;
/* first we need to allocate memory for set bits in port lists */ diff --git a/sound/soc/codecs/rt711-sdw.c b/sound/soc/codecs/rt711-sdw.c index 45b928954b58..a877e366fec5 100644 --- a/sound/soc/codecs/rt711-sdw.c +++ b/sound/soc/codecs/rt711-sdw.c @@ -11,6 +11,7 @@ #include <linux/mod_devicetable.h> #include <linux/soundwire/sdw.h> #include <linux/soundwire/sdw_type.h> +#include <linux/soundwire/sdw_registers.h> #include <linux/module.h> #include <linux/regmap.h> #include <sound/soc.h> @@ -342,6 +343,9 @@ static int rt711_read_prop(struct sdw_slave *slave) unsigned long addr; struct sdw_dpn_prop *dpn;
+ prop->scp_int1_mask = SDW_SCP_INT1_IMPL_DEF | SDW_SCP_INT1_BUS_CLASH | + SDW_SCP_INT1_PARITY; + prop->paging_support = false;
/* first we need to allocate memory for set bits in port lists */ diff --git a/sound/soc/codecs/rt715-sdw.c b/sound/soc/codecs/rt715-sdw.c index d11b23d6b240..0eb8943ed6ff 100644 --- a/sound/soc/codecs/rt715-sdw.c +++ b/sound/soc/codecs/rt715-sdw.c @@ -12,6 +12,7 @@ #include <linux/mod_devicetable.h> #include <linux/soundwire/sdw.h> #include <linux/soundwire/sdw_type.h> +#include <linux/soundwire/sdw_registers.h> #include <linux/module.h> #include <linux/of.h> #include <linux/regmap.h> @@ -436,6 +437,9 @@ static int rt715_read_prop(struct sdw_slave *slave) unsigned long addr; struct sdw_dpn_prop *dpn;
+ prop->scp_int1_mask = SDW_SCP_INT1_IMPL_DEF | SDW_SCP_INT1_BUS_CLASH | + SDW_SCP_INT1_PARITY; + prop->paging_support = false;
/* first we need to allocate memory for set bits in port lists */ diff --git a/sound/soc/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c index d39d479e2378..68e774e69c85 100644 --- a/sound/soc/codecs/wsa881x.c +++ b/sound/soc/codecs/wsa881x.c @@ -1112,6 +1112,7 @@ static int wsa881x_probe(struct sdw_slave *pdev, wsa881x->sconfig.type = SDW_STREAM_PDM; pdev->prop.sink_ports = GENMASK(WSA881X_MAX_SWR_PORTS, 0); pdev->prop.sink_dpn_prop = wsa_sink_dpn_prop; + pdev->prop.scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; gpiod_direction_output(wsa881x->sd_n, 1);
wsa881x->regmap = devm_regmap_init_sdw(pdev, &wsa881x_regmap_config);
Hi Mark,
On 18-08-20, 22:06, Bard Liao wrote:
From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com
Add a slave-level property and program the SCP_INT1_MASK as desired by the codec driver. Since there is no DisCo property this has to be an implementation-specific firmware property or hard-coded in the driver.
The only functionality change is that implementation-defined interrupts are no longer set for amplifiers - those interrupts are typically for jack detection or acoustic event detection/hotwording.
Tested-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Reviewed-by: Kai Vehmanen kai.vehmanen@linux.intel.com Reviewed-by: Guennadi Liakhovetski guennadi.liakhovetski@linux.intel.com Signed-off-by: Bard Liao yung-chuan.liao@linux.intel.com
drivers/soundwire/bus.c | 12 ++++++------ include/linux/soundwire/sdw.h | 2 ++ sound/soc/codecs/max98373-sdw.c | 3 +++ sound/soc/codecs/rt1308-sdw.c | 2 ++ sound/soc/codecs/rt5682-sdw.c | 4 ++++ sound/soc/codecs/rt700-sdw.c | 4 ++++ sound/soc/codecs/rt711-sdw.c | 4 ++++ sound/soc/codecs/rt715-sdw.c | 4 ++++ sound/soc/codecs/wsa881x.c | 1 +
This touches codecs, can you Ack it please
Ideally this should have been split up to header, the codec updates and finally the bus change!
9 files changed, 30 insertions(+), 6 deletions(-)
diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index e6e0fb9a81b4..3b6a87bc254e 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -1184,13 +1184,13 @@ static int sdw_initialize_slave(struct sdw_slave *slave) return ret;
/*
* Set bus clash, parity and SCP implementation
* defined interrupt mask
* TODO: Read implementation defined interrupt mask
* from Slave property
* Set SCP_INT1_MASK register, typically bus clash and
* implementation-defined interrupt mask. The Parity detection
* may not always be correct on startup so its use is
* device-dependent, it might e.g. only be enabled in
*/* steady-state after a couple of frames.
- val = SDW_SCP_INT1_IMPL_DEF | SDW_SCP_INT1_BUS_CLASH |
SDW_SCP_INT1_PARITY;
val = slave->prop.scp_int1_mask;
/* Enable SCP interrupts */ ret = sdw_update(slave, SDW_SCP_INTMASK1, val, val);
diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index 76052f12c9f7..6d91f2ca20b2 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -355,6 +355,7 @@ struct sdw_dpn_prop {
- @dp0_prop: Data Port 0 properties
- @src_dpn_prop: Source Data Port N properties
- @sink_dpn_prop: Sink Data Port N properties
*/
- @scp_int1_mask: SCP_INT1_MASK desired settings
struct sdw_slave_prop { u32 mipi_revision; @@ -376,6 +377,7 @@ struct sdw_slave_prop { struct sdw_dp0_prop *dp0_prop; struct sdw_dpn_prop *src_dpn_prop; struct sdw_dpn_prop *sink_dpn_prop;
- u8 scp_int1_mask;
};
/** diff --git a/sound/soc/codecs/max98373-sdw.c b/sound/soc/codecs/max98373-sdw.c index 5fe724728e84..17fd1989e873 100644 --- a/sound/soc/codecs/max98373-sdw.c +++ b/sound/soc/codecs/max98373-sdw.c @@ -15,6 +15,7 @@ #include <linux/of.h> #include <linux/soundwire/sdw.h> #include <linux/soundwire/sdw_type.h> +#include <linux/soundwire/sdw_registers.h> #include "max98373.h" #include "max98373-sdw.h"
@@ -287,6 +288,8 @@ static int max98373_read_prop(struct sdw_slave *slave) unsigned long addr; struct sdw_dpn_prop *dpn;
- prop->scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY;
- /* BITMAP: 00001000 Dataport 3 is active */ prop->source_ports = BIT(3); /* BITMAP: 00000010 Dataport 1 is active */
diff --git a/sound/soc/codecs/rt1308-sdw.c b/sound/soc/codecs/rt1308-sdw.c index b0ba0d2acbdd..5cf10fd447eb 100644 --- a/sound/soc/codecs/rt1308-sdw.c +++ b/sound/soc/codecs/rt1308-sdw.c @@ -123,6 +123,8 @@ static int rt1308_read_prop(struct sdw_slave *slave) unsigned long addr; struct sdw_dpn_prop *dpn;
prop->scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY;
prop->paging_support = true;
/* first we need to allocate memory for set bits in port lists */
diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c index 94bf6bee78e6..544073975020 100644 --- a/sound/soc/codecs/rt5682-sdw.c +++ b/sound/soc/codecs/rt5682-sdw.c @@ -19,6 +19,7 @@ #include <linux/mutex.h> #include <linux/soundwire/sdw.h> #include <linux/soundwire/sdw_type.h> +#include <linux/soundwire/sdw_registers.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> @@ -542,6 +543,9 @@ static int rt5682_read_prop(struct sdw_slave *slave) unsigned long addr; struct sdw_dpn_prop *dpn;
prop->scp_int1_mask = SDW_SCP_INT1_IMPL_DEF | SDW_SCP_INT1_BUS_CLASH |
SDW_SCP_INT1_PARITY;
prop->paging_support = false;
/* first we need to allocate memory for set bits in port lists */
diff --git a/sound/soc/codecs/rt700-sdw.c b/sound/soc/codecs/rt700-sdw.c index 4d14048d1197..a46b957a3f1b 100644 --- a/sound/soc/codecs/rt700-sdw.c +++ b/sound/soc/codecs/rt700-sdw.c @@ -11,6 +11,7 @@ #include <linux/mod_devicetable.h> #include <linux/soundwire/sdw.h> #include <linux/soundwire/sdw_type.h> +#include <linux/soundwire/sdw_registers.h> #include <linux/module.h> #include <linux/regmap.h> #include <sound/soc.h> @@ -338,6 +339,9 @@ static int rt700_read_prop(struct sdw_slave *slave) unsigned long addr; struct sdw_dpn_prop *dpn;
prop->scp_int1_mask = SDW_SCP_INT1_IMPL_DEF | SDW_SCP_INT1_BUS_CLASH |
SDW_SCP_INT1_PARITY;
prop->paging_support = false;
/* first we need to allocate memory for set bits in port lists */
diff --git a/sound/soc/codecs/rt711-sdw.c b/sound/soc/codecs/rt711-sdw.c index 45b928954b58..a877e366fec5 100644 --- a/sound/soc/codecs/rt711-sdw.c +++ b/sound/soc/codecs/rt711-sdw.c @@ -11,6 +11,7 @@ #include <linux/mod_devicetable.h> #include <linux/soundwire/sdw.h> #include <linux/soundwire/sdw_type.h> +#include <linux/soundwire/sdw_registers.h> #include <linux/module.h> #include <linux/regmap.h> #include <sound/soc.h> @@ -342,6 +343,9 @@ static int rt711_read_prop(struct sdw_slave *slave) unsigned long addr; struct sdw_dpn_prop *dpn;
prop->scp_int1_mask = SDW_SCP_INT1_IMPL_DEF | SDW_SCP_INT1_BUS_CLASH |
SDW_SCP_INT1_PARITY;
prop->paging_support = false;
/* first we need to allocate memory for set bits in port lists */
diff --git a/sound/soc/codecs/rt715-sdw.c b/sound/soc/codecs/rt715-sdw.c index d11b23d6b240..0eb8943ed6ff 100644 --- a/sound/soc/codecs/rt715-sdw.c +++ b/sound/soc/codecs/rt715-sdw.c @@ -12,6 +12,7 @@ #include <linux/mod_devicetable.h> #include <linux/soundwire/sdw.h> #include <linux/soundwire/sdw_type.h> +#include <linux/soundwire/sdw_registers.h> #include <linux/module.h> #include <linux/of.h> #include <linux/regmap.h> @@ -436,6 +437,9 @@ static int rt715_read_prop(struct sdw_slave *slave) unsigned long addr; struct sdw_dpn_prop *dpn;
prop->scp_int1_mask = SDW_SCP_INT1_IMPL_DEF | SDW_SCP_INT1_BUS_CLASH |
SDW_SCP_INT1_PARITY;
prop->paging_support = false;
/* first we need to allocate memory for set bits in port lists */
diff --git a/sound/soc/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c index d39d479e2378..68e774e69c85 100644 --- a/sound/soc/codecs/wsa881x.c +++ b/sound/soc/codecs/wsa881x.c @@ -1112,6 +1112,7 @@ static int wsa881x_probe(struct sdw_slave *pdev, wsa881x->sconfig.type = SDW_STREAM_PDM; pdev->prop.sink_ports = GENMASK(WSA881X_MAX_SWR_PORTS, 0); pdev->prop.sink_dpn_prop = wsa_sink_dpn_prop;
pdev->prop.scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; gpiod_direction_output(wsa881x->sd_n, 1);
wsa881x->regmap = devm_regmap_init_sdw(pdev, &wsa881x_regmap_config);
-- 2.17.1
Dne 28. 08. 20 v 8:51 Vinod Koul napsal(a):
Hi Mark,
On 18-08-20, 22:06, Bard Liao wrote:
From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com
Add a slave-level property and program the SCP_INT1_MASK as desired by the codec driver. Since there is no DisCo property this has to be an implementation-specific firmware property or hard-coded in the driver.
The only functionality change is that implementation-defined interrupts are no longer set for amplifiers - those interrupts are typically for jack detection or acoustic event detection/hotwording.
Tested-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Reviewed-by: Kai Vehmanen kai.vehmanen@linux.intel.com Reviewed-by: Guennadi Liakhovetski guennadi.liakhovetski@linux.intel.com Signed-off-by: Bard Liao yung-chuan.liao@linux.intel.com
drivers/soundwire/bus.c | 12 ++++++------ include/linux/soundwire/sdw.h | 2 ++ sound/soc/codecs/max98373-sdw.c | 3 +++ sound/soc/codecs/rt1308-sdw.c | 2 ++ sound/soc/codecs/rt5682-sdw.c | 4 ++++ sound/soc/codecs/rt700-sdw.c | 4 ++++ sound/soc/codecs/rt711-sdw.c | 4 ++++ sound/soc/codecs/rt715-sdw.c | 4 ++++ sound/soc/codecs/wsa881x.c | 1 +
This touches codecs, can you Ack it please
Mark, could you ack the ASoC change to accept this patch via the soundwire repo?
Ideally this should have been split up to header, the codec updates and finally the bus change!
I don't think that the split is ideal in this case. I tested the code and it looks straight enough.
Acked-by: Jaroslav Kysela perex@perex.cz
On Tue, Sep 08, 2020 at 02:05:11PM +0200, Jaroslav Kysela wrote:
Dne 28. 08. 20 v 8:51 Vinod Koul napsal(a):
sound/soc/codecs/rt700-sdw.c | 4 ++++ sound/soc/codecs/rt711-sdw.c | 4 ++++ sound/soc/codecs/rt715-sdw.c | 4 ++++ sound/soc/codecs/wsa881x.c | 1 +
This touches codecs, can you Ack it please
Mark, could you ack the ASoC change to accept this patch via the soundwire repo?
I don't have this patch and since I seem to get copied on quite a lot of soundwire only serieses I just delete them unread mostly.
Dne 08. 09. 20 v 14:11 Mark Brown napsal(a):
On Tue, Sep 08, 2020 at 02:05:11PM +0200, Jaroslav Kysela wrote:
Dne 28. 08. 20 v 8:51 Vinod Koul napsal(a):
sound/soc/codecs/rt700-sdw.c | 4 ++++ sound/soc/codecs/rt711-sdw.c | 4 ++++ sound/soc/codecs/rt715-sdw.c | 4 ++++ sound/soc/codecs/wsa881x.c | 1 +
This touches codecs, can you Ack it please
Mark, could you ack the ASoC change to accept this patch via the soundwire repo?
I don't have this patch and since I seem to get copied on quite a lot of soundwire only serieses I just delete them unread mostly.
It can be fetched from lore (mbox format):
https://lore.kernel.org/alsa-devel/20200818140656.29014-2-yung-chuan.liao@li...
Thanks, Jaroslav
On Tue, Sep 08, 2020 at 02:28:48PM +0200, Jaroslav Kysela wrote:
Dne 08. 09. 20 v 14:11 Mark Brown napsal(a):
I don't have this patch and since I seem to get copied on quite a lot of soundwire only serieses I just delete them unread mostly.
It can be fetched from lore (mbox format):
https://lore.kernel.org/alsa-devel/20200818140656.29014-2-yung-chuan.liao@li...
Sure, I can go get stuff from the list archives but my list of things to go through is in my inbox.
Dne 08. 09. 20 v 16:33 Mark Brown napsal(a):
On Tue, Sep 08, 2020 at 02:28:48PM +0200, Jaroslav Kysela wrote:
Dne 08. 09. 20 v 14:11 Mark Brown napsal(a):
I don't have this patch and since I seem to get copied on quite a lot of soundwire only serieses I just delete them unread mostly.
It can be fetched from lore (mbox format):
https://lore.kernel.org/alsa-devel/20200818140656.29014-2-yung-chuan.liao@li...
Sure, I can go get stuff from the list archives but my list of things to go through is in my inbox.
Okay, please, Bard resend this patchset as v2 (with already agreed Acked-by:) otherwise it won't be applied. I believe that an ack on my follow-up with the check of the original message should be sufficient, but apparently it isn't.
Thanks, Jaroslav
-----Original Message----- From: Jaroslav Kysela perex@perex.cz Sent: Tuesday, September 8, 2020 10:43 PM To: Mark Brown broonie@kernel.org Cc: Vinod Koul vkoul@kernel.org; Bard Liao <yung- chuan.liao@linux.intel.com>; pierre-louis.bossart@linux.intel.com; alsa- devel@alsa-project.org; tiwai@suse.de; gregkh@linuxfoundation.org; linux- kernel@vger.kernel.org; ranjani.sridharan@linux.intel.com; hui.wang@canonical.com; srinivas.kandagatla@linaro.org; jank@cadence.com; Lin, Mengdong mengdong.lin@intel.com; Kale, Sanyog R sanyog.r.kale@intel.com; rander.wang@linux.intel.com; Liao, Bard bard.liao@intel.com Subject: Re: [PATCH 1/7] soundwire: bus: use property to set interrupt masks
Dne 08. 09. 20 v 16:33 Mark Brown napsal(a):
On Tue, Sep 08, 2020 at 02:28:48PM +0200, Jaroslav Kysela wrote:
Dne 08. 09. 20 v 14:11 Mark Brown napsal(a):
I don't have this patch and since I seem to get copied on quite a lot of soundwire only serieses I just delete them unread mostly.
It can be fetched from lore (mbox format):
https://lore.kernel.org/alsa-devel/20200818140656.29014-2-yung-
chuan.liao@linux.intel.com/raw
Sure, I can go get stuff from the list archives but my list of things to go through is in my inbox.
Okay, please, Bard resend this patchset as v2 (with already agreed Acked-by:) otherwise it won't be applied. I believe that an ack on my follow-up with the check of the original message should be sufficient, but apparently it isn't.
Done. I forgot to mention that the patches themselves are not changed in the cover letter. The only changes in v2 is editing the title with "ASoC/ soundwire:" prefix.
Thanks, Jaroslav
-- Jaroslav Kysela perex@perex.cz Linux Sound Maintainer; ALSA Project; Red Hat, Inc.
On 9/8/20 9:33 AM, Mark Brown wrote:
On Tue, Sep 08, 2020 at 02:28:48PM +0200, Jaroslav Kysela wrote:
Dne 08. 09. 20 v 14:11 Mark Brown napsal(a):
I don't have this patch and since I seem to get copied on quite a lot of soundwire only serieses I just delete them unread mostly.
We now try to use the ASoC/SoundWire prefix for cover letters to highlight that a patchset changes things across two trees, does this help or do we need a different way of flagging these patches?
It can be fetched from lore (mbox format):
https://lore.kernel.org/alsa-devel/20200818140656.29014-2-yung-chuan.liao@li...
Sure, I can go get stuff from the list archives but my list of things to go through is in my inbox.
On Tue, Sep 08, 2020 at 09:47:13AM -0500, Pierre-Louis Bossart wrote:
On 9/8/20 9:33 AM, Mark Brown wrote:
On Tue, Sep 08, 2020 at 02:28:48PM +0200, Jaroslav Kysela wrote:
Dne 08. 09. 20 v 14:11 Mark Brown napsal(a):
I don't have this patch and since I seem to get copied on quite a lot of soundwire only serieses I just delete them unread mostly.
We now try to use the ASoC/SoundWire prefix for cover letters to highlight that a patchset changes things across two trees, does this help or do we need a different way of flagging these patches?
I think the issue is mainly where the patch itself touches both, if some of the patches mention ASoC I'll generally notice them but Soundwire is one of these things I get so many random CCs for I just zone it out so highlighting the individual patches would help.
I don't have this patch and since I seem to get copied on quite a lot of soundwire only serieses I just delete them unread mostly.
We now try to use the ASoC/SoundWire prefix for cover letters to highlight that a patchset changes things across two trees, does this help or do we need a different way of flagging these patches?
I think the issue is mainly where the patch itself touches both, if some of the patches mention ASoC I'll generally notice them but Soundwire is one of these things I get so many random CCs for I just zone it out so highlighting the individual patches would help.
ok, we'll highlight individual patches then and better explain dependencies.
From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com
Unlike the traditional usage, in the SoundWire specification the interrupt masks only gate the propagation of an interrupt condition to the PING frame status. They do not gate the changes of the INT_STAT registers, which will happen regardless of the mask settings. See Figure 116 of the SoundWire 1.2 specification for an in-depth description of the interrupt model.
When the bus driver reads the SCP_INT1_STAT register, it will retrieve all the interrupt status, including for the mask fields that were not explicitly set. For example, even if the PARITY mask is not set, the PARITY error status will be reported if an implementation-defined interrupt for jack detection is enabled and occurs.
Filtering undesired interrupt reports and handling has to be implemented in software. This patch enables this filtering for the INT1_IMPL_DEF, PARITY and BUS_CLASH interrupt sources.
Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Reviewed-by: Kai Vehmanen kai.vehmanen@linux.intel.com Reviewed-by: Guennadi Liakhovetski guennadi.liakhovetski@linux.intel.com Signed-off-by: Bard Liao yung-chuan.liao@linux.intel.com --- drivers/soundwire/bus.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index 3b6a87bc254e..9e5bcd0dd115 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -1394,12 +1394,14 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave) * interrupt */ if (buf & SDW_SCP_INT1_PARITY) { - dev_err(&slave->dev, "Parity error detected\n"); + if (slave->prop.scp_int1_mask & SDW_SCP_INT1_PARITY) + dev_err(&slave->dev, "Parity error detected\n"); clear |= SDW_SCP_INT1_PARITY; }
if (buf & SDW_SCP_INT1_BUS_CLASH) { - dev_err(&slave->dev, "Bus clash error detected\n"); + if (slave->prop.scp_int1_mask & SDW_SCP_INT1_BUS_CLASH) + dev_err(&slave->dev, "Bus clash detected\n"); clear |= SDW_SCP_INT1_BUS_CLASH; }
@@ -1411,9 +1413,11 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave) */
if (buf & SDW_SCP_INT1_IMPL_DEF) { - dev_dbg(&slave->dev, "Slave impl defined interrupt\n"); + if (slave->prop.scp_int1_mask & SDW_SCP_INT1_IMPL_DEF) { + dev_dbg(&slave->dev, "Slave impl defined interrupt\n"); + slave_notify = true; + } clear |= SDW_SCP_INT1_IMPL_DEF; - slave_notify = true; }
/* Check port 0 - 3 interrupts */
From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com
Some Slaves report incorrect information in their interrupt status registers after a master/bus reset, track the initial interrupt handling so that quirks can be introduced to filter out incorrect information while keeping interrupts enabled in steady state.
Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Reviewed-by: Kai Vehmanen kai.vehmanen@linux.intel.com Reviewed-by: Guennadi Liakhovetski guennadi.liakhovetski@linux.intel.com Signed-off-by: Bard Liao yung-chuan.liao@linux.intel.com --- drivers/soundwire/bus.c | 7 ++++++- drivers/soundwire/slave.c | 1 + include/linux/soundwire/sdw.h | 3 +++ 3 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index 9e5bcd0dd115..cddf39e3adfc 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -1472,6 +1472,9 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave) goto io_err; }
+ /* at this point all initial interrupt sources were handled */ + slave->first_interrupt_done = true; + /* * Read status again to ensure no new interrupts arrived * while servicing interrupts. @@ -1674,8 +1677,10 @@ void sdw_clear_slave_status(struct sdw_bus *bus, u32 request) if (!slave) continue;
- if (slave->status != SDW_SLAVE_UNATTACHED) + if (slave->status != SDW_SLAVE_UNATTACHED) { sdw_modify_slave_status(slave, SDW_SLAVE_UNATTACHED); + slave->first_interrupt_done = false; + }
/* keep track of request, used in pm_runtime resume */ slave->unattach_request = request; diff --git a/drivers/soundwire/slave.c b/drivers/soundwire/slave.c index 0839445ee07b..755d43eba63b 100644 --- a/drivers/soundwire/slave.c +++ b/drivers/soundwire/slave.c @@ -57,6 +57,7 @@ static int sdw_slave_add(struct sdw_bus *bus, slave->dev_num = 0; init_completion(&slave->probe_complete); slave->probed = false; + slave->first_interrupt_done = false;
mutex_lock(&bus->bus_lock); list_add_tail(&slave->node, &bus->slaves); diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index 6d91f2ca20b2..3550ab530c43 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -608,6 +608,8 @@ struct sdw_slave_ops { * between the Master suspending and the codec resuming, and make sure that * when the Master triggered a reset the Slave is properly enumerated and * initialized + * @first_interrupt_done: status flag tracking if the interrupt handling + * for a Slave happens for the first time after enumeration */ struct sdw_slave { struct sdw_slave_id id; @@ -629,6 +631,7 @@ struct sdw_slave { struct completion enumeration_complete; struct completion initialization_complete; u32 unattach_request; + bool first_interrupt_done; };
#define dev_to_sdw_dev(_dev) container_of(_dev, struct sdw_slave, dev)
From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com
If a Slave device reports with a quirk that its initial parity check may be incorrect, filter it but keep the parity checks active in steady state.
Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Reviewed-by: Kai Vehmanen kai.vehmanen@linux.intel.com Reviewed-by: Guennadi Liakhovetski guennadi.liakhovetski@linux.intel.com Signed-off-by: Bard Liao yung-chuan.liao@linux.intel.com --- drivers/soundwire/bus.c | 8 +++++++- include/linux/soundwire/sdw.h | 4 ++++ 2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index cddf39e3adfc..869290a8db40 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -1362,6 +1362,8 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave) unsigned long port; bool slave_notify = false; u8 buf, buf2[2], _buf, _buf2[2]; + bool parity_check; + bool parity_quirk;
sdw_modify_slave_status(slave, SDW_SLAVE_ALERT);
@@ -1394,7 +1396,11 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave) * interrupt */ if (buf & SDW_SCP_INT1_PARITY) { - if (slave->prop.scp_int1_mask & SDW_SCP_INT1_PARITY) + parity_check = slave->prop.scp_int1_mask & SDW_SCP_INT1_PARITY; + parity_quirk = !slave->first_interrupt_done && + (slave->prop.quirks & SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY); + + if (parity_check && !parity_quirk) dev_err(&slave->dev, "Parity error detected\n"); clear |= SDW_SCP_INT1_PARITY; } diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index 3550ab530c43..19bec6e4bbb6 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -356,6 +356,7 @@ struct sdw_dpn_prop { * @src_dpn_prop: Source Data Port N properties * @sink_dpn_prop: Sink Data Port N properties * @scp_int1_mask: SCP_INT1_MASK desired settings + * @quirks: bitmask identifying deltas from the MIPI specification */ struct sdw_slave_prop { u32 mipi_revision; @@ -378,8 +379,11 @@ struct sdw_slave_prop { struct sdw_dpn_prop *src_dpn_prop; struct sdw_dpn_prop *sink_dpn_prop; u8 scp_int1_mask; + u32 quirks; };
+#define SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY BIT(0) + /** * struct sdw_master_prop - Master properties * @revision: MIPI spec version of the implementation
From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com
The parity calculation is not reset on a Severe Reset, which leads to misleading/harmless errors reported on startup. The addition of a quirk helps filter out such errors while leaving the error checks on in steady-state.
Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Reviewed-by: Kai Vehmanen kai.vehmanen@linux.intel.com Reviewed-by: Guennadi Liakhovetski guennadi.liakhovetski@linux.intel.com Signed-off-by: Bard Liao yung-chuan.liao@linux.intel.com --- sound/soc/codecs/rt1308-sdw.c | 1 + sound/soc/codecs/rt5682-sdw.c | 1 + sound/soc/codecs/rt700-sdw.c | 1 + sound/soc/codecs/rt711-sdw.c | 1 + sound/soc/codecs/rt715-sdw.c | 1 + 5 files changed, 5 insertions(+)
diff --git a/sound/soc/codecs/rt1308-sdw.c b/sound/soc/codecs/rt1308-sdw.c index 5cf10fd447eb..81e3e2caeb2f 100644 --- a/sound/soc/codecs/rt1308-sdw.c +++ b/sound/soc/codecs/rt1308-sdw.c @@ -124,6 +124,7 @@ static int rt1308_read_prop(struct sdw_slave *slave) struct sdw_dpn_prop *dpn;
prop->scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; + prop->quirks = SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY;
prop->paging_support = true;
diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c index 544073975020..148d4cff267b 100644 --- a/sound/soc/codecs/rt5682-sdw.c +++ b/sound/soc/codecs/rt5682-sdw.c @@ -545,6 +545,7 @@ static int rt5682_read_prop(struct sdw_slave *slave)
prop->scp_int1_mask = SDW_SCP_INT1_IMPL_DEF | SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; + prop->quirks = SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY;
prop->paging_support = false;
diff --git a/sound/soc/codecs/rt700-sdw.c b/sound/soc/codecs/rt700-sdw.c index a46b957a3f1b..2d475405b20d 100644 --- a/sound/soc/codecs/rt700-sdw.c +++ b/sound/soc/codecs/rt700-sdw.c @@ -341,6 +341,7 @@ static int rt700_read_prop(struct sdw_slave *slave)
prop->scp_int1_mask = SDW_SCP_INT1_IMPL_DEF | SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; + prop->quirks = SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY;
prop->paging_support = false;
diff --git a/sound/soc/codecs/rt711-sdw.c b/sound/soc/codecs/rt711-sdw.c index a877e366fec5..7a1ae7442e75 100644 --- a/sound/soc/codecs/rt711-sdw.c +++ b/sound/soc/codecs/rt711-sdw.c @@ -345,6 +345,7 @@ static int rt711_read_prop(struct sdw_slave *slave)
prop->scp_int1_mask = SDW_SCP_INT1_IMPL_DEF | SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; + prop->quirks = SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY;
prop->paging_support = false;
diff --git a/sound/soc/codecs/rt715-sdw.c b/sound/soc/codecs/rt715-sdw.c index 0eb8943ed6ff..761d4663e813 100644 --- a/sound/soc/codecs/rt715-sdw.c +++ b/sound/soc/codecs/rt715-sdw.c @@ -439,6 +439,7 @@ static int rt715_read_prop(struct sdw_slave *slave)
prop->scp_int1_mask = SDW_SCP_INT1_IMPL_DEF | SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; + prop->quirks = SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY;
prop->paging_support = false;
On Tue, Aug 18, 2020 at 10:06:54PM +0800, Bard Liao wrote:
From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com
The parity calculation is not reset on a Severe Reset, which leads to misleading/harmless errors reported on startup. The addition of a quirk helps filter out such errors while leaving the error checks on in steady-state.
Acked-by: Mark Brown broonie@kernel.org
From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com
Provide prototype and export symbol to enable tests. The bus lock is handled externally to avoid conflicts e.g. between kernel-generated traffic and test traffic.
Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Reviewed-by: Kai Vehmanen kai.vehmanen@linux.intel.com Reviewed-by: Guennadi Liakhovetski guennadi.liakhovetski@linux.intel.com Signed-off-by: Bard Liao yung-chuan.liao@linux.intel.com --- drivers/soundwire/bus.c | 56 +++++++++++++++++++++++++++++++++++------ drivers/soundwire/bus.h | 4 +++ 2 files changed, 53 insertions(+), 7 deletions(-)
diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index 869290a8db40..2e08e8f8b9aa 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -255,6 +255,21 @@ static int sdw_reset_page(struct sdw_bus *bus, u16 dev_num) return ret; }
+static int sdw_transfer_unlocked(struct sdw_bus *bus, struct sdw_msg *msg) +{ + int ret; + + ret = do_transfer(bus, msg); + if (ret != 0 && ret != -ENODATA) + dev_err(bus->dev, "trf on Slave %d failed:%d\n", + msg->dev_num, ret); + + if (msg->page) + sdw_reset_page(bus, msg->dev_num); + + return ret; +} + /** * sdw_transfer() - Synchronous transfer message to a SDW Slave device * @bus: SDW bus @@ -266,13 +281,7 @@ int sdw_transfer(struct sdw_bus *bus, struct sdw_msg *msg)
mutex_lock(&bus->msg_lock);
- ret = do_transfer(bus, msg); - if (ret != 0 && ret != -ENODATA) - dev_err(bus->dev, "trf on Slave %d failed:%d\n", - msg->dev_num, ret); - - if (msg->page) - sdw_reset_page(bus, msg->dev_num); + ret = sdw_transfer_unlocked(bus, msg);
mutex_unlock(&bus->msg_lock);
@@ -428,6 +437,39 @@ sdw_bwrite_no_pm(struct sdw_bus *bus, u16 dev_num, u32 addr, u8 value) return sdw_transfer(bus, &msg); }
+int sdw_bread_no_pm_unlocked(struct sdw_bus *bus, u16 dev_num, u32 addr) +{ + struct sdw_msg msg; + u8 buf; + int ret; + + ret = sdw_fill_msg(&msg, NULL, addr, 1, dev_num, + SDW_MSG_FLAG_READ, &buf); + if (ret) + return ret; + + ret = sdw_transfer_unlocked(bus, &msg); + if (ret < 0) + return ret; + + return buf; +} +EXPORT_SYMBOL(sdw_bread_no_pm_unlocked); + +int sdw_bwrite_no_pm_unlocked(struct sdw_bus *bus, u16 dev_num, u32 addr, u8 value) +{ + struct sdw_msg msg; + int ret; + + ret = sdw_fill_msg(&msg, NULL, addr, 1, dev_num, + SDW_MSG_FLAG_WRITE, &value); + if (ret) + return ret; + + return sdw_transfer_unlocked(bus, &msg); +} +EXPORT_SYMBOL(sdw_bwrite_no_pm_unlocked); + static int sdw_read_no_pm(struct sdw_slave *slave, u32 addr) { diff --git a/drivers/soundwire/bus.h b/drivers/soundwire/bus.h index 82484f741168..c53345fbc4c7 100644 --- a/drivers/soundwire/bus.h +++ b/drivers/soundwire/bus.h @@ -168,6 +168,10 @@ sdw_update(struct sdw_slave *slave, u32 addr, u8 mask, u8 val) return sdw_write(slave, addr, tmp); }
+/* broadcast read/write for tests */ +int sdw_bread_no_pm_unlocked(struct sdw_bus *bus, u16 dev_num, u32 addr); +int sdw_bwrite_no_pm_unlocked(struct sdw_bus *bus, u16 dev_num, u32 addr, u8 value); + /* * At the moment we only track Master-initiated hw_reset. * Additional fields can be added as needed
From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com
The Cadence IP can inject errors, let's make use of this capability to test Slave parity error checks.
See e.g. example log where both the master and slave detect the parity error injected on a dummy read command.
cd /sys/kernel/debug/soundwire/master-1/intel-sdw/ echo 1 > cdns-parity-error-injection
[ 44.756249] intel-master sdw-master-1: Parity error [ 44.756313] intel-master sdw-master-1: Msg NACK received [ 44.756366] intel-master sdw-master-1: Msg NACKed for Slave 15 [ 44.756375] intel-master sdw-master-1: trf on Slave 15 failed:-5 [ 44.756382] intel-master sdw-master-1: parity error injection, read: -5 [ 44.756649] rt1308 sdw:1:25d:1308:0: Parity error detected
The code makes sure the Master device is resumed, hence the clock restarted, before sending a parity error.
Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Reviewed-by: Kai Vehmanen kai.vehmanen@linux.intel.com Reviewed-by: Guennadi Liakhovetski guennadi.liakhovetski@linux.intel.com Signed-off-by: Bard Liao yung-chuan.liao@linux.intel.com --- drivers/soundwire/cadence_master.c | 86 ++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+)
diff --git a/drivers/soundwire/cadence_master.c b/drivers/soundwire/cadence_master.c index 24eafe0aa1c3..807d70b82455 100644 --- a/drivers/soundwire/cadence_master.c +++ b/drivers/soundwire/cadence_master.c @@ -13,6 +13,7 @@ #include <linux/io.h> #include <linux/module.h> #include <linux/mod_devicetable.h> +#include <linux/pm_runtime.h> #include <linux/soundwire/sdw_registers.h> #include <linux/soundwire/sdw.h> #include <sound/pcm_params.h> @@ -50,6 +51,9 @@ MODULE_PARM_DESC(cdns_mcp_int_mask, "Cadence MCP IntMask"); #define CDNS_MCP_CONTROL_BLOCK_WAKEUP BIT(0)
#define CDNS_MCP_CMDCTRL 0x8 + +#define CDNS_MCP_CMDCTRL_INSERT_PARITY_ERR BIT(2) + #define CDNS_MCP_SSPSTAT 0xC #define CDNS_MCP_FRAME_SHAPE 0x10 #define CDNS_MCP_FRAME_SHAPE_INIT 0x14 @@ -367,6 +371,85 @@ static int cdns_hw_reset(void *data, u64 value)
DEFINE_DEBUGFS_ATTRIBUTE(cdns_hw_reset_fops, NULL, cdns_hw_reset, "%llu\n");
+static int cdns_parity_error_injection(void *data, u64 value) +{ + struct sdw_cdns *cdns = data; + struct sdw_bus *bus; + int ret; + + if (value != 1) + return -EINVAL; + + bus = &cdns->bus; + + /* + * Resume Master device. If this results in a bus reset, the + * Slave devices will re-attach and be re-enumerated. + */ + ret = pm_runtime_get_sync(bus->dev); + if (ret < 0 && ret != -EACCES) { + dev_err_ratelimited(cdns->dev, + "pm_runtime_get_sync failed in %s, ret %d\n", + __func__, ret); + pm_runtime_put_noidle(bus->dev); + return ret; + } + + /* + * wait long enough for Slave(s) to be in steady state. This + * does not need to be super precise. + */ + msleep(200); + + /* + * Take the bus lock here to make sure that any bus transactions + * will be queued while we inject a parity error on a dummy read + */ + mutex_lock(&bus->bus_lock); + + /* program hardware to inject parity error */ + cdns_updatel(cdns, CDNS_MCP_CMDCTRL, + CDNS_MCP_CMDCTRL_INSERT_PARITY_ERR, + CDNS_MCP_CMDCTRL_INSERT_PARITY_ERR); + + /* commit changes */ + cdns_updatel(cdns, CDNS_MCP_CONFIG_UPDATE, + CDNS_MCP_CONFIG_UPDATE_BIT, + CDNS_MCP_CONFIG_UPDATE_BIT); + + /* do a broadcast dummy read to avoid bus clashes */ + ret = sdw_bread_no_pm_unlocked(&cdns->bus, 0xf, SDW_SCP_DEVID_0); + dev_info(cdns->dev, "parity error injection, read: %d\n", ret); + + /* program hardware to disable parity error */ + cdns_updatel(cdns, CDNS_MCP_CMDCTRL, + CDNS_MCP_CMDCTRL_INSERT_PARITY_ERR, + 0); + + /* commit changes */ + cdns_updatel(cdns, CDNS_MCP_CONFIG_UPDATE, + CDNS_MCP_CONFIG_UPDATE_BIT, + CDNS_MCP_CONFIG_UPDATE_BIT); + + /* Continue bus operation with parity error injection disabled */ + mutex_unlock(&bus->bus_lock); + + /* Userspace changed the hardware state behind the kernel's back */ + add_taint(TAINT_USER, LOCKDEP_STILL_OK); + + /* + * allow Master device to enter pm_runtime suspend. This may + * also result in Slave devices suspending. + */ + pm_runtime_mark_last_busy(bus->dev); + pm_runtime_put_autosuspend(bus->dev); + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(cdns_parity_error_fops, NULL, + cdns_parity_error_injection, "%llu\n"); + /** * sdw_cdns_debugfs_init() - Cadence debugfs init * @cdns: Cadence instance @@ -378,6 +461,9 @@ void sdw_cdns_debugfs_init(struct sdw_cdns *cdns, struct dentry *root)
debugfs_create_file("cdns-hw-reset", 0200, root, cdns, &cdns_hw_reset_fops); + + debugfs_create_file("cdns-parity-error-injection", 0200, root, cdns, + &cdns_parity_error_fops); } EXPORT_SYMBOL_GPL(sdw_cdns_debugfs_init);
Dne 18. 08. 20 v 16:06 Bard Liao napsal(a):
Some codecs may report fake PARITY errors in the initial state. This series will filter them out.
Pierre-Louis Bossart (7): soundwire: bus: use property to set interrupt masks soundwire: bus: filter-out unwanted interrupt reports soundwire: slave: add first_interrupt_done status soundwire: bus: use quirk to filter out invalid parity errors ASoC: codecs: realtek-soundwire: ignore initial PARITY errors soundwire: bus: export broadcast read/write capability for tests soundwire: cadence: add parity error injection through debugfs
drivers/soundwire/bus.c | 93 ++++++++++++++++++++++++------ drivers/soundwire/bus.h | 4 ++ drivers/soundwire/cadence_master.c | 86 +++++++++++++++++++++++++++ drivers/soundwire/slave.c | 1 + include/linux/soundwire/sdw.h | 9 +++ sound/soc/codecs/max98373-sdw.c | 3 + sound/soc/codecs/rt1308-sdw.c | 3 + sound/soc/codecs/rt5682-sdw.c | 5 ++ sound/soc/codecs/rt700-sdw.c | 5 ++ sound/soc/codecs/rt711-sdw.c | 5 ++ sound/soc/codecs/rt715-sdw.c | 5 ++ sound/soc/codecs/wsa881x.c | 1 + 12 files changed, 202 insertions(+), 18 deletions(-)
I tested the changes and it works on my test system. The changes are straight. For all:
Acked-by: Jaroslav Kysela perex@perex.cz
participants (6)
-
Bard Liao
-
Jaroslav Kysela
-
Liao, Bard
-
Mark Brown
-
Pierre-Louis Bossart
-
Vinod Koul