Advertisement
Guest User

doze support

a guest
Oct 10th, 2015
115
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 71.75 KB | None | 0 0
  1. From 61668dc36db47c1fc40a97fe6dc61fc09006fc4b Mon Sep 17 00:00:00 2001
  2. From: Aravind Venkateswaran <aravindh@codeaurora.org>
  3. Date: Fri, 15 Aug 2014 17:04:35 -0700
  4. Subject: [PATCH 1/3] msm: mdss: add support for different panel power states
  5.  
  6. Currently a panel either be in a powered on state or a powered off
  7. state. However, it is possible for panels to be configured in an
  8. intermediate low-power state where the panel is always kept on. In
  9. order to support such use-cases, it is necessary to add the concept
  10. of panel power states in MDSS so that each software layer can
  11. independently maintain it's state and manage transitions between them.
  12. This change just refactors the driver with only two existing power
  13. states - panel on and panel off.
  14.  
  15. [GabrieleM: Adapt code for Motorola msm8226 sources]
  16. Change-Id: I49d1fda506761546c5e22d9106c5177e75053a81
  17. Signed-off-by: Aravind Venkateswaran <aravindh@codeaurora.org>
  18. (cherry picked from commit 543feb0d3107a4e69bb9df7cc8a17d86be57875e)
  19. ---
  20. drivers/video/msm/mdss/dsi_host_v2.c             |   2 +-
  21.  drivers/video/msm/mdss/dsi_status_v2.c           |   2 +-
  22.  drivers/video/msm/mdss/dsi_v2.c                  |   4 +-
  23.  drivers/video/msm/mdss/mdp3_ctrl.c               |   2 +-
  24.  drivers/video/msm/mdss/mdss_dsi.c                | 187 +++++++++++++++--------
  25.  drivers/video/msm/mdss/mdss_dsi_panel.c          |  18 ++-
  26.  drivers/video/msm/mdss/mdss_dsi_status.c         |   4 +-
  27.  drivers/video/msm/mdss/mdss_fb.c                 |  60 ++++----
  28.  drivers/video/msm/mdss/mdss_fb.h                 |   9 +-
  29.  drivers/video/msm/mdss/mdss_mdp.h                |  11 +-
  30.  drivers/video/msm/mdss/mdss_mdp_ctl.c            |  86 ++++++-----
  31.  drivers/video/msm/mdss/mdss_mdp_intf_cmd.c       |  69 ++++-----
  32.  drivers/video/msm/mdss/mdss_mdp_intf_video.c     |   2 +-
  33.  drivers/video/msm/mdss/mdss_mdp_intf_writeback.c |   3 +-
  34.  drivers/video/msm/mdss/mdss_mdp_overlay.c        |  40 ++---
  35.  drivers/video/msm/mdss/mdss_mdp_pp.c             |   4 +-
  36.  drivers/video/msm/mdss/mdss_mdp_wb.c             |   2 +-
  37.  drivers/video/msm/mdss/mdss_panel.h              |  27 +++-
  38.  18 files changed, 316 insertions(+), 216 deletions(-)
  39.  
  40. diff --git a/drivers/video/msm/mdss/dsi_host_v2.c b/drivers/video/msm/mdss/dsi_host_v2.c
  41. index 7f341e9..c2239e7 100644
  42. --- a/drivers/video/msm/mdss/dsi_host_v2.c
  43. +++ b/drivers/video/msm/mdss/dsi_host_v2.c
  44. @@ -1251,7 +1251,7 @@ static int msm_dsi_cont_on(struct mdss_panel_data *pdata)
  45.         mutex_unlock(&ctrl_pdata->mutex);
  46.         return ret;
  47.     }
  48. -   pinfo->panel_power_on = 1;
  49. +   pinfo->panel_power_on = MDSS_PANEL_POWER_ON;
  50.     ret = mdss_dsi_panel_reset(pdata, 1);
  51.     if (ret) {
  52.         pr_err("%s: Panel reset failed\n", __func__);
  53. diff --git a/drivers/video/msm/mdss/dsi_status_v2.c b/drivers/video/msm/mdss/dsi_status_v2.c
  54. index e71b42d..decdc9f 100644
  55. --- a/drivers/video/msm/mdss/dsi_status_v2.c
  56. +++ b/drivers/video/msm/mdss/dsi_status_v2.c
  57. @@ -96,7 +96,7 @@ void check_dsi_ctrl_status(struct work_struct *work)
  58.  
  59.     mutex_unlock(&mdp3_session->lock);
  60.  
  61. -   if ((pdsi_status->mfd->panel_power_on)) {
  62. +   if (pdsi_status->mfd->panel_power_state == MDSS_PANEL_POWER_ON) {
  63.         if (ret > 0) {
  64.             schedule_delayed_work(&pdsi_status->check_status,
  65.                 msecs_to_jiffies(pdsi_status->check_interval));
  66. diff --git a/drivers/video/msm/mdss/dsi_v2.c b/drivers/video/msm/mdss/dsi_v2.c
  67. index ff99b11..29fd2dd 100644
  68. --- a/drivers/video/msm/mdss/dsi_v2.c
  69. +++ b/drivers/video/msm/mdss/dsi_v2.c
  70. @@ -65,7 +65,7 @@ static int dsi_panel_handler(struct mdss_panel_data *pdata, int enable)
  71.                 panel_data);
  72.  
  73.     if (enable) {
  74. -       pdata->panel_info.panel_power_on = 1;
  75. +       pdata->panel_info.panel_power_on = MDSS_PANEL_POWER_ON;
  76.         if (ctrl_pdata->on)
  77.             ctrl_pdata->on(pdata);
  78.         else {
  79. @@ -84,7 +84,7 @@ static int dsi_panel_handler(struct mdss_panel_data *pdata, int enable)
  80.                                 __func__);
  81.             rc = -EINVAL;
  82.         }
  83. -       pdata->panel_info.panel_power_on = 0;
  84. +       pdata->panel_info.panel_power_on = MDSS_PANEL_POWER_OFF;
  85.     }
  86.     return rc;
  87.  }
  88. diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
  89. index a2a71b1..820e54f 100644
  90. --- a/drivers/video/msm/mdss/mdp3_ctrl.c
  91. +++ b/drivers/video/msm/mdss/mdp3_ctrl.c
  92. @@ -962,7 +962,7 @@ static int mdp3_overlay_play(struct msm_fb_data_type *mfd,
  93.  
  94.     mutex_lock(&mdp3_session->lock);
  95.  
  96. -   if (mfd->panel_power_on)
  97. +   if (mdss_fb_is_panel_power_on(mfd))
  98.         rc = mdp3_overlay_queue_buffer(mfd, req);
  99.     else
  100.         rc = -EPERM;
  101. diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
  102. index 1824c68..7db6d09 100644
  103. --- a/drivers/video/msm/mdss/mdss_dsi.c
  104. +++ b/drivers/video/msm/mdss/mdss_dsi.c
  105. @@ -69,7 +69,7 @@ static int mdss_dsi_regulator_init(struct platform_device *pdev)
  106.             ctrl_pdata->power_data.num_vreg, 1);
  107.  }
  108.  
  109. -static int mdss_dsi_panel_power_on(struct mdss_panel_data *pdata, int enable)
  110. +static int mdss_dsi_panel_power_off(struct mdss_panel_data *pdata)
  111.  {
  112.     int ret;
  113.     struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
  114. @@ -77,32 +77,85 @@ static int mdss_dsi_panel_power_on(struct mdss_panel_data *pdata, int enable)
  115.     if (pdata == NULL) {
  116.         pr_err("%s: Invalid input data\n", __func__);
  117.         ret = -EINVAL;
  118. -       goto error;
  119. +       goto end;
  120.     }
  121.  
  122.     ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
  123.                 panel_data);
  124. -   pr_debug("%s: enable=%d\n", __func__, enable);
  125.  
  126. -   if (enable) {
  127. -       ret = msm_dss_enable_vreg(
  128. -           ctrl_pdata->power_data.vreg_config,
  129. -           ctrl_pdata->power_data.num_vreg, 1);
  130. -       if (ret) {
  131. -           pr_err("%s:Failed to enable vregs.rc=%d\n",
  132. -               __func__, ret);
  133. -           goto error;
  134. -       }
  135. -   } else {
  136. -       ret = msm_dss_enable_vreg(
  137. -           ctrl_pdata->power_data.vreg_config,
  138. -           ctrl_pdata->power_data.num_vreg, 0);
  139. -       if (ret) {
  140. -           pr_err("%s: Failed to disable vregs.rc=%d\n",
  141. -               __func__, ret);
  142. -       }
  143. +   ret = msm_dss_enable_vreg(
  144. +       ctrl_pdata->power_data.vreg_config,
  145. +       ctrl_pdata->power_data.num_vreg, 0);
  146. +   if (ret) {
  147. +       pr_err("%s: Failed to disable vregs.rc=%d\n",
  148. +           __func__, ret);
  149.     }
  150. -error:
  151. +end:
  152. +   return ret;
  153. +}
  154. +
  155. +static int mdss_dsi_panel_power_on(struct mdss_panel_data *pdata)
  156. +{
  157. +   int ret;
  158. +   struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
  159. +
  160. +   if (pdata == NULL) {
  161. +       pr_err("%s: Invalid input data\n", __func__);
  162. +       ret = -EINVAL;
  163. +       goto end;
  164. +   }
  165. +
  166. +   ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
  167. +               panel_data);
  168. +
  169. +   ret = msm_dss_enable_vreg(
  170. +       ctrl_pdata->power_data.vreg_config,
  171. +       ctrl_pdata->power_data.num_vreg, 1);
  172. +   if (ret) {
  173. +       pr_err("%s:Failed to enable vregs.rc=%d\n",
  174. +           __func__, ret);
  175. +       goto end;
  176. +   }
  177. +end:
  178. +   return ret;
  179. +}
  180. +
  181. +static int mdss_dsi_panel_power_ctrl(struct mdss_panel_data *pdata,
  182. +   int power_state)
  183. +{
  184. +   int ret;
  185. +   struct mdss_panel_info *pinfo;
  186. +
  187. +   if (pdata == NULL) {
  188. +       pr_err("%s: Invalid input data\n", __func__);
  189. +       return -EINVAL;
  190. +   }
  191. +
  192. +   pinfo = &pdata->panel_info;
  193. +   pr_debug("%s: cur_power_state=%d req_power_state=%d\n", __func__,
  194. +       pinfo->panel_power_state, power_state);
  195. +
  196. +   if (pinfo->panel_power_state == power_state) {
  197. +       pr_debug("%s: no change needed\n", __func__);
  198. +       return 0;
  199. +   }
  200. +
  201. +   switch (power_state) {
  202. +   case MDSS_PANEL_POWER_OFF:
  203. +       ret = mdss_dsi_panel_power_off(pdata);
  204. +       break;
  205. +   case MDSS_PANEL_POWER_ON:
  206. +       ret = mdss_dsi_panel_power_on(pdata);
  207. +       break;
  208. +   default:
  209. +       pr_err("%s: unknown panel power state requested (%d)\n",
  210. +           __func__, power_state);
  211. +       ret = -EINVAL;
  212. +   }
  213. +
  214. +   if (!ret)
  215. +       pinfo->panel_power_state = power_state;
  216. +
  217.     return ret;
  218.  }
  219.  
  220. @@ -304,7 +357,7 @@ static int mdss_dsi_get_panel_cfg(char *panel_cfg)
  221.  static int mdss_dsi_ulps_config_sub(struct mdss_dsi_ctrl_pdata *ctrl_pdata,
  222.                 int enable, int partial);
  223.  
  224. -static int mdss_dsi_off(struct mdss_panel_data *pdata)
  225. +static int mdss_dsi_off(struct mdss_panel_data *pdata, int power_state)
  226.  {
  227.     int ret = 0;
  228.     struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
  229. @@ -316,19 +369,12 @@ static int mdss_dsi_off(struct mdss_panel_data *pdata)
  230.         return -EINVAL;
  231.     }
  232.  
  233. -   if (!pdata->panel_info.panel_power_on) {
  234. -       pr_warn("%s:%d Panel already off.\n", __func__, __LINE__);
  235. -       return -EPERM;
  236. -   }
  237. -
  238. -   pdata->panel_info.panel_power_on = 0;
  239. -
  240.     ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
  241.                 panel_data);
  242.  
  243.     panel_info = &ctrl_pdata->panel_data.panel_info;
  244. -   pr_info("%s+: ctrl=%p ndx=%d\n", __func__,
  245. -               ctrl_pdata, ctrl_pdata->ndx);
  246. +   pr_debug("%s+: ctrl=%p ndx=%d power_state=%d\n",
  247. +       __func__, ctrl_pdata, ctrl_pdata->ndx, power_state);
  248.  
  249.     if (ctrl_pdata->partial_mode_enabled
  250.         && !pdata->panel_info.panel_dead) {
  251. @@ -339,6 +385,12 @@ static int mdss_dsi_off(struct mdss_panel_data *pdata)
  252.             && pdata->panel_info.panel_dead)
  253.             pr_warn("%s: Panel is dead, shut down DSI\n", __func__);
  254.  
  255. +       if (power_state == panel_info->panel_power_state) {
  256. +           pr_debug("%s: No change in power state %d -> %d\n", __func__,
  257. +               panel_info->panel_power_state, power_state);
  258. +           goto end;
  259. +       }
  260. +
  261.         if (pdata->panel_info.type == MIPI_CMD_PANEL)
  262.             mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1);
  263.  
  264. @@ -350,18 +402,12 @@ static int mdss_dsi_off(struct mdss_panel_data *pdata)
  265.  
  266.         mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 0);
  267.  
  268. -       ret = mdss_dsi_panel_power_on(pdata, 0);
  269. -       if (ret) {
  270. +       ret = mdss_dsi_panel_power_ctrl(pdata, power_state);
  271. +       if (ret)
  272.             pr_err("%s: Panel power off failed\n", __func__);
  273. -           return ret;
  274. -       }
  275.     }
  276.  
  277. -   if (panel_info->dynamic_fps
  278. -       && (panel_info->dfps_update == DFPS_SUSPEND_RESUME_MODE)
  279. -       && (panel_info->new_fps != panel_info->mipi.frame_rate))
  280. -       panel_info->mipi.frame_rate = panel_info->new_fps;
  281. -
  282. +end:
  283.     pr_info("%s-:\n", __func__);
  284.  
  285.     return ret;
  286. @@ -487,7 +533,7 @@ static int mdss_dsi_ulps_config_sub(struct mdss_dsi_ctrl_pdata *ctrl_pdata,
  287.  
  288.     if (enable && !ctrl_pdata->ulps) {
  289.         /* No need to configure ULPS mode when entering suspend state */
  290. -       if (!partial && !pdata->panel_info.panel_power_on) {
  291. +       if (!partial && pdata->panel_info.panel_power_state == MDSS_PANEL_POWER_OFF) {
  292.             pr_err("%s: panel off. returning\n", __func__);
  293.             goto error;
  294.         }
  295. @@ -651,22 +697,19 @@ int mdss_dsi_on(struct mdss_panel_data *pdata)
  296.     struct mipi_panel_info *mipi;
  297.     struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
  298.     struct mdss_data_type *mdata = mdss_mdp_get_mdata();
  299. +   int cur_power_state;
  300.  
  301.     if (pdata == NULL) {
  302.         pr_err("%s: Invalid input data\n", __func__);
  303.         return -EINVAL;
  304.     }
  305.  
  306. -   if (pdata->panel_info.panel_power_on) {
  307. -       pr_warn("%s:%d Panel already on.\n", __func__, __LINE__);
  308. -       return 0;
  309. -   }
  310. -
  311.     ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
  312.                 panel_data);
  313.  
  314. -   pr_info("%s+: ctrl=%p ndx=%d\n",
  315. -               __func__, ctrl_pdata, ctrl_pdata->ndx);
  316. +   cur_power_state = pdata->panel_info.panel_power_state;
  317. +   pr_debug("%s+: ctrl=%p ndx=%d cur_power_state=%d\n", __func__,
  318. +       ctrl_pdata, ctrl_pdata->ndx, cur_power_state);
  319.  
  320.     pinfo = &pdata->panel_info;
  321.     mipi = &pdata->panel_info.mipi;
  322. @@ -675,14 +718,19 @@ int mdss_dsi_on(struct mdss_panel_data *pdata)
  323.         && !pdata->panel_info.panel_dead) {
  324.         mdss_dsi_ulps_config_sub(ctrl_pdata, 0, 1);
  325.         mdata->ulps = false;
  326. -       pdata->panel_info.panel_power_on = 1;
  327. +       pdata->panel_info.panel_power_state = MDSS_PANEL_POWER_ON;
  328.         mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1);
  329.     } else {
  330.         if (ctrl_pdata->partial_mode_enabled
  331.             && pdata->panel_info.panel_dead)
  332.             pr_warn("%s: Panel is dead, bring up DSI\n", __func__);
  333.  
  334. -       ret = mdss_dsi_panel_power_on(pdata, 1);
  335. +       if (MDSS_PANEL_POWER_ON == pinfo->panel_power_state) {
  336. +           pr_debug("%s: panel already on\n", __func__);
  337. +           goto end;
  338. +       }
  339. +
  340. +       ret = mdss_dsi_panel_power_ctrl(pdata, MDSS_PANEL_POWER_ON);
  341.         if (ret) {
  342.             pr_err("%s:Panel power on failed. rc=%d\n", __func__, ret);
  343.             return ret;
  344. @@ -692,16 +740,15 @@ int mdss_dsi_on(struct mdss_panel_data *pdata)
  345.         if (ret) {
  346.             pr_err("%s: failed to enable bus clocks. rc=%d\n", __func__,
  347.                 ret);
  348. -           ret = mdss_dsi_panel_power_on(pdata, 0);
  349. +           ret = mdss_dsi_panel_power_on(pdata);
  350.             if (ret) {
  351.                 pr_err("%s: Panel reset failed. rc=%d\n",
  352.                     __func__, ret);
  353.                 return ret;
  354.             }
  355. -           pdata->panel_info.panel_power_on = 0;
  356. +           pdata->panel_info.panel_power_state = MDSS_PANEL_POWER_OFF;
  357.             return ret;
  358.         }
  359. -       pdata->panel_info.panel_power_on = 1;
  360.  
  361.         mdss_dsi_phy_sw_reset((ctrl_pdata->ctrl_base));
  362.         mdss_dsi_phy_init(pdata);
  363. @@ -735,6 +782,7 @@ int mdss_dsi_on(struct mdss_panel_data *pdata)
  364.     if (pdata->panel_info.type == MIPI_CMD_PANEL)
  365.         mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 0);
  366.  
  367. +end:
  368.     pr_info("%s-:\n", __func__);
  369.     return 0;
  370.  }
  371. @@ -745,8 +793,6 @@ static int mdss_dsi_unblank(struct mdss_panel_data *pdata)
  372.     struct mipi_panel_info *mipi;
  373.     struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
  374.  
  375. -   pr_debug("%s+:\n", __func__);
  376. -
  377.     if (pdata == NULL) {
  378.         pr_err("%s: Invalid input data\n", __func__);
  379.         return -EINVAL;
  380. @@ -756,6 +802,9 @@ static int mdss_dsi_unblank(struct mdss_panel_data *pdata)
  381.                 panel_data);
  382.     mipi  = &pdata->panel_info.mipi;
  383.  
  384. +   pr_debug("%s+: ctrl=%p ndx=%d cur_blank_state=%d\n", __func__,
  385. +       ctrl_pdata, ctrl_pdata->ndx, pdata->panel_info.blank_state);
  386. +
  387.     if (!(ctrl_pdata->ctrl_state & CTRL_STATE_PANEL_INIT)) {
  388.         ret = ctrl_pdata->on(pdata);
  389.         if (ret) {
  390. @@ -778,14 +827,12 @@ static int mdss_dsi_unblank(struct mdss_panel_data *pdata)
  391.     return ret;
  392.  }
  393.  
  394. -static int mdss_dsi_blank(struct mdss_panel_data *pdata)
  395. +static int mdss_dsi_blank(struct mdss_panel_data *pdata, int power_state)
  396.  {
  397.     int ret = 0;
  398.     struct mipi_panel_info *mipi;
  399.     struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
  400.  
  401. -   pr_debug("%s+:\n", __func__);
  402. -
  403.     if (pdata == NULL) {
  404.         pr_err("%s: Invalid input data\n", __func__);
  405.         return -EINVAL;
  406. @@ -795,6 +842,9 @@ static int mdss_dsi_blank(struct mdss_panel_data *pdata)
  407.                 panel_data);
  408.     mipi = &pdata->panel_info.mipi;
  409.  
  410. +   pr_debug("%s+: ctrl=%p ndx=%d power_state=%d\n",
  411. +       __func__, ctrl_pdata, ctrl_pdata->ndx, power_state);
  412. +
  413.     if (pdata->panel_info.type == MIPI_VIDEO_PANEL &&
  414.             ctrl_pdata->off_cmds.link_state == DSI_LP_MODE) {
  415.         mdss_dsi_sw_reset(pdata);
  416. @@ -1000,6 +1050,7 @@ static int mdss_dsi_event_handler(struct mdss_panel_data *pdata,
  417.  {
  418.     int rc = 0;
  419.     struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
  420. +   int power_state;
  421.  
  422.     if (pdata == NULL) {
  423.         pr_err("%s: Invalid input data\n", __func__);
  424. @@ -1024,18 +1075,20 @@ static int mdss_dsi_event_handler(struct mdss_panel_data *pdata,
  425.         pdata->panel_info.cont_splash_esd_rdy = true;
  426.         break;
  427.     case MDSS_EVENT_BLANK:
  428. +       power_state = (int) (unsigned long) arg;
  429.         if (ctrl_pdata->off_cmds.link_state == DSI_HS_MODE)
  430. -           rc = mdss_dsi_blank(pdata);
  431. +           rc = mdss_dsi_blank(pdata, power_state);
  432.         break;
  433.     case MDSS_EVENT_PANEL_OFF:
  434. +       power_state = (int) (unsigned long) arg;
  435.         ctrl_pdata->ctrl_state &= ~CTRL_STATE_MDP_ACTIVE;
  436.         if (ctrl_pdata->off_cmds.link_state == DSI_LP_MODE)
  437. -           rc = mdss_dsi_blank(pdata);
  438. -       rc = mdss_dsi_off(pdata);
  439. +           rc = mdss_dsi_blank(pdata, power_state);
  440. +       rc = mdss_dsi_off(pdata, power_state);
  441.         break;
  442.     case MDSS_EVENT_CONT_SPLASH_FINISH:
  443.         if (ctrl_pdata->off_cmds.link_state == DSI_LP_MODE)
  444. -           rc = mdss_dsi_blank(pdata);
  445. +           rc = mdss_dsi_blank(pdata, MDSS_PANEL_POWER_OFF);
  446.         ctrl_pdata->ctrl_state &= ~CTRL_STATE_MDP_ACTIVE;
  447.         rc = mdss_dsi_cont_splash_on(pdata);
  448.         break;
  449. @@ -1219,7 +1272,7 @@ int mdss_dsi_ioctl_handler(struct mdss_panel_data *pdata, u32 cmd, void *arg)
  450.     int old_tx_mode;
  451.     int mode = DSI_MODE_BIT_LP;
  452.  
  453. -   if (!pdata->panel_info.panel_power_on) {
  454. +   if (!mdss_panel_is_panel_power_on(pdata)) {
  455.         pr_err("%s: Panel is off\n", __func__);
  456.         return -EPERM;
  457.     }
  458. @@ -1713,8 +1766,6 @@ int dsi_panel_device_register(struct device_node *pan_node,
  459.     ctrl_pdata->ctrl_state = CTRL_STATE_UNKNOWN;
  460.  
  461.     if (pinfo->cont_splash_enabled) {
  462. -       pinfo->panel_power_on = 1;
  463. -
  464.         /*
  465.          * This call intends to call to gpio_request for display's
  466.          * reset gpio, because with cont_splash_enabled, there is
  467. @@ -1729,17 +1780,19 @@ int dsi_panel_device_register(struct device_node *pan_node,
  468.             return rc;
  469.         }
  470.  
  471. -       rc = mdss_dsi_panel_power_on(&(ctrl_pdata->panel_data), 1);
  472. +       rc = mdss_dsi_panel_power_ctrl(&(ctrl_pdata->panel_data),
  473. +           MDSS_PANEL_POWER_ON);
  474.         if (rc) {
  475.             pr_err("%s: Panel power on failed\n", __func__);
  476.             return rc;
  477.         }
  478.  
  479. +       pinfo->blank_state = MDSS_PANEL_BLANK_UNBLANK;
  480.         mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1);
  481.         ctrl_pdata->ctrl_state |=
  482.             (CTRL_STATE_PANEL_INIT | CTRL_STATE_MDP_ACTIVE);
  483.     } else {
  484. -       pinfo->panel_power_on = 0;
  485. +       pinfo->panel_power_state = MDSS_PANEL_POWER_OFF;
  486.     }
  487.  
  488.     rc = mdss_register_panel(ctrl_pdev, &(ctrl_pdata->panel_data));
  489. diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c
  490. index 9e93671..da915f7 100644
  491. --- a/drivers/video/msm/mdss/mdss_dsi_panel.c
  492. +++ b/drivers/video/msm/mdss/mdss_dsi_panel.c
  493. @@ -594,7 +594,8 @@ int mdss_panel_check_status(struct mdss_dsi_ctrl_pdata *ctrl)
  494.     static int esd_trigger_cnt;
  495.  #endif
  496.  
  497. -   if (!ctrl->panel_data.panel_info.panel_power_on) {
  498. +   if (ctrl->panel_data.panel_info.panel_power_state !=
  499. +       MDSS_PANEL_POWER_ON) {
  500.         ret = 1;
  501.         goto end;
  502.     }
  503. @@ -772,21 +773,22 @@ static int mdss_dsi_quickdraw_check_panel_state(struct mdss_panel_data *pdata,
  504.  
  505.  static int mdss_dsi_panel_on(struct mdss_panel_data *pdata)
  506.  {
  507. -   struct mipi_panel_info *mipi;
  508.     struct mdss_dsi_ctrl_pdata *ctrl = NULL;
  509.     struct msm_fb_data_type *mfd;
  510.     u8 pwr_mode = 0;
  511.     char *dropbox_issue = NULL;
  512.     static int dropbox_count;
  513. +   struct mdss_panel_info *pinfo;
  514.  
  515.     if (pdata == NULL) {
  516.         pr_err("%s: Invalid input data\n", __func__);
  517.         return -EINVAL;
  518.     }
  519.  
  520. +   pinfo = &pdata->panel_info;
  521. +
  522.     ctrl = container_of(pdata, struct mdss_dsi_ctrl_pdata,
  523.                 panel_data);
  524. -   mipi  = &pdata->panel_info.mipi;
  525.  
  526.     mfd = pdata->mfd;
  527.     pr_info("%s+: ctrl=%p ndx=%d\n", __func__, ctrl, ctrl->ndx);
  528. @@ -865,6 +867,8 @@ static int mdss_dsi_panel_on(struct mdss_panel_data *pdata)
  529.         pdata->panel_info.cabc_mode = CABC_UI_MODE;
  530.  
  531.  end:
  532. +   pinfo->blank_state = MDSS_PANEL_BLANK_UNBLANK;
  533. +
  534.     if (dropbox_issue != NULL) {
  535.         char dropbox_entry[256];
  536.  
  537. @@ -885,23 +889,23 @@ end:
  538.  
  539.  static int mdss_dsi_panel_off(struct mdss_panel_data *pdata)
  540.  {
  541. -   struct mipi_panel_info *mipi;
  542.     struct mdss_dsi_ctrl_pdata *ctrl = NULL;
  543.     struct msm_fb_data_type *mfd;
  544. +   struct mdss_panel_info *pinfo;
  545.  
  546.     if (pdata == NULL) {
  547.         pr_err("%s: Invalid input data\n", __func__);
  548.         return -EINVAL;
  549.     }
  550.  
  551. +   pinfo = &pdata->panel_info;
  552. +
  553.     ctrl = container_of(pdata, struct mdss_dsi_ctrl_pdata,
  554.                 panel_data);
  555.  
  556.     mfd = pdata->mfd;
  557.     pr_info("%s+: ctrl=%p ndx=%d\n", __func__, ctrl, ctrl->ndx);
  558.  
  559. -   mipi  = &pdata->panel_info.mipi;
  560. -
  561.     if (!mfd->quickdraw_in_progress)
  562.         mmi_panel_notify(MMI_PANEL_EVENT_PRE_DISPLAY_OFF, NULL);
  563.  
  564. @@ -935,6 +939,8 @@ disable_regs:
  565.     if (pdata->panel_info.dynamic_cabc_enabled)
  566.         pdata->panel_info.cabc_mode = CABC_OFF_MODE;
  567.  
  568. +   pinfo->blank_state = MDSS_PANEL_BLANK_BLANK;
  569. +
  570.     pr_info("%s-:\n", __func__);
  571.  
  572.     return 0;
  573. diff --git a/drivers/video/msm/mdss/mdss_dsi_status.c b/drivers/video/msm/mdss/mdss_dsi_status.c
  574. index 56d0f68..ea24eac 100644
  575. --- a/drivers/video/msm/mdss/mdss_dsi_status.c
  576. +++ b/drivers/video/msm/mdss/mdss_dsi_status.c
  577. @@ -92,7 +92,7 @@ static void check_dsi_ctrl_status(struct work_struct *work)
  578.         return;
  579.     }
  580.  
  581. -   if (!pdsi_status->mfd->panel_power_on) {
  582. +   if (pdsi_status->mfd->panel_power_state == MDSS_PANEL_POWER_OFF) {
  583.         pr_err("%s: panel off\n", __func__);
  584.         return;
  585.     }
  586. @@ -123,7 +123,7 @@ static void check_dsi_ctrl_status(struct work_struct *work)
  587.     mutex_unlock(&ctl->offlock);
  588.  #endif
  589.  
  590. -   if ((pdsi_status->mfd->panel_power_on)) {
  591. +   if (pdsi_status->mfd->panel_power_state == MDSS_PANEL_POWER_ON) {
  592.         if (ret > 0) {
  593.             schedule_delayed_work(&pdsi_status->check_status,
  594.                 msecs_to_jiffies(interval));
  595. diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
  596. index c06d507..fa41c68 100644
  597. --- a/drivers/video/msm/mdss/mdss_fb.c
  598. +++ b/drivers/video/msm/mdss/mdss_fb.c
  599. @@ -144,7 +144,7 @@ static int mdss_fb_notify_update(struct msm_fb_data_type *mfd,
  600.                         &mfd->no_update.comp, 4 * HZ);
  601.         to_user = (unsigned int)mfd->no_update.value;
  602.     } else {
  603. -       if (mfd->panel_power_on) {
  604. +       if (mdss_fb_is_panel_power_on(mfd)) {
  605.             INIT_COMPLETION(mfd->power_off_comp);
  606.             ret = wait_for_completion_interruptible_timeout(
  607.                         &mfd->power_off_comp, 1 * HZ);
  608. @@ -376,10 +376,10 @@ static ssize_t mdss_mdp_show_blank_event(struct device *dev,
  609.     struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
  610.     int ret;
  611.  
  612. -   pr_debug("fb%d panel_power_on = %d\n", mfd->index,
  613. -       mfd->quickdraw_in_progress ? 0 : mfd->panel_power_on);
  614. +   pr_debug("fb%d panel_power_state = %d\n", mfd->index,
  615. +       mfd->panel_power_state);
  616.     ret = scnprintf(buf, PAGE_SIZE, "panel_power_on = %d\n",
  617. -       mfd->quickdraw_in_progress ? 0 : mfd->panel_power_on);
  618. +       mfd->quickdraw_in_progress ? 0 : mfd->panel_power_state);
  619.  
  620.     return ret;
  621.  }
  622. @@ -767,7 +767,7 @@ static int mdss_fb_suspend_sub(struct msm_fb_data_type *mfd)
  623.     }
  624.  
  625.     mfd->suspend.op_enable = mfd->op_enable;
  626. -   mfd->suspend.panel_power_on = mfd->panel_power_on;
  627. +   mfd->suspend.panel_power_state = mfd->panel_power_state;
  628.  
  629.     if (mfd->op_enable) {
  630.         ret = mdss_fb_blank_sub(FB_BLANK_POWERDOWN, mfd->fbi,
  631. @@ -804,7 +804,7 @@ static int mdss_fb_resume_sub(struct msm_fb_data_type *mfd)
  632.     /* resume state var recover */
  633.     mfd->op_enable = mfd->suspend.op_enable;
  634.  
  635. -   if (mfd->suspend.panel_power_on) {
  636. +   if (mfd->suspend.panel_power_state == MDSS_PANEL_POWER_ON) {
  637.         ret = mdss_fb_blank_sub(FB_BLANK_UNBLANK, mfd->fbi,
  638.                     mfd->op_enable);
  639.         if (ret)
  640. @@ -931,7 +931,7 @@ void mdss_fb_set_backlight(struct msm_fb_data_type *mfd, u32 bkl_lvl)
  641.     int (*update_ad_input)(struct msm_fb_data_type *mfd);
  642.     u32 temp = bkl_lvl;
  643.  
  644. -   if (((!mfd->panel_power_on && mfd->dcm_state != DCM_ENTER)
  645. +   if (((!mdss_fb_is_panel_power_on(mfd) && mfd->dcm_state != DCM_ENTER)
  646.         || !mfd->bl_updated) && !IS_CALIB_MODE_BL(mfd)) {
  647.         mfd->unset_bl_level = bkl_lvl;
  648.         return;
  649. @@ -992,8 +992,9 @@ int mdss_fb_blank_sub(int blank_mode, struct fb_info *info, int op_enable)
  650.     struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
  651.     struct mdss_panel_data *pdata;
  652.     int ret = 0;
  653. +   int cur_power_state, req_power_state = MDSS_PANEL_POWER_OFF;
  654.  
  655. -   if (!op_enable && !mfd->quickdraw_in_progress)
  656. +   if (!mfd || (!op_enable && !mfd->quickdraw_in_progress))
  657.         return -EPERM;
  658.  
  659.     if (mfd->dcm_state == DCM_ENTER)
  660. @@ -1001,13 +1002,16 @@ int mdss_fb_blank_sub(int blank_mode, struct fb_info *info, int op_enable)
  661.  
  662.     pdata = dev_get_platdata(&mfd->pdev->dev);
  663.  
  664. +   cur_power_state = mfd->panel_power_state;
  665.     switch (blank_mode) {
  666.     case FB_BLANK_UNBLANK:
  667. -       if (!mfd->panel_power_on && mfd->mdp.on_fnc) {
  668. +       pr_debug("unblank called. cur pwr state=%d\n", cur_power_state);
  669. +       if ((cur_power_state != MDSS_PANEL_POWER_ON) &&
  670. +           mfd->mdp.on_fnc) {
  671.             int panel_dead = mfd->panel_info->panel_dead;
  672.             ret = mfd->mdp.on_fnc(mfd);
  673.             if (ret == 0) {
  674. -               mfd->panel_power_on = true;
  675. +               mfd->panel_power_state = MDSS_PANEL_POWER_ON;
  676.                 if (panel_dead &&
  677.                 mfd->panel_info->bklt_ctrl == BL_DCS_CMD &&
  678.                 pdata) {
  679. @@ -1036,9 +1040,10 @@ int mdss_fb_blank_sub(int blank_mode, struct fb_info *info, int op_enable)
  680.     case FB_BLANK_NORMAL:
  681.     case FB_BLANK_POWERDOWN:
  682.     default:
  683. -       if (mfd->panel_power_on && mfd->mdp.off_fnc) {
  684. -           int curr_pwr_state;
  685. -
  686. +       pr_debug("blank powerdown called. cur mode=%d, req mode=%d\n",
  687. +           cur_power_state, req_power_state);
  688. +       if (mdss_fb_is_panel_power_on(mfd) && mfd->mdp.off_fnc) {
  689. +           cur_power_state = mfd->panel_power_state;
  690.             mutex_lock(&mfd->update.lock);
  691.             mfd->update.type = NOTIFY_TYPE_SUSPEND;
  692.             mfd->update.is_suspend = 1;
  693. @@ -1049,9 +1054,8 @@ int mdss_fb_blank_sub(int blank_mode, struct fb_info *info, int op_enable)
  694.             complete(&mfd->no_update.comp);
  695.  
  696.             mfd->op_enable = false;
  697. -           curr_pwr_state = mfd->panel_power_on;
  698. -           mfd->panel_power_on = false;
  699.             mfd->bl_updated = 0;
  700. +           mfd->panel_power_state = req_power_state;
  701.  
  702.             if (mfd->shutdown_pending &&
  703.                 mfd->panel_info->bl_shutdown_delay)
  704. @@ -1062,7 +1066,7 @@ int mdss_fb_blank_sub(int blank_mode, struct fb_info *info, int op_enable)
  705.  
  706.             ret = mfd->mdp.off_fnc(mfd);
  707.             if (ret)
  708. -               mfd->panel_power_on = curr_pwr_state;
  709. +               mfd->panel_power_state = cur_power_state;
  710.             else
  711.                 mdss_fb_release_fences(mfd);
  712.             mfd->op_enable = true;
  713. @@ -1088,9 +1092,9 @@ static int mdss_fb_blank(int blank_mode, struct fb_info *info)
  714.     mdss_fb_pan_idle(mfd);
  715.     if (mfd->op_enable == 0) {
  716.         if (blank_mode == FB_BLANK_UNBLANK)
  717. -           mfd->suspend.panel_power_on = true;
  718. +           mfd->suspend.panel_power_state = MDSS_PANEL_POWER_ON;
  719.         else
  720. -           mfd->suspend.panel_power_on = false;
  721. +           mfd->suspend.panel_power_state = MDSS_PANEL_POWER_OFF;
  722.         return 0;
  723.     }
  724.     ret = mdss_fb_blank_sub(blank_mode, info, mfd->op_enable);
  725. @@ -1543,7 +1547,7 @@ static int mdss_fb_register(struct msm_fb_data_type *mfd)
  726.     fbi->pseudo_palette = mdss_fb_pseudo_palette;
  727.  
  728.     mfd->ref_cnt = 0;
  729. -   mfd->panel_power_on = false;
  730. +   mfd->panel_power_state = MDSS_PANEL_POWER_OFF;
  731.     mfd->dcm_state = DCM_UNINIT;
  732.  
  733.     mdss_fb_parse_dt(mfd);
  734. @@ -1993,7 +1997,7 @@ int mdss_fb_pan_display_ex(struct fb_info *info,
  735.     int ret = 0;
  736.  
  737.     if (!mfd || (!mfd->op_enable && !mfd->quickdraw_in_progress) ||
  738. -       (!mfd->panel_power_on))
  739. +       (!mdss_fb_is_panel_power_on(mfd)))
  740.         return -EPERM;
  741.  
  742.     if (var->xoffset > (info->var.xres_virtual - info->var.xres))
  743. @@ -2044,7 +2048,7 @@ static int mdss_fb_pan_display_sub(struct fb_var_screeninfo *var,
  744.  {
  745.     struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
  746.  
  747. -   if ((!mfd->op_enable) || (!mfd->panel_power_on))
  748. +   if ((!mfd->op_enable) || (!mdss_fb_is_panel_power_on(mfd)))
  749.         return -EPERM;
  750.  
  751.     if (var->xoffset > (info->var.xres_virtual - info->var.xres))
  752. @@ -2345,10 +2349,10 @@ int mdss_fb_dcm(struct msm_fb_data_type *mfd, int req_state)
  753.     switch (req_state) {
  754.     case DCM_UNBLANK:
  755.         if (mfd->dcm_state == DCM_UNINIT &&
  756. -           !mfd->panel_power_on && mfd->mdp.on_fnc) {
  757. +           !mdss_fb_is_panel_power_on(mfd) && mfd->mdp.on_fnc) {
  758.             ret = mfd->mdp.on_fnc(mfd);
  759.             if (ret == 0) {
  760. -               mfd->panel_power_on = true;
  761. +               mfd->panel_power_state = MDSS_PANEL_POWER_ON;
  762.                 mfd->dcm_state = DCM_UNBLANK;
  763.             }
  764.         }
  765. @@ -2359,24 +2363,24 @@ int mdss_fb_dcm(struct msm_fb_data_type *mfd, int req_state)
  766.              * Keep unblank path available for only
  767.              * DCM operation
  768.              */
  769. -           mfd->panel_power_on = false;
  770. +           mfd->panel_power_state = MDSS_PANEL_POWER_OFF;
  771.             mfd->dcm_state = DCM_ENTER;
  772.         }
  773.         break;
  774.     case DCM_EXIT:
  775.         if (mfd->dcm_state == DCM_ENTER) {
  776.             /* Release the unblank path for exit */
  777. -           mfd->panel_power_on = true;
  778. +           mfd->panel_power_state = MDSS_PANEL_POWER_ON;
  779.             mfd->dcm_state = DCM_EXIT;
  780.         }
  781.         break;
  782.     case DCM_BLANK:
  783.         if ((mfd->dcm_state == DCM_EXIT ||
  784.             mfd->dcm_state == DCM_UNBLANK) &&
  785. -           mfd->panel_power_on && mfd->mdp.off_fnc) {
  786. +           mdss_fb_is_panel_power_on(mfd) && mfd->mdp.off_fnc) {
  787.             ret = mfd->mdp.off_fnc(mfd);
  788.             if (ret == 0) {
  789. -               mfd->panel_power_on = false;
  790. +               mfd->panel_power_state = MDSS_PANEL_POWER_OFF;
  791.                 mfd->dcm_state = DCM_UNINIT;
  792.             }
  793.         }
  794. @@ -2658,7 +2662,7 @@ static int mdss_fb_ioctl(struct fb_info *info, unsigned int cmd,
  795.         ret = copy_from_user(&buf_sync, argp, sizeof(buf_sync));
  796.         if (ret)
  797.             return ret;
  798. -       if ((!mfd->op_enable) || (!mfd->panel_power_on))
  799. +       if ((!mfd->op_enable) || (!mdss_fb_is_panel_power_on(mfd)))
  800.             return -EPERM;
  801.         if (mfd->mdp.get_sync_fnc)
  802.             sync_pt_data = mfd->mdp.get_sync_fnc(mfd, &buf_sync);
  803. diff --git a/drivers/video/msm/mdss/mdss_fb.h b/drivers/video/msm/mdss/mdss_fb.h
  804. index 4256891..f1595af 100644
  805. --- a/drivers/video/msm/mdss/mdss_fb.h
  806. +++ b/drivers/video/msm/mdss/mdss_fb.h
  807. @@ -76,7 +76,7 @@ enum mdp_splash_event {
  808.  
  809.  struct disp_info_type_suspend {
  810.     int op_enable;
  811. -   int panel_power_on;
  812. +   int panel_power_state;
  813.  };
  814.  
  815.  struct disp_info_notify {
  816. @@ -178,7 +178,7 @@ struct msm_fb_data_type {
  817.     int panel_reconfig;
  818.  
  819.     u32 dst_format;
  820. -   int panel_power_on;
  821. +   int panel_power_state;
  822.     struct disp_info_type_suspend suspend;
  823.  
  824.     struct ion_handle *ihdl;
  825. @@ -264,6 +264,11 @@ static inline void mdss_fb_update_notify_update(struct msm_fb_data_type *mfd)
  826.     }
  827.  }
  828.  
  829. +static inline bool mdss_fb_is_panel_power_on(struct msm_fb_data_type *mfd)
  830. +{
  831. +   return (mfd->panel_power_state != MDSS_PANEL_POWER_OFF);
  832. +}
  833. +
  834.  int mdss_fb_get_phys_info(unsigned long *start, unsigned long *len, int fb_num);
  835.  void mdss_fb_set_backlight(struct msm_fb_data_type *mfd, u32 bkl_lvl);
  836.  void mdss_fb_update_backlight(struct msm_fb_data_type *mfd);
  837. diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
  838. index 30b683f..d199e65 100644
  839. --- a/drivers/video/msm/mdss/mdss_mdp.h
  840. +++ b/drivers/video/msm/mdss/mdss_mdp.h
  841. @@ -166,7 +166,7 @@ struct mdss_mdp_ctl {
  842.     char __iomem *base;
  843.     char __iomem *wb_base;
  844.     u32 ref_cnt;
  845. -   int power_on;
  846. +   int power_state;
  847.  
  848.     u32 intf_num;
  849.     u32 intf_type;
  850. @@ -207,7 +207,7 @@ struct mdss_mdp_ctl {
  851.     u8 roi_changed;
  852.  
  853.     int (*start_fnc) (struct mdss_mdp_ctl *ctl);
  854. -   int (*stop_fnc) (struct mdss_mdp_ctl *ctl);
  855. +   int (*stop_fnc) (struct mdss_mdp_ctl *ctl, int panel_power_state);
  856.     int (*prepare_fnc) (struct mdss_mdp_ctl *ctl, void *arg);
  857.     int (*display_fnc) (struct mdss_mdp_ctl *ctl, void *arg);
  858.     int (*wait_fnc) (struct mdss_mdp_ctl *ctl, void *arg);
  859. @@ -485,6 +485,11 @@ static inline u32 mdss_mdp_pingpong_read(struct mdss_mdp_mixer *mixer, u32 reg)
  860.     return readl_relaxed(mixer->pingpong_base + reg);
  861.  }
  862.  
  863. +static inline bool mdss_mdp_ctl_is_power_on(struct mdss_mdp_ctl *ctl)
  864. +{
  865. +   return (ctl->power_state != MDSS_PANEL_POWER_OFF);
  866. +}
  867. +
  868.  irqreturn_t mdss_mdp_isr(int irq, void *ptr);
  869.  int mdss_iommu_attach(struct mdss_data_type *mdata);
  870.  int mdss_iommu_dettach(struct mdss_data_type *mdata);
  871. @@ -539,7 +544,7 @@ int mdss_mdp_ctl_split_display_setup(struct mdss_mdp_ctl *ctl,
  872.         struct mdss_panel_data *pdata);
  873.  int mdss_mdp_ctl_destroy(struct mdss_mdp_ctl *ctl);
  874.  int mdss_mdp_ctl_start(struct mdss_mdp_ctl *ctl, bool handoff);
  875. -int mdss_mdp_ctl_stop(struct mdss_mdp_ctl *ctl);
  876. +int mdss_mdp_ctl_stop(struct mdss_mdp_ctl *ctl, int panel_power_mode);
  877.  int mdss_mdp_ctl_intf_event(struct mdss_mdp_ctl *ctl, int event, void *arg);
  878.  int mdss_mdp_perf_bw_check(struct mdss_mdp_ctl *ctl,
  879.         struct mdss_mdp_pipe **left_plist, int left_cnt,
  880. diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
  881. index 9a038e3..c892173 100644
  882. --- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
  883. +++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
  884. @@ -562,7 +562,7 @@ static u32 mdss_mdp_get_vbp_factor_max(struct mdss_mdp_ctl *ctl)
  885.         struct mdss_mdp_ctl *ctl = mdata->ctl_off + i;
  886.         u32 vbp_fac;
  887.  
  888. -       if (ctl->power_on) {
  889. +       if (mdss_mdp_ctl_is_power_on(ctl)) {
  890.             vbp_fac = mdss_mdp_get_vbp_factor(ctl);
  891.             vbp_max = max(vbp_max, vbp_fac);
  892.         }
  893. @@ -787,7 +787,7 @@ static inline void mdss_mdp_ctl_perf_update_bus(struct mdss_mdp_ctl *ctl)
  894.     for (i = 0; i < mdata->nctl; i++) {
  895.         struct mdss_mdp_ctl *ctl;
  896.         ctl = mdata->ctl_off + i;
  897. -       if (ctl->power_on) {
  898. +       if (mdss_mdp_ctl_is_power_on(ctl)) {
  899.             bw_sum_of_intfs += ctl->cur_perf.bw_ctl;
  900.             pr_debug("c=%d bw=%llu\n", ctl->num,
  901.                 ctl->cur_perf.bw_ctl);
  902. @@ -826,8 +826,7 @@ void mdss_mdp_ctl_perf_release_bw(struct mdss_mdp_ctl *ctl)
  903.      */
  904.     for (i = 0; i < mdata->nctl; i++) {
  905.         struct mdss_mdp_ctl *ctl = mdata->ctl_off + i;
  906. -
  907. -       if (ctl->power_on && ctl->is_video_mode)
  908. +       if (mdss_mdp_ctl_is_power_on(ctl) && ctl->is_video_mode)
  909.             goto exit;
  910.     }
  911.  
  912. @@ -868,7 +867,7 @@ static void mdss_mdp_ctl_perf_update(struct mdss_mdp_ctl *ctl,
  913.      */
  914.     is_bw_released = !mdss_mdp_ctl_perf_get_transaction_status(ctl);
  915.  
  916. -   if (ctl->power_on) {
  917. +   if (mdss_mdp_ctl_is_power_on(ctl)) {
  918.         if (is_bw_released || params_changed)
  919.             mdss_mdp_perf_calc_ctl(ctl, new);
  920.         /*
  921. @@ -908,7 +907,7 @@ static void mdss_mdp_ctl_perf_update(struct mdss_mdp_ctl *ctl,
  922.         for (i = 0; i < mdata->nctl; i++) {
  923.             struct mdss_mdp_ctl *ctl;
  924.             ctl = mdata->ctl_off + i;
  925. -           if (ctl->power_on)
  926. +           if (mdss_mdp_ctl_is_power_on(ctl))
  927.                 clk_rate = max(ctl->cur_perf.mdp_clk_rate,
  928.                            clk_rate);
  929.         }
  930. @@ -974,7 +973,7 @@ static int mdss_mdp_ctl_free(struct mdss_mdp_ctl *ctl)
  931.     ctl->intf_num = MDSS_MDP_NO_INTF;
  932.     ctl->intf_type = MDSS_MDP_NO_INTF;
  933.     ctl->is_secure = false;
  934. -   ctl->power_on = false;
  935. +   ctl->power_state = MDSS_PANEL_POWER_OFF;
  936.     ctl->start_fnc = NULL;
  937.     ctl->stop_fnc = NULL;
  938.     ctl->prepare_fnc = NULL;
  939. @@ -1123,7 +1122,7 @@ struct mdss_mdp_mixer *mdss_mdp_wb_mixer_alloc(int rotator)
  940.     ctl->mixer_left = mixer;
  941.  
  942.     ctl->start_fnc = mdss_mdp_writeback_start;
  943. -   ctl->power_on = true;
  944. +   ctl->power_state = MDSS_PANEL_POWER_ON;
  945.     ctl->wb_type = (rotator ? MDSS_MDP_WB_CTL_TYPE_BLOCK :
  946.             MDSS_MDP_WB_CTL_TYPE_LINE);
  947.     mixer->ctl = ctl;
  948. @@ -1156,7 +1155,7 @@ int mdss_mdp_wb_mixer_destroy(struct mdss_mdp_mixer *mixer)
  949.     pr_debug("destroy ctl=%d mixer=%d\n", ctl->num, mixer->num);
  950.  
  951.     if (ctl->stop_fnc)
  952. -       ctl->stop_fnc(ctl);
  953. +       ctl->stop_fnc(ctl, MDSS_PANEL_POWER_OFF);
  954.  
  955.     mdss_mdp_ctl_free(ctl);
  956.  
  957. @@ -1699,11 +1698,13 @@ static int mdss_mdp_ctl_start_sub(struct mdss_mdp_ctl *ctl, bool handoff)
  958.  
  959.  int mdss_mdp_ctl_start(struct mdss_mdp_ctl *ctl, bool handoff)
  960.  {
  961. -   struct mdss_mdp_ctl *sctl;
  962. +   struct mdss_mdp_ctl *sctl = mdss_mdp_get_split_ctl(ctl);
  963.     struct mdss_data_type *mdata = mdss_mdp_get_mdata();
  964.     int ret = 0;
  965.  
  966. -   if (ctl->power_on) {
  967. +   pr_debug("ctl_num=%d, power_state=%d\n", ctl->num, ctl->power_state);
  968. +
  969. +   if (mdss_mdp_ctl_is_power_on(ctl)) {
  970.         pr_debug("%d: panel already on!\n", __LINE__);
  971.         return 0;
  972.     }
  973. @@ -1716,14 +1717,14 @@ int mdss_mdp_ctl_start(struct mdss_mdp_ctl *ctl, bool handoff)
  974.  
  975.     mutex_lock(&ctl->lock);
  976.  
  977. +   memset(&ctl->cur_perf, 0, sizeof(ctl->cur_perf));
  978. +
  979.     /*
  980.      * keep power_on false during handoff to avoid unexpected
  981.      * operations to overlay.
  982.      */
  983.     if (!handoff)
  984. -       ctl->power_on = true;
  985. -
  986. -   memset(&ctl->cur_perf, 0, sizeof(ctl->cur_perf));
  987. +       ctl->power_state = MDSS_PANEL_POWER_ON;
  988.  
  989.     mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
  990.  
  991. @@ -1753,29 +1754,29 @@ int mdss_mdp_ctl_start(struct mdss_mdp_ctl *ctl, bool handoff)
  992.     }
  993.     mdss_mdp_hist_intr_setup(&mdata->hist_intr, MDSS_IRQ_RESUME);
  994.  
  995. -   mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
  996.  error:
  997. +   mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
  998.     mutex_unlock(&ctl->lock);
  999.  
  1000.     return ret;
  1001.  }
  1002.  
  1003. -int mdss_mdp_ctl_stop(struct mdss_mdp_ctl *ctl)
  1004. +int mdss_mdp_ctl_stop(struct mdss_mdp_ctl *ctl, int power_state)
  1005.  {
  1006.     struct mdss_mdp_ctl *sctl;
  1007.     int ret = 0;
  1008.     struct mdss_data_type *mdata = mdss_mdp_get_mdata();
  1009.     u32 off;
  1010.  
  1011. -   if (!ctl->power_on) {
  1012. +   pr_debug("ctl_num=%d, power_state=%d\n", ctl->num, ctl->power_state);
  1013. +
  1014. +   if (!mdss_mdp_ctl_is_power_on(ctl)) {
  1015.         pr_debug("%s %d already off!\n", __func__, __LINE__);
  1016.         return 0;
  1017.     }
  1018.  
  1019.     sctl = mdss_mdp_get_split_ctl(ctl);
  1020.  
  1021. -   pr_debug("ctl_num=%d\n", ctl->num);
  1022. -
  1023.     mutex_lock(&ctl->lock);
  1024.  
  1025.     mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
  1026. @@ -1783,38 +1784,41 @@ int mdss_mdp_ctl_stop(struct mdss_mdp_ctl *ctl)
  1027.     mdss_mdp_hist_intr_setup(&mdata->hist_intr, MDSS_IRQ_SUSPEND);
  1028.  
  1029.     if (ctl->stop_fnc)
  1030. -       ret = ctl->stop_fnc(ctl);
  1031. +       ret = ctl->stop_fnc(ctl, power_state);
  1032.     else
  1033.         pr_warn("no stop func for ctl=%d\n", ctl->num);
  1034.  
  1035.     if (sctl && sctl->stop_fnc) {
  1036. -       ret = sctl->stop_fnc(sctl);
  1037. +       ret = sctl->stop_fnc(sctl, power_state);
  1038.  
  1039.         mdss_mdp_ctl_split_display_enable(0, ctl, sctl);
  1040.     }
  1041. -
  1042.     if (ret) {
  1043.         pr_warn("error powering off intf ctl=%d\n", ctl->num);
  1044. -   } else {
  1045. -       mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_TOP, 0);
  1046. -       if (sctl)
  1047. -           mdss_mdp_ctl_write(sctl, MDSS_MDP_REG_CTL_TOP, 0);
  1048. +       goto end;
  1049. +   }
  1050.  
  1051. -       if (ctl->mixer_left) {
  1052. -           off = __mdss_mdp_ctl_get_mixer_off(ctl->mixer_left);
  1053. -           mdss_mdp_ctl_write(ctl, off, 0);
  1054. -       }
  1055. +   mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_TOP, 0);
  1056. +   if (sctl)
  1057. +       mdss_mdp_ctl_write(sctl, MDSS_MDP_REG_CTL_TOP, 0);
  1058.  
  1059. -       if (ctl->mixer_right) {
  1060. -           off = __mdss_mdp_ctl_get_mixer_off(ctl->mixer_right);
  1061. -           mdss_mdp_ctl_write(ctl, off, 0);
  1062. -       }
  1063. +   if (ctl->mixer_left) {
  1064. +       off = __mdss_mdp_ctl_get_mixer_off(ctl->mixer_left);
  1065. +       mdss_mdp_ctl_write(ctl, off, 0);
  1066. +   }
  1067.  
  1068. -       ctl->power_on = false;
  1069. -       ctl->play_cnt = 0;
  1070. -       mdss_mdp_ctl_perf_update(ctl, 0);
  1071. +   if (ctl->mixer_right) {
  1072. +       off = __mdss_mdp_ctl_get_mixer_off(ctl->mixer_right);
  1073. +       mdss_mdp_ctl_write(ctl, off, 0);
  1074.     }
  1075.  
  1076. +   ctl->play_cnt = 0;
  1077. +   mdss_mdp_ctl_perf_update(ctl, 0);
  1078. +
  1079. +end:
  1080. +   if (!ret)
  1081. +       ctl->power_state = power_state;
  1082. +
  1083.     mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
  1084.  
  1085.     mutex_unlock(&ctl->lock);
  1086. @@ -2400,7 +2404,7 @@ int mdss_mdp_display_wait4comp(struct mdss_mdp_ctl *ctl)
  1087.     if (ret)
  1088.         return ret;
  1089.  
  1090. -   if (!ctl->power_on) {
  1091. +   if (!mdss_mdp_ctl_is_power_on(ctl)) {
  1092.         mutex_unlock(&ctl->lock);
  1093.         return 0;
  1094.     }
  1095. @@ -2423,7 +2427,7 @@ int mdss_mdp_display_wait4pingpong(struct mdss_mdp_ctl *ctl)
  1096.     if (ret)
  1097.         return ret;
  1098.  
  1099. -   if (!ctl->power_on) {
  1100. +   if (!mdss_mdp_ctl_is_power_on(ctl)) {
  1101.         mutex_unlock(&ctl->lock);
  1102.         return 0;
  1103.     }
  1104. @@ -2451,7 +2455,7 @@ int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg)
  1105.     mutex_lock(&ctl->lock);
  1106.     pr_debug("commit ctl=%d play_cnt=%d\n", ctl->num, ctl->play_cnt);
  1107.  
  1108. -   if (!ctl->power_on) {
  1109. +   if (!mdss_mdp_ctl_is_power_on(ctl)) {
  1110.         mutex_unlock(&ctl->lock);
  1111.         return 0;
  1112.     }
  1113. @@ -2556,7 +2560,7 @@ int mdss_mdp_get_ctl_mixers(u32 fb_num, u32 *mixer_id)
  1114.     mdata = mdss_mdp_get_mdata();
  1115.     for (i = 0; i < mdata->nctl; i++) {
  1116.         ctl = mdata->ctl_off + i;
  1117. -       if ((ctl->power_on) && (ctl->mfd) &&
  1118. +       if ((mdss_mdp_ctl_is_power_on(ctl)) && (ctl->mfd) &&
  1119.             (ctl->mfd->index == fb_num)) {
  1120.             if (ctl->mixer_left) {
  1121.                 mixer_id[mixer_cnt] = ctl->mixer_left->num;
  1122. diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
  1123. index 11aad01..a4b76f0 100644
  1124. --- a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
  1125. +++ b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
  1126. @@ -40,7 +40,7 @@ struct mdss_mdp_cmd_ctx {
  1127.     struct completion pp_comp;
  1128.     struct completion stop_comp;
  1129.     struct list_head vsync_handlers;
  1130. -   int panel_on;
  1131. +   int panel_power_state;
  1132.     int koff_cnt;
  1133.     int clk_enabled;
  1134.     int vsync_enabled;
  1135. @@ -64,6 +64,11 @@ struct mdss_mdp_cmd_ctx {
  1136.  
  1137.  struct mdss_mdp_cmd_ctx mdss_mdp_cmd_ctx_list[MAX_SESSIONS];
  1138.  
  1139. +static bool __mdss_mdp_cmd_panel_power_on(struct mdss_mdp_cmd_ctx *ctx)
  1140. +{
  1141. +   return (ctx->panel_power_state == MDSS_PANEL_POWER_ON);
  1142. +}
  1143. +
  1144.  static inline u32 mdss_mdp_cmd_line_count(struct mdss_mdp_ctl *ctl)
  1145.  {
  1146.     struct mdss_mdp_mixer *mixer;
  1147. @@ -251,7 +256,7 @@ static inline void mdss_mdp_cmd_clk_off(struct mdss_mdp_cmd_ctx *ctx)
  1148.         mdss_mdp_ctl_intf_event
  1149.             (ctx->ctl, MDSS_EVENT_PANEL_CLK_CTRL, (void *)0);
  1150.         mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
  1151. -       if (ctx->panel_on &&
  1152. +       if (!__mdss_mdp_cmd_panel_power_on(ctx) &&
  1153.             ctx->ctl->panel_data->panel_info.ulps_feature_enabled)
  1154.             schedule_delayed_work(&ctx->ulps_work, ULPS_ENTER_TIME);
  1155.     }
  1156. @@ -406,7 +411,7 @@ static void __mdss_mdp_cmd_ulps_work(struct work_struct *work)
  1157.     }
  1158.     mutex_unlock(&ctx->clk_mtx);
  1159.  
  1160. -   if (!ctx->panel_on) {
  1161. +   if (!__mdss_mdp_cmd_panel_power_on(ctx)) {
  1162.         pr_err("Panel is off. skipping ULPS configuration\n");
  1163.         return;
  1164.     }
  1165. @@ -569,11 +574,11 @@ int mdss_mdp_cmd_panel_on_locked(struct mdss_mdp_ctl *ctl)
  1166.     }
  1167.  
  1168.     mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
  1169. -   if (ctx->panel_on == 0) {
  1170. +   if (!__mdss_mdp_cmd_panel_power_on(ctx)) {
  1171.         rc = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_UNBLANK, NULL);
  1172.         WARN(rc, "intf %d unblank error (%d)\n", ctl->intf_num, rc);
  1173.  
  1174. -       ctx->panel_on++;
  1175. +       ctx->panel_power_state = MDSS_PANEL_POWER_ON;
  1176.  
  1177.         rc = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_PANEL_ON, NULL);
  1178.         WARN(rc, "intf %d panel on error (%d)\n", ctl->intf_num, rc);
  1179. @@ -627,10 +632,9 @@ int mdss_mdp_cmd_kickoff(struct mdss_mdp_ctl *ctl, void *arg)
  1180.     return 0;
  1181.  }
  1182.  
  1183. -int mdss_mdp_cmd_stop(struct mdss_mdp_ctl *ctl)
  1184. +int mdss_mdp_cmd_stop(struct mdss_mdp_ctl *ctl, int panel_power_state)
  1185.  {
  1186.     struct mdss_mdp_cmd_ctx *ctx;
  1187. -   struct mdss_panel_info *pinfo;
  1188.     unsigned long flags;
  1189.     struct mdss_mdp_vsync_handler *tmp, *handle;
  1190.     int need_wait = 0;
  1191. @@ -660,22 +664,13 @@ int mdss_mdp_cmd_stop(struct mdss_mdp_ctl *ctl)
  1192.             ctx->rdptr_enabled = 0;
  1193.             goto skip_wait;
  1194.         }
  1195. -       if (wait_for_completion_timeout(&ctx->stop_comp, STOP_TIMEOUT)
  1196. -           <= 0) {
  1197. +       if (wait_for_completion_timeout(&ctx->stop_comp,
  1198. +           STOP_TIMEOUT) <= 0) {
  1199.             WARN(1, "stop cmd time out\n");
  1200. -
  1201. -           if (IS_ERR_OR_NULL(ctl->panel_data)) {
  1202. -               pr_err("no panel data\n");
  1203. -           } else {
  1204. -               pinfo = &ctl->panel_data->panel_info;
  1205. -
  1206. -               if (pinfo->panel_dead) {
  1207. -                   mdss_mdp_irq_disable
  1208. -                       (MDSS_MDP_IRQ_PING_PONG_RD_PTR,
  1209. -                               ctx->pp_num);
  1210. -                   ctx->rdptr_enabled = 0;
  1211. -               }
  1212. -           }
  1213. +           mdss_mdp_irq_disable(MDSS_MDP_IRQ_PING_PONG_RD_PTR,
  1214. +               ctx->pp_num);
  1215. +           ctx->rdptr_enabled = 0;
  1216. +           ctx->koff_cnt = 0;
  1217.         }
  1218.     }
  1219.  skip_wait:
  1220. @@ -689,27 +684,21 @@ skip_wait:
  1221.             MDSS_EVENT_REGISTER_RECOVERY_HANDLER,
  1222.             NULL);
  1223.  
  1224. -   turn_off_panel = ctx->panel_on;
  1225. -   ctx->panel_on = 0;
  1226. +   turn_off_panel = ctx->panel_power_state;
  1227.     mdss_mdp_cmd_clk_off(ctx);
  1228.  
  1229.     flush_work(&ctx->pp_done_work);
  1230. +   ctx->panel_power_state = panel_power_state;
  1231.  
  1232.  
  1233. -   mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_RD_PTR, ctx->pp_num,
  1234. -                  NULL, NULL);
  1235. -   mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_COMP, ctx->pp_num,
  1236. -                  NULL, NULL);
  1237. -
  1238. -   memset(ctx, 0, sizeof(*ctx));
  1239. -   ctl->priv_data = NULL;
  1240. -
  1241. -   if (turn_off_panel) {
  1242. +   if (turn_off_panel != MDSS_PANEL_POWER_OFF) {
  1243.         mutex_lock(&ctl->offlock);
  1244. -       ret = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_BLANK, NULL);
  1245. +       ret = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_BLANK,
  1246. +           (void *) (long int) panel_power_state);
  1247.         WARN(ret, "intf %d unblank error (%d)\n", ctl->intf_num, ret);
  1248.  
  1249. -       ret = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_PANEL_OFF, NULL);
  1250. +       ret = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_PANEL_OFF,
  1251. +               (void *) (long int) panel_power_state);
  1252.         WARN(ret, "intf %d unblank error (%d)\n", ctl->intf_num, ret);
  1253.         mutex_unlock(&ctl->offlock);
  1254.     }
  1255. @@ -721,6 +710,14 @@ skip_wait:
  1256.     ctl->remove_vsync_handler = NULL;
  1257.     ctl->panel_on_locked = NULL;
  1258.  
  1259. +   mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_RD_PTR, ctx->pp_num,
  1260. +                  NULL, NULL);
  1261. +   mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_COMP, ctx->pp_num,
  1262. +                  NULL, NULL);
  1263. +
  1264. +   memset(ctx, 0, sizeof(*ctx));
  1265. +   ctl->priv_data = NULL;
  1266. +
  1267.     pr_debug("%s:-\n", __func__);
  1268.  
  1269.     return 0;
  1270. @@ -731,7 +728,7 @@ void mdss_mdp_cmd_dump_ctx(struct mdss_mdp_ctl *ctl)
  1271.     struct mdss_mdp_cmd_ctx *ctx = ctl->priv_data;
  1272.  
  1273.     MDSS_TIMEOUT_LOG("pp_num=%u\n", ctx->pp_num);
  1274. -   MDSS_TIMEOUT_LOG("panel_on=%d\n", ctx->panel_on);
  1275. +   MDSS_TIMEOUT_LOG("panel_on=%d\n", !__mdss_mdp_cmd_panel_power_on(ctx));
  1276.     MDSS_TIMEOUT_LOG("koff_cnt=%d\n", ctx->koff_cnt);
  1277.     MDSS_TIMEOUT_LOG("clk_enabled=%d\n", ctx->clk_enabled);
  1278.     MDSS_TIMEOUT_LOG("vsync_enabled=%d\n", ctx->vsync_enabled);
  1279. diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
  1280. index 6dfcace..d890646 100644
  1281. --- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c
  1282. +++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
  1283. @@ -296,7 +296,7 @@ static int mdss_mdp_video_remove_vsync_handler(struct mdss_mdp_ctl *ctl,
  1284.     return 0;
  1285.  }
  1286.  
  1287. -static int mdss_mdp_video_stop(struct mdss_mdp_ctl *ctl)
  1288. +static int mdss_mdp_video_stop(struct mdss_mdp_ctl *ctl, int panel_power_state)
  1289.  {
  1290.     struct mdss_mdp_video_ctx *ctx;
  1291.     struct mdss_mdp_vsync_handler *tmp, *handle;
  1292. diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
  1293. index ff55c57..2bdc27d 100644
  1294. --- a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
  1295. +++ b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
  1296. @@ -348,7 +348,8 @@ exit:
  1297.     return ret;
  1298.  }
  1299.  
  1300. -static int mdss_mdp_writeback_stop(struct mdss_mdp_ctl *ctl)
  1301. +static int mdss_mdp_writeback_stop(struct mdss_mdp_ctl *ctl,
  1302. +   int panel_power_state)
  1303.  {
  1304.     struct mdss_mdp_writeback_ctx *ctx;
  1305.     struct mdss_mdp_vsync_handler *t, *handle;
  1306. diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
  1307. index 0f6204d..9f046d1 100644
  1308. --- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
  1309. +++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
  1310. @@ -667,7 +667,7 @@ int mdss_mdp_overlay_set(struct msm_fb_data_type *mfd,
  1311.     if (ret)
  1312.         return ret;
  1313.  
  1314. -   if (!mfd->panel_power_on) {
  1315. +   if (!mdss_fb_is_panel_power_on(mfd)) {
  1316.         mutex_unlock(&mdp5_data->ov_lock);
  1317.         return -EPERM;
  1318.     }
  1319. @@ -861,7 +861,7 @@ static int mdss_mdp_overlay_start(struct msm_fb_data_type *mfd)
  1320.     struct mdss_data_type *mdata = mfd_to_mdata(mfd);
  1321.     struct mdss_mdp_ctl *ctl = mdp5_data->ctl;
  1322.  
  1323. -   if (ctl->power_on) {
  1324. +   if (mdss_mdp_ctl_is_power_on(ctl)) {
  1325.         if (mdp5_data->mdata->ulps) {
  1326.             mdss_mdp_footswitch_ctrl_ulps(1, &mfd->pdev->dev);
  1327.             mdss_mdp_ctl_restore(ctl);
  1328. @@ -1188,7 +1188,7 @@ int mdss_mdp_overlay_unset(struct msm_fb_data_type *mfd, int ndx)
  1329.         goto done;
  1330.     }
  1331.  
  1332. -   if (!mfd->panel_power_on) {
  1333. +   if (!mdss_fb_is_panel_power_on(mfd)) {
  1334.         ret = -EPERM;
  1335.         goto done;
  1336.     }
  1337. @@ -1330,7 +1330,7 @@ int mdss_mdp_overlay_play(struct msm_fb_data_type *mfd,
  1338.     if (ret)
  1339.         return ret;
  1340.  
  1341. -   if (!mfd->panel_power_on) {
  1342. +   if (!mdss_fb_is_panel_power_on(mfd)) {
  1343.         ret = -EPERM;
  1344.         goto done;
  1345.     }
  1346. @@ -1497,7 +1497,7 @@ static void mdss_mdp_overlay_pan_display(struct msm_fb_data_type *mfd,
  1347.     if (mutex_lock_interruptible(&mdp5_data->ov_lock))
  1348.         return;
  1349.  
  1350. -   if (!mfd->panel_power_on) {
  1351. +   if (!mdss_fb_is_panel_power_on(mfd)) {
  1352.         mutex_unlock(&mdp5_data->ov_lock);
  1353.         return;
  1354.     }
  1355. @@ -1630,7 +1630,7 @@ int mdss_mdp_overlay_vsync_ctrl(struct msm_fb_data_type *mfd, int en)
  1356.     if (!ctl->add_vsync_handler || !ctl->remove_vsync_handler)
  1357.         return -EOPNOTSUPP;
  1358.     if (!ctl->panel_data->panel_info.cont_splash_enabled
  1359. -           && !ctl->power_on) {
  1360. +           && !mdss_mdp_ctl_is_power_on(ctl)) {
  1361.         pr_debug("fb%d vsync pending first update en=%d\n",
  1362.                 mfd->index, en);
  1363.         return -EPERM;
  1364. @@ -1657,7 +1657,7 @@ static ssize_t dynamic_fps_sysfs_rda_dfps(struct device *dev,
  1365.     struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
  1366.     struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
  1367.  
  1368. -   if (!mdp5_data->ctl || !mdp5_data->ctl->power_on)
  1369. +   if (!mdp5_data->ctl || !mdss_mdp_ctl_is_power_on(mdp5_data->ctl))
  1370.         return 0;
  1371.  
  1372.     pdata = dev_get_platdata(&mfd->pdev->dev);
  1373. @@ -1689,7 +1689,7 @@ static ssize_t dynamic_fps_sysfs_wta_dfps(struct device *dev,
  1374.         return rc;
  1375.     }
  1376.  
  1377. -   if (!mdp5_data->ctl || !mdp5_data->ctl->power_on)
  1378. +   if (!mdp5_data->ctl || !mdss_mdp_ctl_is_power_on(mdp5_data->ctl))
  1379.         return 0;
  1380.  
  1381.     pdata = dev_get_platdata(&mfd->pdev->dev);
  1382. @@ -1778,7 +1778,7 @@ static ssize_t cabc_mode_store(struct device *dev,
  1383.     }
  1384.  
  1385.     mutex_lock(&ctl->offlock);
  1386. -   if (!mfd->panel_power_on) {
  1387. +   if (!mdss_fb_is_panel_power_on(mfd)) {
  1388.         pr_warn("panel is powered off\n");
  1389.         ret = -EPERM;
  1390.         goto unlock;
  1391. @@ -1878,7 +1878,7 @@ static ssize_t te_enable_store(struct device *dev,
  1392.         goto end;
  1393.     }
  1394.  
  1395. -   if (!mfd->panel_power_on) {
  1396. +   if (!mdss_fb_is_panel_power_on(mfd)) {
  1397.         pr_warning("panel is not powered\n");
  1398.         r = -EPERM;
  1399.         goto end;
  1400. @@ -1980,7 +1980,7 @@ static ssize_t hbm_store(struct device *dev,
  1401.     }
  1402.  
  1403.     mutex_lock(&ctl->offlock);
  1404. -   if (!mfd->panel_power_on) {
  1405. +   if (!mdss_fb_is_panel_power_on(mfd)) {
  1406.         pr_warning("panel is not powered\n");
  1407.         r = -EPERM;
  1408.         goto unlock;
  1409. @@ -2027,7 +2027,7 @@ static ssize_t mdss_mdp_vsync_show_event(struct device *dev,
  1410.  
  1411.     if (!mdp5_data->ctl ||
  1412.         (!mdp5_data->ctl->panel_data->panel_info.cont_splash_enabled
  1413. -           && !mdp5_data->ctl->power_on))
  1414. +           && !mdss_mdp_ctl_is_power_on(mdp5_data->ctl)))
  1415.         return -EAGAIN;
  1416.  
  1417.     vsync_ticks = ktime_to_ns(mdp5_data->vsync_time);
  1418. @@ -2389,7 +2389,7 @@ static int mdss_mdp_histo_ioctl(struct msm_fb_data_type *mfd, u32 cmd,
  1419.  
  1420.     switch (cmd) {
  1421.     case MSMFB_HISTOGRAM_START:
  1422. -       if (!mfd->panel_power_on)
  1423. +       if (!mdss_fb_is_panel_power_on(mfd))
  1424.             return -EPERM;
  1425.  
  1426.         pp_bus_handle = mdss_mdp_get_mdata()->pp_bus_hdl;
  1427. @@ -2425,7 +2425,7 @@ static int mdss_mdp_histo_ioctl(struct msm_fb_data_type *mfd, u32 cmd,
  1428.         break;
  1429.  
  1430.     case MSMFB_HISTOGRAM:
  1431. -       if (!mfd->panel_power_on)
  1432. +       if (!mdss_fb_is_panel_power_on(mfd))
  1433.             return -EPERM;
  1434.  
  1435.         ret = copy_from_user(&hist, argp, sizeof(hist));
  1436. @@ -2459,7 +2459,7 @@ static int mdss_fb_set_metadata(struct msm_fb_data_type *mfd,
  1437.             ret = -EINVAL;
  1438.         break;
  1439.     case metadata_op_crc:
  1440. -       if (!mfd->panel_power_on)
  1441. +       if (!mdss_fb_is_panel_power_on(mfd))
  1442.             return -EPERM;
  1443.         ret = mdss_misr_set(mdata, &metadata->data.misr_request, ctl);
  1444.         break;
  1445. @@ -2514,7 +2514,7 @@ static int mdss_fb_get_metadata(struct msm_fb_data_type *mfd,
  1446.         ret = mdss_fb_get_hw_caps(mfd, &metadata->data.caps);
  1447.         break;
  1448.     case metadata_op_crc:
  1449. -       if (!mfd->panel_power_on)
  1450. +       if (!mdss_fb_is_panel_power_on(mfd))
  1451.             return -EPERM;
  1452.         ret = mdss_misr_get(mdata, &metadata->data.misr_request, ctl);
  1453.         break;
  1454. @@ -2549,7 +2549,7 @@ static int __handle_overlay_prepare(struct msm_fb_data_type *mfd,
  1455.     if (ret)
  1456.         return ret;
  1457.  
  1458. -   if (!mfd->panel_power_on) {
  1459. +   if (!mdss_fb_is_panel_power_on(mfd)) {
  1460.         mutex_unlock(&mdp5_data->ov_lock);
  1461.         return -EPERM;
  1462.     }
  1463. @@ -2937,7 +2937,7 @@ static int mdss_mdp_overlay_off(struct msm_fb_data_type *mfd)
  1464.         return -ENODEV;
  1465.     }
  1466.  
  1467. -   if (!mdp5_data->ctl->power_on)
  1468. +   if (!mdss_mdp_ctl_is_power_on(mdp5_data->ctl))
  1469.         return 0;
  1470.  
  1471.     mdss_mdp_overlay_free_fb_pipe(mfd);
  1472. @@ -2973,7 +2973,7 @@ static int mdss_mdp_overlay_off(struct msm_fb_data_type *mfd)
  1473.         __vsync_retire_signal(mfd, mdp5_data->retire_cnt);
  1474.     }
  1475.  
  1476. -   rc = mdss_mdp_ctl_stop(mdp5_data->ctl);
  1477. +   rc = mdss_mdp_ctl_stop(mdp5_data->ctl, mfd->panel_power_state);
  1478.     if (rc == 0) {
  1479.         __mdss_mdp_overlay_free_list_purge(mfd);
  1480.         mdss_mdp_ctl_notifier_unregister(mdp5_data->ctl,
  1481. @@ -3262,7 +3262,7 @@ __vsync_retire_get_fence(struct msm_sync_pt_data *sync_pt_data)
  1482.     if (!ctl->add_vsync_handler)
  1483.         return ERR_PTR(-EOPNOTSUPP);
  1484.  
  1485. -   if (!ctl->power_on) {
  1486. +   if (!mdss_mdp_ctl_is_power_on(ctl)) {
  1487.         pr_debug("fb%d vsync pending first update\n", mfd->index);
  1488.         return ERR_PTR(-EPERM);
  1489.     }
  1490. diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
  1491. index 4b89a37..23b2f33 100644
  1492. --- a/drivers/video/msm/mdss/mdss_mdp_pp.c
  1493. +++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
  1494. @@ -1551,7 +1551,7 @@ int mdss_mdp_pp_setup(struct mdss_mdp_ctl *ctl)
  1495.  
  1496.     /* TODO: have some sort of reader/writer lock to prevent unclocked
  1497.      * access while display power is toggled */
  1498. -   if (!ctl->mfd->panel_power_on) {
  1499. +   if (!mdss_mdp_ctl_is_power_on(ctl)) {
  1500.         ret = -EPERM;
  1501.         goto error;
  1502.     }
  1503. @@ -3699,7 +3699,7 @@ static struct msm_fb_data_type *mdss_get_mfd_from_index(int index)
  1504.  
  1505.     for (i = 0; i < mdata->nctl; i++) {
  1506.         ctl = mdata->ctl_off + i;
  1507. -       if ((ctl->power_on) && (ctl->mfd)
  1508. +       if ((mdss_mdp_ctl_is_power_on(ctl)) && (ctl->mfd)
  1509.                 && (ctl->mfd->index == index))
  1510.             out = ctl->mfd;
  1511.     }
  1512. diff --git a/drivers/video/msm/mdss/mdss_mdp_wb.c b/drivers/video/msm/mdss/mdss_mdp_wb.c
  1513. index c021ba5..529d4e0 100644
  1514. --- a/drivers/video/msm/mdss/mdss_mdp_wb.c
  1515. +++ b/drivers/video/msm/mdss/mdss_mdp_wb.c
  1516. @@ -555,7 +555,7 @@ int mdss_mdp_wb_kickoff(struct msm_fb_data_type *mfd)
  1517.     int ret = 0;
  1518.     struct mdss_mdp_writeback_arg wb_args;
  1519.  
  1520. -   if (!ctl->power_on)
  1521. +   if (!mdss_mdp_ctl_is_power_on(ctl))
  1522.         return 0;
  1523.  
  1524.     memset(&wb_args, 0, sizeof(wb_args));
  1525. diff --git a/drivers/video/msm/mdss/mdss_panel.h b/drivers/video/msm/mdss/mdss_panel.h
  1526. index 76be0cb..db1821c 100644
  1527. --- a/drivers/video/msm/mdss/mdss_panel.h
  1528. +++ b/drivers/video/msm/mdss/mdss_panel.h
  1529. @@ -75,6 +75,16 @@ enum {
  1530.  };
  1531.  
  1532.  enum {
  1533. +   MDSS_PANEL_POWER_OFF = 0,
  1534. +   MDSS_PANEL_POWER_ON,
  1535. +};
  1536. +
  1537. +enum {
  1538. +   MDSS_PANEL_BLANK_BLANK = 0,
  1539. +   MDSS_PANEL_BLANK_UNBLANK,
  1540. +};
  1541. +
  1542. +enum {
  1543.     MODE_GPIO_NOT_VALID = 0,
  1544.     MODE_GPIO_HIGH,
  1545.     MODE_GPIO_LOW,
  1546. @@ -342,7 +352,8 @@ struct mdss_panel_info {
  1547.     u32 no_solid_fill;
  1548.     u32 partial_update_enabled;
  1549.     struct ion_handle *splash_ihdl;
  1550. -   u32 panel_power_on;
  1551. +   int panel_power_state;
  1552. +   int blank_state;
  1553.     bool hs_cmds_post_init;
  1554.     bool hbm_feature_enabled;
  1555.     bool hbm_state;
  1556. @@ -473,6 +484,20 @@ static inline int mdss_panel_get_htotal(struct mdss_panel_info *pinfo)
  1557.             pinfo->lcdc.h_pulse_width;
  1558.  }
  1559.  
  1560. +/**
  1561. + * mdss_panel_is_panel_power_on: - checks if a panel is on
  1562. + * @pdata: pointer to the panel struct associated to the panel
  1563. + *
  1564. + * A panel is considered to be on as long as it can accept any commands
  1565. + * or data. Sometimes it is posible to program the panel to be in a low
  1566. + * power state. This function returns false only if panel has explicitly
  1567. + * been turned off.
  1568. + */
  1569. +static inline bool mdss_panel_is_panel_power_on(struct mdss_panel_data *pdata)
  1570. +{
  1571. +   return (pdata->panel_info.panel_power_state != MDSS_PANEL_POWER_OFF);
  1572. +}
  1573. +
  1574.  int mdss_register_panel(struct platform_device *pdev,
  1575.     struct mdss_panel_data *pdata);
  1576.  void mdss_dsi_lock_panel_mutex(void);
  1577. --
  1578. 2.6.1
  1579.  
  1580.  
  1581. From 815e21e6d17d7e6f3303ed333d544060dc4a5284 Mon Sep 17 00:00:00 2001
  1582. From: Aravind Venkateswaran <aravindh@codeaurora.org>
  1583. Date: Tue, 29 Jul 2014 00:11:45 -0700
  1584. Subject: [PATCH 2/3] msm: mdss: add support for display always on mode
  1585.  
  1586. Add a new panel power state to represent a panel low power mode. Add a
  1587. new sysfs node to control when to configure the panel into this new
  1588. mode.
  1589.  
  1590. [GabrieleM: Adapt code for Motorola msm8226 sources]
  1591. Change-Id: I7df8bf63470bec893c6b7481678f00ce76b6875c
  1592. Signed-off-by: Aravind Venkateswaran <aravindh@codeaurora.org>
  1593. (cherry picked from commit d5a864dce942e675246d6b8414bdd16add748ac7)
  1594. ---
  1595. drivers/video/msm/mdss/mdss_dsi.c          | 39 ++++++++++++++++++++
  1596.  drivers/video/msm/mdss/mdss_dsi.h          |  1 +
  1597.  drivers/video/msm/mdss/mdss_dsi_panel.c    | 29 +++++++++++++++
  1598.  drivers/video/msm/mdss/mdss_fb.c           | 58 ++++++++++++++++++++++++++++--
  1599.  drivers/video/msm/mdss/mdss_fb.h           |  2 ++
  1600.  drivers/video/msm/mdss/mdss_mdp_ctl.c      | 10 ++++--
  1601.  drivers/video/msm/mdss/mdss_mdp_intf_cmd.c | 35 ++++++++++++++++++
  1602.  drivers/video/msm/mdss/mdss_mdp_overlay.c  | 39 +++++++++++++-------
  1603.  drivers/video/msm/mdss/mdss_panel.h        |  2 ++
  1604.  9 files changed, 199 insertions(+), 16 deletions(-)
  1605.  
  1606. diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
  1607. index 7db6d09..50f55ab 100644
  1608. --- a/drivers/video/msm/mdss/mdss_dsi.c
  1609. +++ b/drivers/video/msm/mdss/mdss_dsi.c
  1610. @@ -120,6 +120,12 @@ end:
  1611.     return ret;
  1612.  }
  1613.  
  1614. +static int mdss_dsi_panel_power_doze(struct mdss_panel_data *pdata, int enable)
  1615. +{
  1616. +   /* Panel power control when entering/exiting doze mode */
  1617. +   return 0;
  1618. +}
  1619. +
  1620.  static int mdss_dsi_panel_power_ctrl(struct mdss_panel_data *pdata,
  1621.     int power_state)
  1622.  {
  1623. @@ -146,6 +152,13 @@ static int mdss_dsi_panel_power_ctrl(struct mdss_panel_data *pdata,
  1624.         break;
  1625.     case MDSS_PANEL_POWER_ON:
  1626.         ret = mdss_dsi_panel_power_on(pdata);
  1627. +       if (pinfo->panel_power_state == MDSS_PANEL_POWER_DOZE)
  1628. +           ret = mdss_dsi_panel_power_doze(pdata, false);
  1629. +       else
  1630. +           ret = mdss_dsi_panel_power_on(pdata);
  1631. +       break;
  1632. +   case MDSS_PANEL_POWER_DOZE:
  1633. +       ret = mdss_dsi_panel_power_doze(pdata, true);
  1634.         break;
  1635.     default:
  1636.         pr_err("%s: unknown panel power state requested (%d)\n",
  1637. @@ -391,6 +404,11 @@ static int mdss_dsi_off(struct mdss_panel_data *pdata, int power_state)
  1638.             goto end;
  1639.         }
  1640.  
  1641. +       if (power_state != MDSS_PANEL_POWER_OFF) {
  1642. +           pr_debug("%s: dsi_off with panel always on\n", __func__);
  1643. +           goto panel_power_ctrl;
  1644. +       }
  1645. +
  1646.         if (pdata->panel_info.type == MIPI_CMD_PANEL)
  1647.             mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1);
  1648.  
  1649. @@ -402,6 +420,7 @@ static int mdss_dsi_off(struct mdss_panel_data *pdata, int power_state)
  1650.  
  1651.         mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 0);
  1652.  
  1653. +panel_power_ctrl:
  1654.         ret = mdss_dsi_panel_power_ctrl(pdata, power_state);
  1655.         if (ret)
  1656.             pr_err("%s: Panel power off failed\n", __func__);
  1657. @@ -753,6 +772,12 @@ int mdss_dsi_on(struct mdss_panel_data *pdata)
  1658.         mdss_dsi_phy_sw_reset((ctrl_pdata->ctrl_base));
  1659.         mdss_dsi_phy_init(pdata);
  1660.         mdss_dsi_clk_ctrl(ctrl_pdata, DSI_BUS_CLKS, 0);
  1661. +
  1662. +       if (cur_power_state != MDSS_PANEL_POWER_OFF) {
  1663. +           pr_debug("%s: dsi_on from panel low power state\n", __func__);
  1664. +           goto end;
  1665. +       }
  1666. +
  1667.         mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1);
  1668.  
  1669.         __mdss_dsi_ctrl_setup(pdata);
  1670. @@ -805,6 +830,13 @@ static int mdss_dsi_unblank(struct mdss_panel_data *pdata)
  1671.     pr_debug("%s+: ctrl=%p ndx=%d cur_blank_state=%d\n", __func__,
  1672.         ctrl_pdata, ctrl_pdata->ndx, pdata->panel_info.blank_state);
  1673.  
  1674. +   if (pdata->panel_info.blank_state == MDSS_PANEL_BLANK_LOW_POWER) {
  1675. +       pr_debug("%s: dsi_unblank with panel always on\n", __func__);
  1676. +       if (ctrl_pdata->low_power_config)
  1677. +           ret = ctrl_pdata->low_power_config(pdata, false);
  1678. +       return ret;
  1679. +   }
  1680. +
  1681.     if (!(ctrl_pdata->ctrl_state & CTRL_STATE_PANEL_INIT)) {
  1682.         ret = ctrl_pdata->on(pdata);
  1683.         if (ret) {
  1684. @@ -845,6 +877,13 @@ static int mdss_dsi_blank(struct mdss_panel_data *pdata, int power_state)
  1685.     pr_debug("%s+: ctrl=%p ndx=%d power_state=%d\n",
  1686.         __func__, ctrl_pdata, ctrl_pdata->ndx, power_state);
  1687.  
  1688. +   if (power_state == MDSS_PANEL_POWER_DOZE) {
  1689. +       pr_debug("%s: low power state requested\n", __func__);
  1690. +       if (ctrl_pdata->low_power_config)
  1691. +           ret = ctrl_pdata->low_power_config(pdata, true);
  1692. +       return ret;
  1693. +   }
  1694. +
  1695.     if (pdata->panel_info.type == MIPI_VIDEO_PANEL &&
  1696.             ctrl_pdata->off_cmds.link_state == DSI_LP_MODE) {
  1697.         mdss_dsi_sw_reset(pdata);
  1698. diff --git a/drivers/video/msm/mdss/mdss_dsi.h b/drivers/video/msm/mdss/mdss_dsi.h
  1699. index f3f31db..897bf90 100644
  1700. --- a/drivers/video/msm/mdss/mdss_dsi.h
  1701. +++ b/drivers/video/msm/mdss/mdss_dsi.h
  1702. @@ -263,6 +263,7 @@ struct mdss_dsi_ctrl_pdata {
  1703.     int ndx;    /* panel_num */
  1704.     int (*on) (struct mdss_panel_data *pdata);
  1705.     int (*off) (struct mdss_panel_data *pdata);
  1706. +   int (*low_power_config) (struct mdss_panel_data *pdata, int enable);
  1707.     int (*partial_update_fnc) (struct mdss_panel_data *pdata);
  1708.     int (*check_status) (struct mdss_dsi_ctrl_pdata *pdata);
  1709.     int (*cmdlist_commit)(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp,
  1710. diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c
  1711. index da915f7..1f8e8e4 100644
  1712. --- a/drivers/video/msm/mdss/mdss_dsi_panel.c
  1713. +++ b/drivers/video/msm/mdss/mdss_dsi_panel.c
  1714. @@ -946,6 +946,34 @@ disable_regs:
  1715.     return 0;
  1716.  }
  1717.  
  1718. +static int mdss_dsi_panel_low_power_config(struct mdss_panel_data *pdata,
  1719. +   int enable)
  1720. +{
  1721. +   struct mdss_dsi_ctrl_pdata *ctrl = NULL;
  1722. +   struct mdss_panel_info *pinfo;
  1723. +
  1724. +   if (pdata == NULL) {
  1725. +       pr_err("%s: Invalid input data\n", __func__);
  1726. +       return -EINVAL;
  1727. +   }
  1728. +
  1729. +   pinfo = &pdata->panel_info;
  1730. +   ctrl = container_of(pdata, struct mdss_dsi_ctrl_pdata,
  1731. +               panel_data);
  1732. +
  1733. +   pr_debug("%s: ctrl=%p ndx=%d enable=%d\n", __func__, ctrl, ctrl->ndx,
  1734. +       enable);
  1735. +
  1736. +   /* Any panel specific low power commands/config */
  1737. +   if (enable)
  1738. +       pinfo->blank_state = MDSS_PANEL_BLANK_LOW_POWER;
  1739. +   else
  1740. +       pinfo->blank_state = MDSS_PANEL_BLANK_UNBLANK;
  1741. +
  1742. +   pr_debug("%s:-\n", __func__);
  1743. +   return 0;
  1744. +}
  1745. +
  1746.  static void mdss_dsi_parse_lane_swap(struct device_node *np, char *dlane_swap)
  1747.  {
  1748.     const char *data;
  1749. @@ -2159,6 +2187,7 @@ int mdss_dsi_panel_init(struct device_node *node,
  1750.  
  1751.     ctrl_pdata->on = mdss_dsi_panel_on;
  1752.     ctrl_pdata->off = mdss_dsi_panel_off;
  1753. +   ctrl_pdata->low_power_config = mdss_dsi_panel_low_power_config;
  1754.     ctrl_pdata->panel_data.set_backlight = mdss_dsi_panel_bl_ctrl;
  1755.     ctrl_pdata->cont_splash_on = mdss_dsi_panel_cont_splash_on;
  1756.     ctrl_pdata->check_status_disabled =
  1757. diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
  1758. index fa41c68..69000585 100644
  1759. --- a/drivers/video/msm/mdss/mdss_fb.c
  1760. +++ b/drivers/video/msm/mdss/mdss_fb.c
  1761. @@ -440,6 +440,38 @@ static ssize_t mdss_fb_get_idle_notify(struct device *dev,
  1762.     return ret;
  1763.  }
  1764.  
  1765. +static ssize_t mdss_fb_set_doze_mode(struct device *dev,
  1766. +   struct device_attribute *attr, const char *buf, size_t count)
  1767. +{
  1768. +   struct fb_info *fbi = dev_get_drvdata(dev);
  1769. +   struct msm_fb_data_type *mfd = fbi->par;
  1770. +   int rc = 0;
  1771. +   int doze_mode = 0;
  1772. +
  1773. +   rc = kstrtoint(buf, 10, &doze_mode);
  1774. +   if (rc) {
  1775. +       pr_err("kstrtoint failed. rc=%d\n", rc);
  1776. +       return rc;
  1777. +   }
  1778. +
  1779. +   pr_debug("Always-on mode %s\n", doze_mode ? "enabled" : "disabled");
  1780. +   if (mfd->panel_info->type !=  MIPI_CMD_PANEL)
  1781. +       pr_err("Always on mode only supported for cmd mode panel\n");
  1782. +   else
  1783. +       mfd->doze_mode = doze_mode;
  1784. +
  1785. +   return count;
  1786. +}
  1787. +
  1788. +static ssize_t mdss_fb_get_doze_mode(struct device *dev,
  1789. +       struct device_attribute *attr, char *buf)
  1790. +{
  1791. +   struct fb_info *fbi = dev_get_drvdata(dev);
  1792. +   struct msm_fb_data_type *mfd = fbi->par;
  1793. +
  1794. +   return scnprintf(buf, PAGE_SIZE, "%d\n", mfd->doze_mode);
  1795. +}
  1796. +
  1797.  static DEVICE_ATTR(msm_fb_type, S_IRUGO, mdss_fb_get_type, NULL);
  1798.  static DEVICE_ATTR(msm_fb_split, S_IRUGO, mdss_fb_get_split, NULL);
  1799.  static DEVICE_ATTR(show_blank_event, S_IRUGO, mdss_mdp_show_blank_event, NULL);
  1800. @@ -447,6 +479,8 @@ static DEVICE_ATTR(idle_time, S_IRUGO | S_IWUSR | S_IWGRP,
  1801.     mdss_fb_get_idle_time, mdss_fb_set_idle_time);
  1802.  static DEVICE_ATTR(idle_notify, S_IRUGO, mdss_fb_get_idle_notify, NULL);
  1803.  static DEVICE_ATTR(rgb, S_IRUGO | S_IWUSR | S_IWGRP, mdss_get_rgb, mdss_set_rgb);
  1804. +static DEVICE_ATTR(always_on, S_IRUGO | S_IWUSR | S_IWGRP,
  1805. +   mdss_fb_get_doze_mode, mdss_fb_set_doze_mode);
  1806.  
  1807.  static struct attribute *mdss_fb_attrs[] = {
  1808.     &dev_attr_msm_fb_type.attr,
  1809. @@ -455,6 +489,7 @@ static struct attribute *mdss_fb_attrs[] = {
  1810.     &dev_attr_idle_time.attr,
  1811.     &dev_attr_idle_notify.attr,
  1812.     &dev_attr_rgb.attr,
  1813. +   &dev_attr_always_on.attr,
  1814.     NULL,
  1815.  };
  1816.  
  1817. @@ -770,8 +805,15 @@ static int mdss_fb_suspend_sub(struct msm_fb_data_type *mfd)
  1818.     mfd->suspend.panel_power_state = mfd->panel_power_state;
  1819.  
  1820.     if (mfd->op_enable) {
  1821. -       ret = mdss_fb_blank_sub(FB_BLANK_POWERDOWN, mfd->fbi,
  1822. -               mfd->suspend.op_enable);
  1823. +       /*
  1824. +        * Ideally, display should have been blanked by now.
  1825. +        * If not, then blank the display based on whether always-on
  1826. +        * feature is enabled or not
  1827. +        */
  1828. +       int unblank_flag = mfd->doze_mode ? FB_BLANK_VSYNC_SUSPEND :
  1829. +           FB_BLANK_POWERDOWN;
  1830. +       ret = mdss_fb_blank_sub(unblank_flag, mfd->fbi,
  1831. +                   mfd->suspend.op_enable);
  1832.         if (ret) {
  1833.             pr_warn("can't turn off display!\n");
  1834.             return ret;
  1835. @@ -931,6 +973,13 @@ void mdss_fb_set_backlight(struct msm_fb_data_type *mfd, u32 bkl_lvl)
  1836.     int (*update_ad_input)(struct msm_fb_data_type *mfd);
  1837.     u32 temp = bkl_lvl;
  1838.  
  1839. +   /* todo: temporary workaround to support doze mode */
  1840. +   if ((bkl_lvl == 0) && (mfd->doze_mode)) {
  1841. +       pr_debug("keeping backlight on with always-on displays\n");
  1842. +       mfd->unset_bl_level = 0;
  1843. +       return;
  1844. +   }
  1845. +
  1846.     if (((!mdss_fb_is_panel_power_on(mfd) && mfd->dcm_state != DCM_ENTER)
  1847.         || !mfd->bl_updated) && !IS_CALIB_MODE_BL(mfd)) {
  1848.         mfd->unset_bl_level = bkl_lvl;
  1849. @@ -1036,6 +1085,8 @@ int mdss_fb_blank_sub(int blank_mode, struct fb_info *info, int op_enable)
  1850.         break;
  1851.  
  1852.     case FB_BLANK_VSYNC_SUSPEND:
  1853. +       req_power_state = MDSS_PANEL_POWER_DOZE;
  1854. +       pr_debug("Doze power mode requested\n");
  1855.     case FB_BLANK_HSYNC_SUSPEND:
  1856.     case FB_BLANK_NORMAL:
  1857.     case FB_BLANK_POWERDOWN:
  1858. @@ -1093,6 +1144,8 @@ static int mdss_fb_blank(int blank_mode, struct fb_info *info)
  1859.     if (mfd->op_enable == 0) {
  1860.         if (blank_mode == FB_BLANK_UNBLANK)
  1861.             mfd->suspend.panel_power_state = MDSS_PANEL_POWER_ON;
  1862. +       else if (blank_mode == FB_BLANK_VSYNC_SUSPEND)
  1863. +           mfd->suspend.panel_power_state = MDSS_PANEL_POWER_DOZE;
  1864.         else
  1865.             mfd->suspend.panel_power_state = MDSS_PANEL_POWER_OFF;
  1866.         return 0;
  1867. @@ -2346,6 +2399,7 @@ int mdss_fb_dcm(struct msm_fb_data_type *mfd, int req_state)
  1868.         return ret;
  1869.     }
  1870.  
  1871. +   /* todo: this needs to be checked */
  1872.     switch (req_state) {
  1873.     case DCM_UNBLANK:
  1874.         if (mfd->dcm_state == DCM_UNINIT &&
  1875. diff --git a/drivers/video/msm/mdss/mdss_fb.h b/drivers/video/msm/mdss/mdss_fb.h
  1876. index f1595af..78d5fd8 100644
  1877. --- a/drivers/video/msm/mdss/mdss_fb.h
  1878. +++ b/drivers/video/msm/mdss/mdss_fb.h
  1879. @@ -235,6 +235,8 @@ struct msm_fb_data_type {
  1880.     bool quickdraw_in_progress;
  1881.     u32 quickdraw_panel_state;
  1882.     bool quickdraw_reset_panel;
  1883. +
  1884. +   int doze_mode;
  1885.  };
  1886.  
  1887.  struct sys_panelinfo {
  1888. diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
  1889. index c892173..12dd0c5 100644
  1890. --- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
  1891. +++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
  1892. @@ -1704,7 +1704,7 @@ int mdss_mdp_ctl_start(struct mdss_mdp_ctl *ctl, bool handoff)
  1893.  
  1894.     pr_debug("ctl_num=%d, power_state=%d\n", ctl->num, ctl->power_state);
  1895.  
  1896. -   if (mdss_mdp_ctl_is_power_on(ctl)) {
  1897. +   if (ctl->power_state == MDSS_PANEL_POWER_ON) {
  1898.         pr_debug("%d: panel already on!\n", __LINE__);
  1899.         return 0;
  1900.     }
  1901. @@ -1717,7 +1717,8 @@ int mdss_mdp_ctl_start(struct mdss_mdp_ctl *ctl, bool handoff)
  1902.  
  1903.     mutex_lock(&ctl->lock);
  1904.  
  1905. -   memset(&ctl->cur_perf, 0, sizeof(ctl->cur_perf));
  1906. +   if (ctl->power_state == MDSS_PANEL_POWER_OFF)
  1907. +       memset(&ctl->cur_perf, 0, sizeof(ctl->cur_perf));
  1908.  
  1909.     /*
  1910.      * keep power_on false during handoff to avoid unexpected
  1911. @@ -1798,6 +1799,11 @@ int mdss_mdp_ctl_stop(struct mdss_mdp_ctl *ctl, int power_state)
  1912.         goto end;
  1913.     }
  1914.  
  1915. +   if (power_state != MDSS_PANEL_POWER_OFF) {
  1916. +       pr_debug("panel is not off, leaving ctl power on\n");
  1917. +       goto end;
  1918. +   }
  1919. +
  1920.     mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_TOP, 0);
  1921.     if (sctl)
  1922.         mdss_mdp_ctl_write(sctl, MDSS_MDP_REG_CTL_TOP, 0);
  1923. diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
  1924. index a4b76f0..61c749c 100644
  1925. --- a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
  1926. +++ b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
  1927. @@ -632,6 +632,17 @@ int mdss_mdp_cmd_kickoff(struct mdss_mdp_ctl *ctl, void *arg)
  1928.     return 0;
  1929.  }
  1930.  
  1931. +int mdss_mdp_cmd_restore(struct mdss_mdp_ctl *ctl)
  1932. +{
  1933. +   pr_debug("%s: called for ctl%d\n", __func__, ctl->num);
  1934. +   mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
  1935. +   if (mdss_mdp_cmd_tearcheck_setup(ctl, true))
  1936. +       pr_warn("%s: tearcheck setup failed\n", __func__);
  1937. +   mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
  1938. +
  1939. +   return 0;
  1940. +}
  1941. +
  1942.  int mdss_mdp_cmd_stop(struct mdss_mdp_ctl *ctl, int panel_power_state)
  1943.  {
  1944.     struct mdss_mdp_cmd_ctx *ctx;
  1945. @@ -710,6 +721,11 @@ skip_wait:
  1946.     ctl->remove_vsync_handler = NULL;
  1947.     ctl->panel_on_locked = NULL;
  1948.  
  1949. +   if (panel_power_state != MDSS_PANEL_POWER_OFF) {
  1950. +       pr_debug("%s: cmd_off with panel always on\n", __func__);
  1951. +       goto end;
  1952. +   }
  1953. +
  1954.     mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_RD_PTR, ctx->pp_num,
  1955.                    NULL, NULL);
  1956.     mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_COMP, ctx->pp_num,
  1957. @@ -718,6 +734,7 @@ skip_wait:
  1958.     memset(ctx, 0, sizeof(*ctx));
  1959.     ctl->priv_data = NULL;
  1960.  
  1961. +end:
  1962.     pr_debug("%s:-\n", __func__);
  1963.  
  1964.     return 0;
  1965. @@ -743,6 +760,24 @@ int mdss_mdp_cmd_start(struct mdss_mdp_ctl *ctl)
  1966.  
  1967.     pr_debug("%s:+\n", __func__);
  1968.  
  1969. +   if (!ctl)
  1970. +       return -EINVAL;
  1971. +
  1972. +   ctx = (struct mdss_mdp_cmd_ctx *) ctl->priv_data;
  1973. +   if (ctx && (ctx->panel_power_state != MDSS_PANEL_POWER_OFF)) {
  1974. +       pr_debug("%s: cmd_start with panel always on\n",
  1975. +           __func__);
  1976. +       /*
  1977. +        * It is possible that the resume was called from the panel
  1978. +        * always on state without MDSS every power-collapsed (such
  1979. +        * as a case with any other interfaces connected). In such
  1980. +        * cases, we need to explictly call the restore function to
  1981. +        * enable tearcheck logic.
  1982. +        */
  1983. +       mdss_mdp_cmd_restore(ctl);
  1984. +       return 0;
  1985. +   }
  1986. +
  1987.     mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_LEFT);
  1988.     if (!mixer) {
  1989.         pr_err("mixer not setup correctly\n");
  1990. diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
  1991. index 9f046d1..44dc8e1 100644
  1992. --- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
  1993. +++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
  1994. @@ -2883,6 +2883,12 @@ static int mdss_mdp_overlay_on(struct msm_fb_data_type *mfd)
  1995.         mdp5_data->ctl = ctl;
  1996.     }
  1997.  
  1998. +   if (mdss_fb_is_panel_power_on(mfd)) {
  1999. +       pr_debug("panel was never turned off\n");
  2000. +       rc = mdss_mdp_ctl_start(mdp5_data->ctl, false);
  2001. +       goto panel_on;
  2002. +   }
  2003. +
  2004.     if (!mfd->panel_info->cont_splash_enabled &&
  2005.         (mfd->panel_info->type != DTV_PANEL)) {
  2006.         rc = mdss_mdp_overlay_start(mfd);
  2007. @@ -2907,6 +2913,7 @@ static int mdss_mdp_overlay_on(struct msm_fb_data_type *mfd)
  2008.             return rc;
  2009.     }
  2010.  
  2011. +panel_on:
  2012.     if (IS_ERR_VALUE(rc)) {
  2013.         pr_err("Failed to turn on fb%d\n", mfd->index);
  2014.         mdss_mdp_overlay_off(mfd);
  2015. @@ -2940,6 +2947,11 @@ static int mdss_mdp_overlay_off(struct msm_fb_data_type *mfd)
  2016.     if (!mdss_mdp_ctl_is_power_on(mdp5_data->ctl))
  2017.         return 0;
  2018.  
  2019. +   if (mfd->panel_power_state != MDSS_PANEL_POWER_OFF) {
  2020. +       pr_debug("panel not turned off. keeping overlay on\n");
  2021. +       goto ctl_stop;
  2022. +   }
  2023. +
  2024.     mdss_mdp_overlay_free_fb_pipe(mfd);
  2025.  
  2026.     mixer = mdss_mdp_mixer_get(mdp5_data->ctl, MDSS_MDP_MIXER_MUX_LEFT);
  2027. @@ -2973,22 +2985,25 @@ static int mdss_mdp_overlay_off(struct msm_fb_data_type *mfd)
  2028.         __vsync_retire_signal(mfd, mdp5_data->retire_cnt);
  2029.     }
  2030.  
  2031. +ctl_stop:
  2032.     rc = mdss_mdp_ctl_stop(mdp5_data->ctl, mfd->panel_power_state);
  2033.     if (rc == 0) {
  2034. -       __mdss_mdp_overlay_free_list_purge(mfd);
  2035. -       mdss_mdp_ctl_notifier_unregister(mdp5_data->ctl,
  2036. -               &mfd->mdp_sync_pt_data.notifier);
  2037. -
  2038. -       if (!mfd->ref_cnt) {
  2039. -           mdp5_data->borderfill_enable = false;
  2040. -           mdss_mdp_ctl_destroy(mdp5_data->ctl);
  2041. -           mdp5_data->ctl = NULL;
  2042. -       }
  2043. +       if (mfd->panel_power_state == MDSS_PANEL_POWER_OFF) {
  2044. +           __mdss_mdp_overlay_free_list_purge(mfd);
  2045. +           mdss_mdp_ctl_notifier_unregister(mdp5_data->ctl,
  2046. +                   &mfd->mdp_sync_pt_data.notifier);
  2047. +
  2048. +           if (!mfd->ref_cnt) {
  2049. +               mdp5_data->borderfill_enable = false;
  2050. +               mdss_mdp_ctl_destroy(mdp5_data->ctl);
  2051. +               mdp5_data->ctl = NULL;
  2052. +           }
  2053.  
  2054. -       if (atomic_dec_return(&ov_active_panels) == 0)
  2055. -           mdss_mdp_rotator_release_all();
  2056. +           if (atomic_dec_return(&ov_active_panels) == 0)
  2057. +               mdss_mdp_rotator_release_all();
  2058.  
  2059. -       mdss_mdp_footswitch_ctrl(mdata, false);
  2060. +           mdss_mdp_footswitch_ctrl(mdata, false);
  2061. +       }
  2062.     }
  2063.  
  2064.     return rc;
  2065. diff --git a/drivers/video/msm/mdss/mdss_panel.h b/drivers/video/msm/mdss/mdss_panel.h
  2066. index db1821c..ea4378c 100644
  2067. --- a/drivers/video/msm/mdss/mdss_panel.h
  2068. +++ b/drivers/video/msm/mdss/mdss_panel.h
  2069. @@ -77,11 +77,13 @@ enum {
  2070.  enum {
  2071.     MDSS_PANEL_POWER_OFF = 0,
  2072.     MDSS_PANEL_POWER_ON,
  2073. +   MDSS_PANEL_POWER_DOZE,
  2074.  };
  2075.  
  2076.  enum {
  2077.     MDSS_PANEL_BLANK_BLANK = 0,
  2078.     MDSS_PANEL_BLANK_UNBLANK,
  2079. +   MDSS_PANEL_BLANK_LOW_POWER,
  2080.  };
  2081.  
  2082.  enum {
  2083. --
  2084. 2.6.1
  2085.  
  2086.  
  2087. From 2041a68828f1b87b2c8cccac8087dff07f5d614e Mon Sep 17 00:00:00 2001
  2088. From: Aravind Venkateswaran <aravindh@codeaurora.org>
  2089. Date: Fri, 15 Aug 2014 17:04:35 -0700
  2090. Subject: [PATCH 3/3] msm: mdss: support transition from suspend to doze mode
  2091.  
  2092. If a transition from full suspend to doze mode is requested, first
  2093. unblank the panel and then enter the doze mode.
  2094.  
  2095. [GabrieleM: Adapt code for Motorola msm8226 sources]
  2096. Change-Id: I8c4e55bc320aeed948bc725cba78460a234d1193
  2097. Signed-off-by: Aravind Venkateswaran <aravindh@codeaurora.org>
  2098. ---
  2099. drivers/video/msm/mdss/mdss_fb.c | 11 +++++++++++
  2100.  1 file changed, 11 insertions(+)
  2101.  
  2102. diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
  2103. index 69000585..a048ef5 100644
  2104. --- a/drivers/video/msm/mdss/mdss_fb.c
  2105. +++ b/drivers/video/msm/mdss/mdss_fb.c
  2106. @@ -1093,6 +1093,17 @@ int mdss_fb_blank_sub(int blank_mode, struct fb_info *info, int op_enable)
  2107.     default:
  2108.         pr_debug("blank powerdown called. cur mode=%d, req mode=%d\n",
  2109.             cur_power_state, req_power_state);
  2110. +       /*
  2111. +        * If doze mode is requested when panel is already off,
  2112. +        * then first unblank the panel before entering doze mode
  2113. +        */
  2114. +       if ((MDSS_PANEL_POWER_DOZE == req_power_state) &&
  2115. +           !mdss_fb_is_panel_power_on(mfd) && mfd->mdp.on_fnc) {
  2116. +           pr_debug("off --> doze. switch to on first\n");
  2117. +           ret = mfd->mdp.on_fnc(mfd);
  2118. +           if (ret == 0)
  2119. +               mfd->panel_power_state = MDSS_PANEL_POWER_ON;
  2120. +       }
  2121.         if (mdss_fb_is_panel_power_on(mfd) && mfd->mdp.off_fnc) {
  2122.             cur_power_state = mfd->panel_power_state;
  2123.             mutex_lock(&mfd->update.lock);
  2124. --
  2125. 2.6.1
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement