aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/omap2/dss/dsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/omap2/dss/dsi.c')
-rw-r--r--drivers/video/omap2/dss/dsi.c167
1 files changed, 132 insertions, 35 deletions
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 1dd019cf9649..4d748139315d 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -1454,26 +1454,17 @@ found:
1454} 1454}
1455 1455
1456static int dsi_pll_calc_ddrfreq(struct platform_device *dsidev, 1456static int dsi_pll_calc_ddrfreq(struct platform_device *dsidev,
1457 unsigned long req_clk, struct dsi_clock_info *cinfo) 1457 unsigned long req_clkin4ddr, struct dsi_clock_info *cinfo)
1458{ 1458{
1459 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 1459 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1460 struct dsi_clock_info cur, best; 1460 struct dsi_clock_info cur, best;
1461 unsigned long dss_sys_clk, max_dss_fck, max_dsi_fck;
1462 unsigned long req_clkin4ddr;
1463 1461
1464 DSSDBG("dsi_pll_calc_ddrfreq\n"); 1462 DSSDBG("dsi_pll_calc_ddrfreq\n");
1465 1463
1466 dss_sys_clk = clk_get_rate(dsi->sys_clk);
1467
1468 max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
1469 max_dsi_fck = dss_feat_get_param_max(FEAT_PARAM_DSI_FCK);
1470
1471 memset(&best, 0, sizeof(best)); 1464 memset(&best, 0, sizeof(best));
1472 memset(&cur, 0, sizeof(cur)); 1465 memset(&cur, 0, sizeof(cur));
1473 1466
1474 cur.clkin = dss_sys_clk; 1467 cur.clkin = clk_get_rate(dsi->sys_clk);
1475
1476 req_clkin4ddr = req_clk * 4;
1477 1468
1478 for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) { 1469 for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) {
1479 cur.fint = cur.clkin / cur.regn; 1470 cur.fint = cur.clkin / cur.regn;
@@ -1503,18 +1494,107 @@ static int dsi_pll_calc_ddrfreq(struct platform_device *dsidev,
1503 } 1494 }
1504 } 1495 }
1505found: 1496found:
1506 best.regm_dispc = DIV_ROUND_UP(best.clkin4ddr, max_dss_fck);
1507 best.dsi_pll_hsdiv_dispc_clk = best.clkin4ddr / best.regm_dispc;
1508
1509 best.regm_dsi = DIV_ROUND_UP(best.clkin4ddr, max_dsi_fck);
1510 best.dsi_pll_hsdiv_dsi_clk = best.clkin4ddr / best.regm_dsi;
1511
1512 if (cinfo) 1497 if (cinfo)
1513 *cinfo = best; 1498 *cinfo = best;
1514 1499
1515 return 0; 1500 return 0;
1516} 1501}
1517 1502
1503static void dsi_pll_calc_dsi_fck(struct platform_device *dsidev,
1504 struct dsi_clock_info *cinfo)
1505{
1506 unsigned long max_dsi_fck;
1507
1508 max_dsi_fck = dss_feat_get_param_max(FEAT_PARAM_DSI_FCK);
1509
1510 cinfo->regm_dsi = DIV_ROUND_UP(cinfo->clkin4ddr, max_dsi_fck);
1511 cinfo->dsi_pll_hsdiv_dsi_clk = cinfo->clkin4ddr / cinfo->regm_dsi;
1512}
1513
1514static int dsi_pll_calc_dispc_fck(struct platform_device *dsidev,
1515 unsigned long req_pck, struct dsi_clock_info *cinfo,
1516 struct dispc_clock_info *dispc_cinfo)
1517{
1518 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1519 unsigned regm_dispc, best_regm_dispc;
1520 unsigned long dispc_clk, best_dispc_clk;
1521 int min_fck_per_pck;
1522 unsigned long max_dss_fck;
1523 struct dispc_clock_info best_dispc;
1524 bool match;
1525
1526 max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
1527
1528 min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
1529
1530 if (min_fck_per_pck &&
1531 req_pck * min_fck_per_pck > max_dss_fck) {
1532 DSSERR("Requested pixel clock not possible with the current "
1533 "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
1534 "the constraint off.\n");
1535 min_fck_per_pck = 0;
1536 }
1537
1538retry:
1539 best_regm_dispc = 0;
1540 best_dispc_clk = 0;
1541 memset(&best_dispc, 0, sizeof(best_dispc));
1542 match = false;
1543
1544 for (regm_dispc = 1; regm_dispc < dsi->regm_dispc_max; ++regm_dispc) {
1545 struct dispc_clock_info cur_dispc;
1546
1547 dispc_clk = cinfo->clkin4ddr / regm_dispc;
1548
1549 /* this will narrow down the search a bit,
1550 * but still give pixclocks below what was
1551 * requested */
1552 if (dispc_clk < req_pck)
1553 break;
1554
1555 if (dispc_clk > max_dss_fck)
1556 continue;
1557
1558 if (min_fck_per_pck && dispc_clk < req_pck * min_fck_per_pck)
1559 continue;
1560
1561 match = true;
1562
1563 dispc_find_clk_divs(req_pck, dispc_clk, &cur_dispc);
1564
1565 if (abs(cur_dispc.pck - req_pck) <
1566 abs(best_dispc.pck - req_pck)) {
1567 best_regm_dispc = regm_dispc;
1568 best_dispc_clk = dispc_clk;
1569 best_dispc = cur_dispc;
1570
1571 if (cur_dispc.pck == req_pck)
1572 goto found;
1573 }
1574 }
1575
1576 if (!match) {
1577 if (min_fck_per_pck) {
1578 DSSERR("Could not find suitable clock settings.\n"
1579 "Turning FCK/PCK constraint off and"
1580 "trying again.\n");
1581 min_fck_per_pck = 0;
1582 goto retry;
1583 }
1584
1585 DSSERR("Could not find suitable clock settings.\n");
1586
1587 return -EINVAL;
1588 }
1589found:
1590 cinfo->regm_dispc = best_regm_dispc;
1591 cinfo->dsi_pll_hsdiv_dispc_clk = best_dispc_clk;
1592
1593 *dispc_cinfo = best_dispc;
1594
1595 return 0;
1596}
1597
1518int dsi_pll_set_clock_div(struct platform_device *dsidev, 1598int dsi_pll_set_clock_div(struct platform_device *dsidev,
1519 struct dsi_clock_info *cinfo) 1599 struct dsi_clock_info *cinfo)
1520{ 1600{
@@ -1591,21 +1671,27 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev,
1591 1671
1592 BUG_ON(cinfo->fint < dsi->fint_min || cinfo->fint > dsi->fint_max); 1672 BUG_ON(cinfo->fint < dsi->fint_min || cinfo->fint > dsi->fint_max);
1593 1673
1674 l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2);
1675
1594 if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) { 1676 if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) {
1595 f = cinfo->fint < 1000000 ? 0x3 : 1677 f = cinfo->fint < 1000000 ? 0x3 :
1596 cinfo->fint < 1250000 ? 0x4 : 1678 cinfo->fint < 1250000 ? 0x4 :
1597 cinfo->fint < 1500000 ? 0x5 : 1679 cinfo->fint < 1500000 ? 0x5 :
1598 cinfo->fint < 1750000 ? 0x6 : 1680 cinfo->fint < 1750000 ? 0x6 :
1599 0x7; 1681 0x7;
1600 }
1601 1682
1602 l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2);
1603
1604 if (dss_has_feature(FEAT_DSI_PLL_FREQSEL))
1605 l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */ 1683 l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */
1684 } else if (dss_has_feature(FEAT_DSI_PLL_SELFREQDCO)) {
1685 f = cinfo->clkin4ddr < 1000000000 ? 0x2 : 0x4;
1686
1687 l = FLD_MOD(l, f, 4, 1); /* PLL_SELFREQDCO */
1688 }
1689
1606 l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */ 1690 l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */
1607 l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */ 1691 l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */
1608 l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */ 1692 l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */
1693 if (dss_has_feature(FEAT_DSI_PLL_REFSEL))
1694 l = FLD_MOD(l, 3, 22, 21); /* REF_SYSCLK = sysclk */
1609 dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION2, l); 1695 dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION2, l);
1610 1696
1611 REG_FLD_MOD(dsidev, DSI_PLL_GO, 1, 0, 0); /* DSI_PLL_GO */ 1697 REG_FLD_MOD(dsidev, DSI_PLL_GO, 1, 0, 0); /* DSI_PLL_GO */
@@ -2069,6 +2155,8 @@ static unsigned dsi_get_line_buf_size(struct platform_device *dsidev)
2069 return 1194 * 3; /* 1194x24 bits */ 2155 return 1194 * 3; /* 1194x24 bits */
2070 case 6: 2156 case 6:
2071 return 1365 * 3; /* 1365x24 bits */ 2157 return 1365 * 3; /* 1365x24 bits */
2158 case 7:
2159 return 1920 * 3; /* 1920x24 bits */
2072 default: 2160 default:
2073 BUG(); 2161 BUG();
2074 return 0; 2162 return 0;
@@ -2204,6 +2292,13 @@ static void dsi_cio_timings(struct platform_device *dsidev)
2204 r = FLD_MOD(r, tlpx_half, 22, 16); 2292 r = FLD_MOD(r, tlpx_half, 22, 16);
2205 r = FLD_MOD(r, tclk_trail, 15, 8); 2293 r = FLD_MOD(r, tclk_trail, 15, 8);
2206 r = FLD_MOD(r, tclk_zero, 7, 0); 2294 r = FLD_MOD(r, tclk_zero, 7, 0);
2295
2296 if (dss_has_feature(FEAT_DSI_PHY_DCC)) {
2297 r = FLD_MOD(r, 0, 21, 21); /* DCCEN = disable */
2298 r = FLD_MOD(r, 1, 22, 22); /* CLKINP_DIVBY2EN = enable */
2299 r = FLD_MOD(r, 1, 23, 23); /* CLKINP_SEL = enable */
2300 }
2301
2207 dsi_write_reg(dsidev, DSI_DSIPHY_CFG1, r); 2302 dsi_write_reg(dsidev, DSI_DSIPHY_CFG1, r);
2208 2303
2209 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG2); 2304 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG2);
@@ -4188,33 +4283,35 @@ int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
4188 4283
4189 mutex_lock(&dsi->lock); 4284 mutex_lock(&dsi->lock);
4190 4285
4191 r = dsi_pll_calc_ddrfreq(dsidev, ddr_clk, &cinfo); 4286 /* Calculate PLL output clock */
4287 r = dsi_pll_calc_ddrfreq(dsidev, ddr_clk * 4, &cinfo);
4192 if (r) 4288 if (r)
4193 goto err; 4289 goto err;
4194 4290
4195 dssdev->clocks.dsi.regn = cinfo.regn; 4291 /* Calculate PLL's DSI clock */
4196 dssdev->clocks.dsi.regm = cinfo.regm; 4292 dsi_pll_calc_dsi_fck(dsidev, &cinfo);
4197 dssdev->clocks.dsi.regm_dispc = cinfo.regm_dispc;
4198 dssdev->clocks.dsi.regm_dsi = cinfo.regm_dsi;
4199 4293
4294 /* Calculate PLL's DISPC clock and pck & lck divs */
4295 pck = cinfo.clkin4ddr / 16 * (dsi->num_lanes_used - 1) * 8 / bpp;
4296 DSSDBG("finding dispc dividers for pck %lu\n", pck);
4297 r = dsi_pll_calc_dispc_fck(dsidev, pck, &cinfo, &dispc_cinfo);
4298 if (r)
4299 goto err;
4200 4300
4301 /* Calculate LP clock */
4201 dsi_fclk = cinfo.dsi_pll_hsdiv_dsi_clk; 4302 dsi_fclk = cinfo.dsi_pll_hsdiv_dsi_clk;
4202 lp_clk_div = DIV_ROUND_UP(dsi_fclk, lp_clk * 2); 4303 lp_clk_div = DIV_ROUND_UP(dsi_fclk, lp_clk * 2);
4203 4304
4204 dssdev->clocks.dsi.lp_clk_div = lp_clk_div; 4305 dssdev->clocks.dsi.regn = cinfo.regn;
4205 4306 dssdev->clocks.dsi.regm = cinfo.regm;
4206 /* pck = TxByteClkHS * datalanes * 8 / bitsperpixel */ 4307 dssdev->clocks.dsi.regm_dispc = cinfo.regm_dispc;
4207 4308 dssdev->clocks.dsi.regm_dsi = cinfo.regm_dsi;
4208 pck = cinfo.clkin4ddr / 16 * (dsi->num_lanes_used - 1) * 8 / bpp;
4209
4210 DSSDBG("finding dispc dividers for pck %lu\n", pck);
4211 4309
4212 dispc_find_clk_divs(pck, cinfo.dsi_pll_hsdiv_dispc_clk, &dispc_cinfo); 4310 dssdev->clocks.dsi.lp_clk_div = lp_clk_div;
4213 4311
4214 dssdev->clocks.dispc.channel.lck_div = dispc_cinfo.lck_div; 4312 dssdev->clocks.dispc.channel.lck_div = dispc_cinfo.lck_div;
4215 dssdev->clocks.dispc.channel.pck_div = dispc_cinfo.pck_div; 4313 dssdev->clocks.dispc.channel.pck_div = dispc_cinfo.pck_div;
4216 4314
4217
4218 dssdev->clocks.dispc.dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK; 4315 dssdev->clocks.dispc.dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK;
4219 4316
4220 dssdev->clocks.dispc.channel.lcd_clk_src = 4317 dssdev->clocks.dispc.channel.lcd_clk_src =