From 13351cd17791694f2dcc96dc920e58b090b18c31 Mon Sep 17 00:00:00 2001 From: Hai Li Date: Wed, 10 Jun 2015 13:18:17 -0400 Subject: drm/msm/dsi: Update source PLL selection in DSI PHY The source PLL to be used by each DSI PHY should be decided by DSI manager based on dual DSI information, while the register programming to select PLL is different from one type of PHY to another. This change adds the H/W difference to PHY configuration and updates the interface between DSI manager and PHY. With this change, PLL selection can be supported on different targets. Signed-off-by: Hai Li Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/dsi.h | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'drivers/gpu/drm/msm/dsi/dsi.h') diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 92d697de4858..5e29aadc0bee 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -27,18 +27,6 @@ #define DSI_1 1 #define DSI_MAX 2 -#define DSI_CLOCK_MASTER DSI_0 -#define DSI_CLOCK_SLAVE DSI_1 - -#define DSI_LEFT DSI_0 -#define DSI_RIGHT DSI_1 - -/* According to the current drm framework sequence, take the encoder of - * DSI_1 as master encoder - */ -#define DSI_ENCODER_MASTER DSI_1 -#define DSI_ENCODER_SLAVE DSI_0 - enum msm_dsi_phy_type { MSM_DSI_PHY_28NM_HPM, MSM_DSI_PHY_28NM_LP, @@ -153,7 +141,7 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi); struct msm_dsi_phy; void msm_dsi_phy_driver_register(void); void msm_dsi_phy_driver_unregister(void); -int msm_dsi_phy_enable(struct msm_dsi_phy *phy, bool is_dual_panel, +int msm_dsi_phy_enable(struct msm_dsi_phy *phy, int src_pll_id, const unsigned long bit_rate, const unsigned long esc_rate); int msm_dsi_phy_disable(struct msm_dsi_phy *phy); void msm_dsi_phy_get_clk_pre_post(struct msm_dsi_phy *phy, -- cgit v1.2.3 From dcefc117cc192f215d04c4e7cbae6b76a9bafcf4 Mon Sep 17 00:00:00 2001 From: Hai Li Date: Thu, 18 Jun 2015 10:14:21 -0400 Subject: 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 Signed-off-by: Rob Clark --- Documentation/devicetree/bindings/drm/msm/dsi.txt | 7 ++ drivers/gpu/drm/msm/dsi/dsi.h | 1 + drivers/gpu/drm/msm/dsi/dsi_host.c | 18 +++ drivers/gpu/drm/msm/dsi/dsi_phy.c | 131 ++++++++++++++++++++++ 4 files changed, 157 insertions(+) (limited to 'drivers/gpu/drm/msm/dsi/dsi.h') 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: - compatible: Could be the following * "qcom,dsi-phy-28nm-hpm" * "qcom,dsi-phy-28nm-lp" + * "qcom,dsi-phy-20nm" - reg: Physical base address and length of the registers of PLL, PHY and PHY regulator - reg-names: The names of register regions. The following regions are required: @@ -62,6 +63,10 @@ Required properties: * "iface_clk" - vddio-supply: phandle to vdd-io regulator device node +Optional properties: +- qcom,dsi-phy-regulator-ldo-mode: Boolean value indicating if the LDO mode PHY + regulator is wanted. + Example: mdss_dsi0: qcom,mdss_dsi@fd922800 { compatible = "qcom,mdss-dsi-ctrl"; @@ -124,4 +129,6 @@ Example: clock-names = "iface_clk"; clocks = <&mmcc MDSS_AHB_CLK>; vddio-supply = <&pma8084_l12>; + + qcom,dsi-phy-regulator-ldo-mode; }; 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 @@ enum msm_dsi_phy_type { MSM_DSI_PHY_28NM_HPM, MSM_DSI_PHY_28NM_LP, + MSM_DSI_PHY_20NM, MSM_DSI_PHY_MAX }; 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 @@ #define MSM_DSI_6G_VER_MINOR_V1_1 0x10010000 #define MSM_DSI_6G_VER_MINOR_V1_1_1 0x10010001 #define MSM_DSI_6G_VER_MINOR_V1_2 0x10020000 +#define MSM_DSI_6G_VER_MINOR_V1_3 0x10030000 #define MSM_DSI_6G_VER_MINOR_V1_3_1 0x10030001 #define DSI_6G_REG_SHIFT 4 @@ -117,6 +118,23 @@ static const struct dsi_config dsi_cfgs[] = { }, }, }, + { /* 8x94 */ + .major = MSM_DSI_VER_MAJOR_6G, + .minor = MSM_DSI_6G_VER_MINOR_V1_3, + .io_offset = DSI_6G_REG_SHIFT, + .reg_cfg = { + .num = 7, + .regs = { + {"gdsc", -1, -1, -1, -1}, + {"vdda", 1250000, 1250000, 100000, 100}, + {"vddio", 1800000, 1800000, 100000, 100}, + {"vcca", 1000000, 1000000, 10000, 100}, + {"vdd", 1800000, 1800000, 100000, 100}, + {"lab_reg", -1, -1, -1, -1}, + {"ibb_reg", -1, -1, -1, -1}, + }, + } + }, }; static 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 { struct dsi_dphy_timing timing; const struct dsi_phy_cfg *cfg; + bool regulator_ldo_mode; + struct msm_dsi_pll *pll; }; @@ -406,6 +408,115 @@ static int dsi_28nm_phy_disable(struct msm_dsi_phy *phy) return 0; } +static void dsi_20nm_phy_regulator_ctrl(struct msm_dsi_phy *phy, bool enable) +{ + void __iomem *base = phy->reg_base; + + if (!enable) { + dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CAL_PWR_CFG, 0); + return; + } + + if (phy->regulator_ldo_mode) { + dsi_phy_write(phy->base + REG_DSI_20nm_PHY_LDO_CNTRL, 0x1d); + return; + } + + /* non LDO mode */ + dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CTRL_1, 0x03); + dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CTRL_2, 0x03); + dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CTRL_3, 0x00); + dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CTRL_4, 0x20); + dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CAL_PWR_CFG, 0x01); + dsi_phy_write(phy->base + REG_DSI_20nm_PHY_LDO_CNTRL, 0x00); + dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CTRL_0, 0x03); +} + +static int dsi_20nm_phy_enable(struct msm_dsi_phy *phy, int src_pll_id, + const unsigned long bit_rate, const unsigned long esc_rate) +{ + struct dsi_dphy_timing *timing = &phy->timing; + int i; + void __iomem *base = phy->base; + u32 cfg_4[4] = {0x20, 0x40, 0x20, 0x00}; + + DBG(""); + + if (dsi_dphy_timing_calc(timing, bit_rate, esc_rate)) { + pr_err("%s: D-PHY timing calculation failed\n", __func__); + return -EINVAL; + } + + dsi_20nm_phy_regulator_ctrl(phy, true); + + dsi_phy_write(base + REG_DSI_20nm_PHY_STRENGTH_0, 0xff); + + dsi_phy_set_src_pll(phy, src_pll_id, REG_DSI_20nm_PHY_GLBL_TEST_CTRL); + + for (i = 0; i < 4; i++) { + dsi_phy_write(base + REG_DSI_20nm_PHY_LN_CFG_3(i), + (i >> 1) * 0x40); + dsi_phy_write(base + REG_DSI_20nm_PHY_LN_TEST_STR_0(i), 0x01); + dsi_phy_write(base + REG_DSI_20nm_PHY_LN_TEST_STR_1(i), 0x46); + dsi_phy_write(base + REG_DSI_20nm_PHY_LN_CFG_0(i), 0x02); + dsi_phy_write(base + REG_DSI_20nm_PHY_LN_CFG_1(i), 0xa0); + dsi_phy_write(base + REG_DSI_20nm_PHY_LN_CFG_4(i), cfg_4[i]); + } + + dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_CFG_3, 0x80); + dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_TEST_STR0, 0x01); + dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_TEST_STR1, 0x46); + dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_CFG_0, 0x00); + dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_CFG_1, 0xa0); + dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_CFG_2, 0x00); + dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_CFG_4, 0x00); + + dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_0, + DSI_20nm_PHY_TIMING_CTRL_0_CLK_ZERO(timing->clk_zero)); + dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_1, + DSI_20nm_PHY_TIMING_CTRL_1_CLK_TRAIL(timing->clk_trail)); + dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_2, + DSI_20nm_PHY_TIMING_CTRL_2_CLK_PREPARE(timing->clk_prepare)); + if (timing->clk_zero & BIT(8)) + dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_3, + DSI_20nm_PHY_TIMING_CTRL_3_CLK_ZERO_8); + dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_4, + DSI_20nm_PHY_TIMING_CTRL_4_HS_EXIT(timing->hs_exit)); + dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_5, + DSI_20nm_PHY_TIMING_CTRL_5_HS_ZERO(timing->hs_zero)); + dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_6, + DSI_20nm_PHY_TIMING_CTRL_6_HS_PREPARE(timing->hs_prepare)); + dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_7, + DSI_20nm_PHY_TIMING_CTRL_7_HS_TRAIL(timing->hs_trail)); + dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_8, + DSI_20nm_PHY_TIMING_CTRL_8_HS_RQST(timing->hs_rqst)); + dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_9, + DSI_20nm_PHY_TIMING_CTRL_9_TA_GO(timing->ta_go) | + DSI_20nm_PHY_TIMING_CTRL_9_TA_SURE(timing->ta_sure)); + dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_10, + DSI_20nm_PHY_TIMING_CTRL_10_TA_GET(timing->ta_get)); + dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_11, + DSI_20nm_PHY_TIMING_CTRL_11_TRIG3_CMD(0)); + + dsi_phy_write(base + REG_DSI_20nm_PHY_CTRL_1, 0x00); + + dsi_phy_write(base + REG_DSI_20nm_PHY_STRENGTH_1, 0x06); + + /* make sure everything is written before enable */ + wmb(); + dsi_phy_write(base + REG_DSI_20nm_PHY_CTRL_0, 0x7f); + + return 0; +} + +static int dsi_20nm_phy_disable(struct msm_dsi_phy *phy) +{ + dsi_phy_write(phy->base + REG_DSI_20nm_PHY_CTRL_0, 0); + dsi_20nm_phy_regulator_ctrl(phy, false); + + return 0; +} + static int dsi_phy_enable_resource(struct msm_dsi_phy *phy) { int ret; @@ -456,6 +567,21 @@ static const struct dsi_phy_cfg dsi_phy_cfgs[MSM_DSI_PHY_MAX] = { .disable = dsi_28nm_phy_disable, } }, + [MSM_DSI_PHY_20NM] = { + .type = MSM_DSI_PHY_20NM, + .src_pll_truthtable = { {false, true}, {false, true} }, + .reg_cfg = { + .num = 2, + .regs = { + {"vddio", 1800000, 1800000, 100000, 100}, + {"vcca", 1000000, 1000000, 10000, 100}, + }, + }, + .ops = { + .enable = dsi_20nm_phy_enable, + .disable = dsi_20nm_phy_disable, + } + }, }; static const struct of_device_id dsi_phy_dt_match[] = { @@ -463,6 +589,8 @@ static const struct of_device_id dsi_phy_dt_match[] = { .data = &dsi_phy_cfgs[MSM_DSI_PHY_28NM_HPM],}, { .compatible = "qcom,dsi-phy-28nm-lp", .data = &dsi_phy_cfgs[MSM_DSI_PHY_28NM_LP],}, + { .compatible = "qcom,dsi-phy-20nm", + .data = &dsi_phy_cfgs[MSM_DSI_PHY_20NM],}, {} }; @@ -492,6 +620,9 @@ static int dsi_phy_driver_probe(struct platform_device *pdev) goto fail; } + phy->regulator_ldo_mode = of_property_read_bool(pdev->dev.of_node, + "qcom,dsi-phy-regulator-ldo-mode"); + phy->base = msm_ioremap(pdev, "dsi_phy", "DSI_PHY"); if (IS_ERR(phy->base)) { dev_err(&pdev->dev, "%s: failed to map phy base\n", __func__); -- cgit v1.2.3 From 328e1a633c9bc26c36ecd320246e4a9b2726e81a Mon Sep 17 00:00:00 2001 From: Hai Li Date: Fri, 3 Jul 2015 10:09:46 -0400 Subject: drm/msm/dsi: Save/Restore PLL status across PHY reset Reset DSI PHY silently changes its PLL registers to reset status, which will make cached status in clock driver invalid and result in wrong output rate of link clocks. The current restore mechanism in DSI PLL does not cover all the cases. This change is to recover PLL status after PHY reset to match HW status with cached status in clock driver. Signed-off-by: Hai Li Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/dsi.h | 9 +++++++ drivers/gpu/drm/msm/dsi/dsi_manager.c | 21 +++++++++++++++ drivers/gpu/drm/msm/dsi/pll/dsi_pll.c | 42 +++++++++++++++++------------- drivers/gpu/drm/msm/dsi/pll/dsi_pll.h | 1 + drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c | 31 +++++++++------------- 5 files changed, 68 insertions(+), 36 deletions(-) (limited to 'drivers/gpu/drm/msm/dsi/dsi.h') diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index e18872a62806..912057df5c02 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -95,6 +95,8 @@ struct msm_dsi_pll *msm_dsi_pll_init(struct platform_device *pdev, void msm_dsi_pll_destroy(struct msm_dsi_pll *pll); int msm_dsi_pll_get_clk_provider(struct msm_dsi_pll *pll, struct clk **byte_clk_provider, struct clk **pixel_clk_provider); +void msm_dsi_pll_save_state(struct msm_dsi_pll *pll); +int msm_dsi_pll_restore_state(struct msm_dsi_pll *pll); #else static inline struct msm_dsi_pll *msm_dsi_pll_init(struct platform_device *pdev, enum msm_dsi_phy_type type, int id) { @@ -108,6 +110,13 @@ static inline int msm_dsi_pll_get_clk_provider(struct msm_dsi_pll *pll, { return -ENODEV; } +static inline void msm_dsi_pll_save_state(struct msm_dsi_pll *pll) +{ +} +static inline int msm_dsi_pll_restore_state(struct msm_dsi_pll *pll) +{ + return 0; +} #endif /* dsi host */ diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index bd247b7dbc44..ca4ff4ab663e 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -611,12 +611,28 @@ int msm_dsi_manager_phy_enable(int id, struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); struct msm_dsi_phy *phy = msm_dsi->phy; int src_pll_id = IS_DUAL_DSI() ? DSI_CLOCK_MASTER : id; + struct msm_dsi_pll *pll = msm_dsi_phy_get_pll(msm_dsi->phy); int ret; ret = msm_dsi_phy_enable(phy, src_pll_id, bit_rate, esc_rate); if (ret) return ret; + /* + * Reset DSI PHY silently changes its PLL registers to reset status, + * which will confuse clock driver and result in wrong output rate of + * link clocks. Restore PLL status if its PLL is being used as clock + * source. + */ + if (!IS_DUAL_DSI() || (id == DSI_CLOCK_MASTER)) { + ret = msm_dsi_pll_restore_state(pll); + if (ret) { + pr_err("%s: failed to restore pll state\n", __func__); + msm_dsi_phy_disable(phy); + return ret; + } + } + msm_dsi->phy_enabled = true; msm_dsi_phy_get_clk_pre_post(phy, clk_pre, clk_post); @@ -629,6 +645,11 @@ void msm_dsi_manager_phy_disable(int id) struct msm_dsi *mdsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER); struct msm_dsi *sdsi = dsi_mgr_get_dsi(DSI_CLOCK_SLAVE); struct msm_dsi_phy *phy = msm_dsi->phy; + struct msm_dsi_pll *pll = msm_dsi_phy_get_pll(msm_dsi->phy); + + /* Save PLL status if it is a clock source */ + if (!IS_DUAL_DSI() || (id == DSI_CLOCK_MASTER)) + msm_dsi_pll_save_state(pll); /* disable DSI phy * In dual-dsi configuration, the phy should be disabled for the diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll.c b/drivers/gpu/drm/msm/dsi/pll/dsi_pll.c index 509376fdd112..5104fc9f9a53 100644 --- a/drivers/gpu/drm/msm/dsi/pll/dsi_pll.c +++ b/drivers/gpu/drm/msm/dsi/pll/dsi_pll.c @@ -72,31 +72,14 @@ long msm_dsi_pll_helper_clk_round_rate(struct clk_hw *hw, int msm_dsi_pll_helper_clk_prepare(struct clk_hw *hw) { struct msm_dsi_pll *pll = hw_clk_to_pll(hw); - int ret; - - /* - * Certain PLLs need to update the same VCO rate and registers - * after resume in suspend/resume scenario. - */ - if (pll->restore_state) { - ret = pll->restore_state(pll); - if (ret) - goto error; - } - ret = dsi_pll_enable(pll); - -error: - return ret; + return dsi_pll_enable(pll); } void msm_dsi_pll_helper_clk_unprepare(struct clk_hw *hw) { struct msm_dsi_pll *pll = hw_clk_to_pll(hw); - if (pll->save_state) - pll->save_state(pll); - dsi_pll_disable(pll); } @@ -134,6 +117,29 @@ void msm_dsi_pll_destroy(struct msm_dsi_pll *pll) pll->destroy(pll); } +void msm_dsi_pll_save_state(struct msm_dsi_pll *pll) +{ + if (pll->save_state) { + pll->save_state(pll); + pll->state_saved = true; + } +} + +int msm_dsi_pll_restore_state(struct msm_dsi_pll *pll) +{ + int ret; + + if (pll->restore_state && pll->state_saved) { + ret = pll->restore_state(pll); + if (ret) + return ret; + + pll->state_saved = false; + } + + return 0; +} + struct msm_dsi_pll *msm_dsi_pll_init(struct platform_device *pdev, enum msm_dsi_phy_type type, int id) { diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll.h b/drivers/gpu/drm/msm/dsi/pll/dsi_pll.h index 5a3bb241c039..b69df19f1fd4 100644 --- a/drivers/gpu/drm/msm/dsi/pll/dsi_pll.h +++ b/drivers/gpu/drm/msm/dsi/pll/dsi_pll.h @@ -27,6 +27,7 @@ struct msm_dsi_pll { struct clk_hw clk_hw; bool pll_on; + bool state_saved; unsigned long min_rate; unsigned long max_rate; diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c index eb8ac3097ff5..1912cfcca48c 100644 --- a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c +++ b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c @@ -465,26 +465,21 @@ static int dsi_pll_28nm_restore_state(struct msm_dsi_pll *pll) void __iomem *base = pll_28nm->mmio; int ret; - if ((cached_state->vco_rate != 0) && - (cached_state->vco_rate == __clk_get_rate(pll->clk_hw.clk))) { - ret = dsi_pll_28nm_clk_set_rate(&pll->clk_hw, - cached_state->vco_rate, 0); - if (ret) { - dev_err(&pll_28nm->pdev->dev, - "restore vco rate failed. ret=%d\n", ret); - return ret; - } - - pll_write(base + REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG, - cached_state->postdiv3); - pll_write(base + REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG, - cached_state->postdiv1); - pll_write(base + REG_DSI_28nm_PHY_PLL_VREG_CFG, - cached_state->byte_mux); - - cached_state->vco_rate = 0; + ret = dsi_pll_28nm_clk_set_rate(&pll->clk_hw, + cached_state->vco_rate, 0); + if (ret) { + dev_err(&pll_28nm->pdev->dev, + "restore vco rate failed. ret=%d\n", ret); + return ret; } + pll_write(base + REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG, + cached_state->postdiv3); + pll_write(base + REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG, + cached_state->postdiv1); + pll_write(base + REG_DSI_28nm_PHY_PLL_VREG_CFG, + cached_state->byte_mux); + return 0; } -- cgit v1.2.3 From a9ddac9c5765712fa7eace55feeaf7c4ac75e32b Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Mon, 3 Aug 2015 14:05:45 +0530 Subject: drm/msm/dsi: Refer to connected device as 'device' instead of 'panel' We currently support only panels connected to dsi output. We're going to also support external bridge chips now. Change 'panel_node' to 'device_node' in the struct msm_dsi_host and 'panel_flags' to 'device_flags' in msm_dsi. This makes things sound a bit more generic. Signed-off-by: Archit Taneja Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/dsi.c | 2 +- drivers/gpu/drm/msm/dsi/dsi.h | 2 +- drivers/gpu/drm/msm/dsi/dsi_host.c | 24 ++++++++++++------------ drivers/gpu/drm/msm/dsi/dsi_manager.c | 4 ++-- 4 files changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers/gpu/drm/msm/dsi/dsi.h') diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c index 3d6ae79a6bb4..5c8fbc475831 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.c +++ b/drivers/gpu/drm/msm/dsi/dsi.c @@ -18,7 +18,7 @@ struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi) if (!msm_dsi || !msm_dsi->panel) return NULL; - return (msm_dsi->panel_flags & MIPI_DSI_MODE_VIDEO) ? + return (msm_dsi->device_flags & MIPI_DSI_MODE_VIDEO) ? msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID] : msm_dsi->encoders[MSM_DSI_CMD_ENCODER_ID]; } diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 912057df5c02..1a5990551c15 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -60,7 +60,7 @@ struct msm_dsi { struct mipi_dsi_host *host; struct msm_dsi_phy *phy; struct drm_panel *panel; - unsigned long panel_flags; + unsigned long device_flags; struct device *phy_dev; bool phy_enabled; diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 9b784321c2e0..0fa55354ad2c 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -232,8 +232,8 @@ struct msm_dsi_host { struct drm_display_mode *mode; - /* Panel info */ - struct device_node *panel_node; + /* connected device info */ + struct device_node *device_node; unsigned int channel; unsigned int lanes; enum mipi_dsi_pixel_format format; @@ -1404,7 +1404,7 @@ static int dsi_host_attach(struct mipi_dsi_host *host, msm_host->format = dsi->format; msm_host->mode_flags = dsi->mode_flags; - WARN_ON(dsi->dev.of_node != msm_host->panel_node); + WARN_ON(dsi->dev.of_node != msm_host->device_node); /* Some gpios defined in panel DT need to be controlled by host */ ret = dsi_host_init_panel_gpios(msm_host, &dsi->dev); @@ -1423,7 +1423,7 @@ static int dsi_host_detach(struct mipi_dsi_host *host, { struct msm_dsi_host *msm_host = to_msm_dsi_host(host); - msm_host->panel_node = NULL; + msm_host->device_node = NULL; DBG("id=%d", msm_host->id); if (msm_host->dev) @@ -1458,7 +1458,7 @@ static int dsi_host_parse_dt(struct msm_dsi_host *msm_host) { struct device *dev = &msm_host->pdev->dev; struct device_node *np = dev->of_node; - struct device_node *endpoint, *panel_node; + struct device_node *endpoint, *device_node; int ret; ret = of_property_read_u32(np, "qcom,dsi-host-index", &msm_host->id); @@ -1481,17 +1481,17 @@ static int dsi_host_parse_dt(struct msm_dsi_host *msm_host) } /* Get panel node from the output port's endpoint data */ - panel_node = of_graph_get_remote_port_parent(endpoint); - if (!panel_node) { + device_node = of_graph_get_remote_port_parent(endpoint); + if (!device_node) { dev_err(dev, "%s: no valid device\n", __func__); of_node_put(endpoint); return -ENODEV; } of_node_put(endpoint); - of_node_put(panel_node); + of_node_put(device_node); - msm_host->panel_node = panel_node; + msm_host->device_node = device_node; return 0; } @@ -1644,8 +1644,8 @@ int msm_dsi_host_register(struct mipi_dsi_host *host, bool check_defer) * Don't try to defer if there is nothing connected to the dsi * output */ - if (check_defer && msm_host->panel_node) { - if (!of_drm_find_panel(msm_host->panel_node)) + if (check_defer && msm_host->device_node) { + if (!of_drm_find_panel(msm_host->device_node)) return -EPROBE_DEFER; } } @@ -2066,7 +2066,7 @@ struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host, struct msm_dsi_host *msm_host = to_msm_dsi_host(host); struct drm_panel *panel; - panel = of_drm_find_panel(msm_host->panel_node); + panel = of_drm_find_panel(msm_host->device_node); if (panel_flags) *panel_flags = msm_host->mode_flags; diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index ca4ff4ab663e..f43c66ca81fb 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -156,7 +156,7 @@ static enum drm_connector_status dsi_mgr_connector_detect( DBG("id=%d", id); if (!msm_dsi->panel) { msm_dsi->panel = msm_dsi_host_get_panel(msm_dsi->host, - &msm_dsi->panel_flags); + &msm_dsi->device_flags); /* There is only 1 panel in the global panel list * for dual DSI mode. Therefore slave dsi should get @@ -177,7 +177,7 @@ static enum drm_connector_status dsi_mgr_connector_detect( */ if (msm_dsi->panel && IS_DUAL_DSI() && other_dsi && other_dsi->panel) { - bool cmd_mode = !(msm_dsi->panel_flags & + bool cmd_mode = !(msm_dsi->device_flags & MIPI_DSI_MODE_VIDEO); struct drm_encoder *encoder = msm_dsi_get_encoder( dsi_mgr_get_dsi(DSI_ENCODER_MASTER)); -- cgit v1.2.3 From 6f054ec5b9ced3041f29541ae79402198678fc06 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Mon, 3 Aug 2015 14:08:33 +0530 Subject: drm/msm/dsi: Create a helper to check if there is a connected device Create a helper msm_dsi_device_connected() which checks whether we have a device connected to the dsi host or not. This check gets messy when we have support external bridges too. Having an inline function makes it more legible. For now, the check only consists of msm_dsi->panel being non-NULL. Later, this will check if we have an external bridge or not. This helper isn't used in dsi_connector related code as that's specific to only when a drm_panel is connected. Signed-off-by: Archit Taneja Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/dsi.c | 2 +- drivers/gpu/drm/msm/dsi/dsi.h | 5 +++++ drivers/gpu/drm/msm/dsi/dsi_manager.c | 6 ++++-- 3 files changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/msm/dsi/dsi.h') diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c index 5c8fbc475831..ffaf77f623c6 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.c +++ b/drivers/gpu/drm/msm/dsi/dsi.c @@ -15,7 +15,7 @@ struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi) { - if (!msm_dsi || !msm_dsi->panel) + if (!msm_dsi || !msm_dsi_device_connected(msm_dsi)) return NULL; return (msm_dsi->device_flags & MIPI_DSI_MODE_VIDEO) ? diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 1a5990551c15..1636513347e0 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -85,6 +85,11 @@ int msm_dsi_manager_register(struct msm_dsi *msm_dsi); void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi); /* msm dsi */ +static inline bool msm_dsi_device_connected(struct msm_dsi *msm_dsi) +{ + return msm_dsi->panel; +} + struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi); /* dsi pll */ diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index f43c66ca81fb..60dbd829d7a9 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -344,7 +344,8 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge) int ret; DBG("id=%d", id); - if (!panel || (is_dual_dsi && (DSI_1 == id))) + if (!msm_dsi_device_connected(msm_dsi) || + (is_dual_dsi && (DSI_1 == id))) return; ret = msm_dsi_host_power_on(host); @@ -431,7 +432,8 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge) DBG("id=%d", id); - if (!panel || (is_dual_dsi && (DSI_1 == id))) + if (!msm_dsi_device_connected(msm_dsi) || + (is_dual_dsi && (DSI_1 == id))) return; ret = drm_panel_disable(panel); -- cgit v1.2.3 From c118e29033aa5b38b593ebd0e02f8b1224c20ed3 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Fri, 31 Jul 2015 14:06:10 +0530 Subject: drm/msm/dsi: Allow dsi to connect to an external bridge There are platforms where the DSI output can be connected to another encoder bridge chip (DSI to HDMI, DSI to LVDS etc). Add support for external bridge support to the dsi driver. We assume that the external bridge chip would be of the type drm_bridge. The dsi driver's internal drm_bridge (msm_dsi->bridge) is linked to the external bridge's drm_bridge struct. In the case we're connected to an external bridge, we don't need to create and manage a connector within our driver, it's the bridge driver's responsibility to create one. v2: - Move the external bridge attaching stuff to dsi manager to make things cleaner. - Force the bridge to connect to a video mode encoder for now (the dsi mode flags may have not been populated by modeset_init) Signed-off-by: Archit Taneja Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/dsi.c | 28 ++++++++++++++++---- drivers/gpu/drm/msm/dsi/dsi.h | 12 ++++++++- drivers/gpu/drm/msm/dsi/dsi_host.c | 9 ++++++- drivers/gpu/drm/msm/dsi/dsi_manager.c | 49 ++++++++++++++++++++++++++++++++++- 4 files changed, 90 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/msm/dsi/dsi.h') diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c index ffaf77f623c6..6edcd6f57e70 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.c +++ b/drivers/gpu/drm/msm/dsi/dsi.c @@ -190,6 +190,7 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev, struct drm_encoder *encoders[MSM_DSI_ENCODER_NUM]) { struct msm_drm_private *priv = dev->dev_private; + struct drm_bridge *ext_bridge; int ret, i; if (WARN_ON(!encoders[MSM_DSI_VIDEO_ENCODER_ID] || @@ -217,10 +218,25 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev, msm_dsi->encoders[i] = encoders[i]; } - msm_dsi->connector = msm_dsi_manager_connector_init(msm_dsi->id); + /* + * check if the dsi encoder output is connected to a panel or an + * external bridge. We create a connector only if we're connected to a + * drm_panel device. When we're connected to an external bridge, we + * assume that the drm_bridge driver will create the connector itself. + */ + ext_bridge = msm_dsi_host_get_bridge(msm_dsi->host); + + if (ext_bridge) + msm_dsi->connector = + msm_dsi_manager_ext_bridge_init(msm_dsi->id); + else + msm_dsi->connector = + msm_dsi_manager_connector_init(msm_dsi->id); + if (IS_ERR(msm_dsi->connector)) { ret = PTR_ERR(msm_dsi->connector); - dev_err(dev->dev, "failed to create dsi connector: %d\n", ret); + dev_err(dev->dev, + "failed to create dsi connector: %d\n", ret); msm_dsi->connector = NULL; goto fail; } @@ -236,10 +252,12 @@ fail: msm_dsi_manager_bridge_destroy(msm_dsi->bridge); msm_dsi->bridge = NULL; } - if (msm_dsi->connector) { + + /* don't destroy connector if we didn't make it */ + if (msm_dsi->connector && !msm_dsi->external_bridge) msm_dsi->connector->funcs->destroy(msm_dsi->connector); - msm_dsi->connector = NULL; - } + + msm_dsi->connector = NULL; } return ret; diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 1636513347e0..09492bfc0e02 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -54,12 +54,20 @@ struct msm_dsi { struct drm_device *dev; struct platform_device *pdev; + /* connector managed by us when we're connected to a drm_panel */ struct drm_connector *connector; + /* internal dsi bridge attached to MDP interface */ struct drm_bridge *bridge; struct mipi_dsi_host *host; struct msm_dsi_phy *phy; + + /* + * panel/external_bridge connected to dsi bridge output, only one of the + * two can be valid at a time + */ struct drm_panel *panel; + struct drm_bridge *external_bridge; unsigned long device_flags; struct device *phy_dev; @@ -75,6 +83,7 @@ struct msm_dsi { struct drm_bridge *msm_dsi_manager_bridge_init(u8 id); void msm_dsi_manager_bridge_destroy(struct drm_bridge *bridge); struct drm_connector *msm_dsi_manager_connector_init(u8 id); +struct drm_connector *msm_dsi_manager_ext_bridge_init(u8 id); int msm_dsi_manager_phy_enable(int id, const unsigned long bit_rate, const unsigned long esc_rate, u32 *clk_pre, u32 *clk_post); @@ -87,7 +96,7 @@ void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi); /* msm dsi */ static inline bool msm_dsi_device_connected(struct msm_dsi *msm_dsi) { - return msm_dsi->panel; + return msm_dsi->panel || msm_dsi->external_bridge; } struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi); @@ -143,6 +152,7 @@ int msm_dsi_host_set_display_mode(struct mipi_dsi_host *host, struct drm_display_mode *mode); struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host, unsigned long *panel_flags); +struct drm_bridge *msm_dsi_host_get_bridge(struct mipi_dsi_host *host); int msm_dsi_host_register(struct mipi_dsi_host *host, bool check_defer); void msm_dsi_host_unregister(struct mipi_dsi_host *host); int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host, diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 0fa55354ad2c..af40d428ff44 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -1646,7 +1646,8 @@ int msm_dsi_host_register(struct mipi_dsi_host *host, bool check_defer) */ if (check_defer && msm_host->device_node) { if (!of_drm_find_panel(msm_host->device_node)) - return -EPROBE_DEFER; + if (!of_drm_find_bridge(msm_host->device_node)) + return -EPROBE_DEFER; } } @@ -2073,3 +2074,9 @@ struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host, return panel; } +struct drm_bridge *msm_dsi_host_get_bridge(struct mipi_dsi_host *host) +{ + struct msm_dsi_host *msm_host = to_msm_dsi_host(host); + + return of_drm_find_bridge(msm_host->device_node); +} diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index 60dbd829d7a9..dc3d322375e9 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -517,7 +517,7 @@ static const struct drm_bridge_funcs dsi_mgr_bridge_funcs = { .mode_set = dsi_mgr_bridge_mode_set, }; -/* initialize connector */ +/* initialize connector when we're connected to a drm_panel */ struct drm_connector *msm_dsi_manager_connector_init(u8 id) { struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); @@ -602,6 +602,53 @@ fail: return ERR_PTR(ret); } +struct drm_connector *msm_dsi_manager_ext_bridge_init(u8 id) +{ + struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); + struct drm_device *dev = msm_dsi->dev; + struct drm_encoder *encoder; + struct drm_bridge *int_bridge, *ext_bridge; + struct drm_connector *connector; + struct list_head *connector_list; + + int_bridge = msm_dsi->bridge; + ext_bridge = msm_dsi->external_bridge = + msm_dsi_host_get_bridge(msm_dsi->host); + + /* + * HACK: we may not know the external DSI bridge device's mode + * flags here. We'll get to know them only when the device + * attaches to the dsi host. For now, assume the bridge supports + * DSI video mode + */ + encoder = msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID]; + + /* link the internal dsi bridge to the external bridge */ + int_bridge->next = ext_bridge; + /* set the external bridge's encoder as dsi's encoder */ + ext_bridge->encoder = encoder; + + drm_bridge_attach(dev, ext_bridge); + + /* + * we need the drm_connector created by the external bridge + * driver (or someone else) to feed it to our driver's + * priv->connector[] list, mainly for msm_fbdev_init() + */ + connector_list = &dev->mode_config.connector_list; + + list_for_each_entry(connector, connector_list, head) { + int i; + + for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { + if (connector->encoder_ids[i] == encoder->base.id) + return connector; + } + } + + return ERR_PTR(-ENODEV); +} + void msm_dsi_manager_bridge_destroy(struct drm_bridge *bridge) { } -- cgit v1.2.3 From 29e61690130adb1c27053558d2f21af88ae0334e Mon Sep 17 00:00:00 2001 From: Hai Li Date: Thu, 13 Aug 2015 17:45:51 -0400 Subject: drm/msm/dsi: Return void from msm_dsi_phy_disable() We are not checking the return value from msm_dsi_phy_disable(). Change the return type to void. Signed-off-by: Hai Li Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/dsi/dsi.h | 2 +- drivers/gpu/drm/msm/dsi/dsi_phy.c | 16 +++++----------- 2 files changed, 6 insertions(+), 12 deletions(-) (limited to 'drivers/gpu/drm/msm/dsi/dsi.h') diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 09492bfc0e02..5f5a3732cdf6 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -168,7 +168,7 @@ void msm_dsi_phy_driver_register(void); void msm_dsi_phy_driver_unregister(void); int msm_dsi_phy_enable(struct msm_dsi_phy *phy, int src_pll_id, const unsigned long bit_rate, const unsigned long esc_rate); -int msm_dsi_phy_disable(struct msm_dsi_phy *phy); +void msm_dsi_phy_disable(struct msm_dsi_phy *phy); void msm_dsi_phy_get_clk_pre_post(struct msm_dsi_phy *phy, u32 *clk_pre, u32 *clk_post); struct msm_dsi_pll *msm_dsi_phy_get_pll(struct msm_dsi_phy *phy); diff --git a/drivers/gpu/drm/msm/dsi/dsi_phy.c b/drivers/gpu/drm/msm/dsi/dsi_phy.c index 799201e1a14f..77f1efe4e013 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_phy.c +++ b/drivers/gpu/drm/msm/dsi/dsi_phy.c @@ -23,7 +23,7 @@ struct dsi_phy_ops { int (*enable)(struct msm_dsi_phy *phy, int src_pll_id, const unsigned long bit_rate, const unsigned long esc_rate); - int (*disable)(struct msm_dsi_phy *phy); + void (*disable)(struct msm_dsi_phy *phy); }; struct dsi_phy_cfg { @@ -399,7 +399,7 @@ static int dsi_28nm_phy_enable(struct msm_dsi_phy *phy, int src_pll_id, return 0; } -static int dsi_28nm_phy_disable(struct msm_dsi_phy *phy) +static void dsi_28nm_phy_disable(struct msm_dsi_phy *phy) { dsi_phy_write(phy->base + REG_DSI_28nm_PHY_CTRL_0, 0); dsi_28nm_phy_regulator_ctrl(phy, false); @@ -409,8 +409,6 @@ static int dsi_28nm_phy_disable(struct msm_dsi_phy *phy) * ensure that the phy is completely disabled */ wmb(); - - return 0; } static void dsi_20nm_phy_regulator_ctrl(struct msm_dsi_phy *phy, bool enable) @@ -515,12 +513,10 @@ static int dsi_20nm_phy_enable(struct msm_dsi_phy *phy, int src_pll_id, return 0; } -static int dsi_20nm_phy_disable(struct msm_dsi_phy *phy) +static void dsi_20nm_phy_disable(struct msm_dsi_phy *phy) { dsi_phy_write(phy->base + REG_DSI_20nm_PHY_CTRL_0, 0); dsi_20nm_phy_regulator_ctrl(phy, false); - - return 0; } static int dsi_phy_enable_resource(struct msm_dsi_phy *phy) @@ -730,15 +726,13 @@ int msm_dsi_phy_enable(struct msm_dsi_phy *phy, int src_pll_id, return phy->cfg->ops.enable(phy, src_pll_id, bit_rate, esc_rate); } -int msm_dsi_phy_disable(struct msm_dsi_phy *phy) +void msm_dsi_phy_disable(struct msm_dsi_phy *phy) { if (!phy || !phy->cfg->ops.disable) - return -EINVAL; + return; phy->cfg->ops.disable(phy); dsi_phy_regulator_disable(phy); - - return 0; } void msm_dsi_phy_get_clk_pre_post(struct msm_dsi_phy *phy, -- cgit v1.2.3