aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/msm/dsi/dsi_phy.c
diff options
context:
space:
mode:
authorHai Li <hali@codeaurora.org>2015-06-18 10:14:21 -0400
committerRob Clark <robdclark@gmail.com>2015-08-15 18:27:12 -0400
commitdcefc117cc192f215d04c4e7cbae6b76a9bafcf4 (patch)
treeb5e108bbf5348284be68c4495726f3dd9c577086 /drivers/gpu/drm/msm/dsi/dsi_phy.c
parentab8909b032ffccc15384879dd5798b8647d6ab8a (diff)
drm/msm/dsi: Add support for msm8x94
DSI controller on msm8x94 is version 1.3, which requires different power supplies and works with 20nm DSI PHY. This change is to add the basic support for this version. Signed-off-by: Hai Li <hali@codeaurora.org> Signed-off-by: Rob Clark <robdclark@gmail.com>
Diffstat (limited to 'drivers/gpu/drm/msm/dsi/dsi_phy.c')
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_phy.c131
1 files changed, 131 insertions, 0 deletions
diff --git a/drivers/gpu/drm/msm/dsi/dsi_phy.c b/drivers/gpu/drm/msm/dsi/dsi_phy.c
index 52b463e51202..bd37e61123bf 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_phy.c
@@ -66,6 +66,8 @@ struct msm_dsi_phy {
66 struct dsi_dphy_timing timing; 66 struct dsi_dphy_timing timing;
67 const struct dsi_phy_cfg *cfg; 67 const struct dsi_phy_cfg *cfg;
68 68
69 bool regulator_ldo_mode;
70
69 struct msm_dsi_pll *pll; 71 struct msm_dsi_pll *pll;
70}; 72};
71 73
@@ -406,6 +408,115 @@ static int dsi_28nm_phy_disable(struct msm_dsi_phy *phy)
406 return 0; 408 return 0;
407} 409}
408 410
411static void dsi_20nm_phy_regulator_ctrl(struct msm_dsi_phy *phy, bool enable)
412{
413 void __iomem *base = phy->reg_base;
414
415 if (!enable) {
416 dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CAL_PWR_CFG, 0);
417 return;
418 }
419
420 if (phy->regulator_ldo_mode) {
421 dsi_phy_write(phy->base + REG_DSI_20nm_PHY_LDO_CNTRL, 0x1d);
422 return;
423 }
424
425 /* non LDO mode */
426 dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CTRL_1, 0x03);
427 dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CTRL_2, 0x03);
428 dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CTRL_3, 0x00);
429 dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CTRL_4, 0x20);
430 dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CAL_PWR_CFG, 0x01);
431 dsi_phy_write(phy->base + REG_DSI_20nm_PHY_LDO_CNTRL, 0x00);
432 dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CTRL_0, 0x03);
433}
434
435static int dsi_20nm_phy_enable(struct msm_dsi_phy *phy, int src_pll_id,
436 const unsigned long bit_rate, const unsigned long esc_rate)
437{
438 struct dsi_dphy_timing *timing = &phy->timing;
439 int i;
440 void __iomem *base = phy->base;
441 u32 cfg_4[4] = {0x20, 0x40, 0x20, 0x00};
442
443 DBG("");
444
445 if (dsi_dphy_timing_calc(timing, bit_rate, esc_rate)) {
446 pr_err("%s: D-PHY timing calculation failed\n", __func__);
447 return -EINVAL;
448 }
449
450 dsi_20nm_phy_regulator_ctrl(phy, true);
451
452 dsi_phy_write(base + REG_DSI_20nm_PHY_STRENGTH_0, 0xff);
453
454 dsi_phy_set_src_pll(phy, src_pll_id, REG_DSI_20nm_PHY_GLBL_TEST_CTRL);
455
456 for (i = 0; i < 4; i++) {
457 dsi_phy_write(base + REG_DSI_20nm_PHY_LN_CFG_3(i),
458 (i >> 1) * 0x40);
459 dsi_phy_write(base + REG_DSI_20nm_PHY_LN_TEST_STR_0(i), 0x01);
460 dsi_phy_write(base + REG_DSI_20nm_PHY_LN_TEST_STR_1(i), 0x46);
461 dsi_phy_write(base + REG_DSI_20nm_PHY_LN_CFG_0(i), 0x02);
462 dsi_phy_write(base + REG_DSI_20nm_PHY_LN_CFG_1(i), 0xa0);
463 dsi_phy_write(base + REG_DSI_20nm_PHY_LN_CFG_4(i), cfg_4[i]);
464 }
465
466 dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_CFG_3, 0x80);
467 dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_TEST_STR0, 0x01);
468 dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_TEST_STR1, 0x46);
469 dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_CFG_0, 0x00);
470 dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_CFG_1, 0xa0);
471 dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_CFG_2, 0x00);
472 dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_CFG_4, 0x00);
473
474 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_0,
475 DSI_20nm_PHY_TIMING_CTRL_0_CLK_ZERO(timing->clk_zero));
476 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_1,
477 DSI_20nm_PHY_TIMING_CTRL_1_CLK_TRAIL(timing->clk_trail));
478 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_2,
479 DSI_20nm_PHY_TIMING_CTRL_2_CLK_PREPARE(timing->clk_prepare));
480 if (timing->clk_zero & BIT(8))
481 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_3,
482 DSI_20nm_PHY_TIMING_CTRL_3_CLK_ZERO_8);
483 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_4,
484 DSI_20nm_PHY_TIMING_CTRL_4_HS_EXIT(timing->hs_exit));
485 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_5,
486 DSI_20nm_PHY_TIMING_CTRL_5_HS_ZERO(timing->hs_zero));
487 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_6,
488 DSI_20nm_PHY_TIMING_CTRL_6_HS_PREPARE(timing->hs_prepare));
489 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_7,
490 DSI_20nm_PHY_TIMING_CTRL_7_HS_TRAIL(timing->hs_trail));
491 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_8,
492 DSI_20nm_PHY_TIMING_CTRL_8_HS_RQST(timing->hs_rqst));
493 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_9,
494 DSI_20nm_PHY_TIMING_CTRL_9_TA_GO(timing->ta_go) |
495 DSI_20nm_PHY_TIMING_CTRL_9_TA_SURE(timing->ta_sure));
496 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_10,
497 DSI_20nm_PHY_TIMING_CTRL_10_TA_GET(timing->ta_get));
498 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_11,
499 DSI_20nm_PHY_TIMING_CTRL_11_TRIG3_CMD(0));
500
501 dsi_phy_write(base + REG_DSI_20nm_PHY_CTRL_1, 0x00);
502
503 dsi_phy_write(base + REG_DSI_20nm_PHY_STRENGTH_1, 0x06);
504
505 /* make sure everything is written before enable */
506 wmb();
507 dsi_phy_write(base + REG_DSI_20nm_PHY_CTRL_0, 0x7f);
508
509 return 0;
510}
511
512static int dsi_20nm_phy_disable(struct msm_dsi_phy *phy)
513{
514 dsi_phy_write(phy->base + REG_DSI_20nm_PHY_CTRL_0, 0);
515 dsi_20nm_phy_regulator_ctrl(phy, false);
516
517 return 0;
518}
519
409static int dsi_phy_enable_resource(struct msm_dsi_phy *phy) 520static int dsi_phy_enable_resource(struct msm_dsi_phy *phy)
410{ 521{
411 int ret; 522 int ret;
@@ -456,6 +567,21 @@ static const struct dsi_phy_cfg dsi_phy_cfgs[MSM_DSI_PHY_MAX] = {
456 .disable = dsi_28nm_phy_disable, 567 .disable = dsi_28nm_phy_disable,
457 } 568 }
458 }, 569 },
570 [MSM_DSI_PHY_20NM] = {
571 .type = MSM_DSI_PHY_20NM,
572 .src_pll_truthtable = { {false, true}, {false, true} },
573 .reg_cfg = {
574 .num = 2,
575 .regs = {
576 {"vddio", 1800000, 1800000, 100000, 100},
577 {"vcca", 1000000, 1000000, 10000, 100},
578 },
579 },
580 .ops = {
581 .enable = dsi_20nm_phy_enable,
582 .disable = dsi_20nm_phy_disable,
583 }
584 },
459}; 585};
460 586
461static const struct of_device_id dsi_phy_dt_match[] = { 587static const struct of_device_id dsi_phy_dt_match[] = {
@@ -463,6 +589,8 @@ static const struct of_device_id dsi_phy_dt_match[] = {
463 .data = &dsi_phy_cfgs[MSM_DSI_PHY_28NM_HPM],}, 589 .data = &dsi_phy_cfgs[MSM_DSI_PHY_28NM_HPM],},
464 { .compatible = "qcom,dsi-phy-28nm-lp", 590 { .compatible = "qcom,dsi-phy-28nm-lp",
465 .data = &dsi_phy_cfgs[MSM_DSI_PHY_28NM_LP],}, 591 .data = &dsi_phy_cfgs[MSM_DSI_PHY_28NM_LP],},
592 { .compatible = "qcom,dsi-phy-20nm",
593 .data = &dsi_phy_cfgs[MSM_DSI_PHY_20NM],},
466 {} 594 {}
467}; 595};
468 596
@@ -492,6 +620,9 @@ static int dsi_phy_driver_probe(struct platform_device *pdev)
492 goto fail; 620 goto fail;
493 } 621 }
494 622
623 phy->regulator_ldo_mode = of_property_read_bool(pdev->dev.of_node,
624 "qcom,dsi-phy-regulator-ldo-mode");
625
495 phy->base = msm_ioremap(pdev, "dsi_phy", "DSI_PHY"); 626 phy->base = msm_ioremap(pdev, "dsi_phy", "DSI_PHY");
496 if (IS_ERR(phy->base)) { 627 if (IS_ERR(phy->base)) {
497 dev_err(&pdev->dev, "%s: failed to map phy base\n", __func__); 628 dev_err(&pdev->dev, "%s: failed to map phy base\n", __func__);