aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--Documentation/devicetree/bindings/drm/msm/dsi.txt7
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.h1
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_host.c18
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_phy.c131
4 files changed, 157 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/drm/msm/dsi.txt b/Documentation/devicetree/bindings/drm/msm/dsi.txt
index 4edd6fa920cf..4309f0fc4dba 100644
--- a/Documentation/devicetree/bindings/drm/msm/dsi.txt
+++ b/Documentation/devicetree/bindings/drm/msm/dsi.txt
@@ -47,6 +47,7 @@ Required properties:
47- compatible: Could be the following 47- compatible: Could be the following
48 * "qcom,dsi-phy-28nm-hpm" 48 * "qcom,dsi-phy-28nm-hpm"
49 * "qcom,dsi-phy-28nm-lp" 49 * "qcom,dsi-phy-28nm-lp"
50 * "qcom,dsi-phy-20nm"
50- reg: Physical base address and length of the registers of PLL, PHY and PHY 51- reg: Physical base address and length of the registers of PLL, PHY and PHY
51 regulator 52 regulator
52- reg-names: The names of register regions. The following regions are required: 53- reg-names: The names of register regions. The following regions are required:
@@ -62,6 +63,10 @@ Required properties:
62 * "iface_clk" 63 * "iface_clk"
63- vddio-supply: phandle to vdd-io regulator device node 64- vddio-supply: phandle to vdd-io regulator device node
64 65
66Optional properties:
67- qcom,dsi-phy-regulator-ldo-mode: Boolean value indicating if the LDO mode PHY
68 regulator is wanted.
69
65Example: 70Example:
66 mdss_dsi0: qcom,mdss_dsi@fd922800 { 71 mdss_dsi0: qcom,mdss_dsi@fd922800 {
67 compatible = "qcom,mdss-dsi-ctrl"; 72 compatible = "qcom,mdss-dsi-ctrl";
@@ -124,4 +129,6 @@ Example:
124 clock-names = "iface_clk"; 129 clock-names = "iface_clk";
125 clocks = <&mmcc MDSS_AHB_CLK>; 130 clocks = <&mmcc MDSS_AHB_CLK>;
126 vddio-supply = <&pma8084_l12>; 131 vddio-supply = <&pma8084_l12>;
132
133 qcom,dsi-phy-regulator-ldo-mode;
127 }; 134 };
diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index 5e29aadc0bee..e18872a62806 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -30,6 +30,7 @@
30enum msm_dsi_phy_type { 30enum msm_dsi_phy_type {
31 MSM_DSI_PHY_28NM_HPM, 31 MSM_DSI_PHY_28NM_HPM,
32 MSM_DSI_PHY_28NM_LP, 32 MSM_DSI_PHY_28NM_LP,
33 MSM_DSI_PHY_20NM,
33 MSM_DSI_PHY_MAX 34 MSM_DSI_PHY_MAX
34}; 35};
35 36
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 69c13970a36c..2d8f19450788 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -34,6 +34,7 @@
34#define MSM_DSI_6G_VER_MINOR_V1_1 0x10010000 34#define MSM_DSI_6G_VER_MINOR_V1_1 0x10010000
35#define MSM_DSI_6G_VER_MINOR_V1_1_1 0x10010001 35#define MSM_DSI_6G_VER_MINOR_V1_1_1 0x10010001
36#define MSM_DSI_6G_VER_MINOR_V1_2 0x10020000 36#define MSM_DSI_6G_VER_MINOR_V1_2 0x10020000
37#define MSM_DSI_6G_VER_MINOR_V1_3 0x10030000
37#define MSM_DSI_6G_VER_MINOR_V1_3_1 0x10030001 38#define MSM_DSI_6G_VER_MINOR_V1_3_1 0x10030001
38 39
39#define DSI_6G_REG_SHIFT 4 40#define DSI_6G_REG_SHIFT 4
@@ -117,6 +118,23 @@ static const struct dsi_config dsi_cfgs[] = {
117 }, 118 },
118 }, 119 },
119 }, 120 },
121 { /* 8x94 */
122 .major = MSM_DSI_VER_MAJOR_6G,
123 .minor = MSM_DSI_6G_VER_MINOR_V1_3,
124 .io_offset = DSI_6G_REG_SHIFT,
125 .reg_cfg = {
126 .num = 7,
127 .regs = {
128 {"gdsc", -1, -1, -1, -1},
129 {"vdda", 1250000, 1250000, 100000, 100},
130 {"vddio", 1800000, 1800000, 100000, 100},
131 {"vcca", 1000000, 1000000, 10000, 100},
132 {"vdd", 1800000, 1800000, 100000, 100},
133 {"lab_reg", -1, -1, -1, -1},
134 {"ibb_reg", -1, -1, -1, -1},
135 },
136 }
137 },
120}; 138};
121 139
122static int dsi_get_version(const void __iomem *base, u32 *major, u32 *minor) 140static int dsi_get_version(const void __iomem *base, u32 *major, u32 *minor)
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__);