Loading drivers/video/msm/mdss/mdss_dsi.c +6 −0 Original line number Diff line number Diff line Loading @@ -2892,6 +2892,12 @@ static int mdss_dsi_cont_splash_config(struct mdss_panel_info *pinfo, mdss_dsi_panel_pwm_enable(ctrl_pdata); ctrl_pdata->ctrl_state |= (CTRL_STATE_PANEL_INIT | CTRL_STATE_MDP_ACTIVE | CTRL_STATE_DSI_ACTIVE); /* * MDP client removes this extra vote during splash reconfigure * for command mode panel from interface. DSI removes the vote * during suspend-resume for video mode panel. */ if (ctrl_pdata->panel_data.panel_info.type == MIPI_CMD_PANEL) clk_handle = ctrl_pdata->mdp_clk_handle; else Loading drivers/video/msm/mdss/mdss_dsi.h +2 −1 Original line number Diff line number Diff line Loading @@ -523,7 +523,8 @@ struct mdss_dsi_ctrl_pdata { void *clk_mngr; void *dsi_clk_handle; void *mdp_clk_handle; int m_vote_cnt; int m_dsi_vote_cnt; int m_mdp_vote_cnt; /* debugfs structure */ struct mdss_dsi_debugfs_info *debugfs_info; Loading drivers/video/msm/mdss/mdss_dsi_clk.c +25 −3 Original line number Diff line number Diff line Loading @@ -722,8 +722,30 @@ error: return rc; } bool is_dsi_clk_in_ecg_state(void *client) { struct mdss_dsi_clk_client_info *c = client; struct mdss_dsi_clk_mngr *mngr; bool is_ecg = false; if (!client) { pr_err("Invalid client params\n"); goto end; } mngr = c->mngr; mutex_lock(&mngr->clk_mutex); is_ecg = (c->core_clk_state == MDSS_DSI_CLK_EARLY_GATE); mutex_unlock(&mngr->clk_mutex); end: return is_ecg; } int mdss_dsi_clk_req_state(void *client, enum mdss_dsi_clk_type clk, enum mdss_dsi_clk_state state) enum mdss_dsi_clk_state state, u32 index) { int rc = 0; struct mdss_dsi_clk_client_info *c = client; Loading @@ -744,7 +766,7 @@ int mdss_dsi_clk_req_state(void *client, enum mdss_dsi_clk_type clk, c->name, mngr->name, clk, state, c->core_clk_state, c->link_clk_state); MDSS_XLOG(clk, state, c->core_clk_state, c->link_clk_state); MDSS_XLOG(index, clk, state, c->core_clk_state, c->link_clk_state); /* * Refcount handling rules: * 1. Increment refcount whenever ON is called Loading Loading @@ -810,7 +832,7 @@ int mdss_dsi_clk_req_state(void *client, enum mdss_dsi_clk_type clk, pr_debug("[%s]%s: change=%d, Core (ref=%d, state=%d), Link (ref=%d, state=%d)\n", c->name, mngr->name, changed, c->core_refcount, c->core_clk_state, c->link_refcount, c->link_clk_state); MDSS_XLOG(clk, state, c->core_clk_state, c->link_clk_state); MDSS_XLOG(index, clk, state, c->core_clk_state, c->link_clk_state); if (changed) { rc = dsi_recheck_clk_state(mngr); Loading drivers/video/msm/mdss/mdss_dsi_clk.h +15 −2 Original line number Diff line number Diff line /* Copyright (c) 2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-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 Loading Loading @@ -194,6 +194,7 @@ int mdss_dsi_clk_deregister(void *client); * @client: client handle. * @clk: Type of clock requested (enum mdss_dsi_clk_type). * @state: clock state requested. * @index: controller index. * * This routine is used to request a new clock state for a specific clock. If * turning ON the clocks, this guarantees that clocks will be on before Loading @@ -203,7 +204,7 @@ int mdss_dsi_clk_deregister(void *client); * @return: error code. */ int mdss_dsi_clk_req_state(void *client, enum mdss_dsi_clk_type clk, enum mdss_dsi_clk_state state); enum mdss_dsi_clk_state state, u32 index); /** * mdss_dsi_clk_set_link_rate() - set clock rate for link clocks Loading Loading @@ -235,4 +236,16 @@ int mdss_dsi_clk_set_link_rate(void *client, enum mdss_dsi_link_clk_type clk, * @return:error code. */ int mdss_dsi_clk_force_toggle(void *client, u32 clk); /** * is_dsi_clk_in_ecg_state() - Checks the current state of clocks * @client: client handle. * * This routine returns checks the clocks status for client and return * success code based on it. * * @return:true: if clocks are in ECG state * false: for all other cases */ bool is_dsi_clk_in_ecg_state(void *client); #endif /* _MDSS_DSI_CLK_H_ */ drivers/video/msm/mdss/msm_mdss_io_8974.c +37 −15 Original line number Diff line number Diff line Loading @@ -1945,7 +1945,11 @@ int mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, void *clk_handle, { int rc = 0; struct mdss_dsi_ctrl_pdata *mctrl = NULL; int i; int i, *vote_cnt; void *m_clk_handle; bool is_ecg = false; int state = MDSS_DSI_CLK_OFF; if (!ctrl) { pr_err("%s: Invalid arg\n", __func__); Loading Loading @@ -1976,6 +1980,18 @@ int mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, void *clk_handle, __func__); } /* * it should add and remove extra votes based on voting clients to avoid * removal of legitimate vote from DSI client. */ if (mctrl && (clk_handle == ctrl->dsi_clk_handle)) { m_clk_handle = mctrl->dsi_clk_handle; vote_cnt = &mctrl->m_dsi_vote_cnt; } else if (mctrl) { m_clk_handle = mctrl->mdp_clk_handle; vote_cnt = &mctrl->m_mdp_vote_cnt; } /* * When DSI is used in split mode, the link clock for master controller * has to be turned on first before the link clock for slave can be Loading @@ -1988,18 +2004,24 @@ int mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, void *clk_handle, __func__, ctrl->ndx, clk_type, clk_state, __builtin_return_address(0), mctrl ? 1 : 0); if (mctrl && (clk_type & MDSS_DSI_LINK_CLK)) { rc = mdss_dsi_clk_req_state(mctrl->dsi_clk_handle, MDSS_DSI_ALL_CLKS, MDSS_DSI_CLK_ON); if (clk_state != MDSS_DSI_CLK_ON) { /* preserve clk state; do not turn off forcefully */ is_ecg = is_dsi_clk_in_ecg_state(m_clk_handle); if (is_ecg) state = MDSS_DSI_CLK_EARLY_GATE; } rc = mdss_dsi_clk_req_state(m_clk_handle, MDSS_DSI_ALL_CLKS, MDSS_DSI_CLK_ON, mctrl->ndx); if (rc) { pr_err("%s: failed to turn on mctrl clocks, rc=%d\n", __func__, rc); goto error; } ctrl->m_vote_cnt++; (*vote_cnt)++; } rc = mdss_dsi_clk_req_state(clk_handle, clk_type, clk_state); rc = mdss_dsi_clk_req_state(clk_handle, clk_type, clk_state, ctrl->ndx); if (rc) { pr_err("%s: failed set clk state, rc = %d\n", __func__, rc); goto error; Loading Loading @@ -2028,24 +2050,24 @@ int mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, void *clk_handle, * for ON, since the previous ECG state must have * removed two votes to let clocks turn off. * * To satisfy the above requirement, m_vote_cnt keeps track of * To satisfy the above requirement, vote_cnt keeps track of * the number of ON votes for master requested by slave. For * every OFF/ECG state request, Either 2 or m_vote_cnt number of * every OFF/ECG state request, Either 2 or vote_cnt number of * votes are removed depending on which is lower. */ for (i = 0; (i < ctrl->m_vote_cnt && i < 2); i++) { rc = mdss_dsi_clk_req_state(mctrl->dsi_clk_handle, MDSS_DSI_ALL_CLKS, MDSS_DSI_CLK_OFF); for (i = 0; (i < *vote_cnt && i < 2); i++) { rc = mdss_dsi_clk_req_state(m_clk_handle, MDSS_DSI_ALL_CLKS, state, mctrl->ndx); if (rc) { pr_err("%s: failed to set mctrl clk state, rc = %d\n", __func__, rc); goto error; } } ctrl->m_vote_cnt -= i; pr_debug("%s: ctrl=%d, m_vote_cnt=%d\n", __func__, ctrl->ndx, ctrl->m_vote_cnt); (*vote_cnt) -= i; pr_debug("%s: ctrl=%d, vote_cnt=%d dsi_vote_cnt=%d mdp_vote_cnt:%d\n", __func__, ctrl->ndx, *vote_cnt, mctrl->m_dsi_vote_cnt, mctrl->m_mdp_vote_cnt); } error: Loading Loading
drivers/video/msm/mdss/mdss_dsi.c +6 −0 Original line number Diff line number Diff line Loading @@ -2892,6 +2892,12 @@ static int mdss_dsi_cont_splash_config(struct mdss_panel_info *pinfo, mdss_dsi_panel_pwm_enable(ctrl_pdata); ctrl_pdata->ctrl_state |= (CTRL_STATE_PANEL_INIT | CTRL_STATE_MDP_ACTIVE | CTRL_STATE_DSI_ACTIVE); /* * MDP client removes this extra vote during splash reconfigure * for command mode panel from interface. DSI removes the vote * during suspend-resume for video mode panel. */ if (ctrl_pdata->panel_data.panel_info.type == MIPI_CMD_PANEL) clk_handle = ctrl_pdata->mdp_clk_handle; else Loading
drivers/video/msm/mdss/mdss_dsi.h +2 −1 Original line number Diff line number Diff line Loading @@ -523,7 +523,8 @@ struct mdss_dsi_ctrl_pdata { void *clk_mngr; void *dsi_clk_handle; void *mdp_clk_handle; int m_vote_cnt; int m_dsi_vote_cnt; int m_mdp_vote_cnt; /* debugfs structure */ struct mdss_dsi_debugfs_info *debugfs_info; Loading
drivers/video/msm/mdss/mdss_dsi_clk.c +25 −3 Original line number Diff line number Diff line Loading @@ -722,8 +722,30 @@ error: return rc; } bool is_dsi_clk_in_ecg_state(void *client) { struct mdss_dsi_clk_client_info *c = client; struct mdss_dsi_clk_mngr *mngr; bool is_ecg = false; if (!client) { pr_err("Invalid client params\n"); goto end; } mngr = c->mngr; mutex_lock(&mngr->clk_mutex); is_ecg = (c->core_clk_state == MDSS_DSI_CLK_EARLY_GATE); mutex_unlock(&mngr->clk_mutex); end: return is_ecg; } int mdss_dsi_clk_req_state(void *client, enum mdss_dsi_clk_type clk, enum mdss_dsi_clk_state state) enum mdss_dsi_clk_state state, u32 index) { int rc = 0; struct mdss_dsi_clk_client_info *c = client; Loading @@ -744,7 +766,7 @@ int mdss_dsi_clk_req_state(void *client, enum mdss_dsi_clk_type clk, c->name, mngr->name, clk, state, c->core_clk_state, c->link_clk_state); MDSS_XLOG(clk, state, c->core_clk_state, c->link_clk_state); MDSS_XLOG(index, clk, state, c->core_clk_state, c->link_clk_state); /* * Refcount handling rules: * 1. Increment refcount whenever ON is called Loading Loading @@ -810,7 +832,7 @@ int mdss_dsi_clk_req_state(void *client, enum mdss_dsi_clk_type clk, pr_debug("[%s]%s: change=%d, Core (ref=%d, state=%d), Link (ref=%d, state=%d)\n", c->name, mngr->name, changed, c->core_refcount, c->core_clk_state, c->link_refcount, c->link_clk_state); MDSS_XLOG(clk, state, c->core_clk_state, c->link_clk_state); MDSS_XLOG(index, clk, state, c->core_clk_state, c->link_clk_state); if (changed) { rc = dsi_recheck_clk_state(mngr); Loading
drivers/video/msm/mdss/mdss_dsi_clk.h +15 −2 Original line number Diff line number Diff line /* Copyright (c) 2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-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 Loading Loading @@ -194,6 +194,7 @@ int mdss_dsi_clk_deregister(void *client); * @client: client handle. * @clk: Type of clock requested (enum mdss_dsi_clk_type). * @state: clock state requested. * @index: controller index. * * This routine is used to request a new clock state for a specific clock. If * turning ON the clocks, this guarantees that clocks will be on before Loading @@ -203,7 +204,7 @@ int mdss_dsi_clk_deregister(void *client); * @return: error code. */ int mdss_dsi_clk_req_state(void *client, enum mdss_dsi_clk_type clk, enum mdss_dsi_clk_state state); enum mdss_dsi_clk_state state, u32 index); /** * mdss_dsi_clk_set_link_rate() - set clock rate for link clocks Loading Loading @@ -235,4 +236,16 @@ int mdss_dsi_clk_set_link_rate(void *client, enum mdss_dsi_link_clk_type clk, * @return:error code. */ int mdss_dsi_clk_force_toggle(void *client, u32 clk); /** * is_dsi_clk_in_ecg_state() - Checks the current state of clocks * @client: client handle. * * This routine returns checks the clocks status for client and return * success code based on it. * * @return:true: if clocks are in ECG state * false: for all other cases */ bool is_dsi_clk_in_ecg_state(void *client); #endif /* _MDSS_DSI_CLK_H_ */
drivers/video/msm/mdss/msm_mdss_io_8974.c +37 −15 Original line number Diff line number Diff line Loading @@ -1945,7 +1945,11 @@ int mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, void *clk_handle, { int rc = 0; struct mdss_dsi_ctrl_pdata *mctrl = NULL; int i; int i, *vote_cnt; void *m_clk_handle; bool is_ecg = false; int state = MDSS_DSI_CLK_OFF; if (!ctrl) { pr_err("%s: Invalid arg\n", __func__); Loading Loading @@ -1976,6 +1980,18 @@ int mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, void *clk_handle, __func__); } /* * it should add and remove extra votes based on voting clients to avoid * removal of legitimate vote from DSI client. */ if (mctrl && (clk_handle == ctrl->dsi_clk_handle)) { m_clk_handle = mctrl->dsi_clk_handle; vote_cnt = &mctrl->m_dsi_vote_cnt; } else if (mctrl) { m_clk_handle = mctrl->mdp_clk_handle; vote_cnt = &mctrl->m_mdp_vote_cnt; } /* * When DSI is used in split mode, the link clock for master controller * has to be turned on first before the link clock for slave can be Loading @@ -1988,18 +2004,24 @@ int mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, void *clk_handle, __func__, ctrl->ndx, clk_type, clk_state, __builtin_return_address(0), mctrl ? 1 : 0); if (mctrl && (clk_type & MDSS_DSI_LINK_CLK)) { rc = mdss_dsi_clk_req_state(mctrl->dsi_clk_handle, MDSS_DSI_ALL_CLKS, MDSS_DSI_CLK_ON); if (clk_state != MDSS_DSI_CLK_ON) { /* preserve clk state; do not turn off forcefully */ is_ecg = is_dsi_clk_in_ecg_state(m_clk_handle); if (is_ecg) state = MDSS_DSI_CLK_EARLY_GATE; } rc = mdss_dsi_clk_req_state(m_clk_handle, MDSS_DSI_ALL_CLKS, MDSS_DSI_CLK_ON, mctrl->ndx); if (rc) { pr_err("%s: failed to turn on mctrl clocks, rc=%d\n", __func__, rc); goto error; } ctrl->m_vote_cnt++; (*vote_cnt)++; } rc = mdss_dsi_clk_req_state(clk_handle, clk_type, clk_state); rc = mdss_dsi_clk_req_state(clk_handle, clk_type, clk_state, ctrl->ndx); if (rc) { pr_err("%s: failed set clk state, rc = %d\n", __func__, rc); goto error; Loading Loading @@ -2028,24 +2050,24 @@ int mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, void *clk_handle, * for ON, since the previous ECG state must have * removed two votes to let clocks turn off. * * To satisfy the above requirement, m_vote_cnt keeps track of * To satisfy the above requirement, vote_cnt keeps track of * the number of ON votes for master requested by slave. For * every OFF/ECG state request, Either 2 or m_vote_cnt number of * every OFF/ECG state request, Either 2 or vote_cnt number of * votes are removed depending on which is lower. */ for (i = 0; (i < ctrl->m_vote_cnt && i < 2); i++) { rc = mdss_dsi_clk_req_state(mctrl->dsi_clk_handle, MDSS_DSI_ALL_CLKS, MDSS_DSI_CLK_OFF); for (i = 0; (i < *vote_cnt && i < 2); i++) { rc = mdss_dsi_clk_req_state(m_clk_handle, MDSS_DSI_ALL_CLKS, state, mctrl->ndx); if (rc) { pr_err("%s: failed to set mctrl clk state, rc = %d\n", __func__, rc); goto error; } } ctrl->m_vote_cnt -= i; pr_debug("%s: ctrl=%d, m_vote_cnt=%d\n", __func__, ctrl->ndx, ctrl->m_vote_cnt); (*vote_cnt) -= i; pr_debug("%s: ctrl=%d, vote_cnt=%d dsi_vote_cnt=%d mdp_vote_cnt:%d\n", __func__, ctrl->ndx, *vote_cnt, mctrl->m_dsi_vote_cnt, mctrl->m_mdp_vote_cnt); } error: Loading