msm: mdss: dsi: enable idle power collapse without DSI ULPS

It is possible to power collaps MDSS without configuring the DSI
lanes in Ultra Low Power State (ULPS). Add support for this by
configuring DSI clamps irrespective of whether ULPS feature is
enabled or not.

Change-Id: I0564216737cc6e98c1e8658862cf7af5dabd363c
Signed-off-by: Aravind Venkateswaran <aravindh@codeaurora.org>
This commit is contained in:
Aravind Venkateswaran 2014-04-25 12:29:50 -07:00 committed by David Keitel
parent e2b32b069d
commit 7503cdffec
3 changed files with 402 additions and 249 deletions

View file

@ -430,7 +430,7 @@ static int mdss_dsi_off(struct mdss_panel_data *pdata)
return ret;
}
static void __mdss_dsi_ctrl_setup(struct mdss_panel_data *pdata)
void mdss_dsi_ctrl_setup(struct mdss_panel_data *pdata)
{
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
struct mdss_panel_info *pinfo;
@ -515,185 +515,16 @@ static void __mdss_dsi_ctrl_setup(struct mdss_panel_data *pdata)
}
}
int mdss_dsi_ulps_config(struct mdss_dsi_ctrl_pdata *ctrl_pdata, int enable)
void mdss_dsi_reset(struct mdss_dsi_ctrl_pdata *ctrl)
{
int ret = 0;
struct mdss_panel_data *pdata = NULL;
struct mdss_panel_info *pinfo;
struct mipi_panel_info *mipi;
u32 lane_status = 0, regval;
u32 active_lanes = 0, clamp_reg;
u32 clamp_reg_off, phyrst_reg_off;
struct mdss_panel_data *pdata = &ctrl->panel_data;
if (!ctrl_pdata) {
pr_err("%s: invalid input\n", __func__);
return -EINVAL;
}
pr_debug("%s: called for ctrl%d\n", __func__, ctrl->ndx);
if (&ctrl_pdata->mmss_misc_io == NULL) {
pr_err("%s: mmss_misc_io is NULL. ULPS not valid\n", __func__);
return -EINVAL;
}
pdata = &ctrl_pdata->panel_data;
if (!pdata) {
pr_err("%s: Invalid panel data\n", __func__);
return -EINVAL;
}
pinfo = &pdata->panel_info;
mipi = &pinfo->mipi;
clamp_reg_off = ctrl_pdata->ulps_clamp_ctrl_off;
phyrst_reg_off = ctrl_pdata->ulps_phyrst_ctrl_off;
if (!mdss_dsi_ulps_feature_enabled(pdata)) {
pr_debug("%s: ULPS feature not supported. enable=%d\n",
__func__, enable);
return -ENOTSUPP;
}
/*
* No need to enter ULPS when transitioning from splash screen to
* boot animation since it is expected that the clocks would be turned
* right back on.
*/
if (pinfo->cont_splash_enabled) {
pr_debug("%s: skip ULPS config with splash screen enabled\n",
__func__);
return 0;
}
/* clock lane will always be programmed for ulps and will be clamped */
active_lanes = BIT(4);
clamp_reg = BIT(8) | BIT(9);
/*
* make a note of all active data lanes for which ulps entry/exit
* as well as DSI clamps are needed
*/
if (mipi->data_lane0) {
active_lanes |= BIT(0);
clamp_reg |= (BIT(0) | BIT(1));
}
if (mipi->data_lane1) {
active_lanes |= BIT(1);
clamp_reg |= (BIT(2) | BIT(3));
}
if (mipi->data_lane2) {
active_lanes |= BIT(2);
clamp_reg |= (BIT(4) | BIT(5));
}
if (mipi->data_lane3) {
active_lanes |= BIT(3);
clamp_reg |= (BIT(6) | BIT(7));
}
pr_debug("%s: configuring ulps (%s) for ctrl%d, active lanes=0x%08x\n",
__func__, (enable ? "on" : "off"), ctrl_pdata->ndx,
active_lanes);
if (enable && !ctrl_pdata->ulps) {
/*
* ULPS Entry Request.
* Wait for a short duration to ensure that the lanes
* enter ULP state.
*/
MIPI_OUTP(ctrl_pdata->ctrl_base + 0x0AC, active_lanes);
usleep(100);
/* Check to make sure that all active data lanes are in ULPS */
lane_status = MIPI_INP(ctrl_pdata->ctrl_base + 0xA8);
if (lane_status & (active_lanes << 8)) {
pr_err("%s: ULPS entry req failed for ctrl%d. Lane status=0x%08x\n",
__func__, ctrl_pdata->ndx, lane_status);
ret = -EINVAL;
goto error;
}
/* Enable MMSS DSI Clamps */
if (ctrl_pdata->ndx == DSI_CTRL_0) {
regval = MIPI_INP(ctrl_pdata->mmss_misc_io.base +
clamp_reg_off);
MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + clamp_reg_off,
regval | clamp_reg);
MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + clamp_reg_off,
regval | (clamp_reg | BIT(15)));
} else if (ctrl_pdata->ndx == DSI_CTRL_1) {
regval = MIPI_INP(ctrl_pdata->mmss_misc_io.base +
clamp_reg_off);
MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + clamp_reg_off,
regval | (clamp_reg << 16));
MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + clamp_reg_off,
regval | ((clamp_reg << 16) | BIT(31)));
}
wmb();
/*
* This register write ensures that DSI PHY will not be
* reset when mdss ahb clock reset is asserted while coming
* out of power collapse
*/
MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + phyrst_reg_off, 0x1);
ctrl_pdata->ulps = true;
} else if (ctrl_pdata->ulps) {
MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + phyrst_reg_off, 0x0);
if (ctrl_pdata->ctrl_rev == MDSS_DSI_HW_REV_103)
mdss_dsi_20nm_phy_init(pdata);
else
mdss_dsi_phy_init(pdata);
__mdss_dsi_ctrl_setup(pdata);
mdss_dsi_sw_reset(pdata);
mdss_dsi_host_init(pdata);
mdss_dsi_op_mode_config(pdata->panel_info.mipi.mode,
pdata);
/*
* ULPS Entry Request. This is needed because, after power
* collapse and reset, the DSI controller resets back to
* idle state and not ULPS.
* Wait for a short duration to ensure that the lanes
* enter ULP state.
*/
MIPI_OUTP(ctrl_pdata->ctrl_base + 0x0AC, active_lanes);
usleep(100);
/* Disable MMSS DSI Clamps */
if (ctrl_pdata->ndx == DSI_CTRL_0) {
regval = MIPI_INP(ctrl_pdata->mmss_misc_io.base +
clamp_reg_off);
MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + clamp_reg_off,
regval & ~(clamp_reg | BIT(15)));
} else if (ctrl_pdata->ndx == DSI_CTRL_1) {
regval = MIPI_INP(ctrl_pdata->mmss_misc_io.base +
clamp_reg_off);
MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + clamp_reg_off,
regval & ~((clamp_reg << 16) | BIT(31)));
}
/*
* ULPS Exit Request
* Hardware requirement is to wait for at least 1ms
*/
MIPI_OUTP(ctrl_pdata->ctrl_base + 0x0AC, active_lanes << 8);
usleep(1000);
MIPI_OUTP(ctrl_pdata->ctrl_base + 0x0AC, 0x0);
/*
* Wait for a short duration before enabling
* data transmission
*/
usleep(100);
lane_status = MIPI_INP(ctrl_pdata->ctrl_base + 0xA8);
ctrl_pdata->ulps = false;
}
pr_debug("%s: DSI lane status = 0x%08x. Ulps %s\n", __func__,
lane_status, enable ? "enabled" : "disabled");
error:
return ret;
/* DSI controller reset and init */
mdss_dsi_sw_reset(pdata);
mdss_dsi_host_init(pdata);
mdss_dsi_op_mode_config(pdata->panel_info.mipi.mode, pdata);
}
static int mdss_dsi_update_panel_config(struct mdss_dsi_ctrl_pdata *ctrl_pdata,
@ -754,36 +585,13 @@ int mdss_dsi_on(struct mdss_panel_data *pdata)
return ret;
}
mdss_dsi_clk_ctrl(ctrl_pdata, DSI_BUS_CLKS, 1);
if (ret) {
pr_err("%s: failed to enable bus clocks. rc=%d\n", __func__,
ret);
ret = mdss_dsi_panel_power_on(pdata, 0);
if (ret) {
pr_err("%s: Panel reset failed. rc=%d\n",
__func__, ret);
return ret;
}
pdata->panel_info.panel_power_on = 0;
return ret;
}
pdata->panel_info.panel_power_on = 1;
ctrl_pdata->ctrl_rev = MIPI_INP(ctrl_pdata->ctrl_base);
mdss_dsi_phy_sw_reset((ctrl_pdata->ctrl_base));
if (ctrl_pdata->ctrl_rev == MDSS_DSI_HW_REV_103)
mdss_dsi_20nm_phy_init(pdata);
else
mdss_dsi_phy_init(pdata);
mdss_dsi_clk_ctrl(ctrl_pdata, DSI_BUS_CLKS, 0);
/*
* Enable DSI clocks.
* This is also enable the DSI core power block and reset/setup
* DSI phy
*/
mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1);
__mdss_dsi_ctrl_setup(pdata);
mdss_dsi_sw_reset(pdata);
mdss_dsi_host_init(pdata);
pdata->panel_info.panel_power_on = 1;
/*
* Issue hardware reset line after enabling the DSI clocks and data
@ -992,9 +800,7 @@ int mdss_dsi_cont_splash_on(struct mdss_panel_data *pdata)
WARN((ctrl_pdata->ctrl_state & CTRL_STATE_PANEL_INIT),
"Incorrect Ctrl state=0x%x\n", ctrl_pdata->ctrl_state);
mdss_dsi_sw_reset(pdata);
mdss_dsi_host_init(pdata);
mdss_dsi_op_mode_config(mipi->mode, pdata);
mdss_dsi_reset(ctrl_pdata);
pr_debug("%s-:End\n", __func__);
return ret;
}

View file

@ -336,9 +336,11 @@ struct mdss_dsi_ctrl_pdata {
struct mutex mutex;
struct mutex cmd_mutex;
bool ulps;
u32 ulps_clamp_ctrl_off;
u32 ulps_phyrst_ctrl_off;
bool ulps;
bool core_power;
bool mmss_clamp;
struct dsi_buf tx_buf;
struct dsi_buf rx_buf;
@ -410,7 +412,8 @@ void mdss_dsi_cmdlist_kickoff(int intf);
int mdss_dsi_bta_status_check(struct mdss_dsi_ctrl_pdata *ctrl);
int mdss_dsi_reg_status_check(struct mdss_dsi_ctrl_pdata *ctrl);
bool __mdss_dsi_clk_enabled(struct mdss_dsi_ctrl_pdata *ctrl, u8 clk_type);
int mdss_dsi_ulps_config(struct mdss_dsi_ctrl_pdata *ctrl, int enable);
void mdss_dsi_reset(struct mdss_dsi_ctrl_pdata *ctrl);
void mdss_dsi_ctrl_setup(struct mdss_panel_data *pdata);
int mdss_dsi_panel_init(struct device_node *node,
struct mdss_dsi_ctrl_pdata *ctrl_pdata,

View file

@ -484,6 +484,366 @@ static void mdss_dsi_link_clk_stop(struct mdss_dsi_ctrl_pdata *ctrl)
mdss_dsi_link_clk_unprepare(ctrl);
}
/**
* mdss_dsi_ulps_config() - Program DSI lanes to enter/exit ULPS mode
* @ctrl: pointer to DSI controller structure
* @enable: 1 to enter ULPS, 0 to exit ULPS
*
* This function executes the necessary programming sequence to enter/exit
* DSI Ultra-Low Power State (ULPS). This function assumes that the link and
* bus clocks are already on.
*/
static int mdss_dsi_ulps_config(struct mdss_dsi_ctrl_pdata *ctrl,
int enable)
{
int ret = 0;
struct mdss_panel_data *pdata = NULL;
struct mdss_panel_info *pinfo;
struct mipi_panel_info *mipi;
u32 lane_status = 0;
u32 active_lanes = 0;
if (!ctrl) {
pr_err("%s: invalid input\n", __func__);
return -EINVAL;
}
pdata = &ctrl->panel_data;
if (!pdata) {
pr_err("%s: Invalid panel data\n", __func__);
return -EINVAL;
}
pinfo = &pdata->panel_info;
mipi = &pinfo->mipi;
if (!mdss_dsi_ulps_feature_enabled(pdata)) {
pr_debug("%s: ULPS feature not supported. enable=%d\n",
__func__, enable);
return -ENOTSUPP;
}
/*
* No need to enter ULPS when transitioning from splash screen to
* boot animation since it is expected that the clocks would be turned
* right back on.
*/
if (pinfo->cont_splash_enabled) {
pr_debug("%s: skip ULPS config with splash screen enabled\n",
__func__);
return 0;
}
/* clock lane will always be programmed for ulps */
active_lanes = BIT(4);
/*
* make a note of all active data lanes for which ulps entry/exit
* is needed
*/
if (mipi->data_lane0)
active_lanes |= BIT(0);
if (mipi->data_lane1)
active_lanes |= BIT(1);
if (mipi->data_lane2)
active_lanes |= BIT(2);
if (mipi->data_lane3)
active_lanes |= BIT(3);
pr_debug("%s: configuring ulps (%s) for ctrl%d, active lanes=0x%08x\n",
__func__, (enable ? "on" : "off"), ctrl->ndx,
active_lanes);
if (enable && !ctrl->ulps) {
/*
* ULPS Entry Request.
* Wait for a short duration to ensure that the lanes
* enter ULP state.
*/
MIPI_OUTP(ctrl->ctrl_base + 0x0AC, active_lanes);
usleep(100);
/* Check to make sure that all active data lanes are in ULPS */
lane_status = MIPI_INP(ctrl->ctrl_base + 0xA8);
if (lane_status & (active_lanes << 8)) {
pr_err("%s: ULPS entry req failed for ctrl%d. Lane status=0x%08x\n",
__func__, ctrl->ndx, lane_status);
ret = -EINVAL;
goto error;
}
ctrl->ulps = true;
} else if (!enable && ctrl->ulps) {
/*
* ULPS Exit Request
* Hardware requirement is to wait for at least 1ms
*/
MIPI_OUTP(ctrl->ctrl_base + 0x0AC, active_lanes << 8);
usleep(1000);
MIPI_OUTP(ctrl->ctrl_base + 0x0AC, 0x0);
/*
* Wait for a short duration before enabling
* data transmission
*/
usleep(100);
lane_status = MIPI_INP(ctrl->ctrl_base + 0xA8);
ctrl->ulps = false;
} else {
pr_debug("%s: No change requested: %s -> %s\n", __func__,
ctrl->ulps ? "enabled" : "disabled",
enable ? "enabled" : "disabled");
}
pr_debug("%s: DSI lane status = 0x%08x. Ulps %s\n", __func__,
lane_status, enable ? "enabled" : "disabled");
error:
return ret;
}
/**
* mdss_dsi_clamp_ctrl() - Program DSI clamps for supporting power collapse
* @ctrl: pointer to DSI controller structure
* @enable: 1 to enable clamps, 0 to disable clamps
*
* For idle-screen usecases with command mode panels, MDSS can be power
* collapsed. However, DSI phy needs to remain on. To avoid any mismatch
* between the DSI controller state, DSI phy needs to be clamped before
* power collapsing. This function executes the required programming
* sequence to configure these DSI clamps. This function should only be called
* when the DSI link clocks are disabled.
*/
static int mdss_dsi_clamp_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable)
{
struct mipi_panel_info *mipi = NULL;
u32 clamp_reg, regval = 0;
u32 clamp_reg_off, phyrst_reg_off;
if (!ctrl) {
pr_err("%s: invalid input\n", __func__);
return -EINVAL;
}
if (!ctrl->mmss_misc_io.base) {
pr_err("%s: mmss_misc_io not mapped\nn", __func__);
return -EINVAL;
}
clamp_reg_off = ctrl->ulps_clamp_ctrl_off;
phyrst_reg_off = ctrl->ulps_phyrst_ctrl_off;
mipi = &ctrl->panel_data.panel_info.mipi;
/* clock lane will always be clamped */
clamp_reg = BIT(9);
if (ctrl->ulps)
clamp_reg |= BIT(8);
/* make a note of all active data lanes which need to be clamped */
if (mipi->data_lane0) {
clamp_reg |= BIT(7);
if (ctrl->ulps)
clamp_reg |= BIT(6);
}
if (mipi->data_lane1) {
clamp_reg |= BIT(5);
if (ctrl->ulps)
clamp_reg |= BIT(4);
}
if (mipi->data_lane2) {
clamp_reg |= BIT(3);
if (ctrl->ulps)
clamp_reg |= BIT(2);
}
if (mipi->data_lane3) {
clamp_reg |= BIT(1);
if (ctrl->ulps)
clamp_reg |= BIT(0);
}
pr_debug("%s: called for ctrl%d, enable=%d, clamp_reg=0x%08x\n",
__func__, ctrl->ndx, enable, clamp_reg);
if (enable && !ctrl->mmss_clamp) {
/* Enable MMSS DSI Clamps */
if (ctrl->ndx == DSI_CTRL_0) {
regval = MIPI_INP(ctrl->mmss_misc_io.base +
clamp_reg_off);
MIPI_OUTP(ctrl->mmss_misc_io.base + clamp_reg_off,
regval | clamp_reg);
MIPI_OUTP(ctrl->mmss_misc_io.base + clamp_reg_off,
regval | (clamp_reg | BIT(15)));
} else if (ctrl->ndx == DSI_CTRL_1) {
regval = MIPI_INP(ctrl->mmss_misc_io.base +
clamp_reg_off);
MIPI_OUTP(ctrl->mmss_misc_io.base + clamp_reg_off,
regval | (clamp_reg << 16));
MIPI_OUTP(ctrl->mmss_misc_io.base + clamp_reg_off,
regval | ((clamp_reg << 16) | BIT(31)));
}
/*
* This register write ensures that DSI PHY will not be
* reset when mdss ahb clock reset is asserted while coming
* out of power collapse
*/
MIPI_OUTP(ctrl->mmss_misc_io.base + phyrst_reg_off, 0x1);
ctrl->mmss_clamp = true;
} else if (!enable && ctrl->mmss_clamp) {
MIPI_OUTP(ctrl->mmss_misc_io.base + phyrst_reg_off, 0x0);
/* Disable MMSS DSI Clamps */
if (ctrl->ndx == DSI_CTRL_0) {
regval = MIPI_INP(ctrl->mmss_misc_io.base +
clamp_reg_off);
MIPI_OUTP(ctrl->mmss_misc_io.base + clamp_reg_off,
regval & ~(clamp_reg | BIT(15)));
} else if (ctrl->ndx == DSI_CTRL_1) {
regval = MIPI_INP(ctrl->mmss_misc_io.base +
clamp_reg_off);
MIPI_OUTP(ctrl->mmss_misc_io.base + clamp_reg_off,
regval & ~((clamp_reg << 16) | BIT(31)));
}
ctrl->mmss_clamp = false;
} else {
pr_debug("%s: No change requested: %s -> %s\n", __func__,
ctrl->mmss_clamp ? "enabled" : "disabled",
enable ? "enabled" : "disabled");
}
return 0;
}
/**
* mdss_dsi_core_power_ctrl() - Enable/disable DSI core power
* @ctrl: pointer to DSI controller structure
* @enable: 1 to enable power, 0 to disable power
*
* When all DSI bus clocks are disabled, DSI core power module can be turned
* off to save any leakage current. This function implements the necessary
* programming sequence for the same. For command mode panels, the core power
* can be turned off for idle-screen usecases, where additional programming is
* needed to clamp DSI phy.
*/
static int mdss_dsi_core_power_ctrl(struct mdss_dsi_ctrl_pdata *ctrl,
int enable)
{
int rc = 0;
struct mdss_panel_data *pdata = NULL;
if (!ctrl) {
pr_err("%s: invalid input\n", __func__);
return -EINVAL;
}
pdata = &ctrl->panel_data;
if (!pdata) {
pr_err("%s: Invalid panel data\n", __func__);
return -EINVAL;
}
if (enable) {
if (!ctrl->core_power) {
/* enable mdss gdsc */
pr_debug("%s: Enable MDP FS\n", __func__);
rc = msm_dss_enable_vreg(
ctrl->power_data[DSI_CORE_PM].vreg_config,
ctrl->power_data[DSI_CORE_PM].num_vreg, 1);
if (rc) {
pr_err("%s: failed to enable vregs for %s\n",
__func__,
__mdss_dsi_pm_name(DSI_CORE_PM));
goto error;
}
ctrl->core_power = true;
}
rc = mdss_dsi_bus_clk_start(ctrl);
if (rc) {
pr_err("%s: Failed to start bus clocks. rc=%d\n",
__func__, rc);
goto error_bus_clk_start;
}
/*
* Phy software reset should not be done for idle screen power
* collapse use-case. Issue a phy software reset only when
* unblanking the panel.
*/
if (!pdata->panel_info.panel_power_on)
mdss_dsi_phy_sw_reset(ctrl->ctrl_base);
mdss_dsi_phy_init(pdata);
mdss_dsi_ctrl_setup(pdata);
if (ctrl->ulps) {
/*
* ULPS Entry Request. This is needed if the lanes were
* in ULPS prior to power collapse, since after
* power collapse and reset, the DSI controller resets
* back to idle state and not ULPS. This ulps entry
* request will transition the state of the DSI
* controller to ULPS which will match the state of the
* DSI phy. This needs to be done prior to disabling
* the DSI clamps.
*/
rc = mdss_dsi_ulps_config(ctrl, 1);
if (rc) {
pr_err("%s: Failed to enter ULPS. rc=%d\n",
__func__, rc);
goto error_ulps;
}
}
rc = mdss_dsi_clamp_ctrl(ctrl, 0);
if (rc) {
pr_err("%s: Failed to disable dsi clamps. rc=%d\n",
__func__, rc);
goto error_ulps;
}
} else {
/* Enable DSI clamps only if entering idle power collapse */
if (ctrl->panel_data.panel_info.panel_power_on) {
rc = mdss_dsi_clamp_ctrl(ctrl, 1);
if (rc)
pr_err("%s: Failed to enable dsi clamps. rc=%d\n",
__func__, rc);
}
/*
* disable bus clocks irrespective of whether dsi phy was
* successfully clamped or not
*/
mdss_dsi_bus_clk_stop(ctrl);
/* disable mdss gdsc only if dsi phy was successfully clamped*/
if (rc) {
pr_debug("%s: leaving mdss gdsc on\n", __func__);
} else {
pr_debug("%s: Disable MDP FS\n", __func__);
rc = msm_dss_enable_vreg(
ctrl->power_data[DSI_CORE_PM].vreg_config,
ctrl->power_data[DSI_CORE_PM].num_vreg, 0);
if (rc) {
pr_warn("%s: failed to disable vregs for %s\n",
__func__,
__mdss_dsi_pm_name(DSI_CORE_PM));
rc = 0;
} else {
ctrl->core_power = false;
}
}
}
return rc;
error_ulps:
mdss_dsi_bus_clk_stop(ctrl);
error_bus_clk_start:
if (msm_dss_enable_vreg(ctrl->power_data[DSI_CORE_PM].vreg_config,
ctrl->power_data[DSI_CORE_PM].num_vreg, 0))
pr_warn("%s: failed to disable vregs for %s\n",
__func__, __mdss_dsi_pm_name(DSI_CORE_PM));
else
ctrl->core_power = false;
error:
return rc;
}
static int __mdss_dsi_update_clk_cnt(u32 *clk_cnt, int enable)
{
int changed = 0;
@ -510,6 +870,7 @@ static int mdss_dsi_clk_ctrl_sub(struct mdss_dsi_ctrl_pdata *ctrl,
{
int rc = 0;
struct mdss_panel_data *pdata;
bool core_power_enabled = false;
if (!ctrl) {
pr_err("%s: Invalid arg\n", __func__);
@ -523,41 +884,37 @@ static int mdss_dsi_clk_ctrl_sub(struct mdss_dsi_ctrl_pdata *ctrl,
if (enable) {
if (clk_type & DSI_BUS_CLKS) {
/* enable mdss gdsc */
pr_debug("%s: Enable MDP FS\n", __func__);
rc = msm_dss_enable_vreg(
ctrl->power_data[DSI_CORE_PM].vreg_config,
ctrl->power_data[DSI_CORE_PM].num_vreg, 1);
rc = mdss_dsi_core_power_ctrl(ctrl, enable);
if (rc) {
pr_err("%s: failed to enable vregs for %s\n",
__func__,
__mdss_dsi_pm_name(DSI_CORE_PM));
pr_err("%s: Failed to enable core power. rc=%d\n",
__func__, rc);
goto error;
}
rc = mdss_dsi_bus_clk_start(ctrl);
if (rc) {
pr_err("Failed to start bus clocks. rc=%d\n",
rc);
goto error_vreg;
}
core_power_enabled = true;
}
if (clk_type & DSI_LINK_CLKS) {
rc = mdss_dsi_link_clk_start(ctrl);
if (rc) {
pr_err("Failed to start link clocks. rc=%d\n",
rc);
pr_err("%s: Failed to start link clocks. rc=%d\n",
__func__, rc);
goto error_link_clk_start;
}
/* Disable ULPS, if enabled */
if (ctrl->ulps) {
rc = mdss_dsi_ulps_config(ctrl, 0);
if (rc) {
pr_err("Failed to exit ulps. rc=%d\n",
rc);
pr_err("%s: Failed to exit ulps. rc=%d\n",
__func__, rc);
goto error_ulps_exit;
}
}
/*
* If we are coming out of idle power collapse, then
* reset DSI controller state
*/
if (core_power_enabled)
mdss_dsi_reset(ctrl);
}
} else {
if (clk_type & DSI_LINK_CLKS) {
@ -572,18 +929,10 @@ static int mdss_dsi_clk_ctrl_sub(struct mdss_dsi_ctrl_pdata *ctrl,
mdss_dsi_link_clk_stop(ctrl);
}
if (clk_type & DSI_BUS_CLKS) {
mdss_dsi_bus_clk_stop(ctrl);
/* disable mdss gdsc */
pr_debug("%s: Disable MDP FS\n", __func__);
rc = msm_dss_enable_vreg(
ctrl->power_data[DSI_CORE_PM].vreg_config,
ctrl->power_data[DSI_CORE_PM].num_vreg, 0);
rc = mdss_dsi_core_power_ctrl(ctrl, enable);
if (rc) {
pr_warn("%s: failed to disable vregs for %s\n",
__func__,
__mdss_dsi_pm_name(DSI_CORE_PM));
rc = 0;
pr_err("%s: Failed to disable core power. rc=%d\n",
__func__, rc);
}
}
}
@ -593,15 +942,10 @@ static int mdss_dsi_clk_ctrl_sub(struct mdss_dsi_ctrl_pdata *ctrl,
error_ulps_exit:
mdss_dsi_link_clk_stop(ctrl);
error_link_clk_start:
if (clk_type & DSI_BUS_CLKS)
mdss_dsi_bus_clk_stop(ctrl);
error_vreg:
if ((clk_type & DSI_BUS_CLKS) &&
(msm_dss_enable_vreg(ctrl->power_data[DSI_CORE_PM].vreg_config,
ctrl->power_data[DSI_CORE_PM].num_vreg, 0))) {
pr_warn("%s: failed to disable vregs for %s\n", __func__,
__mdss_dsi_pm_name(DSI_CORE_PM));
}
(mdss_dsi_core_power_ctrl(ctrl, !enable)))
pr_warn("%s: Failed to disable core power. rc=%d\n",
__func__, rc);
error:
return rc;
}