diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/video/fbdev/msm/mdss_dsi.c | 25 | ||||
-rw-r--r-- | drivers/video/fbdev/msm/mdss_dsi.h | 2 | ||||
-rw-r--r-- | drivers/video/fbdev/msm/mdss_dsi_clk.c | 62 | ||||
-rw-r--r-- | drivers/video/fbdev/msm/mdss_dsi_clk.h | 4 | ||||
-rw-r--r-- | drivers/video/fbdev/msm/msm_mdss_io_8974.c | 9 |
5 files changed, 100 insertions, 2 deletions
diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c index 903d8741ae13..0573dcb3c9d6 100644 --- a/drivers/video/fbdev/msm/mdss_dsi.c +++ b/drivers/video/fbdev/msm/mdss_dsi.c @@ -2788,6 +2788,7 @@ static int mdss_dsi_ctrl_clock_init(struct platform_device *ctrl_pdev, info.link_clks.esc_clk = ctrl_pdata->esc_clk; info.link_clks.byte_clk = ctrl_pdata->byte_clk; info.link_clks.pixel_clk = ctrl_pdata->pixel_clk; + info.link_clks.byte_intf_clk = ctrl_pdata->byte_intf_clk; info.pre_clkoff_cb = mdss_dsi_pre_clkoff_cb; info.post_clkon_cb = mdss_dsi_post_clkon_cb; @@ -2950,6 +2951,24 @@ end: return rc; } +static int mdss_dsi_ctrl_validate_config(struct mdss_dsi_ctrl_pdata *ctrl) +{ + int rc = 0; + + /* + * check to make sure that the byte interface clock is specified for + * DSI ctrl version 2 and above. + */ + if ((ctrl->shared_data->hw_rev >= MDSS_DSI_HW_REV_200) && + (!ctrl->byte_intf_clk)) { + pr_err("%s: byte intf clk must be defined for hw rev 0x%08x\n", + __func__, ctrl->shared_data->hw_rev); + rc = -EINVAL; + } + + return rc; +} + static int mdss_dsi_ctrl_probe(struct platform_device *pdev) { int rc = 0; @@ -3099,6 +3118,12 @@ static int mdss_dsi_ctrl_probe(struct platform_device *pdev) INIT_DELAYED_WORK(&ctrl_pdata->dba_work, mdss_dsi_dba_work); + rc = mdss_dsi_ctrl_validate_config(ctrl_pdata); + if (rc) { + pr_err("%s: invalid controller configuration\n", __func__); + goto error_shadow_clk_deinit; + } + pr_info("%s: Dsi Ctrl->%d initialized, DSI rev:0x%x, PHY rev:0x%x\n", __func__, index, ctrl_pdata->shared_data->hw_rev, ctrl_pdata->shared_data->phy_rev); diff --git a/drivers/video/fbdev/msm/mdss_dsi.h b/drivers/video/fbdev/msm/mdss_dsi.h index 56e12dc5ca48..c91bc29c9bcc 100644 --- a/drivers/video/fbdev/msm/mdss_dsi.h +++ b/drivers/video/fbdev/msm/mdss_dsi.h @@ -57,6 +57,7 @@ #define MDSS_DSI_HW_REV_104 0x10040000 /* 8996 */ #define MDSS_DSI_HW_REV_104_1 0x10040001 /* 8996 */ #define MDSS_DSI_HW_REV_104_2 0x10040002 /* 8937 */ +#define MDSS_DSI_HW_REV_200 0x20000000 /* cobalt */ #define MDSS_DSI_HW_REV_STEP_0 0x0 #define MDSS_DSI_HW_REV_STEP_1 0x1 @@ -419,6 +420,7 @@ struct mdss_dsi_ctrl_pdata { struct clk *byte_clk_rcg; struct clk *pixel_clk_rcg; struct clk *vco_dummy_clk; + struct clk *byte_intf_clk; u8 ctrl_state; int panel_mode; int irq_cnt; diff --git a/drivers/video/fbdev/msm/mdss_dsi_clk.c b/drivers/video/fbdev/msm/mdss_dsi_clk.c index 727d6707444c..a43174d8ce84 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_clk.c +++ b/drivers/video/fbdev/msm/mdss_dsi_clk.c @@ -178,6 +178,21 @@ static int dsi_link_clk_set_rate(struct dsi_link_clks *l_clks) goto error; } + /* + * If byte_intf_clk is present, set rate for that too. + * For DPHY: + * byte_intf_clk_rate = byte_clk_rate / 2 + * todo: this needs to be revisited when support for CPHY is added + */ + if (l_clks->clks.byte_intf_clk) { + rc = clk_set_rate(l_clks->clks.byte_intf_clk, + l_clks->byte_clk_rate / 2); + if (rc) { + pr_err("set rate failed for byte intf clk rc=%d\n", rc); + goto error; + } + } + error: return rc; } @@ -204,8 +219,19 @@ static int dsi_link_clk_prepare(struct dsi_link_clks *l_clks) goto pixel_clk_err; } + if (l_clks->clks.byte_intf_clk) { + rc = clk_prepare(l_clks->clks.byte_intf_clk); + if (rc) { + pr_err("%s: Failed to prepare dsi byte_intf clk\n", + __func__); + goto byte_intf_clk_err; + } + } + return rc; +byte_intf_clk_err: + clk_unprepare(l_clks->clks.pixel_clk); pixel_clk_err: clk_unprepare(l_clks->clks.byte_clk); byte_clk_err: @@ -218,6 +244,8 @@ static int dsi_link_clk_unprepare(struct dsi_link_clks *l_clks) { int rc = 0; + if (l_clks->clks.byte_intf_clk) + clk_unprepare(l_clks->clks.byte_intf_clk); clk_unprepare(l_clks->clks.pixel_clk); clk_unprepare(l_clks->clks.byte_clk); clk_unprepare(l_clks->clks.esc_clk); @@ -247,8 +275,19 @@ static int dsi_link_clk_enable(struct dsi_link_clks *l_clks) goto pixel_clk_err; } + if (l_clks->clks.byte_intf_clk) { + rc = clk_enable(l_clks->clks.byte_intf_clk); + if (rc) { + pr_err("%s: Failed to enable dsi byte_intf clk\n", + __func__); + goto byte_intf_clk_err; + } + } + return rc; +byte_intf_clk_err: + clk_disable(l_clks->clks.pixel_clk); pixel_clk_err: clk_disable(l_clks->clks.byte_clk); byte_clk_err: @@ -261,6 +300,8 @@ static int dsi_link_clk_disable(struct dsi_link_clks *l_clks) { int rc = 0; + if (l_clks->clks.byte_intf_clk) + clk_disable(l_clks->clks.byte_intf_clk); clk_disable(l_clks->clks.esc_clk); clk_disable(l_clks->clks.pixel_clk); clk_disable(l_clks->clks.byte_clk); @@ -622,9 +663,27 @@ static int dsi_set_clk_rate(struct mdss_dsi_clk_mngr *mngr, int clk, u32 rate, mngr->link_clks.byte_clk_rate = rate; if (!flags) { rc = clk_set_rate(mngr->link_clks.clks.byte_clk, rate); - if (rc) + if (rc) { pr_err("set rate failed for byte clk rc=%d\n", rc); + goto error; + } + + /* + * If byte_intf_clk is present, set rate for that too. + * For DPHY: + * byte_intf_clk_rate = byte_clk_rate / 2 + * todo: this needs to be revisited when support for + * CPHY is added. + */ + if (mngr->link_clks.clks.byte_intf_clk) { + rc = clk_set_rate( + mngr->link_clks.clks.byte_intf_clk, + rate / 2); + if (rc) + pr_err("set rate failed for byte intf clk rc=%d\n", + rc); + } } break; case MDSS_DSI_LINK_PIX_CLK: @@ -642,6 +701,7 @@ static int dsi_set_clk_rate(struct mdss_dsi_clk_mngr *mngr, int clk, u32 rate, break; } +error: return rc; } diff --git a/drivers/video/fbdev/msm/mdss_dsi_clk.h b/drivers/video/fbdev/msm/mdss_dsi_clk.h index d42228b48171..f4d9c016e0c5 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_clk.h +++ b/drivers/video/fbdev/msm/mdss_dsi_clk.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -36,6 +36,7 @@ enum mdss_dsi_link_clk_type { MDSS_DSI_LINK_ESC_CLK, MDSS_DSI_LINK_BYTE_CLK, MDSS_DSI_LINK_PIX_CLK, + MDSS_DSI_LINK_BYTE_INTF_CLK, MDSS_DSI_LINK_CLK_MAX, }; @@ -105,6 +106,7 @@ struct mdss_dsi_link_clk_info { struct clk *esc_clk; struct clk *byte_clk; struct clk *pixel_clk; + struct clk *byte_intf_clk; }; struct dsi_panel_clk_ctrl { diff --git a/drivers/video/fbdev/msm/msm_mdss_io_8974.c b/drivers/video/fbdev/msm/msm_mdss_io_8974.c index 805f58d65e62..f14082968d84 100644 --- a/drivers/video/fbdev/msm/msm_mdss_io_8974.c +++ b/drivers/video/fbdev/msm/msm_mdss_io_8974.c @@ -1416,6 +1416,8 @@ error: void mdss_dsi_link_clk_deinit(struct device *dev, struct mdss_dsi_ctrl_pdata *ctrl) { + if (ctrl->byte_intf_clk) + devm_clk_put(dev, ctrl->byte_intf_clk); if (ctrl->vco_dummy_clk) devm_clk_put(dev, ctrl->vco_dummy_clk); if (ctrl->pixel_clk_rcg) @@ -1490,6 +1492,13 @@ int mdss_dsi_link_clk_init(struct platform_device *pdev, ctrl->vco_dummy_clk = NULL; } + ctrl->byte_intf_clk = devm_clk_get(dev, "byte_intf_clk"); + if (IS_ERR(ctrl->byte_intf_clk)) { + pr_debug("%s: can't find byte int clk. rc=%d\n", __func__, rc); + ctrl->byte_intf_clk = NULL; + } + + error: if (rc) mdss_dsi_link_clk_deinit(dev, ctrl); |