OMAPDSS: DSI: add new clock calculation code
Add new way to iterate over DSI PLL and HSDIV clock divisors. dsi_pll_calc() and dss_hsdiv_calc() provide a generic way to go over all the divisors, within given clock range. The functions will call a callback function for each divider set, making the function reusable for all use cases. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
This commit is contained in:
Родитель
43417823fd
Коммит
72658f0716
|
@ -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)
|
||||
|
|
|
@ -295,6 +295,18 @@ void dsi_dump_clocks(struct seq_file *s);
|
|||
void dsi_irq_handler(void);
|
||||
u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt);
|
||||
|
||||
unsigned long dsi_get_pll_clkin(struct platform_device *dsidev);
|
||||
|
||||
typedef bool (*dsi_pll_calc_func)(int regn, int regm, unsigned long fint,
|
||||
unsigned long pll, void *data);
|
||||
typedef bool (*dsi_hsdiv_calc_func)(int regm_dispc, unsigned long dispc,
|
||||
void *data);
|
||||
bool dsi_hsdiv_calc(struct platform_device *dsidev, unsigned long pll,
|
||||
unsigned long out_min, dsi_hsdiv_calc_func func, void *data);
|
||||
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);
|
||||
|
||||
unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev);
|
||||
int dsi_pll_set_clock_div(struct platform_device *dsidev,
|
||||
struct dsi_clock_info *cinfo);
|
||||
|
|
Загрузка…
Ссылка в новой задаче