On Fri, Oct 25, 2019 at 3:14 AM Mark Brown broonie@kernel.org wrote:
On Fri, Oct 25, 2019 at 02:23:18AM +0800, Tzung-Bi Shih wrote:
The playback stream becomes silent and the console keeps printing "PLL unlocked". But, if comment out the msleep(10) between the SHDN off and on, the issue fixed. I am trying to find the reason but facing further more questions and may need your inputs.
Wow, that's a bit special. I'm wondering if the PLL unlock error handling isn't connected to the PLL configuration?
I don't quite understand here. Did you mean: when max98090_pll_work() get called, the PLL may have locked. The code doesn't check M98090_REG_DEVICE_STATUS but shutdown and on anyway. In the case max98090 may generate a new interrupt and again and again?
I feel it is weird to sleep in max98090_pll_work(). Especially, at this line https://elixir.bootlin.com/linux/v5.4-rc2/source/sound/soc/codecs/max98090.c... (it makes less sense to "wait" in another thread). Note that, the threaded IRQF_ONESHOT handler and max98090_pll_work() are in 2 different threads.
Sleeping after starting a PLL to give it time to lock is pretty normal.
I was trying to say: sleeping after starting in max98090_pll_work() makes less sense by current implementation. During the sleep time, max98090 may generate a new ULK interrupt and try to schedule max98090_pll_work() again.
Doing so after stopping is a bit more fun.
Yes, and I couldn't find a recommendation of SHDN hold time in the datasheet. I guess we're safe to remove the sleep after stopping. But I also don't expect it would be causing any problems if sleeping after stopping.
I guess the original intention is:
- disable ULK interrupt in IRQ handler
(https://elixir.bootlin.com/linux/v5.4-rc2/source/sound/soc/codecs/max98090.c...)
- schedule max98090_pll_work() to workaround it
- wait 10ms to give PLL chance to lock
- enable ULK interrupt again
If max98090 claims its PLL is unlocked again, repeat the above by receiving another ULK interrupt.
I think so.
I will fix toward this direction.
- According to the datasheet page 164 table 90
(https://datasheets.maximintegrated.com/en/ds/MAX98090.pdf), there are some registers should only be adjusted when SHDN==0. But I fail to find max98090.c tries to set SHDN to 0 and restore it afterwards when writing to these registers. For example, https://elixir.bootlin.com/linux/v5.4-rc2/source/sound/soc/codecs/max98090.c.... I am wondering if it would bring any side effects because the datasheet states "Changing these settings during normal operation (SHDN=1) can compromise device stability and performance specifications."
That does sound like it might be causing problems, yes - even if it's not the problem you're seeing it's probably a good idea to try to follow the datsheet recommendation in case it's causing some other problem.
I will try to fix toward this direction too.
One observed drawback of the fix is: when playbacking something, the playback stream will be silent shortly if starting to capture (because of the SHDN off and on). Is it acceptable? One workaround of this issue in ChromeOS is: enable DMIC-related functions even if only speaker will be used. More power consumption would be expected in the case. Would it be acceptable?
If the ChromeOS code is working for you we may as well get it upstream, if we can start the PLL faster than the 10ms that's a win and the confirmation that we got lock looks like a win too.
From the datasheet page 26, the table states "PLL Lock Time" needs 2ms
typically and 7ms at most. I will fix toward this direction: to see if PLL could get locked less than 10ms and confirm we got lock in max98090_pll_work().
With all proper fixes above, I should re-insert the msleep between SHDN off and on to observe if the odd issue happens again. We haven't figured out the root cause afterall.