You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[ADL/RPL] [Bug] BT HFP offload capture stops working from second time #7548
[ transferred - previously filed to SOF Linux driver as https://github.com/thesofproject/linux/issues/4330 ]
Description
with BToffload enabled , when we connect HFP-only supported bt headset, mic stops working from second try, from sof trace logs we see
[ 85209608.124491] ( 1869.218628) c0 dw-dma src/drivers/dw/dma.c:1062 INFO dw_dma_avail_data_size() size is 0!
[ 85209633.593240] ( 25.468748) c0 dw-dma src/drivers/dw/dma.c:1128 ERROR dw_dma_get_data_size(): xrun detected dmesg.log
@Vamshigopal I replicated the exact sequence without real BT connection and FW seems to behave as expected. The cavs2.5-001 branch has some recent updates for early BCLK/MCLK, but these don't seem to cause trouble in this sequence. When the playback is running constantly on the background, the FW will ignore most of the setup and teardown in steps 2+3+4 as the SSP2 hardware is already programmed and running. Both in my local tests and the provided logs, these seem to be good.
So it does seem there is no data transferred from BT to ADSP in step 5 and the ADSP times out.
One experiment is to enable loopback mode in topology for SSP2 (set LBM bit and set ADSP as clock master) and run through the test sequence. I'd expect data flow to continue in step 5. This is good test to make in any case to ensure the ADSP side is working correctly.
@sathyap-chrome I think the link to A2DP support is because A2DP is not offloaded on these devices. So what happens is that with A2DP enabled headset, step 1 (youtube clip) is not offloaded and ADSP is not active in the use-case. Not sure what happens in step 2 on these systems, it either keeps offload disabled, or switches playback to HFP, but the flow is anyways different.
With HFP only headset, step 1 already starts ADSP use, so step 2-5 requre a different flow, starting and stopping capture over an already running SSP/I2S interface.
I did not test with actual BT/Chrome device, just replicated the steps on a development system. I wanted to check we don't have a regression in start/stopping capture when playback is already active. This does not seem to be the case.
with A2DP+HFP device , as soon as the capture starts , cras will switch to HFP profile and ADSP will become active.
whereas in HFP only device, ADSP is active during intial playback itself.
This seems to only affect the capture/record device, and specific to mode where codec is clocking provider (like the A2DP SCO case). If the use-case is reversed so that recording is kept running, playback stream can be stopped and restarted multiple times, no problem seen. The hardware programming flow seems correct, but alas record restart fails...
This seems to be a clear FW issue, so moving to the correct tracker. Not a kernel driver issue.
The SSP fifo can be seen getting data, so we can conclude BT is sending data and we do receive, but for some reason DMA is stuck in this specific sequence.
@Vamshigopal we managed to repro this now. running a stress test with aplay running and arecord repeatedl start/stopped seems to catch this sooner or later. There seems to be some timing issue and/or race with how we flush the RX queue upon start.
@Vamshigopal Ack, also with nocodec. It seems the drain at start is too slow and the RX fifo manages to get filled up by the time DMA starts up, leading to the XRUN. A tentative fix in #7711 -- this is directly on stable-v2.2 branch for easier testing.
I think there is another angle to this issue which is brought to light by the TX FIFO drain simplifications.
The setup is SSP1 - clock provider, playback only to speaker, want MCLK as 19200000 SSP2 - clock receiver, playback/capture to BT, want MCLK as 38400000
We see this sequence in case of a failure:
SSP2 start (sets MCLK to 38400000)
ssp-dai 1.2 /drivers/intel/ssp/ssp.c:1111 INFO ssp_trigger() cmd 7
ssp-dai 1.2 /drivers/intel/ssp/ssp.c:900 INFO ssp_pre_start()
mn ./drivers/intel/ssp/mn.c:259 INFO mclk_rate 38400000, mclk_source_clock 1
mn ./drivers/intel/ssp/mn.c:220 INFO mclk_id 0 mdivr_val 1
mn ./drivers/intel/ssp/mn.c:330 INFO find_mn for freq 38400000 bclk 128000
mn ./drivers/intel/ssp/mn.c:628 INFO bclk_rate 128000, *out_scr_div 300, m 1, n 1
ssp-dai 1.2 /drivers/intel/ssp/ssp.c:234 INFO ssp_bclk_prepare_enable(): sscr0 = 0xc0c12b7f
ssp-dai 1.2 /drivers/intel/ssp/ssp.c:993 INFO ssp_early_start(): SSE set for SSP2
ssp-dai 1.2 /drivers/intel/ssp/ssp.c:1111 INFO ssp_trigger() cmd 1
ssp-dai 1.2 /drivers/intel/ssp/ssp.c:1008 INFO ssp_start()
SSP2 start (clocks have been configured for SSP2 already)
ssp-dai 1.2 /drivers/intel/ssp/ssp.c:1111 INFO ssp_trigger() cmd 7
ssp-dai 1.2 /drivers/intel/ssp/ssp.c:900 INFO ssp_pre_start()
ssp-dai 1.2 /drivers/intel/ssp/ssp.c:993 INFO ssp_early_start(): SSE set for SSP2
ssp-dai 1.2 /drivers/intel/ssp/ssp.c:1111 INFO ssp_trigger() cmd 1
ssp-dai 1.2 /drivers/intel/ssp/ssp.c:1008 INFO ssp_start()
SSP2 RX stop
SSP2 start
ssp-dai 1.2 /drivers/intel/ssp/ssp.c:1111 INFO ssp_trigger() cmd 7
ssp-dai 1.2 /drivers/intel/ssp/ssp.c:900 INFO ssp_pre_start()
ssp-dai 1.2 /drivers/intel/ssp/ssp.c:993 INFO ssp_early_start(): SSE set for SSP2
ssp-dai 1.2 /drivers/intel/ssp/ssp.c:1111 INFO ssp_trigger() cmd 1
ssp-dai 1.2 /drivers/intel/ssp/ssp.c:1008 INFO ssp_start()
SSP2 TX stop
At this point we have SSP2 RX still running, MCLK is configured for 38400000
SSP1 start (fails to set the MCLK to 19200000)
ssp-dai 1.1 /drivers/intel/ssp/ssp.c:1111 INFO ssp_trigger() cmd 7
ssp-dai 1.1 /drivers/intel/ssp/ssp.c:900 INFO ssp_pre_start()
mn ./drivers/intel/ssp/mn.c:180 INFO MCLK 19200000, source = 1
mn ./drivers/intel/ssp/mn.c:192 ERROR Can't set MCLK 0 to 19200000, it is already configured to 38400000
ssp-dai 1.1 /drivers/intel/ssp/ssp.c:161 ERROR ssp_mclk_prepare_enable(): invalid mclk_rate = 19200000 for mclk_id = 0
ssp-dai 1.1 /drivers/intel/ssp/ssp.c:993 INFO ssp_early_start(): SSE set for SSP1
demux 1.2 src/audio/mux/mux.c:693 INFO mux_trigger(), command = 1
ssp-dai 1.1 /drivers/intel/ssp/ssp.c:1111 INFO ssp_trigger() cmd 1
ssp-dai 1.1 /drivers/intel/ssp/ssp.c:1008 INFO ssp_start()
Note that the MCLK request fails since the same clock is already used by SSP2 and it is set to 38400000, the MCLK request fail is handled by skipping the BCLK setup for SSP1 but the error from ssp_pre_start() is ignored, so we go on and start the SSP1 anyways.
This will lead to:
dw-dma src/drivers/dw/dma.c:1093 INFO dw_dma_free_data_size() size is 0!
dw-dma src/drivers/dw/dma.c:1128 ERROR dw_dma_get_data_size(): xrun detected
dai 1.6 src/audio/dai.c:881 ERROR dai_report_xrun(): underrun due to no data available
dai 1.6 src/audio/dai.c:775 ERROR comp_underrun(): dev->comp.id = 6, source->avail = 192, copy_bytes = 0
pipe 1.7 ....../pipeline-stream.c:270 INFO pipe trigger cmd 6
pipe 1.7 ....../pipeline-stream.c:143 ERROR pipeline_copy(): ret = -61, start->comp.id = 6, dir = 1
pipe 1.7 ..../pipeline-schedule.c:187 ERROR pipeline_task(): xrun recovery failed! pipeline is stopped.
Which is not a surprise without BCLK setup for a clock provider.
I think this setup is not correct. SSP1 and SSP2 can be used at the same time and they want the very same MCLK to run in different speeds. A clock cannot be 38400000 and 19200000 at the same time.
Either both SSPs should be asking for the same MCLK rate
or
the two SSP should use different mclk_id from topology (if it is possible at all).
Closing this issue, let's follow-up on MCLK configuration question in separate bug #7803 as that seems to be a separate issue (albeit uncovered by same testing steps).
Activity
Vamshigopal commentedon Apr 26, 2023
cc: @sathyap-chrome @sathya-nujella @ranj063 @plbossart @ujfalusi @juimonen
kv2019i commentedon Apr 27, 2023
@Vamshigopal I replicated the exact sequence without real BT connection and FW seems to behave as expected. The cavs2.5-001 branch has some recent updates for early BCLK/MCLK, but these don't seem to cause trouble in this sequence. When the playback is running constantly on the background, the FW will ignore most of the setup and teardown in steps 2+3+4 as the SSP2 hardware is already programmed and running. Both in my local tests and the provided logs, these seem to be good.
So it does seem there is no data transferred from BT to ADSP in step 5 and the ADSP times out.
One experiment is to enable loopback mode in topology for SSP2 (set LBM bit and set ADSP as clock master) and run through the test sequence. I'd expect data flow to continue in step 5. This is good test to make in any case to ensure the ADSP side is working correctly.
sathyap-chrome commentedon Apr 27, 2023
@kv2019i this issue only happens when you try HFP only headset. If headset supports A2DP, this issue doesnt happen
best way to confirm is at this step:
Start a youtube clip via BT output - > check btmon logs for a SCO connection
Also can you confirm which OS version you used from CHROME - currently offload is disabled and we need to enable from OS manually
kv2019i commentedon Apr 27, 2023
@sathyap-chrome I think the link to A2DP support is because A2DP is not offloaded on these devices. So what happens is that with A2DP enabled headset, step 1 (youtube clip) is not offloaded and ADSP is not active in the use-case. Not sure what happens in step 2 on these systems, it either keeps offload disabled, or switches playback to HFP, but the flow is anyways different.
With HFP only headset, step 1 already starts ADSP use, so step 2-5 requre a different flow, starting and stopping capture over an already running SSP/I2S interface.
I did not test with actual BT/Chrome device, just replicated the steps on a development system. I wanted to check we don't have a regression in start/stopping capture when playback is already active. This does not seem to be the case.
Vamshigopal commentedon Apr 27, 2023
Copying this message from partner bug , as it explains the flow.
with A2DP+HFP device , as soon as the capture starts , cras will switch to HFP profile and ADSP will become active.
whereas in HFP only device, ADSP is active during intial playback itself.
Vamshigopal commentedon Apr 28, 2023
@kv2019i with LBM bit set and ADSP as master, we would able reproduce the issue.
We see the same error signature in SSP loopback mode also
[ 74093953.618271] ( 1874.010376) c0 dw-dma src/drivers/dw/dma.c:1062 INFO dw_dma_avail_data_size() size is 0!
[ 74093978.722436] ( 25.104166) c0 dw-dma src/drivers/dw/dma.c:1128 ERROR dw_dma_get_data_size(): xrun detected
The rec1 is the first capture, rec2 and rec3 are 2nd and 3rd captures.
dmesg.log
sof-logger.log
rec.zip
kv2019i commentedon May 2, 2023
Ack @Vamshigopal -- so this seems like an issue with SSP stop/stat flow. Trying to reproduce this on a local setup now.
kv2019i commentedon May 2, 2023
And managed to hit this now locally, debug ongoing.
kv2019i commentedon May 2, 2023
This seems to only affect the capture/record device, and
specific to mode where codec is clocking provider (like the A2DP SCO case). If the use-case is reversed so that recording is kept running, playback stream can be stopped and restarted multiple times, no problem seen. The hardware programming flow seems correct, but alas record restart fails...kv2019i commentedon May 2, 2023
Did also a short bisect and seems this problem appears also with older SOF releases, so this is a problem that has existed for a while.
kv2019i commentedon May 2, 2023
This seems to be a clear FW issue, so moving to the correct tracker. Not a kernel driver issue.
The SSP fifo can be seen getting data, so we can conclude BT is sending data and we do receive, but for some reason DMA is stuck in this specific sequence.
22 remaining items
intel: ssp: drain RX fifo when starting
intel: ssp: drain RX fifo when starting
Vamshigopal commentedon May 30, 2023
Hi @kv2019i
Re-opened as we observe issue reproduced again with same error signature ,
dmesg.log
trace.log
steps to reproduce
kv2019i commentedon May 30, 2023
@Vamshigopal we managed to repro this now. running a stress test with aplay running and arecord repeatedl start/stopped seems to catch this sooner or later. There seems to be some timing issue and/or race with how we flush the RX queue upon start.
Vamshigopal commentedon May 30, 2023
@kv2019i is it with nocodec tplg ?
intel: ssp: fix RX fifo drain logic
kv2019i commentedon May 30, 2023
@Vamshigopal Ack, also with nocodec. It seems the drain at start is too slow and the RX fifo manages to get filled up by the time DMA starts up, leading to the XRUN. A tentative fix in #7711 -- this is directly on stable-v2.2 branch for easier testing.
kv2019i commentedon May 31, 2023
Updated patch -> #7717
ujfalusi commentedon Jun 7, 2023
I think there is another angle to this issue which is brought to light by the TX FIFO drain simplifications.
The setup is
SSP1 - clock provider, playback only to speaker, want MCLK as 19200000
SSP2 - clock receiver, playback/capture to BT, want MCLK as 38400000
We see this sequence in case of a failure:
SSP2 start (sets MCLK to 38400000)
SSP2 start (clocks have been configured for SSP2 already)
SSP2 RX stop
SSP2 start
SSP2 TX stop
At this point we have
SSP2 RXstill running, MCLK is configured for 38400000SSP1 start (fails to set the MCLK to 19200000)
Note that the MCLK request fails since the same clock is already used by
SSP2and it is set to 38400000, the MCLK request fail is handled by skipping the BCLK setup for SSP1 but the error fromssp_pre_start()is ignored, so we go on and start the SSP1 anyways.This will lead to:
Which is not a surprise without BCLK setup for a clock provider.
I think this setup is not correct. SSP1 and SSP2 can be used at the same time and they want the very same MCLK to run in different speeds. A clock cannot be 38400000 and 19200000 at the same time.
Either both SSPs should be asking for the same MCLK rate
or
the two SSP should use different mclk_id from topology (if it is possible at all).
kv2019i commentedon Jun 14, 2023
Closing this issue, let's follow-up on MCLK configuration question in separate bug #7803 as that seems to be a separate issue (albeit uncovered by same testing steps).
intel: ssp: drain RX fifo when starting
intel: ssp: drain RX fifo when starting
intel: ssp: drain RX fifo when starting