msm: mdss: add support for dsi byte interface clock
DSI controller version 2.0 and above require configuring an additional link clock called the byte interface clock which is used to drive all high-speed PPI signals. Add support to configure this clock. CRs-Fixed: 1000724 Change-Id: I907823b21ad2c6152899233fc52f38d17bcc5ed1 Signed-off-by: Aravind Venkateswaran <aravindh@codeaurora.org>
This commit is contained in:
parent
d5faefb415
commit
37b3e8da8b
5 changed files with 100 additions and 2 deletions
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue