Skip to content

SoundWire: add mockup codec support - #2827

Merged
bardliao merged 10 commits into
thesofproject:topic/sof-devfrom
plbossart:sdw/dummy-codec
May 12, 2021
Merged

bardliao merged 10 commits into
thesofproject:topic/sof-devfrom
plbossart:sdw/dummy-codec

Conversation

@plbossart

Copy link
Copy Markdown
Member

This is an early POC to see if we can support a 'nocodec' mode for SoundWire.

The following PR is the companion of thesofproject/acpi-scripts#12, which registers pretend devices so that we can load a machine driver.

This loads a card but fails since transactions on the bus fail: there is nothing connected so that's quite normal.
I tested this with the sof-cml-rt711-rt1308-mono-rt715.tplg copied as sof-cnl-sdw-null.tplg
The case with the dual amps failed with a kernel oops, but that should be for another day.

Additional work is required to avoid sending any commands to the codec, or alternatively ignore -ENODATA results.

@ranj063 @bardliao this could be useful to debug driver/topology changes without having any actual device connected.

@plbossart
plbossart requested review from bardliao and ranj063 April 7, 2021 22:34
@plbossart

Copy link
Copy Markdown
Member Author

@bardliao @ranj063 I figured out how to do a 'playback', the data seems to be consumed at the right rate (still an issue in the resume case)
If you have an UpExtreme you can start checking this out, but it looks promising.

@ranj063

ranj063 commented Apr 8, 2021 •

Copy link
Copy Markdown
Collaborator

@bardliao @ranj063 I figured out how to do a 'playback', the data seems to be consumed at the right rate (still an issue in the resume case)
If you have an UpExtreme you can start checking this out, but it looks promising.

@plbossart this is awesome. Btw which topology do I use for testing?

Comment thread sound/soc/codecs/sdw-null.c Resolved
Comment thread sound/soc/codecs/sdw-null.c Resolved
@bardliao

bardliao commented Apr 8, 2021

Copy link
Copy Markdown
Collaborator

@plbossart @ranj063 I did a quick test with sof-cnl-sdw-null.m4.txt tplg.
But I got soundwire sdw-master-0: Slave frame_ctrl reg write failed in playback.
See sdw-nocodec-playback.txt

@bardliao

bardliao commented Apr 8, 2021 •

Copy link
Copy Markdown
Collaborator

BTW, there is no 0xded0 id on my Up Xtreme board. So I use 0x0700 instead.

@bardliao

bardliao commented Apr 8, 2021

Copy link
Copy Markdown
Collaborator

@plbossart @ranj063 I did a quick test with sof-cnl-sdw-null.m4.txt tplg.
But I got soundwire sdw-master-0: Slave frame_ctrl reg write failed in playback.
See sdw-nocodec-playback.txt

I can work around it by

diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c
index ef7b7b976b0b..83ed0c4b8ab4 100644
--- a/drivers/soundwire/bus.c
+++ b/drivers/soundwire/bus.c
@@ -215,7 +215,7 @@ static inline int do_transfer(struct sdw_bus *bus, struct sdw_msg *msg)

                /* if cmd is ok or ignored return */
                if (ret == 0 || ret == -ENODATA)
-                       return ret;
+                       return 0;
        }

        return ret;

Now, I can run about 2 sec playback and end up with IO error.
dmesg_sdw_nocodec_playback.txt

@plbossart

Copy link
Copy Markdown
Member Author

@plbossart @ranj063 I did a quick test with sof-cnl-sdw-null.m4.txt tplg.

let's use an existing topology for now.

But I got soundwire sdw-master-0: Slave frame_ctrl reg write failed in playback.
See sdw-nocodec-playback.txt

I can work around it by

diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c
index ef7b7b976b0b..83ed0c4b8ab4 100644
--- a/drivers/soundwire/bus.c
+++ b/drivers/soundwire/bus.c
@@ -215,7 +215,7 @@ static inline int do_transfer(struct sdw_bus *bus, struct sdw_msg *msg)

                /* if cmd is ok or ignored return */
                if (ret == 0 || ret == -ENODATA)
-                       return ret;
+                       return 0;
        }

        return ret;

Now, I can run about 2 sec playback and end up with IO error.
dmesg_sdw_nocodec_playback.txt

BTW, there is no 0xded0 id on my Up Xtreme board. So I use 0x0700 instead.

See above, this assumes that the ACPI table in thesofproject/acpi-scripts#12 is used.

I used the usual CML mono topology and copied it over. If I used the two amp version there is a kernel oops that I will need to debug with @ranj063
We will need a new topology with more streams but for now I am only trying to replace the existing topologies and make them work, but without any codec connected.

@plbossart
plbossart force-pushed the sdw/dummy-codec branch 2 times, most recently from df896e4 to daaf359 Compare April 8, 2021 22:20
@plbossart

Copy link
Copy Markdown
Member Author

@bardliao @RanderWang @ranj063 I updated the code to work with CML topologies, we can either use the 1amp or the 2-amp aggregated mode (that part doesn't work due to a regression in topic/sof-dev).

Comments and feedback welcome.

@ranj063

ranj063 commented Apr 8, 2021

Copy link
Copy Markdown
Collaborator

@bardliao @RanderWang @ranj063 I updated the code to work with CML topologies, we can either use the 1amp or the 2-amp aggregated mode (that part doesn't work due to a regression in topic/sof-dev).

Comments and feedback welcome.

@plbossart this fix works for me #2832

@bardliao

bardliao commented Apr 9, 2021

Copy link
Copy Markdown
Collaborator

@plbossart Now I can do playback/capture with below patch. Note that capture can only get silence data as expected.

diff --git a/drivers/soundwire/stream.c b/drivers/soundwire/stream.c
index 1eaedaaba094..92fc033ad246 100644
--- a/drivers/soundwire/stream.c
+++ b/drivers/soundwire/stream.c
@@ -133,6 +133,8 @@ static int sdw_program_slave_port_params(struct sdw_bus *bus,
        int ret;
        u8 wbuf;

+       if (s_rt->slave->is_null_device)
+               return 0;
        dpn_prop = sdw_get_slave_dpn_prop(s_rt->slave,
                                          s_rt->direction,
                                          t_params->port_num);
@@ -698,7 +700,7 @@ static int sdw_bank_switch(struct sdw_bus *bus, int m_rt_count)
        else
                ret = sdw_transfer(bus, wr_msg);

-       if (ret < 0) {
+       if (ret < 0 && ret != -ENODATA) {
                dev_err(bus->dev, "Slave frame_ctrl reg write failed\n");
                goto error;
        }

@plbossart
plbossart marked this pull request as ready for review April 9, 2021 16:09
@plbossart

Copy link
Copy Markdown
Member Author

@plbossart Now I can do playback/capture with below patch. Note that capture can only get silence data as expected.

@bardliao I don't get why I am able to play/record without your patch. @ranj063 also tested yesterday. Weird.

@bardliao

Copy link
Copy Markdown
Collaborator

@plbossart Now I can do playback/capture with below patch. Note that capture can only get silence data as expected.

@bardliao I don't get why I am able to play/record without your patch. @ranj063 also tested yesterday. Weird.

@plbossart I will get below error without my patch.

[  127.267120] soundwire sdw-master-0: Slave frame_ctrl reg write failed
[  127.267192] soundwire sdw-master-0: Bank switch failed: -61
[  127.267205] soundwire sdw-master-0: Bank switch failed: -61
[  127.267217]  SDW0-Playback: ASoC: error at snd_soc_link_prepare on SDW0-Playback: -61
[  127.267234]  SDW0-Playback: ASoC: soc_pcm_prepare() failed (-61)
[  127.267247]  Jack Out: ASoC: dpcm_be_dai_prepare() failed (-61)
[  127.267260]  Jack Out: ASoC: dpcm_fe_dai_prepare() failed (-61)

See dmesg_sdw_nocodec.txt

@RanderWang

Copy link
Copy Markdown

great! we can even add loop-back feature for nocodec mode, just set the offset of playback & capture with the same value in frame.

@RanderWang RanderWang left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

commit message "a) For some historical reason, we set this CMD_ACCEPT bitfield during
the initialization, but we don't during a resume from a clock-stoppped
state." ?

@plbossart

Copy link
Copy Markdown
Member Author

commit message "a) For some historical reason, we set this CMD_ACCEPT bitfield during
the initialization, but we don't during a resume from a clock-stoppped
state." ?

I meant "I do not know why we are doing things differently for probe and resume". The reason is lost in history.

Comment thread sound/soc/codecs/sdw-null.c Resolved
@plbossart

Copy link
Copy Markdown
Member Author

@bardliao @ranj063 with the update I can test the mockup even on a device with existing codecs. The mockups are added first in the ACPI match tables, so when they are present they will be detected and a different topology chosen.

The only think that will not work is that we cannot enable mockup devices on a link that is not enabled physically in the hardware. We would still try to transmit commands and that could generate conflicts at the PHY level. In other words, we can discard existing codecs or add new codecs on enabled links, not change which links are enabled.

@lyakh lyakh left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

at least the '-' wants to be fixed, not sure if we find a better solution for the header. Maybe wait for some more opinions

Comment thread include/linux/soundwire/sdw.h Resolved
plbossart and others added 8 commits May 7, 2021 15:07
To test the host controller and bus management code, it is currently
required to have a physical SoundWire peripheral attached to the
bus. To help with pre-silicon or early hardware enablement, it would
be very useful to have a SoundWire 'mockup' device that is exposed in
platform firmware but does not drive any signal on the bus.

This is different to the existing ASoC 'dummy' codec uses for I2S/TDM,
the SoundWire spec makes it clear that a device that is not attached
to the bus is not permitted to interact with the bus, be it for
command/control or data.

This patch exposes a 'mockup' device, with a minimalist driver, with 4
partID values reserved by Intel for such test configurations. The
mockup device exposes one full-duplex DAI based on 2 ports (DP1 for
playback and DP8 for capture). The capture data port is just virtual,
such a mockup device is prevented by the SoundWire specification from
presenting any data generated by a Source port without being Attached.

All the callbacks exposed by the SoundWire Slave interface are
populated, even if they just return immediately. This is intentional
to describe what a minimal codec driver should do and implement and
help new codec vendors provide support for their devices.

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Add support for two configurations with SoundWire mockup devices that
emulate the two CometLake configurations with one and two amps. This
patch helps test the SOF firmware on an UpExtreme board without any
hardware connected, e.g. by doing a loopback of the playback stream on
capture streams.

The mapping of the partIDs is as follows:

0xAAAA: generic full-duplex codec (not currently used)
0xAA55: headset codec (mock-up of RT711/RT5682) - full-duplex
0x55AA: amplifier (mock-up of RT1308/RT1316/Maxim 98373) - playback
with IV sense feedback
0x5555: mic codec (mock-up of RT715) - capture-only

The tables are added in a separate file to allow for mockup codecs to be
added on other platforms, but the mapping to specific topologies
remains platform-specific.

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Follow the same idea as for CNL/UpExtreme and add mockup test
first. They will only be selected if the SSDT is modified to add such
mockup devices.

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Add support for SoundWire mockup devices. The configurations assume the
same topology as the CML SoundWire devices and can be used to test the
SOF firmware on a development board (RVP, UpExtreme) without any
hardware connected.

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
This change is needed for support of mockup devices, which by
construction will not provide any answer to a bank switch, but it's
also legit for regular cases.

If for some reason a device loses sync and cannot handle a bank
switch, we should go ahead anyways. The devices can always resync
later.

The only case where the error flow should be used is when there is a
Command_Aborted composite answer from SoundWire devices.

Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
SoundWire mockup devices don't take part in the command/control
protocol, so all commands will complete with -ENODATA or
Command_Ignored results. With a flag, we can suppress such errors in
the bus management and make it appear as if all read/writes succeed.

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
All read and writes from/to SoundWire mockup devices will return
-ENODATA/Command_Ignored, this patch forces a Command_OK result to let
the bus perform the required configurations, e.g. for the Data Ports,
which will only have an effect on the Master side.

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Mockup devices don't take part in command/control operations and their
virtual ports shall not be programmed.

Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
lyakh
lyakh previously approved these changes May 10, 2021
@plbossart

Copy link
Copy Markdown
Member Author

@bardliao I'll let you merge if you approve.

@bardliao bardliao left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@plbossart The code looks good to me. I am just wondering should if (value > pdi_out_num) belong to 98cf1cd?

Comment thread drivers/soundwire/cadence_master.c Resolved
Comment thread drivers/soundwire/cadence_master.c Resolved
RanderWang
RanderWang previously approved these changes May 11, 2021

@RanderWang RanderWang left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

plbossart added 2 commits May 11, 2021 10:11
For debug, it's interesting to create a loopback stream for each link
and use debugfs to set a source and target PDI. The target PDI would
need to be an RX port and use the same register configurations as the
source PDI. This capability allows e.g. for the headphone playback
stream to be snooped on the headset capture stream, or alternatively
for the addition of a dedicated loopback stream, in addition of
regular capture for that link.

This patch only adds the debugfs part, the port/PDI handling will be
handled in the next patches.

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
When we set a source PDI, the target PDI parameters will be overridden
by the source register values. The loopback streams can be
independently enabled on each link.

While the loopback source and target can be configured before any
stream is active on each link, the loopback stream should only be
prepared/triggered when the playback stream is prepared. Otherwise all
registers might be programmed to their reset values and the loopback
will not succeed. The SoundWire bus driver currently does not allow
two streams to be triggered at the same time, so the playback will
have to be started first, and later the loopback.

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
@plbossart
plbossart dismissed stale reviews from RanderWang and lyakh via 79160ee May 11, 2021 15:14

@bardliao bardliao left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @plbossart I will merge it when we have second approval.

@bardliao
bardliao merged commit 93d91f0 into thesofproject:topic/sof-dev May 12, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants