|
@@ -1430,190 +1430,6 @@ static int dsi_calc_clock_rates(struct platform_device *dsidev,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev,
|
|
|
- unsigned long req_pck, struct dsi_clock_info *dsi_cinfo,
|
|
|
- struct dispc_clock_info *dispc_cinfo)
|
|
|
-{
|
|
|
- struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
|
|
- struct dsi_clock_info cur, best;
|
|
|
- struct dispc_clock_info best_dispc;
|
|
|
- int min_fck_per_pck;
|
|
|
- int match = 0;
|
|
|
- unsigned long dss_sys_clk, max_dss_fck;
|
|
|
-
|
|
|
- dss_sys_clk = clk_get_rate(dsi->sys_clk);
|
|
|
-
|
|
|
- max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
|
|
|
-
|
|
|
- if (req_pck == dsi->cache_req_pck &&
|
|
|
- dsi->cache_cinfo.clkin == dss_sys_clk) {
|
|
|
- DSSDBG("DSI clock info found from cache\n");
|
|
|
- *dsi_cinfo = dsi->cache_cinfo;
|
|
|
- dispc_find_clk_divs(req_pck, dsi_cinfo->dsi_pll_hsdiv_dispc_clk,
|
|
|
- dispc_cinfo);
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
|
|
|
-
|
|
|
- if (min_fck_per_pck &&
|
|
|
- req_pck * min_fck_per_pck > max_dss_fck) {
|
|
|
- DSSERR("Requested pixel clock not possible with the current "
|
|
|
- "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
|
|
|
- "the constraint off.\n");
|
|
|
- min_fck_per_pck = 0;
|
|
|
- }
|
|
|
-
|
|
|
- DSSDBG("dsi_pll_calc\n");
|
|
|
-
|
|
|
-retry:
|
|
|
- memset(&best, 0, sizeof(best));
|
|
|
- memset(&best_dispc, 0, sizeof(best_dispc));
|
|
|
-
|
|
|
- memset(&cur, 0, sizeof(cur));
|
|
|
- cur.clkin = dss_sys_clk;
|
|
|
-
|
|
|
- /* 0.75MHz < Fint = clkin / regn < 2.1MHz */
|
|
|
- /* To reduce PLL lock time, keep Fint high (around 2 MHz) */
|
|
|
- for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) {
|
|
|
- cur.fint = cur.clkin / cur.regn;
|
|
|
-
|
|
|
- if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min)
|
|
|
- continue;
|
|
|
-
|
|
|
- /* DSIPHY(MHz) = (2 * regm / regn) * clkin */
|
|
|
- for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) {
|
|
|
- unsigned long a, b;
|
|
|
-
|
|
|
- a = 2 * cur.regm * (cur.clkin/1000);
|
|
|
- b = cur.regn;
|
|
|
- cur.clkin4ddr = a / b * 1000;
|
|
|
-
|
|
|
- if (cur.clkin4ddr > 1800 * 1000 * 1000)
|
|
|
- break;
|
|
|
-
|
|
|
- /* dsi_pll_hsdiv_dispc_clk(MHz) =
|
|
|
- * DSIPHY(MHz) / regm_dispc < 173MHz/186Mhz */
|
|
|
- for (cur.regm_dispc = 1; cur.regm_dispc <
|
|
|
- dsi->regm_dispc_max; ++cur.regm_dispc) {
|
|
|
- struct dispc_clock_info cur_dispc;
|
|
|
- cur.dsi_pll_hsdiv_dispc_clk =
|
|
|
- cur.clkin4ddr / cur.regm_dispc;
|
|
|
-
|
|
|
- if (cur.regm_dispc > 1 &&
|
|
|
- cur.regm_dispc % 2 != 0 &&
|
|
|
- req_pck >= 1000000)
|
|
|
- continue;
|
|
|
-
|
|
|
- /* this will narrow down the search a bit,
|
|
|
- * but still give pixclocks below what was
|
|
|
- * requested */
|
|
|
- if (cur.dsi_pll_hsdiv_dispc_clk < req_pck)
|
|
|
- break;
|
|
|
-
|
|
|
- if (cur.dsi_pll_hsdiv_dispc_clk > max_dss_fck)
|
|
|
- continue;
|
|
|
-
|
|
|
- if (min_fck_per_pck &&
|
|
|
- cur.dsi_pll_hsdiv_dispc_clk <
|
|
|
- req_pck * min_fck_per_pck)
|
|
|
- continue;
|
|
|
-
|
|
|
- match = 1;
|
|
|
-
|
|
|
- dispc_find_clk_divs(req_pck,
|
|
|
- cur.dsi_pll_hsdiv_dispc_clk,
|
|
|
- &cur_dispc);
|
|
|
-
|
|
|
- if (abs(cur_dispc.pck - req_pck) <
|
|
|
- abs(best_dispc.pck - req_pck)) {
|
|
|
- best = cur;
|
|
|
- best_dispc = cur_dispc;
|
|
|
-
|
|
|
- if (cur_dispc.pck == req_pck)
|
|
|
- goto found;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-found:
|
|
|
- if (!match) {
|
|
|
- if (min_fck_per_pck) {
|
|
|
- DSSERR("Could not find suitable clock settings.\n"
|
|
|
- "Turning FCK/PCK constraint off and"
|
|
|
- "trying again.\n");
|
|
|
- min_fck_per_pck = 0;
|
|
|
- goto retry;
|
|
|
- }
|
|
|
-
|
|
|
- DSSERR("Could not find suitable clock settings.\n");
|
|
|
-
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
-
|
|
|
- /* dsi_pll_hsdiv_dsi_clk (regm_dsi) is not used */
|
|
|
- best.regm_dsi = 0;
|
|
|
- best.dsi_pll_hsdiv_dsi_clk = 0;
|
|
|
-
|
|
|
- if (dsi_cinfo)
|
|
|
- *dsi_cinfo = best;
|
|
|
- if (dispc_cinfo)
|
|
|
- *dispc_cinfo = best_dispc;
|
|
|
-
|
|
|
- dsi->cache_req_pck = req_pck;
|
|
|
- dsi->cache_clk_freq = 0;
|
|
|
- dsi->cache_cinfo = best;
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int dsi_pll_calc_ddrfreq(struct platform_device *dsidev,
|
|
|
- unsigned long req_clkin4ddr, struct dsi_clock_info *cinfo)
|
|
|
-{
|
|
|
- struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
|
|
- struct dsi_clock_info cur, best;
|
|
|
-
|
|
|
- DSSDBG("dsi_pll_calc_ddrfreq\n");
|
|
|
-
|
|
|
- memset(&best, 0, sizeof(best));
|
|
|
- memset(&cur, 0, sizeof(cur));
|
|
|
-
|
|
|
- cur.clkin = clk_get_rate(dsi->sys_clk);
|
|
|
-
|
|
|
- for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) {
|
|
|
- cur.fint = cur.clkin / cur.regn;
|
|
|
-
|
|
|
- if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min)
|
|
|
- continue;
|
|
|
-
|
|
|
- /* DSIPHY(MHz) = (2 * regm / regn) * clkin */
|
|
|
- for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) {
|
|
|
- unsigned long a, b;
|
|
|
-
|
|
|
- a = 2 * cur.regm * (cur.clkin/1000);
|
|
|
- b = cur.regn;
|
|
|
- cur.clkin4ddr = a / b * 1000;
|
|
|
-
|
|
|
- if (cur.clkin4ddr > 1800 * 1000 * 1000)
|
|
|
- break;
|
|
|
-
|
|
|
- if (abs(cur.clkin4ddr - req_clkin4ddr) <
|
|
|
- abs(best.clkin4ddr - req_clkin4ddr)) {
|
|
|
- best = cur;
|
|
|
- DSSDBG("best %ld\n", best.clkin4ddr);
|
|
|
- }
|
|
|
-
|
|
|
- if (cur.clkin4ddr == req_clkin4ddr)
|
|
|
- goto found;
|
|
|
- }
|
|
|
- }
|
|
|
-found:
|
|
|
- if (cinfo)
|
|
|
- *cinfo = best;
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
static void dsi_pll_calc_dsi_fck(struct dsi_clock_info *cinfo)
|
|
|
{
|
|
|
unsigned long max_dsi_fck;
|
|
@@ -1624,90 +1440,6 @@ static void dsi_pll_calc_dsi_fck(struct dsi_clock_info *cinfo)
|
|
|
cinfo->dsi_pll_hsdiv_dsi_clk = cinfo->clkin4ddr / cinfo->regm_dsi;
|
|
|
}
|
|
|
|
|
|
-static int dsi_pll_calc_dispc_fck(struct platform_device *dsidev,
|
|
|
- unsigned long req_pck, struct dsi_clock_info *cinfo,
|
|
|
- struct dispc_clock_info *dispc_cinfo)
|
|
|
-{
|
|
|
- struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
|
|
- unsigned regm_dispc, best_regm_dispc;
|
|
|
- unsigned long dispc_clk, best_dispc_clk;
|
|
|
- int min_fck_per_pck;
|
|
|
- unsigned long max_dss_fck;
|
|
|
- struct dispc_clock_info best_dispc;
|
|
|
- bool match;
|
|
|
-
|
|
|
- max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
|
|
|
-
|
|
|
- min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
|
|
|
-
|
|
|
- if (min_fck_per_pck &&
|
|
|
- req_pck * min_fck_per_pck > max_dss_fck) {
|
|
|
- DSSERR("Requested pixel clock not possible with the current "
|
|
|
- "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
|
|
|
- "the constraint off.\n");
|
|
|
- min_fck_per_pck = 0;
|
|
|
- }
|
|
|
-
|
|
|
-retry:
|
|
|
- best_regm_dispc = 0;
|
|
|
- best_dispc_clk = 0;
|
|
|
- memset(&best_dispc, 0, sizeof(best_dispc));
|
|
|
- match = false;
|
|
|
-
|
|
|
- for (regm_dispc = 1; regm_dispc < dsi->regm_dispc_max; ++regm_dispc) {
|
|
|
- struct dispc_clock_info cur_dispc;
|
|
|
-
|
|
|
- dispc_clk = cinfo->clkin4ddr / regm_dispc;
|
|
|
-
|
|
|
- /* this will narrow down the search a bit,
|
|
|
- * but still give pixclocks below what was
|
|
|
- * requested */
|
|
|
- if (dispc_clk < req_pck)
|
|
|
- break;
|
|
|
-
|
|
|
- if (dispc_clk > max_dss_fck)
|
|
|
- continue;
|
|
|
-
|
|
|
- if (min_fck_per_pck && dispc_clk < req_pck * min_fck_per_pck)
|
|
|
- continue;
|
|
|
-
|
|
|
- match = true;
|
|
|
-
|
|
|
- dispc_find_clk_divs(req_pck, dispc_clk, &cur_dispc);
|
|
|
-
|
|
|
- if (abs(cur_dispc.pck - req_pck) <
|
|
|
- abs(best_dispc.pck - req_pck)) {
|
|
|
- best_regm_dispc = regm_dispc;
|
|
|
- best_dispc_clk = dispc_clk;
|
|
|
- best_dispc = cur_dispc;
|
|
|
-
|
|
|
- if (cur_dispc.pck == req_pck)
|
|
|
- goto found;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (!match) {
|
|
|
- if (min_fck_per_pck) {
|
|
|
- DSSERR("Could not find suitable clock settings.\n"
|
|
|
- "Turning FCK/PCK constraint off and"
|
|
|
- "trying again.\n");
|
|
|
- min_fck_per_pck = 0;
|
|
|
- goto retry;
|
|
|
- }
|
|
|
-
|
|
|
- DSSERR("Could not find suitable clock settings.\n");
|
|
|
-
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
-found:
|
|
|
- cinfo->regm_dispc = best_regm_dispc;
|
|
|
- cinfo->dsi_pll_hsdiv_dispc_clk = best_dispc_clk;
|
|
|
-
|
|
|
- *dispc_cinfo = best_dispc;
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
int dsi_pll_set_clock_div(struct platform_device *dsidev,
|
|
|
struct dsi_clock_info *cinfo)
|
|
|
{
|
|
@@ -4384,55 +4116,6 @@ int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,
|
|
|
}
|
|
|
EXPORT_SYMBOL(omapdss_dsi_configure_pins);
|
|
|
|
|
|
-static int dsi_set_clocks(struct omap_dss_device *dssdev,
|
|
|
- unsigned long ddr_clk, unsigned long lp_clk)
|
|
|
-{
|
|
|
- struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
|
|
|
- struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
|
|
- struct dsi_clock_info cinfo;
|
|
|
- struct dispc_clock_info dispc_cinfo;
|
|
|
- unsigned lp_clk_div;
|
|
|
- unsigned long dsi_fclk;
|
|
|
- int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
|
|
|
- unsigned long pck;
|
|
|
- int r;
|
|
|
-
|
|
|
- DSSDBG("Setting DSI clocks: ddr_clk %lu, lp_clk %lu", ddr_clk, lp_clk);
|
|
|
-
|
|
|
- /* Calculate PLL output clock */
|
|
|
- r = dsi_pll_calc_ddrfreq(dsidev, ddr_clk * 4, &cinfo);
|
|
|
- if (r)
|
|
|
- goto err;
|
|
|
-
|
|
|
- /* Calculate PLL's DSI clock */
|
|
|
- dsi_pll_calc_dsi_fck(&cinfo);
|
|
|
-
|
|
|
- /* Calculate PLL's DISPC clock and pck & lck divs */
|
|
|
- pck = cinfo.clkin4ddr / 16 * (dsi->num_lanes_used - 1) * 8 / bpp;
|
|
|
- DSSDBG("finding dispc dividers for pck %lu\n", pck);
|
|
|
- r = dsi_pll_calc_dispc_fck(dsidev, pck, &cinfo, &dispc_cinfo);
|
|
|
- if (r)
|
|
|
- goto err;
|
|
|
-
|
|
|
- /* Calculate LP clock */
|
|
|
- dsi_fclk = cinfo.dsi_pll_hsdiv_dsi_clk;
|
|
|
- lp_clk_div = DIV_ROUND_UP(dsi_fclk, lp_clk * 2);
|
|
|
-
|
|
|
- dsi->user_dsi_cinfo.regn = cinfo.regn;
|
|
|
- dsi->user_dsi_cinfo.regm = cinfo.regm;
|
|
|
- dsi->user_dsi_cinfo.regm_dispc = cinfo.regm_dispc;
|
|
|
- dsi->user_dsi_cinfo.regm_dsi = cinfo.regm_dsi;
|
|
|
-
|
|
|
- dsi->user_dsi_cinfo.lp_clk_div = lp_clk_div;
|
|
|
-
|
|
|
- dsi->user_dispc_cinfo.lck_div = dispc_cinfo.lck_div;
|
|
|
- dsi->user_dispc_cinfo.pck_div = dispc_cinfo.pck_div;
|
|
|
-
|
|
|
- return 0;
|
|
|
-err:
|
|
|
- return r;
|
|
|
-}
|
|
|
-
|
|
|
int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
|
|
|
{
|
|
|
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
|