|
@@ -1280,6 +1280,75 @@ static int dsi_pll_power(struct platform_device *dsidev,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+unsigned long dsi_get_pll_clkin(struct platform_device *dsidev)
|
|
|
+{
|
|
|
+ struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
|
|
+ return clk_get_rate(dsi->sys_clk);
|
|
|
+}
|
|
|
+
|
|
|
+bool dsi_hsdiv_calc(struct platform_device *dsidev, unsigned long pll,
|
|
|
+ unsigned long out_min, dsi_hsdiv_calc_func func, void *data)
|
|
|
+{
|
|
|
+ struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
|
|
+ int regm, regm_start, regm_stop;
|
|
|
+ unsigned long out_max;
|
|
|
+ unsigned long out;
|
|
|
+
|
|
|
+ out_min = out_min ? out_min : 1;
|
|
|
+ out_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
|
|
|
+
|
|
|
+ regm_start = max(DIV_ROUND_UP(pll, out_max), 1ul);
|
|
|
+ regm_stop = min(pll / out_min, dsi->regm_dispc_max);
|
|
|
+
|
|
|
+ for (regm = regm_start; regm <= regm_stop; ++regm) {
|
|
|
+ out = pll / regm;
|
|
|
+
|
|
|
+ if (func(regm, out, data))
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+bool dsi_pll_calc(struct platform_device *dsidev, unsigned long clkin,
|
|
|
+ unsigned long pll_min, unsigned long pll_max,
|
|
|
+ dsi_pll_calc_func func, void *data)
|
|
|
+{
|
|
|
+ struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
|
|
+ int regn, regn_start, regn_stop;
|
|
|
+ int regm, regm_start, regm_stop;
|
|
|
+ unsigned long fint, pll;
|
|
|
+ const unsigned long pll_hw_max = 1800000000;
|
|
|
+ unsigned long fint_hw_min, fint_hw_max;
|
|
|
+
|
|
|
+ fint_hw_min = dsi->fint_min;
|
|
|
+ fint_hw_max = dsi->fint_max;
|
|
|
+
|
|
|
+ regn_start = max(DIV_ROUND_UP(clkin, fint_hw_max), 1ul);
|
|
|
+ regn_stop = min(clkin / fint_hw_min, dsi->regn_max);
|
|
|
+
|
|
|
+ pll_max = pll_max ? pll_max : ULONG_MAX;
|
|
|
+
|
|
|
+ for (regn = regn_start; regn <= regn_stop; ++regn) {
|
|
|
+ fint = clkin / regn;
|
|
|
+
|
|
|
+ regm_start = max(DIV_ROUND_UP(DIV_ROUND_UP(pll_min, fint), 2),
|
|
|
+ 1ul);
|
|
|
+ regm_stop = min3(pll_max / fint / 2,
|
|
|
+ pll_hw_max / fint / 2,
|
|
|
+ dsi->regm_max);
|
|
|
+
|
|
|
+ for (regm = regm_start; regm <= regm_stop; ++regm) {
|
|
|
+ pll = 2 * regm * fint;
|
|
|
+
|
|
|
+ if (func(regn, regm, fint, pll, data))
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
/* calculate clock rates using dividers in cinfo */
|
|
|
static int dsi_calc_clock_rates(struct platform_device *dsidev,
|
|
|
struct dsi_clock_info *cinfo)
|