bool is_vpu_clock;
bool is_mash_clock;
+ bool low_jitter;
u32 tcnt_mux;
};
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;
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)
*div = curdiv << CM_DIV_FRAC_BITS;
*prate = curdiv * best_rate;
+ *avgrate = best_rate;
return best_rate;
}
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;
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;
}
}
req->best_parent_hw = best_parent;
req->best_parent_rate = best_prate;
- req->rate = best_rate;
+ req->rate = best_avgrate;
return 0;
}
.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(