**diff options**

author | Christoph Muellner <christoph.muellner@theobroma-systems.com> | 2019-04-02 16:50:41 +0200 |
---|---|---|

committer | Christoph Muellner <christoph.muellner@theobroma-systems.com> | 2019-04-30 20:02:03 +0200 |

commit | b94c928277c5915602b4e60348b3fe822a6d653f (patch) | |

tree | 1f2b05ef575e98e8d9bf6145ba95a0acca03bcb7 | |

parent | 51a75c32320b49f358def3105946c43c0cc1d223 (diff) |

rk: clk: Allow clk_i2s0_frac to violate precision restriction.

The fraction approximation code for rockchip frac dividers
impose the following requirement (as noted in a driver comment):
fractional divider must set that denominator is 20 times larger than
numerator to generate precise clock frequency.
Additionally the frac driver limits the maximum input frequency
to 600 MHz. This limitation can be achieved by using the integer
divider (limiting to e.g. 400 MHz).
Note, that both restrictions are not stated in the RK3399 TRM.
The implication of these restrictions are, that the range of possible
output frequencies is reduced quite drastically.
This results in the problem, that clk_i2s0_frac cannot generate
a clock of 24.56 MHz and thus audio on RK3399-Q7 is broken.
Therefore this patch whitelists clk_i2s0_frac from the first
restriction, similar to the exception for UART (in the same function).
Signed-off-by: Christoph Muellner <christoph.muellner@theobroma-systems.com>

-rw-r--r-- | drivers/clk/rockchip/clk.c | 9 |

1 files changed, 8 insertions, 1 deletions

diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index d5e130263c05..6f96335913df 100644 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c @@ -207,7 +207,14 @@ static void rockchip_fractional_approximation(struct clk_hw *hw, } } - if (*parent_rate < rate * 20) { + /* + * Check again if parent rate < rate x 20. + * Note that this is needed, because we might have changed + * the parent rate above. + */ + if (*parent_rate < rate * 20 && + /* Whitelist clocks, where we can accept imprecisions. */ + !strstr(clk_hw_get_name(hw), "clk_i2s0_frac")) { pr_warn("%s p_rate(%ld) is low than rate(%ld)*20, use integer or half-div\n", clk_hw_get_name(hw), *parent_rate, rate); *m = 0; |