Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE] Explicit clock control #4156

Closed
brentlu opened this issue May 10, 2021 · 26 comments
Closed

[FEATURE] Explicit clock control #4156

brentlu opened this issue May 10, 2021 · 26 comments
Assignees
Labels
duplicate This issue or pull request already exists enhancement New feature or request IPC4 Issues observed with IPC4 (same IPC as Windows) P1 Blocker bugs or important features
Milestone

Comments

@brentlu
Copy link
Contributor

brentlu commented May 10, 2021

Some codecs need external clock (mclk or bclk) to be ready in prepare stage or some function may broken.

To support those codec, we need to implement explicit clock control so machine driver could enable/disable the clock via DAPM supply widget or set_bias_level callback.

This feature has been implemented on SST FW running on Chrome KBL platforms. Following are the mailthread:
https://mailman.alsa-project.org/pipermail/alsa-devel/2017-November/127833.html
https://mailman.alsa-project.org/pipermail/alsa-devel/2019-October/156161.html

@brentlu
Copy link
Contributor Author

brentlu commented May 10, 2021

same request in linux
thesofproject/linux#2907

@plbossart
Copy link
Member

This was a feature we've put on the back burner since November 2018. #629

If you just want the blk and MCLK, it's rather easy to enable since it's just a change in the clock settings. But if you want the FSYNC to be enabled on demand, then it requires firmware to enable pretend DMA transfers with zero-based values, a lot more work.

@plbossart
Copy link
Member

If I am not mistaken this also causes a 400ms delay on GLK, if the clock is not enabled the codec will play audio with a delay.
I just can't find the issue any longer. @cujomalainey @bzhg can you help track this?

@sathya-nujella
Copy link
Contributor

If I am not mistaken this also causes a 400ms delay on GLK, if the clock is not enabled the codec will play audio with a delay.
I just can't find the issue any longer. @cujomalainey @bzhg can you help track this?

is this one @plbossart ?
#2124

@plbossart
Copy link
Member

Yes @sathya-nujella that was issue #2124 I was looking for, but it does make a reference to the WCLK aka FrameSync, so it's not trivial to fix.

@brentlu
Copy link
Contributor Author

brentlu commented May 10, 2021

@plbossart At least we need to support BCLK for cs42l42. It would be better if MCLK could be supported as well since some codecs like rt5514 needs MCLK.

@cujomalainey
Copy link
Member

cujomalainey commented May 10, 2021

This would also help solve the long pcm open call for da7219 correct?

Got lazy didn't read whole bug, yes, i think your mean #2124

@plbossart
Copy link
Member

This would also help solve the long pcm open call for da7219 correct?

depends what you want for cs42l42. If it's bclk and mclk, it's easier, but that isn't enough for DA7219 which needs FSYNC to be active

@hhyshw
Copy link

hhyshw commented May 12, 2021

@plbossart This is Karl Sun from Cirrus . For cs42l42 ,the the PLL lock will be dependent from bclk input. Then we have all the correct setting ready for Dout and DIn.

@lgirdwood
Copy link
Member

Can anyone give some feedback on the expected clock preamble duration prior to audio data being sent ? This would help with the design.

@plbossart
Copy link
Member

Can anyone give some feedback on the expected clock preamble duration prior to audio data being sent ? This would help with the design.

yes, I don't get what is needed. @brentlu added a 10ms delay initially in the topology but it doesn't seem to fix the issue.

@thesofproject thesofproject deleted a comment from uhs987 May 12, 2021
@brentlu
Copy link
Contributor Author

brentlu commented May 12, 2021

10ms delay is for another TX noise issue. The delay is between bclk on and dma enable to avoid noise.

my understanding of PLL issue is that: this codec requires bclk ready in prepare stage

@hhyshw would you confirm if my understanding is correct and describe the clock requirement of the codec with more detail? thanks.

@hhyshw
Copy link

hhyshw commented May 12, 2021

  • At the stage, the sclk is sent out at the SNDRV_PCM_TRIGGER_START signal of trigger(). But we can't do any register access in a trigger() function that will cause kernel warnings about blocking in an atomic context (and if you don't have that warning enabled, it can cause silent bugs. ). We have tried to have a workaround patch at trigger https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/2874751 but it seemed that we met with one potential issue https://partnerissuetracker.corp.google.com/u/1/issues/187911216 to read/write registers at trigger().
  • The main line branch that we are using is that the code in cs42l42_mute_stream() to switch back to internal oscillator, and implement the PLL Lock request. Here we met with PLL unlock issue without the sclk signal that is always later than we request PLL lock.
  • Ideally to support CS42L42 clocking mechanism we would hope clocks start / stop in Enable sclk in hw_prepare() / Disable SCLK in hw_free() callbacks. In this case we can guarantee that internal clock and external sclk clock source switch smoothly for audio playback.
  • I have read the https://mailman.alsa-project.org/pipermail/alsa-devel/2019-October/156161.html that sclk is enabled early enough and disabled after the headphone audio track stops. It looks fine to me .

@plbossart
Copy link
Member

@hhyshw the reference from 2019 is for a different driver, we do not support the clock enable from the machine driver on GLK.

To help us figure out alternate solutions, can you please clarify how much time is required before the bclk being activated and the PLL lock. I would imagine we can only enable the actual transfers after the PLL lock.

Also, if the issue is only on trigger start, have you tried starting in mute and use a workqueue to unmute some time after the trigger? That would be a way of working around the atomic nature of the trigger proper.

@hhyshw
Copy link

hhyshw commented May 13, 2021

@plbossart
The mute_stream of snd_soc_dai_ops is what we trying to enable the PLL with BCLK. The mute_stream will be ahead than the trigger start from alsa audio interface sequence.
image

Here is the detail status about polling the PLL lock status a few times to wait for the clock status. Because the CS42L42 I2C command read/write must have a working clock(either internal clk or external sclk ), the driver must know the status clearly to switch.Once the blck signal is ready , then the PLL will take about in 250us--12500us to lock for system clock .
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git/commit/?id=b7d00776ebf79402216434ce24a87f072e1438e1

@lgirdwood
Copy link
Member

lgirdwood commented May 13, 2021

IIRC the SSP ports could support a clock control if the DMA/CPU FIFO IRQs were masked until trigger start. i.e we could enable port at prepare() as this would allow clocking BCLK/FRAME for 10s of ms

/* start the SSP for either playback or capture */
static void ssp_start(struct dai *dai, int direction)
{
	struct ssp_pdata *ssp = dai_get_drvdata(dai);

	spin_lock(&dai->lock);

	/* request mclk/bclk */
	ssp_pre_start(dai);

	/* enable port */
	ssp_update_bits(dai, SSCR0, SSCR0_SSE, SSCR0_SSE);
	ssp->state[direction] = COMP_STATE_ACTIVE;

	dai_info(dai, "ssp_start()");

	if (ssp->params.bclk_delay) {
		/* drive BCLK early for guaranteed time,
		 * before first FSYNC, it is required by some codecs
		 */
		wait_delay(clock_ms_to_ticks(PLATFORM_DEFAULT_CLOCK,
					     ssp->params.bclk_delay));   <<<<<<<<<<< small delay here is posssible
	}

	/* enable DMA */  <<<<<<<<<<<<<<<<<<<<<<<<<< DMA is enabled last so port could be enabled in prepare and DMA in trigger()
	if (direction == DAI_DIR_PLAYBACK) {
		ssp_update_bits(dai, SSCR1, SSCR1_TSRE, SSCR1_TSRE);
		ssp_update_bits(dai, SSTSA, SSTSA_TXEN, SSTSA_TXEN);
	} else {
		ssp_update_bits(dai, SSCR1, SSCR1_RSRE, SSCR1_RSRE);
		ssp_update_bits(dai, SSRSA, SSRSA_RXEN, SSRSA_RXEN);
	}

	/* wait to get valid fifo status */
	wait_delay(PLATFORM_SSP_DELAY);

	spin_unlock(&dai->lock);
}

@sathya-nujella
Copy link
Contributor

@plbossart This is Karl Sun from Cirrus . For cs42l42 ,the the PLL lock will be dependent from bclk input. Then we have all the correct setting ready for Dout and DIn.

Hi @hhyshw
After BCLK is available to Codec, how much time (how many milli seconds??) is needed for PLL clock latching/stabilization ? Thanks!

@snake0x65
Copy link

PLL startup time for cs42l42 is 1ms max.

@snake0x65
Copy link

Actually, what is more, important for us is to have SCLK when we switch back from PLL to internal clocks. So, after reset cs42l42 is running on internal clocks, and these clocks also used for I2C bus, then when we have SCLK ( we assume SCLK started before trigger start is called) we will switch the source from internal clocks to SCLK, during this switch I2C bus cannot be used for ~150us, and then I2C bus can be used again. However, the problem is to switch back. If you remove SCLK before we switch the source from PLL to internal clocks, then the I2C bus is locked, and we cannot access codec registers anymore until hard #reset. So, if you keep SCLK running hw_free() then we can switch back safely in mute().

@plbossart
Copy link
Member

@snake0x65 I don't fully understand the request. At what point do you switch from PLL to internal clock?

My worry is that if we keep the SCLK active until the hw_free, the SOF hw_free will be executed before the codec hw_free, and we still have a deadlock.

@snake0x65
Copy link

snake0x65 commented May 14, 2021

@plbossart , sorry, my explanation might be a bit confusing. CS42l42 HW required clocks to be present at the moment of switch from internal clocks to external SCLK and back. The transition takes ~150us. Currently, we are using mute_stream() callback to switch to/from PLL. UNMUTE event -> we switch to PLL, MUTE -> we switch to internal clocks. The problem is that (observed in 4.14 kernel) when mute_stream() is called to unmute SCLK still not available, and when mute_stream() callback is called to mute, SCLK has already stopped. So, we need 2 points where SCLK is stable to make a safe switch to/from PLL. When we use SCLK as a reference for PLL and suddenly SCLK is removed then the I2C bus will be dead and all transitions will fail. We cannot recover from this condition until HW reset.
For transition to PLL we can use PLL_LOCK interrupt, we start PLL, and then when PLL_LOCK happened we can switch from internal clocks to PLL safely, But, the problem is still in switching back from PLL to internal clocks in unmute_stream() as at this point SCLK already stopped and I2C is dead.

@plbossart
Copy link
Member

@snake0x65 I am not familiar with this mute_stream thing, we only deal with trigger_stop, hw_free and release. Where would you want us to stop the clock?

@snake0x65
Copy link

@plbossart hw_free() would be ideal for stop

@plbossart
Copy link
Member

Thanks @snake0x65, we will assume the direction is to turn on the BCLK and FSYNC during .prepare() (or maybe .hw_params(), tbd) and turn them off during .hw_free(). I don't think we have a limitation at the hardware level, but there are currently missing steps in the firmware if you see #4189

@brentlu brentlu linked a pull request May 19, 2021 that will close this issue
@brentlu
Copy link
Contributor Author

brentlu commented May 19, 2021

Hi,

I implement a virtual clock driver for mclk/bclk on Linux side and add a new IPC command on FW side to support explicit clock control. Tested on my TGL chromebook.

Kernel: Chrome v5.4 kernel
FW: main head of sof github

thesofproject/linux#2932
#4213

Regards,
Brent

@mengdonglin mengdonglin added the P1 Blocker bugs or important features label May 20, 2021
@lgirdwood lgirdwood added this to the v1.9 milestone Jun 3, 2021
@mengdonglin mengdonglin added the duplicate This issue or pull request already exists label Feb 16, 2022
@mengdonglin
Copy link
Collaborator

mengdonglin commented Feb 16, 2022

This feature is a duplicate of #629. Close it. @plbossart @bardliao @brentlu Let's track #629. Thanks

@mengdonglin mengdonglin added the IPC4 Issues observed with IPC4 (same IPC as Windows) label Feb 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
duplicate This issue or pull request already exists enhancement New feature or request IPC4 Issues observed with IPC4 (same IPC as Windows) P1 Blocker bugs or important features
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants