From 59be68f4b0f7e59824e493ab3d0b78e4d6d7f37c Mon Sep 17 00:00:00 2001 From: Matthias Reichl Date: Tue, 23 May 2017 18:41:37 +0200 Subject: [PATCH] RPi/RPi2: add kernel patch to fix I2S clock rpi-4.9.y commit 76527b4e6a5dbe55e0b2d8ab533c2388b36c86be This fixes 48kHz samplerate not working on HifiBerry Amp+. See https://github.com/raspberrypi/linux/issues/2016 This patch can be dropped on the next RPi kernel bump. Signed-off-by: Matthias Reichl --- .../patches/linux/linux-02-RPi_clk_fix.patch | 127 ++++++++++++++++++ .../patches/linux/linux-02-RPi_clk_fix.patch | 127 ++++++++++++++++++ 2 files changed, 254 insertions(+) create mode 100644 projects/RPi/patches/linux/linux-02-RPi_clk_fix.patch create mode 100644 projects/RPi2/patches/linux/linux-02-RPi_clk_fix.patch diff --git a/projects/RPi/patches/linux/linux-02-RPi_clk_fix.patch b/projects/RPi/patches/linux/linux-02-RPi_clk_fix.patch new file mode 100644 index 0000000000..6c88610655 --- /dev/null +++ b/projects/RPi/patches/linux/linux-02-RPi_clk_fix.patch @@ -0,0 +1,127 @@ +From 76527b4e6a5dbe55e0b2d8ab533c2388b36c86be Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 22 May 2017 13:56:41 +0100 +Subject: [PATCH] clk: bcm2835: Minimise clock jitter for PCM clock + +Fractional clock dividers generate accurate average frequencies but +with jitter, particularly when the integer divisor is small. + +Introduce a new metric of clock accuracy to penalise clocks with a good +average but worse jitter compared to clocks with an average which is no +better but with lower jitter. The metric is the ideal rate minus the +worse deviation from that ideal using the nearest integer divisors. + +Use this metric for parent selection for clocks requiring low jitter +(currently just PCM). + +Signed-off-by: Phil Elwell +--- + drivers/clk/bcm/clk-bcm2835.c | 39 ++++++++++++++++++++++++++++++++++----- + 1 file changed, 34 insertions(+), 5 deletions(-) + +diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c +index c24b4de..db3ba74 100644 +--- a/drivers/clk/bcm/clk-bcm2835.c ++++ b/drivers/clk/bcm/clk-bcm2835.c +@@ -534,6 +534,7 @@ struct bcm2835_clock_data { + + bool is_vpu_clock; + bool is_mash_clock; ++ bool low_jitter; + + u32 tcnt_mux; + }; +@@ -1154,7 +1155,8 @@ static unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw, + int parent_idx, + unsigned long rate, + u32 *div, +- unsigned long *prate) ++ unsigned long *prate, ++ unsigned long *avgrate) + { + struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw); + struct bcm2835_cprman *cprman = clock->cprman; +@@ -1166,11 +1168,33 @@ static unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw, + parent = clk_hw_get_parent_by_index(hw, parent_idx); + + if (!(BIT(parent_idx) & data->set_rate_parent)) { ++ unsigned long tmp_rate; ++ + *prate = clk_hw_get_rate(parent); + *div = bcm2835_clock_choose_div(hw, rate, *prate, true); + +- return bcm2835_clock_rate_from_divisor(clock, *prate, +- *div); ++ tmp_rate = bcm2835_clock_rate_from_divisor(clock, *prate, *div); ++ *avgrate = tmp_rate; ++ ++ if (data->low_jitter && (*div & CM_DIV_FRAC_MASK)) { ++ unsigned long high, low; ++ u32 idiv = *div & ~CM_DIV_FRAC_MASK; ++ ++ high = bcm2835_clock_rate_from_divisor(clock, *prate, ++ idiv); ++ idiv += CM_DIV_FRAC_MASK + 1; ++ low = bcm2835_clock_rate_from_divisor(clock, *prate, ++ idiv); ++ ++ /* Return a value which is the maximum deviation ++ * below the ideal rate, for use as a metric. ++ */ ++ if ((tmp_rate - low) < (high - tmp_rate)) ++ tmp_rate = low; ++ else ++ tmp_rate -= high - tmp_rate; ++ } ++ return tmp_rate; + } + + if (data->frac_bits) +@@ -1197,6 +1221,7 @@ static unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw, + + *div = curdiv << CM_DIV_FRAC_BITS; + *prate = curdiv * best_rate; ++ *avgrate = best_rate; + + return best_rate; + } +@@ -1208,6 +1233,7 @@ static int bcm2835_clock_determine_rate(struct clk_hw *hw, + bool current_parent_is_pllc; + unsigned long rate, best_rate = 0; + unsigned long prate, best_prate = 0; ++ unsigned long avgrate, best_avgrate = 0; + size_t i; + u32 div; + +@@ -1232,11 +1258,13 @@ static int bcm2835_clock_determine_rate(struct clk_hw *hw, + continue; + + rate = bcm2835_clock_choose_div_and_prate(hw, i, req->rate, +- &div, &prate); ++ &div, &prate, ++ &avgrate); + if (rate > best_rate && rate <= req->rate) { + best_parent = parent; + best_prate = prate; + best_rate = rate; ++ best_avgrate = avgrate; + } + } + +@@ -1246,7 +1274,7 @@ static int bcm2835_clock_determine_rate(struct clk_hw *hw, + req->best_parent_hw = best_parent; + req->best_parent_rate = best_prate; + +- req->rate = best_rate; ++ req->rate = best_avgrate; + + return 0; + } +@@ -2061,6 +2089,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { + .int_bits = 12, + .frac_bits = 12, + .is_mash_clock = true, ++ .low_jitter = true, + .parents = bcm2835_pcm_per_parents, + .tcnt_mux = 23), + [BCM2835_CLOCK_PWM] = REGISTER_PER_CLK( diff --git a/projects/RPi2/patches/linux/linux-02-RPi_clk_fix.patch b/projects/RPi2/patches/linux/linux-02-RPi_clk_fix.patch new file mode 100644 index 0000000000..6c88610655 --- /dev/null +++ b/projects/RPi2/patches/linux/linux-02-RPi_clk_fix.patch @@ -0,0 +1,127 @@ +From 76527b4e6a5dbe55e0b2d8ab533c2388b36c86be Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 22 May 2017 13:56:41 +0100 +Subject: [PATCH] clk: bcm2835: Minimise clock jitter for PCM clock + +Fractional clock dividers generate accurate average frequencies but +with jitter, particularly when the integer divisor is small. + +Introduce a new metric of clock accuracy to penalise clocks with a good +average but worse jitter compared to clocks with an average which is no +better but with lower jitter. The metric is the ideal rate minus the +worse deviation from that ideal using the nearest integer divisors. + +Use this metric for parent selection for clocks requiring low jitter +(currently just PCM). + +Signed-off-by: Phil Elwell +--- + drivers/clk/bcm/clk-bcm2835.c | 39 ++++++++++++++++++++++++++++++++++----- + 1 file changed, 34 insertions(+), 5 deletions(-) + +diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c +index c24b4de..db3ba74 100644 +--- a/drivers/clk/bcm/clk-bcm2835.c ++++ b/drivers/clk/bcm/clk-bcm2835.c +@@ -534,6 +534,7 @@ struct bcm2835_clock_data { + + bool is_vpu_clock; + bool is_mash_clock; ++ bool low_jitter; + + u32 tcnt_mux; + }; +@@ -1154,7 +1155,8 @@ static unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw, + int parent_idx, + unsigned long rate, + u32 *div, +- unsigned long *prate) ++ unsigned long *prate, ++ unsigned long *avgrate) + { + struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw); + struct bcm2835_cprman *cprman = clock->cprman; +@@ -1166,11 +1168,33 @@ static unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw, + parent = clk_hw_get_parent_by_index(hw, parent_idx); + + if (!(BIT(parent_idx) & data->set_rate_parent)) { ++ unsigned long tmp_rate; ++ + *prate = clk_hw_get_rate(parent); + *div = bcm2835_clock_choose_div(hw, rate, *prate, true); + +- return bcm2835_clock_rate_from_divisor(clock, *prate, +- *div); ++ tmp_rate = bcm2835_clock_rate_from_divisor(clock, *prate, *div); ++ *avgrate = tmp_rate; ++ ++ if (data->low_jitter && (*div & CM_DIV_FRAC_MASK)) { ++ unsigned long high, low; ++ u32 idiv = *div & ~CM_DIV_FRAC_MASK; ++ ++ high = bcm2835_clock_rate_from_divisor(clock, *prate, ++ idiv); ++ idiv += CM_DIV_FRAC_MASK + 1; ++ low = bcm2835_clock_rate_from_divisor(clock, *prate, ++ idiv); ++ ++ /* Return a value which is the maximum deviation ++ * below the ideal rate, for use as a metric. ++ */ ++ if ((tmp_rate - low) < (high - tmp_rate)) ++ tmp_rate = low; ++ else ++ tmp_rate -= high - tmp_rate; ++ } ++ return tmp_rate; + } + + if (data->frac_bits) +@@ -1197,6 +1221,7 @@ static unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw, + + *div = curdiv << CM_DIV_FRAC_BITS; + *prate = curdiv * best_rate; ++ *avgrate = best_rate; + + return best_rate; + } +@@ -1208,6 +1233,7 @@ static int bcm2835_clock_determine_rate(struct clk_hw *hw, + bool current_parent_is_pllc; + unsigned long rate, best_rate = 0; + unsigned long prate, best_prate = 0; ++ unsigned long avgrate, best_avgrate = 0; + size_t i; + u32 div; + +@@ -1232,11 +1258,13 @@ static int bcm2835_clock_determine_rate(struct clk_hw *hw, + continue; + + rate = bcm2835_clock_choose_div_and_prate(hw, i, req->rate, +- &div, &prate); ++ &div, &prate, ++ &avgrate); + if (rate > best_rate && rate <= req->rate) { + best_parent = parent; + best_prate = prate; + best_rate = rate; ++ best_avgrate = avgrate; + } + } + +@@ -1246,7 +1274,7 @@ static int bcm2835_clock_determine_rate(struct clk_hw *hw, + req->best_parent_hw = best_parent; + req->best_parent_rate = best_prate; + +- req->rate = best_rate; ++ req->rate = best_avgrate; + + return 0; + } +@@ -2061,6 +2089,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { + .int_bits = 12, + .frac_bits = 12, + .is_mash_clock = true, ++ .low_jitter = true, + .parents = bcm2835_pcm_per_parents, + .tcnt_mux = 23), + [BCM2835_CLOCK_PWM] = REGISTER_PER_CLK(