Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: rt5640: Remove is_sys_clk_from_pll, it has ordering issues

is_sys_clk_from_pll() is used as a snd_soc_dapm_route.connected callback,
checking RT5640_GBL_CLK to determine if the sys-clk is PLL1 and thus the
PWR_PLL bit in reg PWR_ANLG2 must be set.

RT5640_GBL_CLK is changed by rt5640_set_dai_sysclk(), which gets called by
the pre_pmu / post_pmd functions of the "Platform Clock" dapm-supply.

This creates an ordering issue, during a dapm transition first all
connected() callbacks are called to build a list of supplies to enable
and then the complete list is walked to enable the supplies. Since the
connected() check happens before enabling any supplies,
is_sys_clk_from_pll() ends up deciding if the PWR_PLL bit should be set
based on the state the "Platform Clock" supply had *before* the transition.
This sometimes results in PWR_PLL being off, even though *after* the
transition PLL1 is configured as sys-clk.

This commit removes is_sys_clk_from_pll() instead simply setting / clearing
PWR_PLL in rt5640_set_dai_sysclk() based on the selected sys-clk, which
fixes this and as a bonus results in a nice cleanup.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Hans de Goede and committed by
Mark Brown
8e7a1f1f d165b5a8

+4 -25
+4 -25
sound/soc/codecs/rt5640.c
··· 476 476 return idx; 477 477 } 478 478 479 - static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, 480 - struct snd_soc_dapm_widget *sink) 481 - { 482 - struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); 483 - unsigned int val; 484 - 485 - val = snd_soc_component_read32(component, RT5640_GLB_CLK); 486 - val &= RT5640_SCLK_SRC_MASK; 487 - if (val == RT5640_SCLK_SRC_PLL1) 488 - return 1; 489 - else 490 - return 0; 491 - } 492 - 493 479 static int is_using_asrc(struct snd_soc_dapm_widget *source, 494 480 struct snd_soc_dapm_widget *sink) 495 481 { ··· 1057 1071 } 1058 1072 1059 1073 static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = { 1060 - SND_SOC_DAPM_SUPPLY("PLL1", RT5640_PWR_ANLG2, 1061 - RT5640_PWR_PLL_BIT, 0, NULL, 0), 1062 - 1063 1074 /* ASRC */ 1064 1075 SND_SOC_DAPM_SUPPLY_S("Stereo Filter ASRC", 1, RT5640_ASRC_1, 1065 1076 15, 0, NULL, 0), ··· 1410 1427 {"Stereo ADC MIXL", "ADC1 Switch", "Stereo ADC L1 Mux"}, 1411 1428 {"Stereo ADC MIXL", "ADC2 Switch", "Stereo ADC L2 Mux"}, 1412 1429 {"Stereo ADC MIXL", NULL, "Stereo Filter"}, 1413 - {"Stereo Filter", NULL, "PLL1", is_sys_clk_from_pll}, 1414 1430 1415 1431 {"Stereo ADC MIXR", "ADC1 Switch", "Stereo ADC R1 Mux"}, 1416 1432 {"Stereo ADC MIXR", "ADC2 Switch", "Stereo ADC R2 Mux"}, 1417 1433 {"Stereo ADC MIXR", NULL, "Stereo Filter"}, 1418 - {"Stereo Filter", NULL, "PLL1", is_sys_clk_from_pll}, 1419 1434 1420 1435 {"Mono ADC MIXL", "ADC1 Switch", "Mono ADC L1 Mux"}, 1421 1436 {"Mono ADC MIXL", "ADC2 Switch", "Mono ADC L2 Mux"}, 1422 1437 {"Mono ADC MIXL", NULL, "Mono Left Filter"}, 1423 - {"Mono Left Filter", NULL, "PLL1", is_sys_clk_from_pll}, 1424 1438 1425 1439 {"Mono ADC MIXR", "ADC1 Switch", "Mono ADC R1 Mux"}, 1426 1440 {"Mono ADC MIXR", "ADC2 Switch", "Mono ADC R2 Mux"}, 1427 1441 {"Mono ADC MIXR", NULL, "Mono Right Filter"}, 1428 - {"Mono Right Filter", NULL, "PLL1", is_sys_clk_from_pll}, 1429 1442 1430 1443 {"IF2 ADC L", NULL, "Mono ADC MIXL"}, 1431 1444 {"IF2 ADC R", NULL, "Mono ADC MIXR"}, ··· 1491 1512 {"DIG MIXR", "DAC R1 Switch", "DAC MIXR"}, 1492 1513 1493 1514 {"DAC L1", NULL, "Stereo DAC MIXL"}, 1494 - {"DAC L1", NULL, "PLL1", is_sys_clk_from_pll}, 1495 1515 {"DAC L1", NULL, "DAC L1 Power"}, 1496 1516 {"DAC R1", NULL, "Stereo DAC MIXR"}, 1497 - {"DAC R1", NULL, "PLL1", is_sys_clk_from_pll}, 1498 1517 {"DAC R1", NULL, "DAC R1 Power"}, 1499 1518 1500 1519 {"SPK MIXL", "REC MIXL Switch", "RECMIXL"}, ··· 1599 1622 {"DIG MIXL", "DAC L2 Switch", "DAC L2 Mux"}, 1600 1623 1601 1624 {"DAC L2", NULL, "Mono DAC MIXL"}, 1602 - {"DAC L2", NULL, "PLL1", is_sys_clk_from_pll}, 1603 1625 {"DAC L2", NULL, "DAC L2 Power"}, 1604 1626 {"DAC R2", NULL, "Mono DAC MIXR"}, 1605 - {"DAC R2", NULL, "PLL1", is_sys_clk_from_pll}, 1606 1627 {"DAC R2", NULL, "DAC R2 Power"}, 1607 1628 1608 1629 {"SPK MIXL", "DAC L2 Switch", "DAC L2"}, ··· 1836 1861 struct snd_soc_component *component = dai->component; 1837 1862 struct rt5640_priv *rt5640 = snd_soc_component_get_drvdata(component); 1838 1863 unsigned int reg_val = 0; 1864 + unsigned int pll_bit = 0; 1839 1865 1840 1866 if (freq == rt5640->sysclk && clk_id == rt5640->sysclk_src) 1841 1867 return 0; ··· 1847 1871 break; 1848 1872 case RT5640_SCLK_S_PLL1: 1849 1873 reg_val |= RT5640_SCLK_SRC_PLL1; 1874 + pll_bit |= RT5640_PWR_PLL; 1850 1875 break; 1851 1876 case RT5640_SCLK_S_RCCLK: 1852 1877 reg_val |= RT5640_SCLK_SRC_RCCLK; ··· 1856 1879 dev_err(component->dev, "Invalid clock id (%d)\n", clk_id); 1857 1880 return -EINVAL; 1858 1881 } 1882 + snd_soc_component_update_bits(component, RT5640_PWR_ANLG2, 1883 + RT5640_PWR_PLL, pll_bit); 1859 1884 snd_soc_component_update_bits(component, RT5640_GLB_CLK, 1860 1885 RT5640_SCLK_SRC_MASK, reg_val); 1861 1886 rt5640->sysclk = freq;