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

ASoC: wm8904: configure sysclk/FLL automatically

This adds a new mode WM8904_CLK_AUTO which automatically enables the FLL
if a frequency different than the MCLK is set.

These additions make the codec work with the simple-card driver in
general and especially in systems where the MCLK doesn't match the
required clock.

Signed-off-by: Michael Walle <michael@walle.cc>
Acked-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Link: https://lore.kernel.org/r/20191108203152.19098-1-michael@walle.cc
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Michael Walle and committed by
Mark Brown
13409d27 e2db787b

+45 -28
+44 -28
sound/soc/codecs/wm8904.c
··· 1410 1410 return 0; 1411 1411 } 1412 1412 1413 - 1414 - static int wm8904_set_sysclk(struct snd_soc_dai *dai, int clk_id, 1415 - unsigned int freq, int dir) 1416 - { 1417 - struct snd_soc_component *component = dai->component; 1418 - struct wm8904_priv *priv = snd_soc_component_get_drvdata(component); 1419 - 1420 - switch (clk_id) { 1421 - case WM8904_CLK_MCLK: 1422 - priv->sysclk_src = clk_id; 1423 - priv->mclk_rate = freq; 1424 - break; 1425 - 1426 - case WM8904_CLK_FLL: 1427 - priv->sysclk_src = clk_id; 1428 - break; 1429 - 1430 - default: 1431 - return -EINVAL; 1432 - } 1433 - 1434 - dev_dbg(dai->dev, "Clock source is %d at %uHz\n", clk_id, freq); 1435 - 1436 - wm8904_configure_clocking(component); 1437 - 1438 - return 0; 1439 - } 1440 - 1441 1413 static int wm8904_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 1442 1414 { 1443 1415 struct snd_soc_component *component = dai->component; ··· 1792 1820 /* Reenable SYSCLK if it was previously active */ 1793 1821 snd_soc_component_update_bits(component, WM8904_CLOCK_RATES_2, 1794 1822 WM8904_CLK_SYS_ENA, clock2); 1823 + 1824 + return 0; 1825 + } 1826 + 1827 + static int wm8904_set_sysclk(struct snd_soc_dai *dai, int clk_id, 1828 + unsigned int freq, int dir) 1829 + { 1830 + struct snd_soc_component *component = dai->component; 1831 + struct wm8904_priv *priv = snd_soc_component_get_drvdata(component); 1832 + unsigned long mclk_freq; 1833 + int ret; 1834 + 1835 + switch (clk_id) { 1836 + case WM8904_CLK_AUTO: 1837 + mclk_freq = clk_get_rate(priv->mclk); 1838 + /* enable FLL if a different sysclk is desired */ 1839 + if (mclk_freq != freq) { 1840 + priv->sysclk_src = WM8904_CLK_FLL; 1841 + ret = wm8904_set_fll(dai, WM8904_FLL_MCLK, 1842 + WM8904_FLL_MCLK, 1843 + mclk_freq, freq); 1844 + if (ret) 1845 + return ret; 1846 + break; 1847 + } 1848 + clk_id = WM8904_CLK_MCLK; 1849 + /* fallthrough */ 1850 + 1851 + case WM8904_CLK_MCLK: 1852 + priv->sysclk_src = clk_id; 1853 + priv->mclk_rate = freq; 1854 + break; 1855 + 1856 + case WM8904_CLK_FLL: 1857 + priv->sysclk_src = clk_id; 1858 + break; 1859 + 1860 + default: 1861 + return -EINVAL; 1862 + } 1863 + 1864 + dev_dbg(dai->dev, "Clock source is %d at %uHz\n", clk_id, freq); 1865 + 1866 + wm8904_configure_clocking(component); 1795 1867 1796 1868 return 0; 1797 1869 }
+1
sound/soc/codecs/wm8904.h
··· 10 10 #ifndef _WM8904_H 11 11 #define _WM8904_H 12 12 13 + #define WM8904_CLK_AUTO 0 13 14 #define WM8904_CLK_MCLK 1 14 15 #define WM8904_CLK_FLL 2 15 16