mirror of
https://github.com/LibreELEC/LibreELEC.tv.git
synced 2025-07-27 12:46:53 +00:00
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 <hias@horus.com>
This commit is contained in:
parent
2521cb30d5
commit
59be68f4b0
127
projects/RPi/patches/linux/linux-02-RPi_clk_fix.patch
Normal file
127
projects/RPi/patches/linux/linux-02-RPi_clk_fix.patch
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
From 76527b4e6a5dbe55e0b2d8ab533c2388b36c86be Mon Sep 17 00:00:00 2001
|
||||||
|
From: Phil Elwell <phil@raspberrypi.org>
|
||||||
|
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 <phil@raspberrypi.org>
|
||||||
|
---
|
||||||
|
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(
|
127
projects/RPi2/patches/linux/linux-02-RPi_clk_fix.patch
Normal file
127
projects/RPi2/patches/linux/linux-02-RPi_clk_fix.patch
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
From 76527b4e6a5dbe55e0b2d8ab533c2388b36c86be Mon Sep 17 00:00:00 2001
|
||||||
|
From: Phil Elwell <phil@raspberrypi.org>
|
||||||
|
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 <phil@raspberrypi.org>
|
||||||
|
---
|
||||||
|
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(
|
Loading…
x
Reference in New Issue
Block a user