mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
ASoC: tegra: Fix redundant PLLA and PLLA_OUT0 updates
[ Upstream commite765886249
] Tegra audio graph card has many DAI links which connects internal AHUB modules and external audio codecs. Since these are DPCM links, hw_params() call in the machine driver happens for each connected BE link and PLLA is updated every time. This is not really needed for all links as only I/O link DAIs derive respective clocks from PLLA_OUT0 and thus from PLLA. Hence add checks to limit the clock updates to DAIs over I/O links. This found to be fixing a DMIC clock discrepancy which is suspected to happen because of back to back quick PLLA and PLLA_OUT0 rate updates. This was observed on Jetson TX2 platform where DMIC clock ended up with unexpected value. Fixes:202e2f7745
("ASoC: tegra: Add audio graph based card driver") Cc: stable@vger.kernel.org Signed-off-by: Sameer Pujar <spujar@nvidia.com> Link: https://lore.kernel.org/r/1694098945-32760-3-git-send-email-spujar@nvidia.com Signed-off-by: Mark Brown <broonie@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
cab7a48935
commit
457fbd6eb4
@ -10,6 +10,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <sound/graph_card.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc-dai.h>
|
||||
|
||||
#define MAX_PLLA_OUT0_DIV 128
|
||||
|
||||
@ -44,6 +45,21 @@ struct tegra_audio_cdata {
|
||||
unsigned int plla_out0_rates[NUM_RATE_TYPE];
|
||||
};
|
||||
|
||||
static bool need_clk_update(struct snd_soc_dai *dai)
|
||||
{
|
||||
if (snd_soc_dai_is_dummy(dai) ||
|
||||
!dai->driver->ops ||
|
||||
!dai->driver->name)
|
||||
return false;
|
||||
|
||||
if (strstr(dai->driver->name, "I2S") ||
|
||||
strstr(dai->driver->name, "DMIC") ||
|
||||
strstr(dai->driver->name, "DSPK"))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Setup PLL clock as per the given sample rate */
|
||||
static int tegra_audio_graph_update_pll(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
@ -140,19 +156,7 @@ static int tegra_audio_graph_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
|
||||
int err;
|
||||
|
||||
/*
|
||||
* This gets called for each DAI link (FE or BE) when DPCM is used.
|
||||
* We may not want to update PLLA rate for each call. So PLLA update
|
||||
* must be restricted to external I/O links (I2S, DMIC or DSPK) since
|
||||
* they actually depend on it. I/O modules update their clocks in
|
||||
* hw_param() of their respective component driver and PLLA rate
|
||||
* update here helps them to derive appropriate rates.
|
||||
*
|
||||
* TODO: When more HW accelerators get added (like sample rate
|
||||
* converter, volume gain controller etc., which don't really
|
||||
* depend on PLLA) we need a better way to filter here.
|
||||
*/
|
||||
if (cpu_dai->driver->ops && rtd->dai_link->no_pcm) {
|
||||
if (need_clk_update(cpu_dai)) {
|
||||
err = tegra_audio_graph_update_pll(substream, params);
|
||||
if (err)
|
||||
return err;
|
||||
|
Loading…
Reference in New Issue
Block a user