diff options
author | Adam Thomson <Adam.Thomson.Opensource@diasemi.com> | 2019-04-29 06:57:33 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2019-05-01 22:37:08 -0400 |
commit | 1cd472d2ac1654f939ae01164b29e81fc76e0a93 (patch) | |
tree | e24eaf36fb45f41dccf510804bd5489afc543ef8 | |
parent | 406dcbc55a0a20fd155be889a4a0c4b812f7c18e (diff) |
ASoC: da7219: Use clk_round_rate to handle enabled bclk/wclk case
For some platforms where DA7219 is the DAI clock master, BCLK/WCLK
will be set and enabled prior to the codec's hw_params() function
being called. It is possible the platform requires a different
BCLK configuration than would be chosen by hw_params(), for
example S16_LE format needed with a 64-bit frame to satisfy certain
devices using the clocks.
To handle those kinds of scenarios, the use of clk_round_rate() is
now employed as part of hw_params(). If BCLK is already enabled
then this function will just return the currently set rate, if it
is valid for the desired frame size, so the subsequent call to
clk_set_rate() will succeed and nothing changes with regards to
clocking. In addition the specific BCLK & WCLK recalc_rate()
implementations needed updating to always give back a real value,
as those functions are called as part of the clk init code and a
real value is needed for the clk_round_rate() call to work as
expected.
Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | sound/soc/codecs/da7219.c | 21 |
1 files changed, 15 insertions, 6 deletions
diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index 5f5fa3416af3..206d01c6eb7e 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c | |||
@@ -1621,6 +1621,21 @@ static int da7219_hw_params(struct snd_pcm_substream *substream, | |||
1621 | 1621 | ||
1622 | if (bclk) { | 1622 | if (bclk) { |
1623 | bclk_rate = frame_size * sr; | 1623 | bclk_rate = frame_size * sr; |
1624 | /* | ||
1625 | * Rounding the rate here avoids failure trying to set a | ||
1626 | * new rate on an already enabled bclk. In that | ||
1627 | * instance this will just set the same rate as is | ||
1628 | * currently in use, and so should continue without | ||
1629 | * problem, as long as the BCLK rate is suitable for the | ||
1630 | * desired frame size. | ||
1631 | */ | ||
1632 | bclk_rate = clk_round_rate(bclk, bclk_rate); | ||
1633 | if ((bclk_rate / sr) < frame_size) { | ||
1634 | dev_err(component->dev, | ||
1635 | "BCLK rate mismatch against frame size"); | ||
1636 | return -EINVAL; | ||
1637 | } | ||
1638 | |||
1624 | ret = clk_set_rate(bclk, bclk_rate); | 1639 | ret = clk_set_rate(bclk, bclk_rate); |
1625 | if (ret) { | 1640 | if (ret) { |
1626 | dev_err(component->dev, | 1641 | dev_err(component->dev, |
@@ -1927,9 +1942,6 @@ static unsigned long da7219_wclk_recalc_rate(struct clk_hw *hw, | |||
1927 | struct snd_soc_component *component = da7219->component; | 1942 | struct snd_soc_component *component = da7219->component; |
1928 | u8 fs = snd_soc_component_read32(component, DA7219_SR); | 1943 | u8 fs = snd_soc_component_read32(component, DA7219_SR); |
1929 | 1944 | ||
1930 | if (!da7219->master) | ||
1931 | return 0; | ||
1932 | |||
1933 | switch (fs & DA7219_SR_MASK) { | 1945 | switch (fs & DA7219_SR_MASK) { |
1934 | case DA7219_SR_8000: | 1946 | case DA7219_SR_8000: |
1935 | return 8000; | 1947 | return 8000; |
@@ -2016,9 +2028,6 @@ static unsigned long da7219_bclk_recalc_rate(struct clk_hw *hw, | |||
2016 | u8 bclks_per_wclk = snd_soc_component_read32(component, | 2028 | u8 bclks_per_wclk = snd_soc_component_read32(component, |
2017 | DA7219_DAI_CLK_MODE); | 2029 | DA7219_DAI_CLK_MODE); |
2018 | 2030 | ||
2019 | if (!da7219->master) | ||
2020 | return 0; | ||
2021 | |||
2022 | switch (bclks_per_wclk & DA7219_DAI_BCLKS_PER_WCLK_MASK) { | 2031 | switch (bclks_per_wclk & DA7219_DAI_BCLKS_PER_WCLK_MASK) { |
2023 | case DA7219_DAI_BCLKS_PER_WCLK_32: | 2032 | case DA7219_DAI_BCLKS_PER_WCLK_32: |
2024 | return parent_rate * 32; | 2033 | return parent_rate * 32; |